2
* Any copyright is dedicated to the Public Domain.
3
* http://creativecommons.org/licenses/publicdomain/
6
var BUGNUMBER = 646490;
8
"RegExp.prototype.exec doesn't get the lastIndex and ToInteger() it for " +
9
"non-global regular expressions when it should";
11
print(BUGNUMBER + ": " + summary);
17
function expectThrowTypeError(fun)
22
throw new Error("didn't throw TypeError, returned " + r);
26
assertEq(e instanceof TypeError, true,
27
"didn't throw TypeError, got: " + e);
31
function checkExec(description, regex, args, obj)
33
var lastIndex = obj.lastIndex;
34
var index = obj.index;
35
var input = obj.input;
36
var indexArray = obj.indexArray;
38
var res = regex.exec.apply(regex, args);
40
assertEq(Array.isArray(res), true, description + ": not an array");
41
assertEq(regex.lastIndex, lastIndex, description + ": wrong lastIndex");
42
assertEq(res.index, index, description + ": wrong index");
43
assertEq(res.input, input, description + ": wrong input");
44
assertEq(res.length, indexArray.length, description + ": wrong length");
45
for (var i = 0, sz = indexArray.length; i < sz; i++)
46
assertEq(res[i], indexArray[i], description + " " + i + ": wrong index value");
49
var exec = RegExp.prototype.exec;
50
var r, res, called, obj;
52
/* 1. Let R be this RegExp object. */
53
expectThrowTypeError(function() { exec.call(null); });
54
expectThrowTypeError(function() { exec.call(""); });
55
expectThrowTypeError(function() { exec.call(5); });
56
expectThrowTypeError(function() { exec.call({}); });
57
expectThrowTypeError(function() { exec.call([]); });
58
expectThrowTypeError(function() { exec.call(); });
59
expectThrowTypeError(function() { exec.call(true); });
60
expectThrowTypeError(function() { exec.call(Object.create(RegExp.prototype)); });
61
expectThrowTypeError(function() { exec.call(Object.create(/a/)); });
64
/* 2. Let S be the value of ToString(string). */
67
assertEq(r.lastIndex, 0);
69
checkExec("/a/", r, [{ toString: function() { called = true; return 'ba'; } }],
74
assertEq(called, true);
79
res = r.exec({ toString: null, valueOf: function() { called = true; throw 17; } });
80
throw new Error("didn't throw");
87
assertEq(called, true);
90
obj = r.lastIndex = { valueOf: function() { assertEq(true, false, "shouldn't have been called"); } };
93
res = r.exec({ toString: null, valueOf: function() { assertEq(called, false); called = true; throw 17; } });
94
throw new Error("didn't throw");
101
assertEq(called, true);
102
assertEq(r.lastIndex, obj);
104
// We don't test lack of an argument because of RegExp statics non-standard
105
// behaviors overriding what really should happen for lack of an argument, sigh.
109
* 3. Let length be the length of S.
110
* 4. Let lastIndex be the result of calling the [[Get]] internal method of R with argument "lastIndex".
111
* 5. Let i be the value of ToInteger(lastIndex).
114
r.lastIndex = { valueOf: {}, toString: {} };
115
expectThrowTypeError(function() { r.exec("foopy"); });
116
r.lastIndex = { valueOf: function() { throw new TypeError(); } };
117
expectThrowTypeError(function() { r.exec("foopy"); });
121
* 6. Let global be the result of calling the [[Get]] internal method of R with argument "global".
122
* 7. If global is false, then let i = 0.
124
obj = { valueOf: function() { return 5; } };
128
checkExec("/abc/ take one", r, ["abc-------abc"],
131
input: "abc-------abc",
132
indexArray: ["abc"] });
134
checkExec("/abc/ take two", r, ["abc-------abc"],
137
input: "abc-------abc",
138
indexArray: ["abc"] });
142
* 8. Let matchSucceeded be false.
143
* 9. Repeat, while matchSucceeded is false
144
* a. If i < 0 or i > length, then
145
* i. Call the [[Put]] internal method of R with arguments "lastIndex", 0, and true.
147
* b. Call the [[Match]] internal method of R with arguments S and i.
148
* c. If [[Match]] returned failure, then
151
* i. Let r be the State result of the call to [[Match]].
152
* ii. Set matchSucceeded to true.
157
checkExec("/abc()?/ with lastIndex -5", r, ["abc-------abc"],
160
input: "abc-------abc",
161
indexArray: ["abc", undefined] });
166
res = r.exec("cdefg");
168
assertEq(r.lastIndex, -17);
172
res = r.exec("cdefg");
174
assertEq(r.lastIndex, 0);
178
* 10. Let e be r's endIndex value.
179
* 11. If global is true,
180
* a. Call the [[Put]] internal method of R with arguments "lastIndex", e, and true.
184
assertEq(r.exec("sdfs"), null);
185
assertEq(r.lastIndex, 0);
189
checkExec("/abc/g", r, ["00abc"],
193
indexArray: ["abc"] });
199
checkExec("/a(b)c/g take two", r, ["00abcd"],
203
indexArray: ["abc", "b"] });
207
* 12. Let n be the length of r's captures array. (This is the same value as
208
* 15.10.2.1's NCapturingParens.)
209
* 13. Let A be a new array created as if by the expression new Array() where
210
* Array is the standard built-in constructor with that name.
211
* 14. Let matchIndex be the position of the matched substring within the
213
* 15. Call the [[DefineOwnProperty]] internal method of A with arguments
214
* "index", Property Descriptor {[[Value]]: matchIndex, [[Writable]: true,
215
* [[Enumerable]]: true, [[Configurable]]: true}, and true.
216
* 16. Call the [[DefineOwnProperty]] internal method of A with arguments
217
* "input", Property Descriptor {[[Value]]: S, [[Writable]: true,
218
* [[Enumerable]]: true, [[Configurable]]: true}, and true.
219
* 17. Call the [[DefineOwnProperty]] internal method of A with arguments
220
* "length", Property Descriptor {[[Value]]: n + 1}, and true.
221
* 18. Let matchedSubstr be the matched substring (i.e. the portion of S
222
* between offset i inclusive and offset e exclusive).
223
* 19. Call the [[DefineOwnProperty]] internal method of A with arguments "0",
224
* Property Descriptor {[[Value]]: matchedSubstr, [[Writable]: true,
225
* [[Enumerable]]: true, [[Configurable]]: true}, and true.
226
* 20. For each integer i such that I > 0 and I ≤ n
227
* a. Let captureI be i th element of r's captures array.
228
* b. Call the [[DefineOwnProperty]] internal method of A with arguments
229
* ToString(i), Property Descriptor {[[Value]]: captureI, [[Writable]:
230
* true, [[Enumerable]]: true, [[Configurable]]: true}, and true.
233
// throughout, above (and in other tests)
235
/******************************************************************************/
237
if (typeof reportCompare === "function")
238
reportCompare(true, true);
240
print("All tests passed!");