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

RN 0.66.5 + SES 0.18.1: Error failed to del intrinsics.%AsyncGenerator%.length #16

Closed
leotm opened this issue Mar 9, 2023 · 4 comments · Fixed by endojs/endo#1511
Closed
Labels
android error build/run time blocker jsc JavaScriptCore lockdown

Comments

@leotm
Copy link
Member

leotm commented Mar 9, 2023

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)

[email protected] ❌ (default)
[email protected] ❌ (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) ❌

Screenshot 2023-03-13 at 13 07 54

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

Screenshot 2023-03-13 at 16 44 44

RN v8-android

Screenshot 2023-03-13 at 16 05 56

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)

Screenshot 2023-03-13 at 15 31 07

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

Screenshot 2023-03-13 at 21 31 05

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

@leotm leotm changed the title RN 0.66.5 + SES 0.18.1 + Android + JSC: Promise warnings + error failed to delete intrinsics.%AsyncGenerator%.length RN 0.66.5 + SES 0.18.1 + Android + JSC: Error failed to del intrinsics.%AsyncGenerator%.length Mar 9, 2023
@leotm leotm changed the title RN 0.66.5 + SES 0.18.1 + Android + JSC: Error failed to del intrinsics.%AsyncGenerator%.length RN 0.66.5 + SES 0.18.1: Error failed to del intrinsics.%AsyncGenerator%.length Mar 12, 2023
@leotm leotm added jsc JavaScriptCore android error build/run time blocker labels Mar 12, 2023
@leotm
Copy link
Member Author

leotm commented Mar 14, 2023

Next steps to unblock, harmless PR to SES adding length prop, referencing above issue in code comment

@leotm
Copy link
Member Author

leotm commented Mar 15, 2023

@leotm
Copy link
Member Author

leotm commented Mar 15, 2023

Merged ^ 🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
android error build/run time blocker jsc JavaScriptCore lockdown
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant