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

Add support for the 'y' flag to the RegExp constructor #492

Closed
wants to merge 11 commits into from

Conversation

nicolo-ribaudo
Copy link
Contributor

@nicolo-ribaudo nicolo-ribaudo commented Mar 7, 2019

We already partially had this logic in RegExp#@@split: I removed it from there and moved to the RegExp exec internal polyfill.

The changes to the exec constructor are mainly moving things to a single expression to different statements, so that I could place the two SUPPORTS_Y blocks in between.

Fixes #372

@zloirock
Copy link
Owner

zloirock commented Mar 8, 2019

IIRC I had some problems with old FF when I played with something like this. Need to test it.

@nicolo-ribaudo
Copy link
Contributor Author

What do you mean approximately with "old"? I can try to download it and check.

@zloirock
Copy link
Owner

zloirock commented Mar 8, 2019

I don't remember. Early implementations. It was in 2015.

@zloirock
Copy link
Owner

zloirock commented Mar 8, 2019

Most likely it was related this issue.

Repository owner deleted a comment Mar 11, 2019
@nicolo-ribaudo
Copy link
Contributor Author

nicolo-ribaudo commented Mar 12, 2019

I have tested this PR in firefox 11: it was affected by that bug which I fixed in 775b17f.

re.sticky can't be set to true, because it is non-configurable and non-enumerble:
Schermata da 2019-03-13 00-30-50

EDIT: Fixed

RegExpWrapper
);

if (UNSUPPORTED_Y) defineProperty(result, 'sticky', {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be placed on the prototype. I'm not sure that it's 100% safe, but before users issues, we can try it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we place it in the prototype, I'm not sure how we could check if the regexp is sticky.
Maybe I could add a __core-js_sticky__ own property and then make sticky a prototype accessor for that property? I don't want to use a weakmap since it would always need to be polyfilled.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -26,3 +26,33 @@ QUnit.test('RegExp#exec capturing groups', assert => {
// #replace, but here also #replace is buggy :(
// assert.deepEqual(/(a?)?/.exec('x'), ['', undefined], '/(a?)?/.exec("x") returns ["", undefined]');
});

QUnit.test('RegExp#exec sticky', assert => {
const re = new RegExp('a', 'y');
Copy link
Owner

@zloirock zloirock Mar 13, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do not polyfill RegExp constructor in IE8- since we can't add accessors. At least, this test should be ignored in engines without descriptors.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

I'm also moving it to a separate file.

@nicolo-ribaudo
Copy link
Contributor Author

I have tested this PR in modern Chrome (full sticky support), Firefox 11 (broken sticky support) and IE11 (no sticky support). Note that in Firefox 11 it is not possible to polyfill the .sticky accessor, so I had to disable some tests there.

edge: '13',
firefox: '3',
opera: '36',
safari: '10.0',
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I got this data from MDN. Note that on Firefox 3 the y flags doesn't correctly work with regexp methods, but this compat entry is only about the .sticky accessor.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need data for modern opera - it's generated from chrome.

@@ -20,6 +19,12 @@ var REPLACE_SUPPORTS_NAMED_GROUPS = !fails(function () {
return ''.replace(re, '$<a>') !== '7';
});

// IE <= 11 replaces $0 with the whole match, as if it was $&
// https://stackoverflow.com/questions/6024666/getting-ie-to-replace-a-regex-with-the-literal-string-0
var REPLACE_KEEPS_$0 = (function () {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you prefer I can move this fix to a separate PR. I fixed it here just because I saw the tests failing on IE11 and it is related to RegExps.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, it's fine 👍

return new RegExp('a', 'y').sticky === true;
} catch (e) {
return false;
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need try / catch here - we have it in tests runner.

@@ -710,6 +710,13 @@ GLOBAL.tests = {
'es.regexp.flags': function () {
Copy link
Owner

@zloirock zloirock Mar 13, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems we should also update this and RegExp constructor tests and results, maybe something else.

@@ -99,24 +95,22 @@ require('../internals/fix-regexp-well-known-symbol-logic')(
var flags = (rx.ignoreCase ? 'i' : '') +
(rx.multiline ? 'm' : '') +
(rx.unicode ? 'u' : '') +
(SUPPORTS_Y ? 'y' : 'g');
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

!

Repository owner deleted a comment from nicolo-ribaudo Mar 18, 2019
var arrayPush = [].push;
var min = Math.min;
var MAX_UINT32 = 0xffffffff;

// babel-minify transpiles RegExp('x', 'y') -> /x/y and it causes SyntaxError
var SUPPORTS_Y = !fails(function () { return !RegExp(MAX_UINT32, 'y'); });

// @@split logic
require('../internals/fix-regexp-well-known-symbol-logic')(
'split',
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In internalSplit, we have possible RegExp call with y flag.

@zloirock zloirock removed this from the 3.1 milestone Jul 1, 2019
@ThaNarie
Copy link

I realise this issue has been stale for a while, but I would just like to add my findings here.

We've been using the fluent library in our project, which heavily relies on the sticky flag, and uses the lastIndex to move the cursor through the string while using multiple regexps with test and exec.
When merging this PR in a core-js fork we used in our project, we ran into 2 major issues, which I think still need to be addressed here:

  1. regexp.exec wasn't included by babel-preset-env because it still has es.regexp.exec as implemented in ie: '9',:


    Removing this line properly polyfills the exec for IE.

  2. The sticky flag should also modify the behaviour of regexp.test by moving the lastIndex property the same way as exec does. But since there is no test polyfill included in core-js at all, this behaviour doesn't work in IE.

A quick fix for this is to patch regexp.test with return !!re.exec(str);.

Repro that fails in IE:

var re = new RegExp('\\s+', 'y')
re.test('  aa');
console.log(re.lastIndex); // should be 2, but is 0 in IE with current branch

@zloirock
Copy link
Owner

zloirock commented Oct 1, 2019

@ThaNarie since that PR is suspended, feel free to make an alternative version if it's interesting for you.

@nicolo-ribaudo
Copy link
Contributor Author

@ThaNarie I don't have much time to pick this up again, buy if you want you could just take this PR and modify it if it's easier!

@HankMcCoy
Copy link

My team has been running into the same issues w/ Fluent that @ThaNarie mentioned, so we are planning on taking a shot at getting an updated version of this PR up.

We haven't contributed to core-js before, so we'll dig into the CONTRIBUTING doc and see what we can figure out!

@zloirock
Copy link
Owner

zloirock commented Nov 6, 2019

@HankMcCoy if you will have questions, ask me -)

@cvle
Copy link
Contributor

cvle commented Dec 3, 2019

@HankMcCoy I will also dedicate some time in the coming weeks. It would be awesome if we could collaborate.

cvle added a commit to cvle/core-js that referenced this pull request Dec 16, 2019
cvle added a commit to cvle/core-js that referenced this pull request Dec 16, 2019
zloirock#492

Co-authored-by: Nicolò Ribaudo <nicolo.ribaudo@gmail.com>
cvle added a commit to cvle/core-js that referenced this pull request Dec 17, 2019
zloirock#492

Co-authored-by: Nicolò Ribaudo <nicolo.ribaudo@gmail.com>
@zloirock zloirock closed this in 80d7bfe Dec 17, 2019
@nicolo-ribaudo nicolo-ribaudo deleted the re-sticky branch December 18, 2019 00:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Invalid flags supplied to RegExp constructor 'y'
5 participants