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

Make RegExp#[Symbol.*] methods call exec #411

Merged
merged 5 commits into from
Aug 30, 2018

Conversation

nicolo-ribaudo
Copy link
Contributor

@zloirock
Copy link
Owner

Sorry, some more days I'll be unavailable. I'll review it later.

// 21.2.5.8 RegExp.prototype[@@replace](string, replaceValue)
// 21.2.5.11 RegExp.prototype[@@split](string, limit)
? function (string, arg) { return regexMethod.call(string, this, arg); }
// 21.2.5.6 RegExp.prototype[@@match](string)
// 21.2.5.9 RegExp.prototype[@@search](string)
: function (string) { return regexMethod.call(string, this); }
);
// TODO: This line makes the tests fail:
// ReferenceError: Can't find variable: Reflect
// hide(RegExp.prototype[SYMBOL], 'name', '[Symbol.' + KEY + ']');
Copy link
Owner

Choose a reason for hiding this comment

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

In many engines, functions .name property non-writable non-configurable, so, I think, it would be better just remove it.

},
// `RegExp.prototype[@@match]` method
// https://tc39.github.io/ecma262/#sec-regexp.prototype-@@match
function Symbol$match(regexp) {
Copy link
Owner

Choose a reason for hiding this comment

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

For better compression, use named functions only when they should have the same explicit .name property (like match above).

};
try {
return run(assert);
} finally {
Copy link
Owner

Choose a reason for hiding this comment

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

IIRC in very old IE try / finally does not work without catch.

@@ -0,0 +1,5 @@
'use strict';
Copy link
Owner

Choose a reason for hiding this comment

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

Please, add a comment that it's AdvanceStringIndex abstract operation and the link to the spec.

@@ -16,13 +16,17 @@ module.exports = function (KEY, length, exec) {
return ''[KEY](O) != 7;
})) {
Copy link
Owner

Choose a reason for hiding this comment

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

Are you sure that this test also covers all engines without internal execution of .exec method? Maybe makes sense extend it?

var A = [];
var n = 0;
var result;
while ((result = rx.exec(S)) !== null) {
Copy link
Owner

@zloirock zloirock Jun 30, 2018

Choose a reason for hiding this comment

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

In RegExpExec, own .exec should be called only if it's callable. Maybe makes sense to implement RegExpExec abstract operation?

var execCalled = false;
var re = /a/;
re.exec = function () { execCalled = true; return null; };
return re[SYMBOL] && (re[SYMBOL](''), execCalled);
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 return a negative result for the existent feature. Use, for example,

re[SYMBOL]('');
return !execCalled;

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Isn't it faster if it avoid throwing an error?

Copy link
Owner

Choose a reason for hiding this comment

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

It's just an example. The main idea of the comment - the result should be inverted.

var O = {};
O[SYMBOL] = function () { return 7; };
return ''[KEY](O) != 7;
}) || fails(function () {
// Symbol-named RegExp methods call .exec
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This test throws an uncaught stack overflow error in the promises tests and I'm not sure why.

@nicolo-ribaudo
Copy link
Contributor Author

@zloirock I manages to make the tests pass. Could you review this PR again?

@DmitrySoshnikov
Copy link

Hey guys, is this PR good to go yet? Is there still anything blocking?

@nicolo-ribaudo
Copy link
Contributor Author

@zloirock Since Babel uses core-js@2, can I backport this PR?

@zloirock
Copy link
Owner

@nicolo-ribaudo feel free to add the same PR to v2 branch and I'll publish a new core-js@2 version. But let's land this PR at first.

@zloirock
Copy link
Owner

I'll review it today or tomorrow. Could you rebase it?

@zloirock
Copy link
Owner

At first sight, LGTM.

@zloirock zloirock merged commit 6addfef into zloirock:master Aug 30, 2018
@nicolo-ribaudo nicolo-ribaudo deleted the regexp-es2015 branch August 30, 2018 12:35
@zloirock
Copy link
Owner

@nicolo-ribaudo RegExp#@@replace correctly handles substitutions tests fails in many browsers - for example, in modern FF. Could you fix it?

@zloirock
Copy link
Owner

zloirock commented Sep 25, 2018 via email

@zloirock
Copy link
Owner

@nicolo-ribaudo
Chrome 51:
image
Chrome 50:
image
image

@nicolo-ribaudo
Copy link
Contributor Author

I will fix it later.
Just for curiosity, do you have multiple versions of chrome installed on the same machine?

@zloirock
Copy link
Owner

I use Saucelabs and run tests in all available browsers before releases.

@zloirock
Copy link
Owner

zloirock commented Sep 27, 2018

IE8:
image
Safari 9:
image

@nicolo-ribaudo
Copy link
Contributor Author

nicolo-ribaudo commented Nov 9, 2018

I'm working on this now.

EDIT: Ok, I'm downloading windows, ie8, chrome 50 and chrome 51. Hopefully I will be able to debug the issue 😆

@nicolo-ribaudo
Copy link
Contributor Author

nicolo-ribaudo commented Nov 11, 2018

@nicolo-ribaudo RegExp#@@replace correctly handles substitutions tests fails in many browsers - for example, in modern FF. Could you fix it?

Which firefox version? I can't reproduce it.


I'm writing down some notes for myself

  • The tests are failing on IE8 because this code:

    var re = /a/;
    re.exec("a");
    re.lastIndex;

    Should evaluate to 0 (it works in Chrome) but evaluates to 1 in IE8.

    Another reason:

    /^(?:(.)?(.)?)/g.exec(".")[2];

    should be undefined but returns "".

  • The tests are failing on Chrome 51 because native split doesn't work with patched
    RegExp#exec: these two snippets should produce the same output but they don't.

    "ab".split(/a*?/);
    
    > ["a", "b"]
    var exec = RegExp.prototype.exec;
    RegExp.prototype.exec = function () { return exec.apply(this, arguments); };
    "ab".split(/a*?/);
    
    > ["ab"]
  • The tests are failing on Chrome 50 because the polyfilled RegExp#@@match,
    since .exec hasn't been modified, calls String#match assuming that it
    won't call RegExp#@@match again (this assumption is wrong).

  • Safari - TODO

Conclusion: I also need to polyfill .exec 🤦‍♂️

@zloirock
Copy link
Owner

@nicolo-ribaudo

Which firefox version? I can't reproduce it.

IIRC it was fixed in #434

@nicolo-ribaudo
Copy link
Contributor Author

nicolo-ribaudo commented Nov 12, 2018

@zloirock In order to fix some IE8 failing tests, I need to fix this IE bug:

> /^(a?)/.exec("")
["", ""] // correct

> /^(a)?/.exec("")
> ["", ""] // wrong, should be ["", undefined]

I don't think that it is possible, unless we re-implement the regexp engine. Could I disable an assertion on IE8?

PS. For now I got it working in Chrome 50 & 51 and I'm trying to install Safari in a VM.


EDIT: Fixing the IE bug is possible

@zloirock
Copy link
Owner

zloirock commented Dec 4, 2018

Available in core-js@3.0.0-beta.4.

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.

3 participants