mirror of https://github.com/tc39/test262.git
Tests for new lastIndex semantics (#760)
* Tests for new lastIndex semantics Add and update tests for the lastIndex semantic change introduced in https://github.com/tc39/ecma262/pull/627. * Address comments
This commit is contained in:
parent
be16caa4c8
commit
81f66a5a3a
|
@ -17,7 +17,7 @@ info: >
|
|||
21.2.5.2.2 Runtime Semantics: RegExpBuiltinExec ( R, S )
|
||||
|
||||
[...]
|
||||
4. Let lastIndex be ToLength(Get(R,"lastIndex")).
|
||||
8. Else, let lastIndex be ? ToLength(? Get(R, "lastIndex")).
|
||||
features: [Symbol.match]
|
||||
---*/
|
||||
|
||||
|
|
|
@ -21,18 +21,17 @@ info: >
|
|||
|
||||
[...]
|
||||
3. Let length be the number of code units in S.
|
||||
4. Let lastIndex be ToLength(Get(R,"lastIndex")).
|
||||
[...]
|
||||
14. Let matchSucceeded be false.
|
||||
15. Repeat, while matchSucceeded is false
|
||||
11. Let matchSucceeded be false.
|
||||
12. Repeat, while matchSucceeded is false
|
||||
a. If lastIndex > length, then
|
||||
i. Let setStatus be Set(R, "lastIndex", 0, true).
|
||||
ii. ReturnIfAbrupt(setStatus).
|
||||
iii. Return null.
|
||||
i. If global is true or sticky is true, then
|
||||
1. Perform ? Set(R, "lastIndex", 0, true).
|
||||
ii. Return null.
|
||||
features: [Symbol.match]
|
||||
---*/
|
||||
|
||||
var r = /a/;
|
||||
var r = /a/g;
|
||||
Object.defineProperty(r, 'lastIndex', { writable: false });
|
||||
|
||||
assert.throws(TypeError, function() {
|
|
@ -20,18 +20,17 @@ info: >
|
|||
|
||||
[...]
|
||||
3. Let length be the number of code units in S.
|
||||
4. Let lastIndex be ToLength(Get(R,"lastIndex")).
|
||||
[...]
|
||||
14. Let matchSucceeded be false.
|
||||
15. Repeat, while matchSucceeded is false
|
||||
11. Let matchSucceeded be false.
|
||||
12. Repeat, while matchSucceeded is false
|
||||
a. If lastIndex > length, then
|
||||
i. Let setStatus be Set(R, "lastIndex", 0, true).
|
||||
ii. ReturnIfAbrupt(setStatus).
|
||||
iii. Return null.
|
||||
i. If global is true or sticky is true, then
|
||||
1. Perform ? Set(R, "lastIndex", 0, true).
|
||||
ii. Return null.
|
||||
features: [Symbol.match]
|
||||
---*/
|
||||
|
||||
var r = /a/;
|
||||
var r = /a/g;
|
||||
r.lastIndex = 3;
|
||||
|
||||
r[Symbol.match]('b');
|
|
@ -17,12 +17,12 @@ info: >
|
|||
21.2.5.2.2 Runtime Semantics: RegExpBuiltinExec ( R, S )
|
||||
|
||||
[...]
|
||||
4. Let lastIndex be ToLength(Get(R,"lastIndex")).
|
||||
5. ReturnIfAbrupt(lastIndex).
|
||||
7. If global is false and sticky is false, let lastIndex be 0.
|
||||
8. Else, let lastIndex be ? ToLength(? Get(R, "lastIndex")).
|
||||
features: [Symbol.match]
|
||||
---*/
|
||||
|
||||
var r = /./;
|
||||
var r = /./y;
|
||||
r.lastIndex = {
|
||||
valueOf: function() {
|
||||
throw new Test262Error();
|
|
@ -0,0 +1,65 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
es6id: 21.2.5.9
|
||||
description: Behavior when some lastIndex writes should be skipped.
|
||||
info: >
|
||||
[...]
|
||||
4. Let previousLastIndex be ? Get(rx, "lastIndex").
|
||||
5. If SameValue(previousLastIndex, 0) is false, then
|
||||
a. Perform ? Set(rx, "lastIndex", 0, true).
|
||||
[...]
|
||||
7. Let currentLastIndex be ? Get(rx, "lastIndex").
|
||||
8. If SameValue(currentLastIndex, previousLastIndex) is false, then
|
||||
a. Perform ? Set(rx, "lastIndex", previousLastIndex, true).
|
||||
[...]
|
||||
features: [Symbol.search]
|
||||
---*/
|
||||
|
||||
var lastIndexValue;
|
||||
var lastIndexValueAfterExec;
|
||||
var lastIndexReads;
|
||||
var lastIndexWrites;
|
||||
var execCallCount;
|
||||
var result;
|
||||
|
||||
var fakeRe = {
|
||||
get lastIndex() {
|
||||
lastIndexReads++;
|
||||
return lastIndexValue;
|
||||
},
|
||||
set lastIndex(_) {
|
||||
lastIndexWrites++;
|
||||
lastIndexValue = _;
|
||||
},
|
||||
exec: function() {
|
||||
execCallCount++;
|
||||
lastIndexValue = lastIndexValueAfterExec;
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
function reset(value, valueAfterExec) {
|
||||
lastIndexValue = value;
|
||||
lastIndexValueAfterExec = valueAfterExec;
|
||||
lastIndexReads = 0;
|
||||
lastIndexWrites = 0;
|
||||
execCallCount = 0;
|
||||
}
|
||||
|
||||
reset(0, 0);
|
||||
result = RegExp.prototype[Symbol.search].call(fakeRe);
|
||||
assert.sameValue(result, -1);
|
||||
assert.sameValue(lastIndexValue, 0);
|
||||
assert.sameValue(lastIndexReads, 2);
|
||||
assert.sameValue(lastIndexWrites, 0);
|
||||
assert.sameValue(execCallCount, 1);
|
||||
|
||||
reset(420, 420);
|
||||
result = RegExp.prototype[Symbol.search].call(fakeRe);
|
||||
assert.sameValue(result, -1);
|
||||
assert.sameValue(lastIndexValue, 420);
|
||||
assert.sameValue(lastIndexReads, 2);
|
||||
assert.sameValue(lastIndexWrites, 1);
|
||||
assert.sameValue(execCallCount, 1);
|
|
@ -8,18 +8,19 @@ description: >
|
|||
match execution
|
||||
info: >
|
||||
[...]
|
||||
11. Let status be Set(rx, "lastIndex", previousLastIndex, true).
|
||||
12. ReturnIfAbrupt(status).
|
||||
8. If SameValue(currentLastIndex, previousLastIndex) is false, then
|
||||
a. Perform ? Set(rx, "lastIndex", previousLastIndex, true).
|
||||
features: [Symbol.search]
|
||||
---*/
|
||||
|
||||
var callCount;
|
||||
var poisonedLastIndex = {
|
||||
get lastIndex() {},
|
||||
get lastIndex() { return this.lastIndex_; },
|
||||
set lastIndex(_) {
|
||||
if (callCount === 1) {
|
||||
throw new Test262Error();
|
||||
}
|
||||
this.lastIndex_ = _;
|
||||
},
|
||||
exec: function() {
|
||||
callCount += 1;
|
||||
|
|
|
@ -6,20 +6,23 @@ es6id: 21.2.5.9
|
|||
description: The `lastIndex` value is restored following match execution
|
||||
info: >
|
||||
[...]
|
||||
11. Let status be Set(rx, "lastIndex", previousLastIndex, true).
|
||||
8. If SameValue(currentLastIndex, previousLastIndex) is false, then
|
||||
a. Perform ? Set(rx, "lastIndex", previousLastIndex, true).
|
||||
[...]
|
||||
features: [Symbol.search]
|
||||
---*/
|
||||
|
||||
var latestValue;
|
||||
var latestValue = 86;
|
||||
var callCount = 0;
|
||||
var fakeRe = {
|
||||
get lastIndex() {
|
||||
return 86;
|
||||
return latestValue;
|
||||
},
|
||||
set lastIndex(_) {
|
||||
latestValue = _;
|
||||
},
|
||||
exec: function() {
|
||||
callCount++;
|
||||
latestValue = null;
|
||||
return null;
|
||||
}
|
||||
|
@ -27,4 +30,5 @@ var fakeRe = {
|
|||
|
||||
RegExp.prototype[Symbol.search].call(fakeRe);
|
||||
|
||||
assert.sameValue(callCount, 1);
|
||||
assert.sameValue(latestValue, 86);
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
description: lastIndex is read and reset to 0 when global is set and the match
|
||||
fails.
|
||||
es6id: 21.2.5.2.2
|
||||
info: >
|
||||
21.2.5.2.2 Runtime Semantics: RegExpBuiltinExec ( R, S )
|
||||
|
||||
[...]
|
||||
4. Let flags be R.[[OriginalFlags]].
|
||||
5. If flags contains "g", let global be true, else let global be false.
|
||||
[...]
|
||||
7. If global is false and sticky is false, let lastIndex be 0.
|
||||
8. Else, let lastIndex be ? ToLength(? Get(R, "lastIndex")).
|
||||
[...]
|
||||
12. Repeat, while matchSucceeded is false
|
||||
[...]
|
||||
c. If r is failure, then
|
||||
i. If sticky is true, then
|
||||
1. Perform ? Set(R, "lastIndex", 0, true).
|
||||
2. Return null.
|
||||
ii. Let lastIndex be AdvanceStringIndex(S, lastIndex, fullUnicode).
|
||||
---*/
|
||||
|
||||
var lastIndexReads;
|
||||
var result;
|
||||
|
||||
var r = /a/g;
|
||||
|
||||
function reset(value) {
|
||||
r.lastIndex = {
|
||||
valueOf: function() {
|
||||
lastIndexReads++;
|
||||
return value;
|
||||
}
|
||||
};
|
||||
lastIndexReads = 0;
|
||||
}
|
||||
|
||||
reset(42); // lastIndex beyond end of string.
|
||||
result = r.exec('abc');
|
||||
assert.sameValue(result, null);
|
||||
assert.sameValue(r.lastIndex, 0);
|
||||
assert.sameValue(lastIndexReads, 1);
|
||||
|
||||
reset(-1); // No match.
|
||||
result = r.exec('nbc');
|
||||
assert.sameValue(result, null);
|
||||
assert.sameValue(r.lastIndex, 0);
|
||||
assert.sameValue(lastIndexReads, 1);
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
description: lastIndex is not accessed when global and sticky are unset.
|
||||
es6id: 21.2.5.2.2
|
||||
info: >
|
||||
21.2.5.2.2 Runtime Semantics: RegExpBuiltinExec ( R, S )
|
||||
|
||||
[...]
|
||||
7. If global is false and sticky is false, let lastIndex be 0.
|
||||
[...]
|
||||
12. Repeat, while matchSucceeded is false
|
||||
[...]
|
||||
c. If r is failure, then
|
||||
i. If sticky is true, then
|
||||
1. Perform ? Set(R, "lastIndex", 0, true).
|
||||
2. Return null.
|
||||
---*/
|
||||
|
||||
var thrower = {
|
||||
valueOf: function() {
|
||||
throw new Test262Error();
|
||||
}
|
||||
};
|
||||
|
||||
var r = /a/;
|
||||
r.lastIndex = thrower;
|
||||
|
||||
var result = r.exec('nbc');
|
||||
assert.sameValue(result, null);
|
||||
assert.sameValue(r.lastIndex, thrower);
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
description: lastIndex is accessed when global is set.
|
||||
es6id: 21.2.5.2.2
|
||||
info: >
|
||||
21.2.5.2.2 Runtime Semantics: RegExpBuiltinExec ( R, S )
|
||||
|
||||
[...]
|
||||
4. Let flags be R.[[OriginalFlags]].
|
||||
5. If flags contains "g", let global be true, else let global be false.
|
||||
[...]
|
||||
15. If global is true or sticky is true, then
|
||||
a. Perform ? Set(R, "lastIndex", e, true).
|
||||
---*/
|
||||
|
||||
var lastIndexReads = 0;
|
||||
|
||||
var r = /./g;
|
||||
r.lastIndex = {
|
||||
valueOf: function() {
|
||||
lastIndexReads++;
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
var result = r.exec('abc');
|
||||
assert.sameValue(result.length, 1);
|
||||
assert.sameValue(result[0], 'a');
|
||||
assert.sameValue(r.lastIndex, 1);
|
||||
assert.sameValue(lastIndexReads, 1);
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
description: lastIndex is not accessed when global and sticky are unset.
|
||||
es6id: 21.2.5.2.2
|
||||
info: >
|
||||
21.2.5.2.2 Runtime Semantics: RegExpBuiltinExec ( R, S )
|
||||
|
||||
[...]
|
||||
4. Let flags be R.[[OriginalFlags]].
|
||||
5. If flags contains "g", let global be true, else let global be false.
|
||||
[...]
|
||||
15. If global is true or sticky is true, then
|
||||
a. Perform ? Set(R, "lastIndex", e, true).
|
||||
---*/
|
||||
|
||||
var thrower = {
|
||||
valueOf: function() {
|
||||
throw new Test262Error();
|
||||
}
|
||||
};
|
||||
|
||||
var r = /./;
|
||||
r.lastIndex = thrower;
|
||||
|
||||
var result = r.exec('abc');
|
||||
|
||||
assert.notSameValue(result, null);
|
||||
assert.sameValue(result.length, 1);
|
||||
assert.sameValue(result[0], 'a');
|
||||
assert.sameValue(r.lastIndex, thrower);
|
||||
|
Loading…
Reference in New Issue