Follow-up to
As seen in
No error on iOS jsc
No error on Android v8
lockdown({consoleTaming: 'unsafe'});
WARN Removing intrinsics.Promise._B
WARN Removing intrinsics.Promise._C
WARN Removing intrinsics.Promise._D
WARN Removing intrinsics.Promise.resolve.prototype
WARN Tolerating undeletable intrinsics.Promise.resolve.prototype === undefined
WARN Removing intrinsics.Promise.all.prototype
WARN Tolerating undeletable intrinsics.Promise.all.prototype === undefined
WARN Removing intrinsics.Promise.allSettled.prototype
WARN Tolerating undeletable intrinsics.Promise.allSettled.prototype === undefined
WARN Removing intrinsics.Promise.reject.prototype
WARN Tolerating undeletable intrinsics.Promise.reject.prototype === undefined
WARN Removing intrinsics.Promise.race.prototype
WARN Tolerating undeletable intrinsics.Promise.race.prototype === undefined
WARN Removing intrinsics.%AsyncGenerator%.length
ERROR failed to delete intrinsics.%AsyncGenerator%.length [TypeError: Unable to delete property.]
ERROR TypeError: Unable to delete property.
ERROR Invariant Violation: Module AppRegistry is not a registered callable module (calling runApplication). A frequent cause of the error is that the application entry file path is incorrect.
This can also happen when the JS bundle is corrupt or there is an early initialization error when loading React Native.
Android emu: screenshot, then tapping empty white view
ERROR Invariant Violation: Module RCTEventEmitter is not a registered callable module (calling receiveTouches). A frequent cause of the error is that the application entry file path is incorrect.
This can also happen when the JS bundle is corrupt or there is an early initialization error when loading React Native.
Bundle: http://localhost:8081/index.bundle?platform=android
es2018.asyncgenerator
https://tc39.es/proposal-async-iteration/#sec-well-known-intrinsic-objects-patch
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AsyncGenerator
https://github.com/tc39/proposal-async-iteration#async-generator-functions
Our AsyncGenerator is defined in our whitelist.js
'%InertAsyncGeneratorFunction%': {
// Properties of the AsyncGeneratorFunction Constructor
'[[Proto]]': '%InertFunction%',
prototype: '%AsyncGenerator%',
},
'%AsyncGenerator%': {
// Properties of the AsyncGeneratorFunction Prototype Object
'[[Proto]]': '%FunctionPrototype%',
constructor: '%InertAsyncGeneratorFunction%',
prototype: '%AsyncGeneratorPrototype%',
'@@toStringTag': 'string',
},
More: https://github.com/search?q=repo%3Aendojs%2Fendo%20%25AsyncGenerator%25&type=code
With methods: AsyncGenerator.prototype.(next|return|throw)
Inheriting prop functions: Function.prototype.(length|name|prototype) (error failing to delete these one or more of these props)
Disabling @babel/plugin-proposal-async-generator-functions is a red herring, despite being required and pushed in our default preset:
// node_modules/metro-react-native-babel-preset/src/configs/main.js
// ...
if (isNull || src.indexOf("async") !== -1) {
extraPlugins.push([
require("@babel/plugin-proposal-async-generator-functions"),
]);
extraPlugins.push([require("@babel/plugin-transform-async-to-generator")]);
}
// ...
And applying the return _ref.apply(this, arguments); (Out) transform
Since disabling it persists the error (and further disabling Babel plugins w/o breaking React Native)
metro-react-native-babel-preset@0.66.2 ❌ (default)
metro-react-native-babel-preset@0.75.1 ❌ (bumped)
nb: can't bump to 0.76 since this requires Node v16 instead of Node v14 and we're on RN 0.66.5
"@babel/core": "^7.12.9" ❌ (default)
"@babel/core": "7.21.0" ❌ (bumped)
"@babel/runtime": "^7.12.5" ❌ (default)
"@babel/runtime": "7.21.0" ❌ (bumped)
metro-react-native-babel-preset applies no Android/iOS/jsc/v8-specific transforms (only on Hermes)
It doesn't appear to be Babel transforming android-jsc differently to iOS jsc and/or android-v8
Patch react-native to use "jsc-android": "294992.0.0" (WebKitGTK 2.36.3) instead of default "jsc-android": "^250231.0.0" (WebKitGTK 2.26.1) ❌

Test w/o lockdown
async function* foo() {
yield await Promise.resolve('a');
yield await Promise.resolve('b');
yield await Promise.resolve('c');
}
let str = '';
async function generate() {
for await (const val of foo()) {
str = str + val;
}
console.log('output', str);
}
generate();
console.log('this', this);
console.log(foo);
console.log('typeof foo:', typeof foo);
console.log('typeof foo.prototype:', typeof foo.prototype);
console.log('length:', foo.length);
console.log('name:', foo.name);
console.log('prototype:', foo.prototype);
console.log(
'getOwnPropertyDescriptors:',
Object.getOwnPropertyDescriptors(foo),
);
brave/chrome-v8

RN v8-android

RN android-jsc (not-so-expandable logs output to Metro terminal window)
LOG this [Object]
LOG [Function foo]
LOG typeof foo: function
LOG typeof foo.prototype: object
LOG foo.length: 0
LOG foo.name: foo
LOG foo.prototype: {}
LOG foo.prototype.constructor: [Function foo]
LOG getOwnPropertyDescriptors: {"arguments": {"configurable": false, "enumerable": false, "value": null, "writable": false}, "caller": {"configurable": false, "enumerable": false, "value": null, "writable": false}, "length": {"configurable": true, "enumerable": false, "value": 0, "writable": false}, "name": {"configurable": true, "enumerable": false, "value": "foo", "writable": false}, "prototype": {"configurable": false, "enumerable": false, "value": {}, "writable": true}}
LOG output abc
our %AsyncGenerator% exists since it works i.e. we have desired output and it's correct
our length descriptor (inherited prop fn from Function.prototype) exists and is configurable, so SES should be able to delete it during lockdown
lockdown.umd.js test (instead of importing ses)

Result
WARN Removing intrinsics.%AsyncFunctionPrototype%.length
ERROR failed to delete intrinsics.%AsyncFunctionPrototype%.length [TypeError: Unable to delete property.]
But ofc this isn't the right path, but we've got another problem 👆 AsyncFunctionPrototype
Delete snippet of lockdown below
// ...
try {
delete obj[prop];
} catch (err) {
if (prop in obj) {
if (typeof obj === 'function' && prop === 'prototype') {
obj.prototype = undefined;
if (obj.prototype === undefined) {
// eslint-disable-next-line @endo/no-polymorphic-call
console.warn(
`Tolerating undeletable ${subPath} === undefined`,
);
// eslint-disable-next-line no-continue
continue;
}
}
// eslint-disable-next-line @endo/no-polymorphic-call
console.error(`failed to delete ${subPath}`, err);
} else {
// eslint-disable-next-line @endo/no-polymorphic-call
console.error(`deleting ${subPath} threw`, err);
}
throw err;
}
// ...
Adding logs
WARN Removing intrinsics.%AsyncGenerator%.length
LOG {"obj": {}}
LOG {"prop": "length"}
LOG obj[prop] 0
ERROR failed to delete intrinsics.%AsyncGenerator%.length [TypeError: Unable to delete property.]
ERROR TypeError: Unable to delete property.
Why when we call lockdown with android-jsc (WebKitGTK) our %AsyncGenerator% obj doesn't exist (to delete it's props), but it works w/o calling lockdown 🤔
# JSC
LOG {"obj": [Function Function]}
LOG {"obj": [Function GeneratorFunction]}
LOG {"obj": [Function AsyncFunction]}
LOG {"obj": [Function AsyncGeneratorFunction]}
LOG {"obj": [Function Date]}
LOG {"obj": [Function parse]}
LOG {"obj": [Function UTC]}
LOG {"obj": [Function now]}
LOG {"obj": [Function Date]}
LOG {"obj": [Function parse]}
LOG {"obj": [Function UTC]}
LOG {"obj": [Function now]}
LOG {"obj": [Function getStackString]}
LOG {"obj": [Function Error]}
LOG {"obj": [Function get]}
LOG {"obj": [Function set]}
LOG {"obj": [Function Error]}
LOG {"obj": [Function get]}
LOG {"obj": [Function set]}
LOG {"obj": {}}
LOG {"obj": [Function abs]}
LOG {"obj": [Function acos]}
# ...
LOG {"obj": [Function tanh]}
LOG {"obj": [Function trunc]}
LOG {"obj": [Function imul]}
LOG {"obj": {}}
LOG {"obj": [Function abs]}
LOG {"obj": [Function acos]}
# ...
LOG {"obj": [Function RegExp]}
LOG {"obj": [Function get [Symbol.species]]}
LOG {"obj": [Function RegExp]}
LOG {"obj": [Function get [Symbol.species]]}
LOG {"obj": {}}
LOG {"obj": [Function next]}
LOG {"obj": {}}
V8

After further debugging, issue raised here
lockdown({
errorTaming: 'unsafe',
stackFiltering: 'verbose',
overrideTaming: 'severe',
});
No console output in Metro bundler
Android emu: screenshot (OCR'ed to text below)
undefined is not an object (evaluating '(_console = console)._errorOriginal.apply')
undefined is not an object (evaluating (_console = console)._errorOriginal.apply')
reactConsoleErrorHandler@http://localhost:
8081/index.bundle?platform=android&dev=true &minify=false&app=com.rn665&modulesOnly= false&runModule=true:24784:40
http://localhost:8081/index.bundle?platform=
android&dev=true&minify-false&app=com.rn665 &modulesOnly=false&runModule=true:34732:35 native codel
registerError@http://localhost:8081/index.bundle platform=android&dev=true&minify-false&app= com.rn665&modulesOnly=false&runModule=true:
25268:35
http://localhost:8081/index.bundle?platform=
android&dev=true&minify=false&app=com.rn665 &modulesOnly=false&runModule=true:25162:35 levelMethod@http://localhost:8081/index.bundle
?platform=android&dev=true&minify-false&app= com.rn665&modulesOnly=false&runModule=true:
4724:31
reportException@http://localhost:8081/index bundle?platform=android&dev=true&minify= false&app=com.rn665&modulesOnly=false& runModule=true:24733:22 handleException@http://localhost:8081/index bundle?platform=android&dev=true&minify= false&app=com.rn665&modulesOnly=false& runModule=true:24774:22
Current/only vanilla RN 0.66.5 blocker before metamask-mobile integration
Follow-up to
As seen in
No error on iOS jsc
No error on Android v8
Android emu: screenshot, then tapping empty white view
Bundle: http://localhost:8081/index.bundle?platform=android
es2018.asyncgenerator
https://tc39.es/proposal-async-iteration/#sec-well-known-intrinsic-objects-patch
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AsyncGenerator
https://github.com/tc39/proposal-async-iteration#async-generator-functions
Our AsyncGenerator is defined in our whitelist.js
More: https://github.com/search?q=repo%3Aendojs%2Fendo%20%25AsyncGenerator%25&type=code
With methods:
AsyncGenerator.prototype.(next|return|throw)Inheriting prop functions:
Function.prototype.(length|name|prototype)(error failing to deletetheseone or more of these props)Disabling
@babel/plugin-proposal-async-generator-functionsis a red herring, despite being required and pushed in our default preset:And applying the
return _ref.apply(this, arguments);(Out) transformSince disabling it persists the error (and further disabling Babel plugins w/o breaking React Native)
metro-react-native-babel-preset@0.66.2 ❌ (default)
metro-react-native-babel-preset@0.75.1 ❌ (bumped)
nb: can't bump to 0.76 since this requires Node v16 instead of Node v14 and we're on RN 0.66.5
"@babel/core": "^7.12.9" ❌ (default)
"@babel/core": "7.21.0" ❌ (bumped)
"@babel/runtime": "^7.12.5" ❌ (default)
"@babel/runtime": "7.21.0" ❌ (bumped)
metro-react-native-babel-preset applies no Android/iOS/jsc/v8-specific transforms (only on Hermes)
It doesn't appear to be Babel transforming android-jsc differently to iOS jsc and/or android-v8
Patch
react-nativeto use "jsc-android": "294992.0.0" (WebKitGTK 2.36.3) instead of default "jsc-android": "^250231.0.0" (WebKitGTK 2.26.1) ❌Test w/o lockdown
brave/chrome-v8
RN v8-android
RN android-jsc (not-so-expandable logs output to Metro terminal window)
our
%AsyncGenerator%exists since it works i.e. we have desired output and it's correctour
lengthdescriptor (inherited prop fn fromFunction.prototype) exists and is configurable, so SES should be able todeleteit duringlockdownlockdown.umd.jstest (instead of importingses)Result
But ofc this isn't the right path, but we've got another problem 👆 AsyncFunctionPrototype
Delete snippet of lockdown below
Adding logs
Why when we call
lockdownwith android-jsc (WebKitGTK) our%AsyncGenerator%obj doesn't exist (to delete it's props), but it works w/o callinglockdown🤔V8
After further debugging, issue raised here
lengthon AsyncGenerator and AsyncFunctionPrototype react-native-community/jsc-android-buildscripts#181No console output in Metro bundler
Android emu: screenshot (OCR'ed to text below)
Current/only vanilla RN 0.66.5 blocker before metamask-mobile integration