Add tests for RegExp.prototype.compile (#632)

This commit is contained in:
jugglinmike 2016-05-30 16:52:04 -04:00 committed by Leo Balter
parent 8f23cd6775
commit a12e271269
17 changed files with 743 additions and 0 deletions

View File

@ -0,0 +1,43 @@
// Copyright (C) 2016 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-regexp.prototype.compile
es6id: B.2.5.1
description: Behavior when flags is a string describing an invalid flag set
info: |
[...]
5. Return ? RegExpInitialize(O, P, F).
21.2.3.2.2 Runtime Semantics: RegExpInitialize
[...]
3. If flags is undefined, let F be the empty String.
4. Else, let F be ? ToString(flags).
5. If F contains any code unit other than "g", "i", "m", "u", or "y" or if
it contains the same code unit more than once, throw a SyntaxError
exception.
---*/
var subject = /abcd/ig;
assert.throws(SyntaxError, function() {
subject.compile('', 'igi');
}, 'invalid flags: igi');
assert.throws(SyntaxError, function() {
subject.compile('', 'gI');
}, 'invalid flags: gI');
assert.throws(SyntaxError, function() {
subject.compile('', 'w');
}, 'invalid flags: w');
assert.sameValue(
subject.toString(),
new RegExp('abcd', 'ig').toString(),
'[[OriginalSource]] internal slot'
);
assert.sameValue(
subject.test('AbCD'), true, '[[RegExpMatcher]] internal slot'
);

View File

@ -0,0 +1,43 @@
// Copyright (C) 2016 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-regexp.prototype.compile
es6id: B.2.5.1
description: Behavior when provided flags cannot be coerced to a string
info: |
[...]
3. If Type(pattern) is Object and pattern has a [[RegExpMatcher]] internal
slot, then
a. If flags is not undefined, throw a TypeError exception.
b. Let P be the value of pattern's [[OriginalSource]] internal slot.
c. Let F be the value of pattern's [[OriginalFlags]] internal slot.
4. Else,
[...]
5. Return ? RegExpInitialize(O, P, F).
21.2.3.2.2 Runtime Semantics: RegExpInitialize
[...]
3. If flags is undefined, let F be the empty String.
4. Else, let F be ? ToString(flags).
features: [Symbol]
---*/
var symbol = Symbol('');
var subject = /./;
var badToString = {
toString: function() {
throw new Test262Error();
}
};
subject.lastIndex = 99;
assert.throws(Test262Error, function() {
/./.compile('', badToString);
});
assert.throws(TypeError, function() {
/./.compile('', symbol);
});
assert.sameValue(subject.lastIndex, 99);

View File

@ -0,0 +1,39 @@
// Copyright (C) 2016 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-regexp.prototype.compile
es6id: B.2.5.1
description: Behavior when flags is a string describing a valid flag set
info: |
[...]
5. Return ? RegExpInitialize(O, P, F).
21.2.3.2.2 Runtime Semantics: RegExpInitialize
[...]
3. If flags is undefined, let F be the empty String.
4. Else, let F be ? ToString(flags).
[...]
---*/
var subject = /a/g;
subject.compile('a', 'i');
assert.sameValue(
subject.flags,
new RegExp('a', 'i').flags,
'[[OriginalFlags]] internal slot'
);
assert.sameValue(
subject.test('A'),
true,
'[[RegExpMatcher]] internal slot (addition of `i` flag)'
);
subject.lastIndex = 1;
assert.sameValue(
subject.test('A'),
true,
'[[RegExpMatcher]] internal slot (removal of `g` flag)'
);

View 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.
/*---
esid: sec-regexp.prototype.compile
es6id: B.2.5.1
description: Behavior when flags is undefined
info: |
[...]
3. If Type(pattern) is Object and pattern has a [[RegExpMatcher]] internal
slot, then
[...]
4. Else,
a. Let P be pattern.
b. Let F be flags.
5. Return ? RegExpInitialize(O, P, F).
21.2.3.2.2 Runtime Semantics: RegExpInitialize
[...]
3. If flags is undefined, let F be the empty String.
[...]
---*/
var subject, result;
subject = /abc/ig;
result = subject.compile('def');
assert.sameValue(result, subject, 'method return value (unspecified)');
assert.sameValue(
subject.flags, new RegExp('def').flags, '[[OriginalFlags]] (unspecified)'
);
assert.sameValue(
subject.test('DEF'), false, '[[RegExpMatcher]] internal slot (unspecified)'
);
subject = /abc/gi;
result = subject.compile('def', undefined);
assert.sameValue(result, subject, 'method return value (explicit undefined)');
assert.sameValue(
subject.flags,
new RegExp('def').flags,
'[[OriginalSource]] (explicit undefined)'
);
assert.sameValue(
subject.test('DEF'),
false,
'[[RegExpMatcher]] internal slot (explicit undefined)'
);

View File

@ -0,0 +1,37 @@
// Copyright (C) 2016 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-regexp.prototype.compile
es6id: B.2.5.1
description: RegExp is re-initialized when invoked with a distinct instance
info: |
[...]
3. If Type(pattern) is Object and pattern has a [[RegExpMatcher]] internal
slot, then
a. If flags is not undefined, throw a TypeError exception.
b. Let P be the value of pattern's [[OriginalSource]] internal slot.
c. Let F be the value of pattern's [[OriginalFlags]] internal slot.
4. Else,
[...]
5. Return ? RegExpInitialize(O, P, F).
---*/
var subject = /abc/gim;
var pattern = /def/;
var result;
subject.lastIndex = 23;
pattern.lastIndex = 45;
result = subject.compile(pattern);
assert.sameValue(result, subject, 'method return value');
assert.sameValue(subject.lastIndex, 0);
assert.sameValue(pattern.lastIndex, 45);
assert.sameValue(subject.toString(), new RegExp('def').toString());
assert.sameValue(
subject.test('def'), true, '[[RegExpMatcher]] internal slot (source)'
);
assert.sameValue(
subject.test('DEF'), false, '[[RegExpMatch]] internal slot (flags)'
);

View File

@ -0,0 +1,44 @@
// Copyright (C) 2016 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-regexp.prototype.compile
es6id: B.2.5.1
description: >
Behavior when provided pattern is a RegExp instance and flags are specified
info: |
[...]
3. If Type(pattern) is Object and pattern has a [[RegExpMatcher]] internal
slot, then
a. If flags is not undefined, throw a TypeError exception.
---*/
var re = /./;
re.lastIndex = 23;
assert.sameValue(typeof RegExp.prototype.compile, 'function');
assert.throws(TypeError, function() {
re.compile(re, null);
}, 'null');
assert.throws(TypeError, function() {
re.compile(re, 0);
}, 'numeric primitive');
assert.throws(TypeError, function() {
re.compile(re, '');
}, 'string primitive');
assert.throws(TypeError, function() {
re.compile(re, false);
}, 'boolean primitive');
assert.throws(TypeError, function() {
re.compile(re, {});
}, 'ordinary object');
assert.throws(TypeError, function() {
re.compile(re, []);
}, 'array exotic object');
assert.sameValue(re.lastIndex, 23);

View File

@ -0,0 +1,36 @@
// Copyright (C) 2016 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-regexp.prototype.compile
es6id: B.2.5.1
description: Behavior when `lastIndex` property of "this" value is non-writable
info: |
[...]
3. If Type(pattern) is Object and pattern has a [[RegExpMatcher]] internal
slot, then
a. If flags is not undefined, throw a TypeError exception.
b. Let P be the value of pattern's [[OriginalSource]] internal slot.
c. Let F be the value of pattern's [[OriginalFlags]] internal slot.
4. Else,
[...]
5. Return ? RegExpInitialize(O, P, F).
21.2.3.2.2 Runtime Semantics: RegExpInitialize
[...]
12. Perform ? Set(obj, "lastIndex", 0, true).
---*/
var subject = /initial/;
Object.defineProperty(subject, 'lastIndex', { value: 45, writable: false });
assert.throws(TypeError, function() {
subject.compile(/updated/gi);
});
assert.sameValue(
subject.toString(),
new RegExp('updated', 'gi').toString(),
'[[OriginalSource]] internal slot'
);
assert.sameValue(subject.lastIndex, 45);

View File

@ -0,0 +1,73 @@
// Copyright (C) 2016 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-regexp.prototype.compile
es6id: B.2.5.1
description: >
Properties are not referenced when provided pattern is a RegExp instance
info: |
[...]
3. If Type(pattern) is Object and pattern has a [[RegExpMatcher]] internal
slot, then
a. If flags is not undefined, throw a TypeError exception.
b. Let P be the value of pattern's [[OriginalSource]] internal slot.
c. Let F be the value of pattern's [[OriginalFlags]] internal slot.
4. Else,
[...]
5. Return ? RegExpInitialize(O, P, F).
---*/
var thisValue = /abc/gim;
var pattern = /def/mig;
var flagsCount = 0;
var globalCount = 0;
var ignoreCaseCount = 0;
var multilineCount = 0;
var stickyCount = 0;
var unicodeCount = 0;
var counters = {
flags: {
get: function() {
flagsCount += 1;
}
},
global: {
get: function() {
globalCount += 1;
}
},
ignoreCase: {
get: function() {
ignoreCaseCount += 1;
}
},
multiline: {
get: function() {
multilineCount += 1;
}
},
sticky: {
get: function() {
stickyCount += 1;
}
},
unicode: {
get: function() {
unicodeCount += 1;
}
}
};
Object.defineProperties(thisValue, counters);
Object.defineProperties(pattern, counters);
thisValue.compile(thisValue);
thisValue.compile(pattern);
thisValue.compile(thisValue);
assert.sameValue(flagsCount, 0, '`flags` property not accessed');
assert.sameValue(globalCount, 0, '`global` property not accessed');
assert.sameValue(ignoreCaseCount, 0, '`ignoreCase` property not accessed');
assert.sameValue(multilineCount, 0, '`multiline` property not accessed');
assert.sameValue(stickyCount, 0, '`sticky` property not accessed');
assert.sameValue(unicodeCount, 0, '`unicode` property not accessed');

View File

@ -0,0 +1,32 @@
// Copyright (C) 2016 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-regexp.prototype.compile
es6id: B.2.5.1
description: RegExp is re-initialized when invoked with the same instance
info: |
[...]
3. If Type(pattern) is Object and pattern has a [[RegExpMatcher]] internal
slot, then
a. If flags is not undefined, throw a TypeError exception.
b. Let P be the value of pattern's [[OriginalSource]] internal slot.
c. Let F be the value of pattern's [[OriginalFlags]] internal slot.
4. Else,
[...]
5. Return ? RegExpInitialize(O, P, F).
---*/
var subject = /abc/gim;
var result;
subject.lastIndex = 23;
result = subject.compile(subject);
assert.sameValue(result, subject, 'method return value');
assert.sameValue(
subject.toString(),
new RegExp('abc', 'gim').toString(),
'[[OriginalSource]] internal slot'
);
assert.sameValue(subject.lastIndex, 0);
assert.sameValue(subject.test('aBc'), true, '[[RegExpMatcher]] internal slot');

View File

@ -0,0 +1,42 @@
// Copyright (C) 2016 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-regexp.prototype.compile
es6id: B.2.5.1
description: >
Behavior when pattern is a string describing an invalid pattern (unicode)
info: |
[...]
5. Return ? RegExpInitialize(O, P, F).
21.2.3.2.2 Runtime Semantics: RegExpInitialize
6. If F contains "u", let BMP be false; else let BMP be true.
7. If BMP is true, then
a. Parse P using the grammars in 21.2.1 and interpreting each of its
16-bit elements as a Unicode BMP code point. UTF-16 decoding is not
applied to the elements. The goal symbol for the parse is Pattern.
Throw a SyntaxError exception if P did not conform to the grammar, if
any elements of P were not matched by the parse, or if any Early
Error conditions exist.
[...]
---*/
var subject = /test262/ig;
assert.throws(SyntaxError, function() {
subject.compile('{', 'u');
}, 'invalid pattern: {');
assert.throws(SyntaxError, function() {
subject.compile('\\2', 'u');
}, 'invalid pattern: \\2');
assert.sameValue(
subject.toString(),
new RegExp('test262', 'ig').toString(),
'[[OriginalSource]] internal slot'
);
assert.sameValue(
subject.test('tEsT262'), true, '[[RegExpMatcher]] internal slot'
);

View File

@ -0,0 +1,44 @@
// Copyright (C) 2016 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-regexp.prototype.compile
es6id: B.2.5.1
description: >
Behavior when pattern is a string describing an invalid pattern
(non-unicode)
info: |
[...]
5. Return ? RegExpInitialize(O, P, F).
21.2.3.2.2 Runtime Semantics: RegExpInitialize
6. If F contains "u", let BMP be false; else let BMP be true.
7. If BMP is true, then
[...]
8. Else,
a. Parse P using the grammars in 21.2.1 and interpreting P as UTF-16
encoded Unicode code points (6.1.4). The goal symbol for the parse is
Pattern[U]. Throw a SyntaxError exception if P did not conform to the
grammar, if any elements of P were not matched by the parse, or if
any Early Error conditions exist.
---*/
var subject = /test262/ig;
assert.throws(SyntaxError, function() {
subject.compile('?');
}, 'invalid pattern: ?');
assert.throws(SyntaxError, function() {
subject.compile('.{2,1}');
}, 'invalid pattern: .{2,1}');
assert.sameValue(
subject.toString(),
new RegExp('test262', 'ig').toString(),
'[[OriginalSource]] internal slot'
);
assert.sameValue(
subject.test('TEsT262'), true, '[[RegExpMatcher]] internal slot'
);

View File

@ -0,0 +1,51 @@
// Copyright (C) 2016 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-regexp.prototype.compile
es6id: B.2.5.1
description: >
Behavior when pattern is a string describing a valid pattern (unicode)
info: |
[...]
5. Return ? RegExpInitialize(O, P, F).
21.2.3.2.2 Runtime Semantics: RegExpInitialize
6. If F contains "u", let BMP be false; else let BMP be true.
7. If BMP is true, then
a. Parse P using the grammars in 21.2.1 and interpreting each of its
16-bit elements as a Unicode BMP code point. UTF-16 decoding is not
applied to the elements. The goal symbol for the parse is Pattern.
Throw a SyntaxError exception if P did not conform to the grammar, if
any elements of P were not matched by the parse, or if any Early
Error conditions exist.
b. Let patternCharacters be a List whose elements are the code unit
elements of P.
[...]
---*/
var subject = /original value/ig;
subject.compile('[\ud834\udf06]', 'u');
assert.sameValue(
subject.source,
new RegExp('[\ud834\udf06]', 'u').source,
'[[OriginalSource]] internal slot'
);
assert.sameValue(
subject.test('original value'),
false,
'[[RegExpMatcher]] internal slot (source)'
);
assert.sameValue(
subject.test('\ud834'), false, '[[RegExpMatcher]] internal slot (flags #1)'
);
assert.sameValue(
subject.test('\udf06'), false, '[[RegExpMatcher]] internal slot (flags #2)'
);
assert.sameValue(
subject.test('\ud834\udf06'),
true,
'[[RegExpMatcher]] internal slot (flags #3)'
);

View File

@ -0,0 +1,42 @@
// Copyright (C) 2016 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-regexp.prototype.compile
es6id: B.2.5.1
description: >
Behavior when pattern is a string describing a valid pattern (non-unicode)
info: |
[...]
5. Return ? RegExpInitialize(O, P, F).
21.2.3.2.2 Runtime Semantics: RegExpInitialize
6. If F contains "u", let BMP be false; else let BMP be true.
7. If BMP is true, then
[...]
8. Else,
a. Parse P using the grammars in 21.2.1 and interpreting P as UTF-16
encoded Unicode code points (6.1.4). The goal symbol for the parse is
Pattern[U]. Throw a SyntaxError exception if P did not conform to the
grammar, if any elements of P were not matched by the parse, or if
any Early Error conditions exist.
b. Let patternCharacters be a List whose elements are the code points
resulting from applying UTF-16 decoding to P's sequence of elements.
[...]
---*/
var subject = /original value/ig;
subject.compile('new value');
assert.sameValue(
subject.source,
new RegExp('new value').source,
'[[OriginalSource]] internal slot'
);
assert.sameValue(
subject.test('original value'), false, '[[RegExpMatcher]] internal slot'
);
assert.sameValue(
subject.test('new value'), true, '[[RegExpMatcher]] internal slot'
);

View File

@ -0,0 +1,42 @@
// Copyright (C) 2016 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-regexp.prototype.compile
es6id: B.2.5.1
description: Behavior when provided pattern cannot be coerced to a string
info: |
[...]
3. If Type(pattern) is Object and pattern has a [[RegExpMatcher]] internal
slot, then
a. If flags is not undefined, throw a TypeError exception.
b. Let P be the value of pattern's [[OriginalSource]] internal slot.
c. Let F be the value of pattern's [[OriginalFlags]] internal slot.
4. Else,
[...]
5. Return ? RegExpInitialize(O, P, F).
21.2.3.2.2 Runtime Semantics: RegExpInitialize
1. If pattern is undefined, let P be the empty String.
2. Else, let P be ? ToString(pattern).
features: [Symbol]
---*/
var symbol = Symbol('');
var subject = /./;
var badToString = {
toString: function() {
throw new Test262Error();
}
};
subject.lastIndex = 99;
assert.throws(Test262Error, function() {
/./.compile(badToString);
});
assert.throws(TypeError, function() {
/./.compile(symbol);
});
assert.sameValue(subject.lastIndex, 99);

View File

@ -0,0 +1,51 @@
// Copyright (C) 2016 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-regexp.prototype.compile
es6id: B.2.5.1
description: Behavior when pattern is undefined
info: |
[...]
3. If Type(pattern) is Object and pattern has a [[RegExpMatcher]] internal
slot, then
[...]
4. Else,
a. Let P be pattern.
b. Let F be flags.
5. Return ? RegExpInitialize(O, P, F).
21.2.3.2.2 Runtime Semantics: RegExpInitialize
1. If pattern is undefined, let P be the empty String.
[...]
---*/
var subject;
subject = /abc/;
assert.sameValue(
subject.compile(), subject, 'method return value (unspecified)'
);
assert.sameValue(
subject.source, new RegExp('').source, '[[OriginalSource]] (unspecified)'
);
assert.sameValue(
subject.test(''), true, '[[RegExpMatcher]] internal slot (unspecified)'
);
subject = /abc/;
assert.sameValue(
subject.compile(undefined),
subject,
'method return value (explicit undefined)'
);
assert.sameValue(
subject.source,
new RegExp('').source,
'[[OriginalSource]] (explicit undefined)'
);
assert.sameValue(
subject.test(''),
true,
'[[RegExpMatcher]] internal slot (explicit undefined)'
);

View File

@ -0,0 +1,42 @@
// Copyright (C) 2016 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-regexp.prototype.compile
es6id: B.2.5.1
description: Behavior when "this" value is not an Object
info: |
1. Let O be the this value.
2. If Type(O) is not Object or Type(O) is Object and O does not have a
[[RegExpMatcher]] internal slot, then
a. Throw a TypeError exception.
features: [Symbol]
---*/
var compile = RegExp.prototype.compile;
var symbol = Symbol('');
assert.sameValue(typeof compile, 'function');
assert.throws(TypeError, function() {
compile.call(undefined);
}, 'undefined');
assert.throws(TypeError, function() {
compile.call(null);
}, 'null');
assert.throws(TypeError, function() {
compile.call(23);
}, 'number');
assert.throws(TypeError, function() {
compile.call(true);
}, 'boolean');
assert.throws(TypeError, function() {
compile.call('/string/');
}, 'string');
assert.throws(TypeError, function() {
compile.call(symbol);
}, 'symbol');

View File

@ -0,0 +1,30 @@
// Copyright (C) 2016 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-regexp.prototype.compile
es6id: B.2.5.1
description: >
Behavior when "this" value is an Object without a [[RegExpMatcher]]
internal slot
info: |
1. Let O be the this value.
2. If Type(O) is not Object or Type(O) is Object and O does not have a
[[RegExpMatcher]] internal slot, then
a. Throw a TypeError exception.
---*/
var compile = RegExp.prototype.compile;
assert.sameValue(typeof compile, 'function');
assert.throws(TypeError, function() {
compile.call({});
}, 'ordinary object');
assert.throws(TypeError, function() {
compile.call([]);
}, 'array exotic object');
assert.throws(TypeError, function() {
compile.call(arguments);
}, 'arguments exotic object');