-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Feature testing no longer possible with RegExp.prototype.sticky #262
Comments
I tried a couple other browsers. In Edge 25, properties like 'sticky' seem to still seem to be own properties of the RegExp instance, which violates the spec and bypasses this issue. In Firefox Nightly, 'sticky' seems to be a getter property of RegExp.prototype, but it returns false on RegExp.prototype. Maybe we should all adopt the Firefox behavior. The spec's strictness has not been shipped by any of these three browsers, and I suspect web incompatibility is the reason. |
FireFox's current behaviour is the case because RegExp.prototype is still a RegExp instance. Their behaviour will match V8's current behaviour as soon as https://bugzilla.mozilla.org/show_bug.cgi?id=1192038 is fixed, unless the decision ends up being to keep it the way it is now. From a quick look at https://github.com/WebKit/webkit/blob/master/Source/JavaScriptCore/runtime/RegExpPrototype.cpp, JSC simply does not yet implement RegExp.prototype.sticky, however the other getters are currently throwing for non RegExp instances. Like FireFox, RegExp.prototype is still a RegExp instance, which accounts for /CC @evilpie / @bterlson who may be able to comment on spidermonkey and chakra's positions, respectively |
Sounds like Firefox is delaying shipping because they have further web compatibility concerns besides this one with ES2015. This doesn't seem like a big vote of confidence to me. |
I'm not really seeing that, but I'm hoping one of them will comment on this and let us know |
It would be wonderful to not be forced to |
@littledan, no idea why you think that. https://bugzilla.mozilla.org/show_bug.cgi?id=1192038 There is just some Firefox internal code that makes it annoying to implement, we haven't made any decision based on web compat. |
If it turns out that this is an actual web breakage issue, a better fix than returning false would be for the getter to return undefined if its Since this is purely a web compatibility hack, the fix should probably go into Annex B. |
We just haven't gotten to it yet... I hope v8 can get some data on how prevalent this is. Maybe usage is low enough to "evangelize" our way out :-P |
@allenwb I think undefined would make it feature-test as missing, rather than present. I'd rather it feature-test as present so users can take advantage of it. I'd really rather not separate this out into Annex B. Right now, Annex B consists of larger, "chunky" things. There's a lot in the main spec that's there for compatibility, for example all the extra logic in ArraySpeciesCreate. It would be a mess to move everything like this out into Annex B just because it has to do with compatibility. I'm somewhat skeptical putting things in Annex B. There are some things that are really separate and seem to make sense, like @evilpie Oh sorry, I just skimmed the thread and saw a bunch of discussion about things throwing and compatibility concerns; it was an honest misunderstanding. @bterlson It's not clear to me exactly what we would do with usage data. Say we find that 0.5% of the web reads RegExp.prototype.sticky. Then what do we do? How do we do effective evangelism, and then how do we know that we're done? I'd rather stay conservative and maintain existing interfaces until there's a strong justification to changing them. V8 has tried to ship this and run extremely quickly into the fact that it broke the web. The offending code actually looks pretty typical to me, given the way the rest of JavaScript and web APIs work and the way that feature testing is often done. It's the ES2015 spec which is uncharacteristically strict in its checking, not the user code being especially sloppy. It's just not common in JavaScript for reading an innocent property on a primordial to throw like that. The spec change to fix web compatibility would be simple: replace throwing the TypeError with returning false. |
This addresses tc39#262, a web compatibility concern from the addition of 'sticky'. Websites apparently used RegExp.prototype.sticky to feature-test for that RegExp feature. This patch makes all flag accessors simply return *false* if the receiver does not have an [[OriginalFlags]] internal slot.
Generally speaking, I completely understand the desire to avoid breaking changes whenever possible, but there is also a long-term complexity cost to implementing little fixes for every minor breakage that ever occurs. It's nice to be data driven rather than anecdote driven if at all possible. 0.5% of the web is a huge number so obviously we couldn't do anything about that. On the other hand if all we can find are a handful of sites, and those sites get fixed, then I'd say we're done. Microsoft has done this in the past, pretty sure others have as well. In this case the fix is simple enough that I don't mind much. If the committee is fine with #263 so am I, though I reserve the right to feel more strongly one way or the other if we get closer to shipping the current semantics, though :-P |
By the way, it's XRegExp which is the underlying library that does this feature test. I think that's probably copied around pretty widely. Agreed that, in general, when it's just a few sites and/or it would be really ugly or unfortunate to do the change, then going around to the websites can be preferable. I don't think that's this case here. |
oops, see #263 (comment) |
Note that only XRegExp 2 (released in 2012) is affected; a fix was shipped in v3. Depending on how widespread v2 is, it might be possible to evangelize our way out of this… |
What was the reason for changing the RegExp prototype to no longer be a RegExp instance? |
It does seem punitive to change an innocent read to something that now throws. It's not at all "JavaScripty" |
@slightlyoff If only it was that simple. It the root of this is issues relating to the legacy RegExp |
It's also just not true. Pretty much any WebIDL attribute will throw when invoked on the prototype directly rather than an instance of whatever interface |
By the way, a related issue is https://bugs.chromium.org/p/v8/issues/detail?id=4637 (users apparently using RegExp.prototype.toString() as a browser test). I am working on a patch for V8 (https://codereview.chromium.org/1543723002) which will put in workarounds for both of these issues, while installing telemetry to see how often they come up. From there, we can both ship most of ES2015 semantics and find out more about how evangelism for websites to come up-to-date with ES2015 goes. |
We just hadn't gotten around to implementing the standard yet; don't interpret our choice as a "vote" either way. However. I don't especially enjoy driving the clown car directly into every web-compat brick wall, putting it in reverse, backing up a few feet, and leaving it parked in the middle of the road for a few months waiting for data. Being data-driven is important when the benefit is significant. Here, I think it's a waste of time and energy, because there's an alternative: we can just back off a little. I'd be fine with special-casing the built-in prototype in all non-mutating methods and getters that existed in ES5 —under the TypeError branch, so there's no performance penalty to normal use. |
I tried keeping the workaround minimal, to just make I think we should reconsider again extending this compatibility fix to the spec. It's not only that we have to deal with these legacy versions of XRegExp and es6shim while they roll out to the web: We have designed and spec'd an API that our most expert users get tripped up on. |
I would also like to reconsider this. |
With Chrome 49 shipping to stable, we finally have some data on this question (modulo bugs in our data collection system):
Other counters are not yet shipped in any stable version of Chrome, so they don't have much useful data, but bug reports suggest that other flag accessors are also at risk, as historical versions of es6shim called |
Safari returns "/(?:)/" for RegExp.prototype.toString() and has for several years. |
At the March 2016 TC39 meeting, we achieved consensus on semantics that say:
I'll write up a PR for these new semantics. |
This patch makes a change to ES2015 RegExp semantics to prevent certain property accesses and method calls from throwing. Although the feature testing patterns here are dispreferred, they were found necessary to ensure web compatibility of ES2015-based RegExp semantics with respect to old versions of certain libraries. This closes tc39#262.
This patch makes a change to ES2015 RegExp semantics to prevent certain property accesses and method calls from throwing. Although the feature testing patterns here are dispreferred, they were found necessary to ensure web compatibility of ES2015-based RegExp semantics with respect to old versions of certain libraries. This closes #262.
Some websites check for whether the JavaScript implementation supports the 'sticky' flag by reading RegExp.prototype.sticky. Under ES2015, this throws a TypeError because RegExp.prototype is not a RegExp.
https://bugs.chromium.org/p/v8/issues/detail?id=4617#c9
What if we make these flag accessors a little more tolerant? If
this
does not have a [[RegExpMatcher]] internal slot, how about returningfalse
? As it stands, this is blocking us from shipping sticky RegExps.The text was updated successfully, but these errors were encountered: