Bug 1263340 - Part 1: Use internal slot for global and sticky flags in RegExpBuiltinExec. r=h4writer

This commit is contained in:
Tooru Fujisawa 2016-04-22 10:35:41 +09:00
parent 37c8b13e17
commit 818ce9857c
4 changed files with 37 additions and 63 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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);
});

View File

@ -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;