mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-21 17:25:36 +00:00
Bug 1263340 - Part 1: Use internal slot for global and sticky flags in RegExpBuiltinExec. r=h4writer
This commit is contained in:
parent
37c8b13e17
commit
818ce9857c
@ -804,7 +804,7 @@ function RegExpExec(R, S, forTest) {
|
||||
return forTest ? result !== null : result;
|
||||
}
|
||||
|
||||
// ES6 21.2.5.2.2.
|
||||
// ES 2017 draft rev 6a13789aa9e7c6de4e96b7d3e24d9e6eba6584ad 21.2.5.2.2.
|
||||
function RegExpBuiltinExec(R, S, forTest) {
|
||||
// ES6 21.2.5.2.1 step 6.
|
||||
// This check is here for RegExpTest. RegExp_prototype_Exec does same
|
||||
@ -812,51 +812,54 @@ function RegExpBuiltinExec(R, S, forTest) {
|
||||
if (!IsRegExpObject(R))
|
||||
return callFunction(CallRegExpMethodIfWrapped, R, R, S, forTest, "RegExpBuiltinExec");
|
||||
|
||||
// Step 1-2 (skipped).
|
||||
// Steps 1-2 (skipped).
|
||||
|
||||
// Steps 4-5.
|
||||
// Step 4.
|
||||
var lastIndex = ToLength(R.lastIndex);
|
||||
|
||||
// Steps 6-7.
|
||||
var global = !!R.global;
|
||||
// Step 5.
|
||||
var flags = UnsafeGetInt32FromReservedSlot(R, REGEXP_FLAGS_SLOT);
|
||||
|
||||
// Steps 8-9.
|
||||
var sticky = !!R.sticky;
|
||||
// Step 6.
|
||||
var global = !!(flags & REGEXP_GLOBAL_FLAG);
|
||||
|
||||
// Step 10.
|
||||
// Step 7.
|
||||
var sticky = !!(flags & REGEXP_STICKY_FLAG);
|
||||
|
||||
// Step 8.
|
||||
if (!global && !sticky) {
|
||||
lastIndex = 0;
|
||||
} else {
|
||||
if (lastIndex > S.length) {
|
||||
// Steps 15.a.i-ii, 15.c.i.1-2.
|
||||
// Steps 12.a.i-ii, 12.c.i.1-2.
|
||||
R.lastIndex = 0;
|
||||
return forTest ? false : null;
|
||||
}
|
||||
}
|
||||
|
||||
if (forTest) {
|
||||
// Steps 3, 11-17, except 15.a.i-ii, 15.c.i.1-2.
|
||||
// Steps 3, 9-25, except 12.a.i-ii, 12.c.i.1-2, 15.
|
||||
var endIndex = RegExpTester(R, S, lastIndex, sticky);
|
||||
if (endIndex == -1) {
|
||||
// Steps 15.a.i-ii, 15.c.i.1-2.
|
||||
// Steps 12.a.i-ii, 12.c.i.1-2.
|
||||
R.lastIndex = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 18.
|
||||
// Step 15.
|
||||
if (global || sticky)
|
||||
R.lastIndex = endIndex;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Steps 3, 11-17, except 15.a.i-ii, 15.c.i.1-2.
|
||||
// Steps 3, 9-25, except 12.a.i-ii, 12.c.i.1-2, 15.
|
||||
var result = RegExpMatcher(R, S, lastIndex, sticky);
|
||||
if (result === null) {
|
||||
// Steps 15.a.i-ii, 15.c.i.1-2.
|
||||
// Steps 12.a.i-ii, 12.c.i.1-2.
|
||||
R.lastIndex = 0;
|
||||
} else {
|
||||
// Step 18.
|
||||
// Step 15.
|
||||
if (global || sticky)
|
||||
R.lastIndex = result.index + result[0].length;
|
||||
}
|
||||
|
@ -84,4 +84,12 @@
|
||||
|
||||
#define TELEMETRY_DEFINE_GETTER_SETTER_THIS_NULL_UNDEFINED 25
|
||||
|
||||
#define REGEXP_FLAGS_SLOT 2
|
||||
|
||||
#define REGEXP_IGNORECASE_FLAG 0x01
|
||||
#define REGEXP_GLOBAL_FLAG 0x02
|
||||
#define REGEXP_MULTILINE_FLAG 0x04
|
||||
#define REGEXP_STICKY_FLAG 0x08
|
||||
#define REGEXP_UNICODE_FLAG 0x10
|
||||
|
||||
#endif
|
||||
|
@ -69,51 +69,3 @@ testMod(() => {
|
||||
}, () => {
|
||||
RegExp.prototype[Symbol.match] = orig_match;
|
||||
});
|
||||
|
||||
var observed = false;
|
||||
function testObserved(apply, unapply) {
|
||||
var f = function(applied) {
|
||||
observed = false;
|
||||
var result = "abc".match("b."); // Use meta char to avoid flat match.
|
||||
assertEq(result.length, 1);
|
||||
assertEq(result.index, 1);
|
||||
assertEq(result[0], "bc");
|
||||
assertEq(observed, applied);
|
||||
};
|
||||
var applied = false;
|
||||
for (var i = 0; i < 120; i++) {
|
||||
f(applied);
|
||||
if (i == 40) {
|
||||
apply();
|
||||
applied = true;
|
||||
}
|
||||
if (i == 80) {
|
||||
unapply();
|
||||
applied = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var orig_global = Object.getOwnPropertyDescriptor(RegExp.prototype, "global");
|
||||
testObserved(() => {
|
||||
Object.defineProperty(RegExp.prototype, "global", {
|
||||
get: function() {
|
||||
observed = true;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}, () => {
|
||||
Object.defineProperty(RegExp.prototype, "global", orig_global);
|
||||
});
|
||||
|
||||
var orig_sticky = Object.getOwnPropertyDescriptor(RegExp.prototype, "sticky");
|
||||
testObserved(() => {
|
||||
Object.defineProperty(RegExp.prototype, "sticky", {
|
||||
get: function() {
|
||||
observed = true;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}, () => {
|
||||
Object.defineProperty(RegExp.prototype, "sticky", orig_sticky);
|
||||
});
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include "jscntxt.h"
|
||||
|
||||
#include "builtin/SelfHostingDefines.h"
|
||||
#include "gc/Marking.h"
|
||||
#include "gc/Zone.h"
|
||||
#include "proxy/Proxy.h"
|
||||
@ -57,6 +58,13 @@ enum RegExpFlag
|
||||
AllFlags = 0x1f
|
||||
};
|
||||
|
||||
static_assert(IgnoreCaseFlag == REGEXP_IGNORECASE_FLAG &&
|
||||
GlobalFlag == REGEXP_GLOBAL_FLAG &&
|
||||
MultilineFlag == REGEXP_MULTILINE_FLAG &&
|
||||
StickyFlag == REGEXP_STICKY_FLAG &&
|
||||
UnicodeFlag == REGEXP_UNICODE_FLAG,
|
||||
"Flag values should be in sync with self-hosted JS");
|
||||
|
||||
enum RegExpRunStatus
|
||||
{
|
||||
RegExpRunStatus_Error,
|
||||
@ -395,6 +403,9 @@ class RegExpObject : public NativeObject
|
||||
static const unsigned SOURCE_SLOT = 1;
|
||||
static const unsigned FLAGS_SLOT = 2;
|
||||
|
||||
static_assert(RegExpObject::FLAGS_SLOT == REGEXP_FLAGS_SLOT,
|
||||
"FLAGS_SLOT values should be in sync with self-hosted JS");
|
||||
|
||||
public:
|
||||
static const unsigned RESERVED_SLOTS = 3;
|
||||
static const unsigned PRIVATE_SLOT = 3;
|
||||
|
Loading…
Reference in New Issue
Block a user