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
Fix babel helpers to not require Symbol
to exist
#8947
Fix babel helpers to not require Symbol
to exist
#8947
Conversation
Build successful! You can test your changes in the REPL here: https://babeljs.io/repl/build/9378/ |
|| (iter && 'length' in iter) | ||
|| (typeof Map !== 'undefined' && iter instanceof Map) | ||
|| (typeof Set !== 'undefined' && iter instanceof Set) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
es6-shim provides both Map and Set but doesn’t provide Symbol.iterator when native Symbols aren’t supported; so these lines are needed.
f2522e4
to
9f84c1b
Compare
6a1ebbb
to
3ad4dfe
Compare
import _isIterable from "../../core-js/is-iterable"; | ||
import _Symbol from "../../core-js/symbol"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This also shouldn't need to be pulled in; it's referring to the global.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like checking the typeof Symbol === 'function'
results in the build bringing in import, however, the use of Symbol.iterator in Object(iter)
relies on the global. Do we want to explicitly rely on the global in the type check? i.e. typeof global.Symbol === 'function'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Symbol.iterator in something
is a special case which transpiles to isIterable
helper and it does not load full Symbol
polyfill.
For now we could check for Map/Set using toString (like we do for arguments) so that they are not pulled in. I think that, until there is a way to avoid it, importing |
@nicolo-ribaudo i think using |
Anyway, it's enough heavy dependency and it would be better somehow prevent unnecessary adding of this polyfill. |
|| typeof iter === 'string' | ||
|| (typeof Symbol === 'function' && Symbol.iterator in Object(iter)) | ||
|| (iter && 'length' in iter) | ||
|| Object.prototype.toString.call(iter) === "[object Map]" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I think including these is worth it. If it's doesn't pass Array.isArray(iter)
, then we can ask people to load a symbol polyfill or convert it to an array before using it as an iterable, since it really isn't one unless they've done one of those two things anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
es6-shim creates a Map and Set that work with Array.from, without Symbol.iterator - without this change, Airbnb remains broken on environments without symbols.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My issue here is that i'd consider the use of Array.from
an implementation detail. If Symbol
doesn't exist, then your item isn't iterable. The fact that we support it for arrays is a necessity, but I don't see it that way for Map
and Set
. I'd expect you to call Array.from
to convert to an array first.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Anyway, now it will not work with es6-shim
because it does not support @@toStringTag
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don’t think it is an implementation detail.
In an environment with Symbols, i agree - either it’s iterable or not. But in an environment without symbols, there’s no spec to govern it - and it’s entirely reasonable to say that Array.from can accept any builtin that should be iterable - arrays, strings, Sets, and Maps.
This worked fine in babel 6. I’m not sure why it needs to be dropped in this part of babel 7.
@zloirock is correct that toString won’t suffice. It needs to use instanceof
on the global Map/Set to be able to detect this case.
@loganfsmyth Would you consider two branches - one where Symbols exist, which only checks Symbol.iterator, and another where they don’t, that has the (zero-dependency) fallback logic we’ve detailed here?
In |
@sharmilajesupaul I just noticed that I merged 38397ce which uses |
@nicolo-ribaudo yup, i can update it here, will get to PR again this afternoon. |
Update babel helpers to not require Symbol to exist. We ran into an issue with ie11 where Symbol is not supported. This PR gaurds the usage of Symbol by ensuring that it exists first. There are also changes that allow objects with a length property and array-like objects to work with `iterableToArray`.
ca35f9a
to
6785ec9
Compare
This fix is most important to my organization right now. Can't transition to latest babel version until IE11 works. |
@zloirock If that's indeed the new direction of Babel, then somebody needs to update https://babeljs.io/docs/en/caveats And change it to reflect that Spread now requires Symbol. |
I made PR #9794 that only targets Spread support so it can work better on IE11 (after you polyfill Array.from). It's less ambitious and can at least solve the v7 regression. |
I have added this PR to the next meeting agenda. |
It's a bad idea to attempt faking any kind of Symbol support ("spec" mode shouldn't work unless Both models should be supported (shamming Symbol, or not), and this is both an undocumented/unintended regression from babel 6 to 7, and also one that makes babel strictly less useful by forcing use of a Symbol polyfill where it need not. |
It's the base of a big part of
It's an absolutely strange requirement since well-known symbol definition is another part of the spec. However, it could work with
I agree. But adding special cases and dirty hacks only for |
The problem is that loose mode enables other undesired consequences. Again, the spec does not govern an environment with Array.from or spread but without Symbols - as such, babel gets to make a choice here - between "it works intuitively in these environments" or "it breaks in these environments". |
Has v3 resolved this now? |
@matt3224 no, core-js can't possibly solve it because the PR is about fixing babel when core-js is not included (specifically, when a Symbol sham is not applied). |
@ljharb could you add support of |
Only in an environment where native symbols exist; this issue won’t be helped by that. |
If |
es6-shim would use a cached toString, so for a non-symbol environment, it'd only solve it when core-js had been run prior to es6-shim - the whole point is that babel should work without core-js. |
@ljharb how it's related |
Ah, I see what you mean. That's certainly an option; but since in a world with Symbols, Object.prototype.toString isn't reliable, I'd hope babel isn't relying on that result for anything. |
|
@nicolo-ribaudo what was the result of the meeting? (Or has it not happened yet?) |
|| typeof iter === 'string' | ||
|| (typeof Symbol === 'function' && Symbol.iterator in Object(iter)) | ||
|| (iter && 'length' in iter) | ||
|| Object.prototype.toString.call(iter) === "[object Arguments]" | ||
) return Array.from(iter); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I encountered the originating problem on IE11 in the JS library I maintain as well, because we can't use babel-polyfill
either for general compatibility. Wasn't sure how long this PR would take to go through so I tried seeing what would happen if we just polyfill Symbol
, and that surfaced up this line as another issue: Array.from
is also not supported in IE11.
So if you're encountering the Symbol
problem in IE11, it's probably because you aren't using polyfills, which means this will likely be an issue as well. Not sure if that's tangential enough to be in a separate ticket entirely though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
using es6-shim, Array.from works but symbols don’t, leading to this issue.
It’s reasonable to require shimming Array.from; but not to require shamming symbols.
Sorry to disturb, but this PR seems stuck... Can someone sum up why? We really need #7597 fixed... Thanks in advance. |
Hey @zloirock what would be the set of changes you would want to see in this PR to get it merged? We're maintaining a forked copy of the babelHelpers internally at Airbnb to work around this, but that's pretty unfortunate. It also seems other folks are also hitting this issue. I'd love to see this get unstuck, let us know how we can help! |
@esprehn I already wrote it many times - it should not inject unnecessary polyfills in |
With the current version of this PR, if the library contains code like if (typeof Symbol == 'undefined') throw Error('This library requires `Symbol` polyfill'); it will die at this line even with |
closing due to inactivity, feel free to reopen or make another PR for this issue to push this forward |
Fixes #7597
Ensure that
Symbol
exists and is a function before using it.In the
_iterableToArray
helper, we update the condition to check for objects that act as arrays such as, objects with thelength
property, Maps, and Sets. This change is being made because we ran into an issue with the usage ofSymbol
breaking on ie11 because it is not supported.cc. @ljharb @loganfsmyth