1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/tests/ecma_5/RegExp/exec.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,240 @@ 1.4 +/* 1.5 + * Any copyright is dedicated to the Public Domain. 1.6 + * http://creativecommons.org/licenses/publicdomain/ 1.7 + */ 1.8 + 1.9 +var BUGNUMBER = 646490; 1.10 +var summary = 1.11 + "RegExp.prototype.exec doesn't get the lastIndex and ToInteger() it for " + 1.12 + "non-global regular expressions when it should"; 1.13 + 1.14 +print(BUGNUMBER + ": " + summary); 1.15 + 1.16 +/************** 1.17 + * BEGIN TEST * 1.18 + **************/ 1.19 + 1.20 +function expectThrowTypeError(fun) 1.21 +{ 1.22 + try 1.23 + { 1.24 + var r = fun(); 1.25 + throw new Error("didn't throw TypeError, returned " + r); 1.26 + } 1.27 + catch (e) 1.28 + { 1.29 + assertEq(e instanceof TypeError, true, 1.30 + "didn't throw TypeError, got: " + e); 1.31 + } 1.32 +} 1.33 + 1.34 +function checkExec(description, regex, args, obj) 1.35 +{ 1.36 + var lastIndex = obj.lastIndex; 1.37 + var index = obj.index; 1.38 + var input = obj.input; 1.39 + var indexArray = obj.indexArray; 1.40 + 1.41 + var res = regex.exec.apply(regex, args); 1.42 + 1.43 + assertEq(Array.isArray(res), true, description + ": not an array"); 1.44 + assertEq(regex.lastIndex, lastIndex, description + ": wrong lastIndex"); 1.45 + assertEq(res.index, index, description + ": wrong index"); 1.46 + assertEq(res.input, input, description + ": wrong input"); 1.47 + assertEq(res.length, indexArray.length, description + ": wrong length"); 1.48 + for (var i = 0, sz = indexArray.length; i < sz; i++) 1.49 + assertEq(res[i], indexArray[i], description + " " + i + ": wrong index value"); 1.50 +} 1.51 + 1.52 +var exec = RegExp.prototype.exec; 1.53 +var r, res, called, obj; 1.54 + 1.55 +/* 1. Let R be this RegExp object. */ 1.56 +expectThrowTypeError(function() { exec.call(null); }); 1.57 +expectThrowTypeError(function() { exec.call(""); }); 1.58 +expectThrowTypeError(function() { exec.call(5); }); 1.59 +expectThrowTypeError(function() { exec.call({}); }); 1.60 +expectThrowTypeError(function() { exec.call([]); }); 1.61 +expectThrowTypeError(function() { exec.call(); }); 1.62 +expectThrowTypeError(function() { exec.call(true); }); 1.63 +expectThrowTypeError(function() { exec.call(Object.create(RegExp.prototype)); }); 1.64 +expectThrowTypeError(function() { exec.call(Object.create(/a/)); }); 1.65 + 1.66 + 1.67 +/* 2. Let S be the value of ToString(string). */ 1.68 +called = false; 1.69 +r = /a/; 1.70 +assertEq(r.lastIndex, 0); 1.71 + 1.72 +checkExec("/a/", r, [{ toString: function() { called = true; return 'ba'; } }], 1.73 + { lastIndex: 0, 1.74 + index: 1, 1.75 + input: "ba", 1.76 + indexArray: ["a"] }); 1.77 +assertEq(called, true); 1.78 + 1.79 +called = false; 1.80 +try 1.81 +{ 1.82 + res = r.exec({ toString: null, valueOf: function() { called = true; throw 17; } }); 1.83 + throw new Error("didn't throw"); 1.84 +} 1.85 +catch (e) 1.86 +{ 1.87 + assertEq(e, 17); 1.88 +} 1.89 + 1.90 +assertEq(called, true); 1.91 + 1.92 +called = false; 1.93 +obj = r.lastIndex = { valueOf: function() { assertEq(true, false, "shouldn't have been called"); } }; 1.94 +try 1.95 +{ 1.96 + res = r.exec({ toString: null, valueOf: function() { assertEq(called, false); called = true; throw 17; } }); 1.97 + throw new Error("didn't throw"); 1.98 +} 1.99 +catch (e) 1.100 +{ 1.101 + assertEq(e, 17); 1.102 +} 1.103 + 1.104 +assertEq(called, true); 1.105 +assertEq(r.lastIndex, obj); 1.106 + 1.107 +// We don't test lack of an argument because of RegExp statics non-standard 1.108 +// behaviors overriding what really should happen for lack of an argument, sigh. 1.109 + 1.110 + 1.111 +/* 1.112 + * 3. Let length be the length of S. 1.113 + * 4. Let lastIndex be the result of calling the [[Get]] internal method of R with argument "lastIndex". 1.114 + * 5. Let i be the value of ToInteger(lastIndex). 1.115 + */ 1.116 +r = /b/; 1.117 +r.lastIndex = { valueOf: {}, toString: {} }; 1.118 +expectThrowTypeError(function() { r.exec("foopy"); }); 1.119 +r.lastIndex = { valueOf: function() { throw new TypeError(); } }; 1.120 +expectThrowTypeError(function() { r.exec("foopy"); }); 1.121 + 1.122 + 1.123 +/* 1.124 + * 6. Let global be the result of calling the [[Get]] internal method of R with argument "global". 1.125 + * 7. If global is false, then let i = 0. 1.126 + */ 1.127 +obj = { valueOf: function() { return 5; } }; 1.128 +r = /abc/; 1.129 +r.lastIndex = obj; 1.130 + 1.131 +checkExec("/abc/ take one", r, ["abc-------abc"], 1.132 + { lastIndex: obj, 1.133 + index: 0, 1.134 + input: "abc-------abc", 1.135 + indexArray: ["abc"] }); 1.136 + 1.137 +checkExec("/abc/ take two", r, ["abc-------abc"], 1.138 + { lastIndex: obj, 1.139 + index: 0, 1.140 + input: "abc-------abc", 1.141 + indexArray: ["abc"] }); 1.142 + 1.143 + 1.144 +/* 1.145 + * 8. Let matchSucceeded be false. 1.146 + * 9. Repeat, while matchSucceeded is false 1.147 + * a. If i < 0 or i > length, then 1.148 + * i. Call the [[Put]] internal method of R with arguments "lastIndex", 0, and true. 1.149 + * ii. Return null. 1.150 + * b. Call the [[Match]] internal method of R with arguments S and i. 1.151 + * c. If [[Match]] returned failure, then 1.152 + * i. Let i = i+1. 1.153 + * d. else 1.154 + * i. Let r be the State result of the call to [[Match]]. 1.155 + * ii. Set matchSucceeded to true. 1.156 + * e. Let i = i+1. 1.157 + */ 1.158 +r = /abc()?/; 1.159 +r.lastIndex = -5; 1.160 +checkExec("/abc()?/ with lastIndex -5", r, ["abc-------abc"], 1.161 + { lastIndex: -5, 1.162 + index: 0, 1.163 + input: "abc-------abc", 1.164 + indexArray: ["abc", undefined] }); 1.165 + 1.166 + 1.167 +r = /abc/; 1.168 +r.lastIndex = -17; 1.169 +res = r.exec("cdefg"); 1.170 +assertEq(res, null); 1.171 +assertEq(r.lastIndex, 0); 1.172 + 1.173 +r = /abc/g; 1.174 +r.lastIndex = -42; 1.175 +res = r.exec("cdefg"); 1.176 +assertEq(res, null); 1.177 +assertEq(r.lastIndex, 0); 1.178 + 1.179 + 1.180 +/* 1.181 + * 10. Let e be r's endIndex value. 1.182 + * 11. If global is true, 1.183 + * a. Call the [[Put]] internal method of R with arguments "lastIndex", e, and true. 1.184 + */ 1.185 +r = /abc/g; 1.186 +r.lastIndex = 17; 1.187 +assertEq(r.exec("sdfs"), null); 1.188 +assertEq(r.lastIndex, 0); 1.189 + 1.190 +r = /abc/g; 1.191 +r.lastIndex = 2; 1.192 +checkExec("/abc/g", r, ["00abc"], 1.193 + { lastIndex: 5, 1.194 + index: 2, 1.195 + input: "00abc", 1.196 + indexArray: ["abc"] }); 1.197 + 1.198 + 1.199 + 1.200 +r = /a(b)c/g; 1.201 +r.lastIndex = 2; 1.202 +checkExec("/a(b)c/g take two", r, ["00abcd"], 1.203 + { lastIndex: 5, 1.204 + index: 2, 1.205 + input: "00abcd", 1.206 + indexArray: ["abc", "b"] }); 1.207 + 1.208 + 1.209 +/* 1.210 + * 12. Let n be the length of r's captures array. (This is the same value as 1.211 + * 15.10.2.1's NCapturingParens.) 1.212 + * 13. Let A be a new array created as if by the expression new Array() where 1.213 + * Array is the standard built-in constructor with that name. 1.214 + * 14. Let matchIndex be the position of the matched substring within the 1.215 + * complete String S. 1.216 + * 15. Call the [[DefineOwnProperty]] internal method of A with arguments 1.217 + * "index", Property Descriptor {[[Value]]: matchIndex, [[Writable]: true, 1.218 + * [[Enumerable]]: true, [[Configurable]]: true}, and true. 1.219 + * 16. Call the [[DefineOwnProperty]] internal method of A with arguments 1.220 + * "input", Property Descriptor {[[Value]]: S, [[Writable]: true, 1.221 + * [[Enumerable]]: true, [[Configurable]]: true}, and true. 1.222 + * 17. Call the [[DefineOwnProperty]] internal method of A with arguments 1.223 + * "length", Property Descriptor {[[Value]]: n + 1}, and true. 1.224 + * 18. Let matchedSubstr be the matched substring (i.e. the portion of S 1.225 + * between offset i inclusive and offset e exclusive). 1.226 + * 19. Call the [[DefineOwnProperty]] internal method of A with arguments "0", 1.227 + * Property Descriptor {[[Value]]: matchedSubstr, [[Writable]: true, 1.228 + * [[Enumerable]]: true, [[Configurable]]: true}, and true. 1.229 + * 20. For each integer i such that I > 0 and I ≤ n 1.230 + * a. Let captureI be i th element of r's captures array. 1.231 + * b. Call the [[DefineOwnProperty]] internal method of A with arguments 1.232 + * ToString(i), Property Descriptor {[[Value]]: captureI, [[Writable]: 1.233 + * true, [[Enumerable]]: true, [[Configurable]]: true}, and true. 1.234 + * 21. Return A. 1.235 + */ 1.236 +// throughout, above (and in other tests) 1.237 + 1.238 +/******************************************************************************/ 1.239 + 1.240 +if (typeof reportCompare === "function") 1.241 + reportCompare(true, true); 1.242 + 1.243 +print("All tests passed!");