zloirock / core-js

Standard Library
MIT License
24.03k stars 1.62k forks source link

Symbol implementation raises error #1289

Closed yuri-voloshyn closed 9 months ago

yuri-voloshyn commented 9 months ago

I'm using core-js in react project.

In Safari 5.1 (7534.50) the following code: window[Symbol()] = true; raises this error: RangeError: Maximum call stack size exceeded.

Possible error location in file: es.symbol.constructor.js related to setter if (DESCRIPTORS && USE_SETTER) setSymbolDescriptor(ObjectPrototype, tag, { configurable: true, set: setter });

zloirock commented 9 months ago

It looks like a subset of issues like https://github.com/zloirock/core-js/issues/163. Symbol polyfill contains significant internal magic and it's impossible to make it work with all possible exotic environment objects. The README has a note about cases like this.

zloirock commented 9 months ago

Do you have this issue only with window object?

yuri-voloshyn commented 9 months ago

Yes, the issue is only with the window object.

The following code works correctly:

let object = {};
object[Symbol()] = true;
zloirock commented 9 months ago

I added an extra workaround for such cases, however I can't guarantee that it will work in your case. You could try changes from this commit.

yuri-voloshyn commented 8 months ago

This fix works in my case

yuanyingfeiyu commented 8 months ago

Hi, I came across similar problem:

I'm using core-js in react-redux project on safari 7 and safari 8. There's one line of code in react-redux that is setting a Symbol to window: window[Symbol.for('react-redux-context')] = new Map(). link.

This code throw an error Can't call method on undefined.

I found that the problem also come from es.symbol.constructor.js related to setter.

  $Symbol = function Symbol() {
    if (isPrototypeOf(SymbolPrototype, this)) throw new TypeError('Symbol is not a constructor');
    var description = !arguments.length || arguments[0] === undefined ? undefined : $toString(arguments[0]);
    var tag = uid(description);
    var setter = function (value) {
      if (this === ObjectPrototype) call(setter, ObjectPrototypeSymbols, value);
      if (hasOwn(this, HIDDEN) && hasOwn(this[HIDDEN], tag)) this[HIDDEN][tag] = false;
      var descriptor = createPropertyDescriptor(1, value);
      try {
        setSymbolDescriptor(this, tag, descriptor);
      } catch (error) {
        if (!(error instanceof RangeError)) throw error;
        fallbackDefineProperty(this, tag, descriptor);
      }
    };
    if (DESCRIPTORS && USE_SETTER) setSymbolDescriptor(ObjectPrototype, tag, { configurable: true, set: setter });
    return wrap(tag, description);
  };

When it's setting a Symbol property to window, this is undefined, hasOwn call the toObject, and toObject calls requireObjectCoercible . And requireObjectCoercible throws the error:

module.exports = function (it) {
  if (isNullOrUndefined(it)) throw new $TypeError("Can't call method on " + it);
  return it;
};

One possible solution for this is adding extra checks for this :

  $Symbol = function Symbol() {
    if (isPrototypeOf(SymbolPrototype, this)) throw new TypeError('Symbol is not a constructor');
    var description = !arguments.length || arguments[0] === undefined ? undefined : $toString(arguments[0]);
    var tag = uid(description);
    var setter = function (value) {
      if (this === ObjectPrototype) call(setter, ObjectPrototypeSymbols, value);
      if (this && hasOwn(this, HIDDEN) && hasOwn(this[HIDDEN], tag)) this[HIDDEN][tag] = false;
      var descriptor = createPropertyDescriptor(1, value);
      try {
        this && setSymbolDescriptor(this, tag, descriptor);
      } catch (error) {
        if (!(error instanceof RangeError)) throw error;
        fallbackDefineProperty(this, tag, descriptor);
      }
    };
    if (DESCRIPTORS && USE_SETTER) setSymbolDescriptor(ObjectPrototype, tag, { configurable: true, set: setter });
    return wrap(tag, description);
  };

I don't know if there's a better fix for this. Thanks a lot.

zloirock commented 8 months ago

When it's setting a Symbol property to window, this is undefined

That looks strange. Could you add a reproducible example?

yuanyingfeiyu commented 8 months ago

When it's setting a Symbol property to window, this is undefined

That looks strange. Could you add a reproducible example?

Hi, here is a reproducible example. Running it in safari 7.1 and 8. Getting the same error. https://codesandbox.io/s/symbol-test-safari7-forked-wvs9g3

zloirock commented 8 months ago

@yuanyingfeiyu ok, this case in those engines will be fixed in the next release.

yuanyingfeiyu commented 8 months ago

@yuanyingfeiyu ok, this case in those engines will be fixed in the next release.

cool, thanks.