zloirock / core-js

Standard Library

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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

qiulang opened this issue · comments

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" }

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

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;
};

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

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

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.

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.

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.

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

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.

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.

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" }

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.