Closed leotm closed 12 months ago
nb: from before
a Babel plugin looking most likely (least intrusive/patchy) to switcheroo (transform) back
but first the big why polyfill our Android/iOS JSC/V8 global Promise in the first place and why is this polyfill nonstandard to SES
following-up above and
we're polyfilling Promise
because 8 years ago (diff) since (2015) v0.4.0+
// InitializeJavaScriptAppEngine.js
// ...
function setupPromise() {
// The native Promise implementation throws the following error:
// ERROR: Event loop not supported.
GLOBAL.Promise = require('Promise');
}
// ...
still present in main
/ 0.72-stable
(diff)
// react-native/packages/react-native/Libraries/Core/polyfillPromise.js
// ...
/**
* Set up Promise. The native Promise implementation throws the following error:
* ERROR: Event loop not supported.
*
* If you don't need these polyfills, don't use InitializeCore; just directly
* require the modules you need from InitializeCore for setup.
*/
// ...
still the case? after removing our polyfill(s) and testing native Promise
methods below
nb: https://test262.report in future
// Promise.all() example
const promise1 = Promise.resolve('Resolved value 1');
const promise2 = Promise.resolve('Resolved value 2');
const promise3 = Promise.resolve('Resolved value 3');
(async () => {
try {
const values = await Promise.all([promise1, promise2, promise3]);
console.log(values); // ["Resolved value 1", "Resolved value 2", "Resolved value 3"]
} catch (error) {
console.log(error);
}
})();
// Promise.allSettled() example
const promise4 = Promise.resolve('Resolved value 4');
const promise5 = Promise.reject('Rejected value 5');
(async () => {
try {
const results = await Promise.allSettled([promise4, promise5]);
console.log(results);
// [
// { status: "fulfilled", value: "Resolved value 4" },
// { status: "rejected", reason: "Rejected value 5" }
// ]
} catch (error) {
console.log(error);
}
})();
// Promise.any() example
const promise6 = Promise.reject('Rejected value 6');
const promise7 = Promise.resolve('Resolved value 7');
(async () => {
try {
const value = await Promise.any([promise6, promise7]);
console.log(value); // "Resolved value 7"
} catch (errors) {
console.log(errors);
}
})();
// Promise.prototype.catch() example
const promise8 = Promise.reject('Rejected value 8');
(async () => {
promise8.catch((error) => {
console.log(error); // "Rejected value 8"
});
})();
// Promise.prototype.finally() example
const promise9 = Promise.resolve('Resolved value 9');
(async () => {
try {
const value = await promise9;
console.log(value); // "Resolved value 9"
} catch (error) {
console.log(error);
} finally {
console.log('Promise 9 is settled');
}
})();
// Promise.race() example
const promise10 = new Promise((resolve) => {
setTimeout(() => {
resolve('Resolved value 10');
}, 1000);
});
const promise11 = new Promise((resolve) => {
setTimeout(() => {
resolve('Resolved value 11');
}, 500);
});
(async () => {
try {
const value = await Promise.race([promise10, promise11]);
console.log(value); // "Resolved value 11"
} catch (error) {
console.log(error);
}
})();
// Promise.reject() example
const promise12 = Promise.reject(new Error('Rejected value 12'));
(async () => {
promise12.catch((error) => {
console.log(error.message); // "Rejected value 12"
});
})();
// Promise.resolve() example
const promise13 = Promise.resolve('Resolved value 13');
(async () => {
const value = await promise13;
console.log(value); // "Resolved value 13"
})();
// Promise.prototype.then() example
const promise14 = Promise.resolve('Resolved value 14');
(async () => {
const value = await promise14;
console.log(value); // "Resolved value 14"
})();
# iOS JSC/V8, runtime ok (V8 doesnt log TypeError)
LOG [TypeError: Promise.any is not a function. (In 'Promise.any([promise6, promise7])', 'Promise.any' is undefined)]
LOG Rejected value 8
LOG Resolved value 9
LOG Promise 9 is settled
LOG Rejected value 12
LOG Resolved value 13
LOG Resolved value 14
LOG ["Resolved value 1", "Resolved value 2", "Resolved value 3"]
LOG [{"status": "fulfilled", "value": "Resolved value 4"}, {"reason": "Rejected value 5", "status": "rejected"}]
LOG Running "RN665" with {"rootTag":31,"initialProps":{}}
LOG Resolved value 11
# on event e.g. scroll
SES_UNHANDLED_REJECTION: Rejected value 6
nb: yday JSC/V8 throw/console.error'ed and JSC in Metro twice, so smth was cached - now only logging testing in fresh PoC
so we're polyfilling all of
// node_modules/react-native/Libraries/Promise.js
const Promise = require('promise/setimmediate/es6-extensions');
require('promise/setimmediate/done');
require('promise/setimmediate/finally');
if (__DEV__) {
require('promise/setimmediate/rejection-tracking').enable(
require('./promiseRejectionTrackingOptions').default,
);
}
module.exports = Promise;
i.e. overwriting 8 native Promise
methods: Promise.resolve, Promise.all, Promise.allSettled, Promise.reject, Promise.race, Promise.prototype.catch
(es6-extensions), Promise.prototype.done
, Promise.prototype.finally
warned by SES as nonstandard: tolerating undeletable intrinstics
to only polyfill Promise.any
:rage1: overkill
i.e. no longer due to the original (8 year old) stale code comment: ERROR: Event loop not supported
action item PR contributions reflecting above and https://github.com/LavaMoat/docs/issues/5#issuecomment-1482861565
opt1
Promise
methods to standardopt2
Promise.any
from es6-extensions
like done and finally (or find other lib)Promise.any
then remove othersPromise.any
if nonstandardopt3
Promise.any
native method to each engineuntil resolved
and
ERROR: Event loop not supported
no longer trueedit: re-check Promise
methods with polyfill(s)
edit: re-check recent changelogs RE Promise.any and Promise.allSettled
so we're polyfilling all of
...
i.e. overwriting 8 native
Promise
methods:Promise.resolve, Promise.all, Promise.allSettled, Promise.reject, Promise.race, Promise.prototype.catch
(es6-extensions),Promise.prototype.done
,Promise.prototype.finally
warned by SES as nonstandard: tolerating undeletable intrinsticsto only polyfill
Promise.any
:rage1: overkilli.e. no longer due to the original (8 year old) stale code comment:
ERROR: Event loop not supported
reason 2 for excluding: require('./polyfillPromise')
or polyfillGlobal('Promise', () => require('../Promise'))
MMM + SES + V8: including it increasing Remote JS Debugging app bootup time ~20-30s
reason to keep it included (default): excluding it causing SES_UNHANDLED_REJECTION
error https://github.com/LavaMoat/docs/issues/21
no more warnings with SES baked into RN core (instead of app entry file) in
Follow-up to
As seen in
Tolerable as we have a fully functioning RN app These can be ignored via RN's internal LogBox
Or worst-case omit our RN Promise polyfill, then testing meta-maskmobile
Ideal result: Include RN Promise polyfill (or other) with 0 warnings
Not a blocker in RN, unless proves in metamask-mobile (i.e. fuller RN repo's)
First seen in