Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🚑 app does not work on older iPhones due to modern javascript #924

Closed
shankari opened this issue Jun 23, 2023 · 11 comments
Closed

🚑 app does not work on older iPhones due to modern javascript #924

shankari opened this issue Jun 23, 2023 · 11 comments

Comments

@shankari
Copy link
Contributor

Report from a user:

I am participating in a study that uses OpenPATH. After downloading the App from the Apple store, I have never been unable to get beyond a white screen.
I have an iPhone 6+ , with iOS 12.5.7

We are not supporting iPhone 5 any more, but we should support iPhone 6 and above if possible. It looks like some iPhone 6 phones can be upgraded but others are not. If it is too hard to support, we should make that clear in our docs. From an native code perspective, we support iOS 11+.

I tried running on an iOS 13 emulator and I get the following errors

[Error] SyntaxError: Unexpected token '='
	(anonymous function) (infinite_scroll_list.js:298)
[Error] SyntaxError: Unexpected token '='
	(anonymous function) (service.js:164)
[Error] SyntaxError: Unexpected token '='
	(anonymous function) (enketo-add-note-button.js:163)

It looks like it doesn't like statements of the form

      matchingTimelineEntry.additionsList ||= [];
@shankari
Copy link
Contributor Author

on iOS 13, changing that to

-        timelineEntry.additionsList ||= [];
+        if (timelineEntry.additionsList === undefined) {
+            timelineEntry.additionsList = [];
+        }

works.

But that is not enough for iOS12. On iOS 12, we get the following error

[Error] SyntaxError: Unexpected token '.'
	(anonymous function) (notifScheduler.js:63)
[Error] SyntaxError: Unexpected token '.'
	(anonymous function) (intro.js:209)
[Error] SyntaxError: Unexpected token '.'
	(anonymous function) (multi-label-ui.js:351)

Do I even want to do this or should we just say that iOS 12 is unsupported?

@shankari
Copy link
Contributor Author

The problem is that iOS12 is the last supported version; all iOS13+ has been upgraded to iOS15
Only iOS12 sticks around because some iPhones 6s don't support iOS15.

So either we support this, or we drop support for at least some iPhone6.

The error is ?.

            if (!notifs?.length)

Unfortunately, there are 17 of them. That's not too terrible, but enough that I want to see if there is an alternative to fixing them manually. Is there a polyfill for this feature?

@shankari
Copy link
Contributor Author

No polyfill, have to use a transpiler since this is syntax.
This seems promising. Argh! can't move to the new version fast enough!

https://stackoverflow.com/a/62285046/4040267

@shankari
Copy link
Contributor Author

Found the 17 files

$ grep -rl "?\." www/js | wc -l
      17

So transpiling appears to work but generates extremely messy code

npx babel www/js/splash/notifScheduler.js --presets "@babel/preset-env"

The start of the file looks like

'use strict';

function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }

@shankari
Copy link
Contributor Author

Let's try a specific target

{
  "targets": "iOS 12"
}

doesn't change it

Using ios-saf 12 just results in

Error [BrowserslistError]: Unknown browser query `ios-saf 12`. Maybe you are using old Browserslist or made typo in query.

At this point, it is going to be faster to make the changes manually,

From the transpiler,
if (!notifs?.length) is converted to
to
!(notifs !== null && notifs !== void 0 && notifs.length)

@shankari
Copy link
Contributor Author

or should I just check in the messy code - we are not going to merge this anyway.
Let's do that; I don't want to make a stupid mistake because I am tired

@shankari
Copy link
Contributor Author

This is the list of files

www/js/splash/notifScheduler.js
www/js/plugin/logger.js
www/js/intro.js
www/js/appstatus/permissioncheck.js
www/js/diary/infinite_scroll_list.js
www/js/diary/infinite_scroll_trip_item.js
www/js/diary/infinite_scroll_place_item.js
www/js/diary/list.js
www/js/diary/diary_list_item.js
www/js/survey/multilabel/multi-label-ui.js
www/js/survey/enketo/enketo-demographics.js
www/js/survey/enketo/enketo-add-note-button.js
www/js/survey/enketo/answer.js
www/js/survey/enketo/enketo-notes-list.js
www/js/survey/enketo/enketo-trip-button.js
www/js/survey/enketo/launch.js
www/js/control/general-settings.js

@shankari
Copy link
Contributor Author

Converted all of them using

$ for f in `grep -rl "?\." www/js`; do npx babel $f --presets "@babel/preset-env" --out-file www/js/es5/`basename $f`; done

@shankari
Copy link
Contributor Author

shankari commented Jun 23, 2023

There are two launch.js - external survey and enketo.
Renamed the external survey one to ext-launch.js. We can probably remove it at some point since we don't use it actively

shankari added a commit to e-mission/e-mission-phone that referenced this issue Jun 23, 2023
iOS13 does not support `||=`, so launching the app on iOS13 results in a WSOD.
There are only three instances of this, so we fix it by replacing all of them with compatible code.

like so

```
-        timelineEntry.additionsList ||= [];
+        if (timelineEntry.additionsList === undefined) {
+            timelineEntry.additionsList = [];
+        }
```

This is a partial fix for
e-mission/e-mission-docs#924

In the long term, we will not need this, since webpack will automatically
enforce whatever compatibility we want. So this is throwaway code which will
never be merged to master.

Testing done:
- Before this fix, app got WSOD on 13.x emulator
- After this fix, app launched 13.x emulator
shankari added a commit to e-mission/e-mission-phone that referenced this issue Jun 23, 2023
There were more of these files, so I tried to use babel to automatically transpile.
Using the `--presets "@babel/preset-env"` generated very crappy code.
But I couldn't find a config that fixed only this issue in a targeted fashion

` "targets": "iOS 12"` doesn't change anything
`ios-saf 12` results in an error
`targets: {"safari": 12.5}` also failed (don't remember why)

Since this is a workaround, let's just check in the transpiled files separately
and change the index.html to load the new values

Note that there were two `launch.js` files, so we renamed one of them as `ext-launch.js`

Testing done:
- without these changes, the app would generate a WSOD on iOS 12
- with these changes, it does

This fixes e-mission/e-mission-docs#924
@shankari
Copy link
Contributor Author

Fixed in https://github.com/e-mission/e-mission-phone/tree/hack_to_support_old_iphones
Deployed in version 1.3.3 (live on both app store and play store)

@shankari
Copy link
Contributor Author

shankari commented Jul 16, 2023

n.b. to determine these errors, which occur before loading is complete and we can connect the debugger, I add a breakpoint to CDVAppDelegate at didFinishLaunchingWithOptions

    self.window.rootViewController = self.viewController;
    [self.window makeKeyAndVisible];

    return YES;

When the app stops there, I can connect the debugger and then continue the load.
This is much easier with the devapp, since we have plenty of time to connect the debugger before downloading the UI.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant