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

Polyfill esnext.async-iterator causes "Cannot read properties of undefined (reading 'prototype')" error #1309

Closed
qiulang opened this issue Nov 26, 2023 · 12 comments

Comments

@qiulang
Copy link

qiulang commented Nov 26, 2023

My Babel

"presets": [
     [
         "@babel/preset-env",
         {
             "targets": {
                 "chrome": "84"
             },
             "modules": "commonjs",
             "debug": true,
             "useBuiltIns": "usage",
             "corejs": {
                 "version": 3.8
                 "proposals": true
             }
         }
     ]
  ]

Then from log, I saw

[/Users/langqiu/xxx/getLoginInfo.js]
The corejs3 polyfill added the following polyfills:
  es.aggregate-error { "chrome":"84" }
  es.promise.any { "chrome":"84" }
  esnext.async-iterator.map { "chrome":"84" }
  esnext.iterator.map { "chrome":"84" }
  esnext.async-iterator.filter { "chrome":"84" }
  esnext.iterator.constructor { "chrome":"84" }
  esnext.iterator.filter { "chrome":"84" }

This polyfilled file cause the error Uncaught TypeError: Cannot read properties of undefined (reading 'prototype')

    async-iterator-create-proxy.js:42 Uncaught TypeError: Cannot read properties of undefined (reading 'prototype')
    at e.exports (async-iterator-create-proxy.js:42:72)
    at Object.<anonymous> (esnext.async-iterator.map.js:8:26)
    at n (bootstrap:19:22)
    at Object.<anonymous> (getLoginInfo.js:1:13)
    ...
    at bootstrap:83:10

Only after I set "proposals": false and poyfill without async-iterator the code works, but why?

I feel this may be a bug for async-iterator implementation.

[/Users/langqiu/xxx/getLoginInfo.js]
The corejs3 polyfill added the following polyfills:
  es.aggregate-error { "chrome":"84" }
  es.promise.any { "chrome":"84" }
@zloirock
Copy link
Owner

zloirock commented Nov 26, 2023

What core-js version is used? In what engine you have this error? Could you add a reproducible example?

@zloirock
Copy link
Owner

zloirock commented Nov 26, 2023

Note that the line numbers in the stack are not actual and in this file (and in this function) is only one place where we access .prototype, and it can't cause any problems:

module.exports = function (nextHandler, IS_ITERATOR) {
  var AsyncIteratorProxy = function AsyncIterator(record, state) {
    // ...
  };

  AsyncIteratorProxy.prototype = IS_ITERATOR ? WrapForValidAsyncIteratorPrototype : AsyncIteratorHelperPrototype;

  return AsyncIteratorProxy;
};

@qiulang
Copy link
Author

qiulang commented Nov 26, 2023

Thanks for the reply.

I used 3.8 and got the error. If I used the latest 3.33 because async-iterator is not the proposal stage so it won't be polyfill so I won't get the error.

Please check the error below

Screenshot 2023-11-26 at 17 24 00

@qiulang
Copy link
Author

qiulang commented Nov 26, 2023

Yes, let me create a reproducible example later. It is reproducible from my side.

@zloirock
Copy link
Owner

As you can see in the code above, the problem is missing in the actual (3.33.3) version. It seems that in this old (3.8) version was an implicit undeclared dependency of esnext.async-iterator.* from esnext.async-iterator.constructor that was fixed later. You should use the actual version since old versions are not maintained.

@qiulang
Copy link
Author

qiulang commented Nov 26, 2023

But in the 3.33 version, I can see from the log esnext.async-iterator.* is not polyfilled into the , I think that is the reason 3.33 works.

@zloirock
Copy link
Owner

zloirock commented Nov 26, 2023

I'm not sure that I understood you. They should be injected in case of .map or .filter usage with proposals: true. Overwise, it's a Babel, not core-js, issue.

I think that is the reason 3.33 works

The actual core-js versions work since they have access to %AsyncIteratorPrototype% in another way, without esnext.async-iterator.constructor implicit dependency. IIRC it was a bug that was fixed about 3 years ago.

@zloirock
Copy link
Owner

In case they are just missed on %AsyncIteratorPrototype% - check the readme, that requires extra configuration.

@qiulang
Copy link
Author

qiulang commented Nov 26, 2023

Thanks for the reply. Yes, you were right, with 3.33, they are injected and the bundled file works fine!

[/Users/langqiu/Projects/xxx/getLoginInfo.js]
The corejs3 polyfill added the following polyfills:
  es.aggregate-error { "chrome":"84" }
  es.promise.any { "chrome":"84" }
  esnext.async-iterator.map { "chrome":"84" }
  esnext.iterator.map { "chrome":"84" }
  esnext.async-iterator.filter { "chrome":"84" }
  esnext.iterator.constructor { "chrome":"84" }
  esnext.iterator.filter { "chrome":"84" }

Thanks again.

@qiulang
Copy link
Author

qiulang commented Nov 26, 2023

BTW, I will raise an issue to https://babeljs.io/docs/babel-preset-env#corejs too, because it says, "use corejs: { version: "3.8", proposals: true }. " It should emphasize setting the version to the actual core-js version.

@qiulang
Copy link
Author

qiulang commented Nov 26, 2023

May I ask another question? What do these esnext.async-iterator functions provide that Chrome lacks?

I find even with the recent Chome version 114, they are still polyfill. But I find without these polyfill functions my code work just fine.

[/Users/langqiu/xxx/getLoginInfo.js]
The corejs3 polyfill added the following polyfills:
  esnext.async-iterator.map { "chrome":"114" }
  esnext.iterator.map { "chrome":"114" }
  esnext.async-iterator.filter { "chrome":"114" }
  esnext.iterator.constructor { "chrome":"114" }
  esnext.iterator.filter { "chrome":"114" }

@zloirock
Copy link
Owner

zloirock commented Nov 26, 2023

Those features are still missed in any engines, see https://github.com/tc39/proposal-async-iterator-helpers

Most likely, you do not use them and use just Array#{ filter, map } methods - but since in JS in many cases is impossible to determinate a variable type on static analysis (@babel/preset-env works by this way), Babel inject some extra modules which there is a chance that you are using - it's better to load some extra bytes than break your project because something is missing.

import foo from './foo.js';

console.log(...foo.map(it => it ** 2)); // => what is it - Array#map, Iterator#map, AsyncIterator#map, something else?

I don't recommend to use proposals: true, it's just for experimenting. shippedProposals is much better and safer for most cases.

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

2 participants