| /* |
| * Any copyright is dedicated to the Public Domain. |
| * http://creativecommons.org/licenses/publicdomain/ |
| */ |
| |
| var BUGNUMBER = 640072; |
| var summary = |
| "Represent /a/.{lastIndex,global,source,multiline,sticky,ignoreCase} with " + |
| "plain old data properties"; |
| |
| print(BUGNUMBER + ": " + summary); |
| |
| /************** |
| * BEGIN TEST * |
| **************/ |
| |
| function checkDataProperty(obj, p, expect, msg) |
| { |
| var d = Object.getOwnPropertyDescriptor(obj, p); |
| |
| assertEq(d.value, expect.value, msg + ": bad value for " + p); |
| assertEq(d.writable, expect.writable, msg + ": bad writable for " + p); |
| assertEq(d.enumerable, expect.enumerable, msg + ": bad enumerable for " + p); |
| assertEq(d.configurable, expect.configurable, msg + ": bad configurable for " + p); |
| |
| // Try redefining the property using its initial values: these should all be |
| // silent no-ops. |
| Object.defineProperty(obj, p, { value: expect.value }); |
| Object.defineProperty(obj, p, { writable: expect.writable }); |
| Object.defineProperty(obj, p, { enumerable: expect.enumerable }); |
| Object.defineProperty(obj, p, { configurable: expect.configurable }); |
| |
| var d2 = Object.getOwnPropertyDescriptor(obj, p); |
| assertEq(d.value, d2.value, msg + ": value changed on redefinition of " + p + "?"); |
| assertEq(d.writable, d2.writable, msg + ": writable changed on redefinition of " + p + "?"); |
| assertEq(d.enumerable, d2.enumerable, msg + ": enumerable changed on redefinition of " + p + "?"); |
| assertEq(d.configurable, d2.configurable, msg + ": configurable changed on redefinition of " + p + "?"); |
| } |
| |
| |
| // Check a bunch of "empty" regular expressions first. |
| |
| var choices = [{ msg: "RegExp.prototype", |
| get: function() { return RegExp.prototype; } }, |
| { msg: "new RegExp()", |
| get: function() { return new RegExp(); } }, |
| { msg: "/(?:)/", |
| get: Function("return /(?:)/;") }]; |
| |
| function checkRegExp(r, msg, lastIndex) |
| { |
| var expect; |
| |
| expect = { value: lastIndex, enumerable: false, configurable: false, writable: true }; |
| checkDataProperty(r, "lastIndex", expect, msg); |
| } |
| |
| checkRegExp(RegExp.prototype, "RegExp.prototype", 0); |
| checkRegExp(new RegExp(), "new RegExp()", 0); |
| checkRegExp(/(?:)/, "/(?:)/", 0); |
| checkRegExp(Function("return /(?:)/;")(), 'Function("return /(?:)/;")()', 0); |
| |
| for (var i = 0; i < choices.length; i++) |
| { |
| var choice = choices[i]; |
| var msg = choice.msg; |
| var r = choice.get(); |
| |
| checkRegExp(r, msg, 0); |
| } |
| |
| // Now test less generic regular expressions |
| |
| checkRegExp(/a/gim, "/a/gim", 0); |
| |
| var r; |
| |
| do |
| { |
| r = /abcd/mg; |
| checkRegExp(r, "/abcd/mg initially", 0); |
| r.exec("abcdefg"); |
| checkRegExp(r, "/abcd/mg step 1", 4); |
| r.exec("abcdabcd"); |
| checkRegExp(r, "/abcd/mg step 2", 8); |
| r.exec("abcdabcd"); |
| checkRegExp(r, "/abcd/mg end", 0); |
| |
| r = /cde/ig; |
| checkRegExp(r, "/cde/ig initially", 0); |
| var obj = r.lastIndex = { valueOf: function() { return 2; } }; |
| checkRegExp(r, "/cde/ig after lastIndex", obj); |
| r.exec("aaacdef"); |
| checkRegExp(r, "/cde/ig after exec", 6); |
| Object.defineProperty(r, "lastIndex", { value: 3 }); |
| checkRegExp(r, "/cde/ig after define 3", 3); |
| Object.defineProperty(r, "lastIndex", { value: obj }); |
| checkRegExp(r, "/cde/ig after lastIndex", obj); |
| |
| |
| // Tricky bits of testing: make sure that redefining lastIndex doesn't change |
| // the slot where the lastIndex property is initially stored, even if |
| // the redefinition also changes writability. |
| r = /a/g; |
| checkRegExp(r, "/a/g initially", 0); |
| Object.defineProperty(r, "lastIndex", { value: 2 }); |
| r.exec("aabbbba"); |
| checkRegExp(r, "/a/g after first exec", 7); |
| assertEq(r.lastIndex, 7); |
| r.lastIndex = 2; |
| checkRegExp(r, "/a/g after assign", 2); |
| r.exec("aabbbba"); |
| assertEq(r.lastIndex, 7); // check in reverse order |
| checkRegExp(r, "/a/g after second exec", 7); |
| |
| r = /c/g; |
| r.lastIndex = 2; |
| checkRegExp(r, "/c/g initially", 2); |
| Object.defineProperty(r, "lastIndex", { writable: false }); |
| assertEq(Object.getOwnPropertyDescriptor(r, "lastIndex").writable, false); |
| try { r.exec("aabbbba"); } catch (e) { /* swallow error if thrown */ } |
| assertEq(Object.getOwnPropertyDescriptor(r, "lastIndex").writable, false); |
| } |
| while (Math.random() > 17); // fake loop to discourage RegExp object caching |
| |
| /******************************************************************************/ |
| |
| if (typeof reportCompare === "function") |
| reportCompare(true, true); |
| |
| print("All tests passed!"); |