mirror of
https://github.com/tc39/test262.git
synced 2025-07-26 23:44:27 +02:00
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 )
|
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]
|
features: [Symbol.match]
|
||||||
---*/
|
---*/
|
||||||
|
|
||||||
|
@ -21,18 +21,17 @@ info: >
|
|||||||
|
|
||||||
[...]
|
[...]
|
||||||
3. Let length be the number of code units in S.
|
3. Let length be the number of code units in S.
|
||||||
4. Let lastIndex be ToLength(Get(R,"lastIndex")).
|
|
||||||
[...]
|
[...]
|
||||||
14. Let matchSucceeded be false.
|
11. Let matchSucceeded be false.
|
||||||
15. Repeat, while matchSucceeded is false
|
12. Repeat, while matchSucceeded is false
|
||||||
a. If lastIndex > length, then
|
a. If lastIndex > length, then
|
||||||
i. Let setStatus be Set(R, "lastIndex", 0, true).
|
i. If global is true or sticky is true, then
|
||||||
ii. ReturnIfAbrupt(setStatus).
|
1. Perform ? Set(R, "lastIndex", 0, true).
|
||||||
iii. Return null.
|
ii. Return null.
|
||||||
features: [Symbol.match]
|
features: [Symbol.match]
|
||||||
---*/
|
---*/
|
||||||
|
|
||||||
var r = /a/;
|
var r = /a/g;
|
||||||
Object.defineProperty(r, 'lastIndex', { writable: false });
|
Object.defineProperty(r, 'lastIndex', { writable: false });
|
||||||
|
|
||||||
assert.throws(TypeError, function() {
|
assert.throws(TypeError, function() {
|
@ -20,18 +20,17 @@ info: >
|
|||||||
|
|
||||||
[...]
|
[...]
|
||||||
3. Let length be the number of code units in S.
|
3. Let length be the number of code units in S.
|
||||||
4. Let lastIndex be ToLength(Get(R,"lastIndex")).
|
|
||||||
[...]
|
[...]
|
||||||
14. Let matchSucceeded be false.
|
11. Let matchSucceeded be false.
|
||||||
15. Repeat, while matchSucceeded is false
|
12. Repeat, while matchSucceeded is false
|
||||||
a. If lastIndex > length, then
|
a. If lastIndex > length, then
|
||||||
i. Let setStatus be Set(R, "lastIndex", 0, true).
|
i. If global is true or sticky is true, then
|
||||||
ii. ReturnIfAbrupt(setStatus).
|
1. Perform ? Set(R, "lastIndex", 0, true).
|
||||||
iii. Return null.
|
ii. Return null.
|
||||||
features: [Symbol.match]
|
features: [Symbol.match]
|
||||||
---*/
|
---*/
|
||||||
|
|
||||||
var r = /a/;
|
var r = /a/g;
|
||||||
r.lastIndex = 3;
|
r.lastIndex = 3;
|
||||||
|
|
||||||
r[Symbol.match]('b');
|
r[Symbol.match]('b');
|
@ -17,12 +17,12 @@ info: >
|
|||||||
21.2.5.2.2 Runtime Semantics: RegExpBuiltinExec ( R, S )
|
21.2.5.2.2 Runtime Semantics: RegExpBuiltinExec ( R, S )
|
||||||
|
|
||||||
[...]
|
[...]
|
||||||
4. Let lastIndex be ToLength(Get(R,"lastIndex")).
|
7. If global is false and sticky is false, let lastIndex be 0.
|
||||||
5. ReturnIfAbrupt(lastIndex).
|
8. Else, let lastIndex be ? ToLength(? Get(R, "lastIndex")).
|
||||||
features: [Symbol.match]
|
features: [Symbol.match]
|
||||||
---*/
|
---*/
|
||||||
|
|
||||||
var r = /./;
|
var r = /./y;
|
||||||
r.lastIndex = {
|
r.lastIndex = {
|
||||||
valueOf: function() {
|
valueOf: function() {
|
||||||
throw new Test262Error();
|
throw new Test262Error();
|
65
test/built-ins/RegExp/prototype/Symbol.search/lastindex-no-restore.js
vendored
Normal file
65
test/built-ins/RegExp/prototype/Symbol.search/lastindex-no-restore.js
vendored
Normal file
@ -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
|
match execution
|
||||||
info: >
|
info: >
|
||||||
[...]
|
[...]
|
||||||
11. Let status be Set(rx, "lastIndex", previousLastIndex, true).
|
8. If SameValue(currentLastIndex, previousLastIndex) is false, then
|
||||||
12. ReturnIfAbrupt(status).
|
a. Perform ? Set(rx, "lastIndex", previousLastIndex, true).
|
||||||
features: [Symbol.search]
|
features: [Symbol.search]
|
||||||
---*/
|
---*/
|
||||||
|
|
||||||
var callCount;
|
var callCount;
|
||||||
var poisonedLastIndex = {
|
var poisonedLastIndex = {
|
||||||
get lastIndex() {},
|
get lastIndex() { return this.lastIndex_; },
|
||||||
set lastIndex(_) {
|
set lastIndex(_) {
|
||||||
if (callCount === 1) {
|
if (callCount === 1) {
|
||||||
throw new Test262Error();
|
throw new Test262Error();
|
||||||
}
|
}
|
||||||
|
this.lastIndex_ = _;
|
||||||
},
|
},
|
||||||
exec: function() {
|
exec: function() {
|
||||||
callCount += 1;
|
callCount += 1;
|
||||||
|
@ -6,20 +6,23 @@ es6id: 21.2.5.9
|
|||||||
description: The `lastIndex` value is restored following match execution
|
description: The `lastIndex` value is restored following match execution
|
||||||
info: >
|
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]
|
features: [Symbol.search]
|
||||||
---*/
|
---*/
|
||||||
|
|
||||||
var latestValue;
|
var latestValue = 86;
|
||||||
|
var callCount = 0;
|
||||||
var fakeRe = {
|
var fakeRe = {
|
||||||
get lastIndex() {
|
get lastIndex() {
|
||||||
return 86;
|
return latestValue;
|
||||||
},
|
},
|
||||||
set lastIndex(_) {
|
set lastIndex(_) {
|
||||||
latestValue = _;
|
latestValue = _;
|
||||||
},
|
},
|
||||||
exec: function() {
|
exec: function() {
|
||||||
|
callCount++;
|
||||||
latestValue = null;
|
latestValue = null;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -27,4 +30,5 @@ var fakeRe = {
|
|||||||
|
|
||||||
RegExp.prototype[Symbol.search].call(fakeRe);
|
RegExp.prototype[Symbol.search].call(fakeRe);
|
||||||
|
|
||||||
|
assert.sameValue(callCount, 1);
|
||||||
assert.sameValue(latestValue, 86);
|
assert.sameValue(latestValue, 86);
|
||||||
|
52
test/built-ins/RegExp/prototype/exec/failure-g-lastindex-reset.js
vendored
Normal file
52
test/built-ins/RegExp/prototype/exec/failure-g-lastindex-reset.js
vendored
Normal file
@ -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);
|
33
test/built-ins/RegExp/prototype/exec/failure-lastindex-no-access.js
vendored
Normal file
33
test/built-ins/RegExp/prototype/exec/failure-lastindex-no-access.js
vendored
Normal file
@ -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);
|
||||||
|
|
33
test/built-ins/RegExp/prototype/exec/success-g-lastindex-no-access.js
vendored
Normal file
33
test/built-ins/RegExp/prototype/exec/success-g-lastindex-no-access.js
vendored
Normal file
@ -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);
|
||||||
|
|
33
test/built-ins/RegExp/prototype/exec/success-lastindex-no-access.js
vendored
Normal file
33
test/built-ins/RegExp/prototype/exec/success-lastindex-no-access.js
vendored
Normal file
@ -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…
x
Reference in New Issue
Block a user