|
1 /* |
|
2 * Any copyright is dedicated to the Public Domain. |
|
3 * http://creativecommons.org/licenses/publicdomain/ |
|
4 */ |
|
5 |
|
6 var BUGNUMBER = 640072; |
|
7 var summary = |
|
8 "Represent /a/.{lastIndex,global,source,multiline,sticky,ignoreCase} with " + |
|
9 "plain old data properties"; |
|
10 |
|
11 print(BUGNUMBER + ": " + summary); |
|
12 |
|
13 /************** |
|
14 * BEGIN TEST * |
|
15 **************/ |
|
16 |
|
17 function checkDataProperty(obj, p, expect, msg) |
|
18 { |
|
19 var d = Object.getOwnPropertyDescriptor(obj, p); |
|
20 |
|
21 assertEq(d.value, expect.value, msg + ": bad value for " + p); |
|
22 assertEq(d.writable, expect.writable, msg + ": bad writable for " + p); |
|
23 assertEq(d.enumerable, expect.enumerable, msg + ": bad enumerable for " + p); |
|
24 assertEq(d.configurable, expect.configurable, msg + ": bad configurable for " + p); |
|
25 |
|
26 // Try redefining the property using its initial values: these should all be |
|
27 // silent no-ops. |
|
28 Object.defineProperty(obj, p, { value: expect.value }); |
|
29 Object.defineProperty(obj, p, { writable: expect.writable }); |
|
30 Object.defineProperty(obj, p, { enumerable: expect.enumerable }); |
|
31 Object.defineProperty(obj, p, { configurable: expect.configurable }); |
|
32 |
|
33 var d2 = Object.getOwnPropertyDescriptor(obj, p); |
|
34 assertEq(d.value, d2.value, msg + ": value changed on redefinition of " + p + "?"); |
|
35 assertEq(d.writable, d2.writable, msg + ": writable changed on redefinition of " + p + "?"); |
|
36 assertEq(d.enumerable, d2.enumerable, msg + ": enumerable changed on redefinition of " + p + "?"); |
|
37 assertEq(d.configurable, d2.configurable, msg + ": configurable changed on redefinition of " + p + "?"); |
|
38 } |
|
39 |
|
40 |
|
41 // Check a bunch of "empty" regular expressions first. |
|
42 |
|
43 var choices = [{ msg: "RegExp.prototype", |
|
44 get: function() { return RegExp.prototype; } }, |
|
45 { msg: "new RegExp()", |
|
46 get: function() { return new RegExp(); } }, |
|
47 { msg: "/(?:)/", |
|
48 get: Function("return /(?:)/;") }]; |
|
49 |
|
50 function checkRegExp(r, msg, lastIndex, global, ignoreCase, multiline) |
|
51 { |
|
52 var expect; |
|
53 |
|
54 expect = { value: lastIndex, enumerable: false, configurable: false, writable: true }; |
|
55 checkDataProperty(r, "lastIndex", expect, msg); |
|
56 |
|
57 // check source specially: its value is under-defined in the spec |
|
58 var d = Object.getOwnPropertyDescriptor(r, "source"); |
|
59 assertEq(d.writable, false, "bad writable: " + msg); |
|
60 assertEq(d.enumerable, false, "bad enumerable: " + msg); |
|
61 assertEq(d.configurable, false, "bad configurable: " + msg); |
|
62 |
|
63 expect = { value: global, enumerable: false, configurable: false, writable: false }; |
|
64 checkDataProperty(r, "global", expect, msg); |
|
65 |
|
66 expect = { value: ignoreCase, enumerable: false, configurable: false, writable: false }; |
|
67 checkDataProperty(r, "ignoreCase", expect, msg); |
|
68 |
|
69 expect = { value: multiline, enumerable: false, configurable: false, writable: false }; |
|
70 checkDataProperty(r, "multiline", expect, msg); |
|
71 } |
|
72 |
|
73 checkRegExp(RegExp.prototype, "RegExp.prototype", 0, false, false, false); |
|
74 checkRegExp(new RegExp(), "new RegExp()", 0, false, false, false); |
|
75 checkRegExp(/(?:)/, "/(?:)/", 0, false, false, false); |
|
76 checkRegExp(Function("return /(?:)/;")(), 'Function("return /(?:)/;")()', 0, false, false, false); |
|
77 |
|
78 for (var i = 0; i < choices.length; i++) |
|
79 { |
|
80 var choice = choices[i]; |
|
81 var msg = choice.msg; |
|
82 var r = choice.get(); |
|
83 |
|
84 checkRegExp(r, msg, 0, false, false, false); |
|
85 } |
|
86 |
|
87 // Now test less generic regular expressions |
|
88 |
|
89 checkRegExp(/a/gim, "/a/gim", 0, true, true, true); |
|
90 |
|
91 var r; |
|
92 |
|
93 do |
|
94 { |
|
95 r = /abcd/mg; |
|
96 checkRegExp(r, "/abcd/mg initially", 0, true, false, true); |
|
97 r.exec("abcdefg"); |
|
98 checkRegExp(r, "/abcd/mg step 1", 4, true, false, true); |
|
99 r.exec("abcdabcd"); |
|
100 checkRegExp(r, "/abcd/mg step 2", 8, true, false, true); |
|
101 r.exec("abcdabcd"); |
|
102 checkRegExp(r, "/abcd/mg end", 0, true, false, true); |
|
103 |
|
104 r = /cde/ig; |
|
105 checkRegExp(r, "/cde/ig initially", 0, true, true, false); |
|
106 var obj = r.lastIndex = { valueOf: function() { return 2; } }; |
|
107 checkRegExp(r, "/cde/ig after lastIndex", obj, true, true, false); |
|
108 r.exec("aaacdef"); |
|
109 checkRegExp(r, "/cde/ig after exec", 6, true, true, false); |
|
110 Object.defineProperty(r, "lastIndex", { value: 3 }); |
|
111 checkRegExp(r, "/cde/ig after define 3", 3, true, true, false); |
|
112 Object.defineProperty(r, "lastIndex", { value: obj }); |
|
113 checkRegExp(r, "/cde/ig after lastIndex", obj, true, true, false); |
|
114 |
|
115 |
|
116 // Tricky bits of testing: make sure that redefining lastIndex doesn't change |
|
117 // the slot where the lastIndex property is initially stored, even if |
|
118 // the redefinition also changes writability. |
|
119 r = /a/g; |
|
120 checkRegExp(r, "/a/g initially", 0, true, false, false); |
|
121 Object.defineProperty(r, "lastIndex", { value: 2 }); |
|
122 r.exec("aabbbba"); |
|
123 checkRegExp(r, "/a/g after first exec", 7, true, false, false); |
|
124 assertEq(r.lastIndex, 7); |
|
125 r.lastIndex = 2; |
|
126 checkRegExp(r, "/a/g after assign", 2, true, false, false); |
|
127 r.exec("aabbbba"); |
|
128 assertEq(r.lastIndex, 7); // check in reverse order |
|
129 checkRegExp(r, "/a/g after second exec", 7, true, false, false); |
|
130 |
|
131 r = /c/g; |
|
132 r.lastIndex = 2; |
|
133 checkRegExp(r, "/c/g initially", 2, true, false, false); |
|
134 Object.defineProperty(r, "lastIndex", { writable: false }); |
|
135 assertEq(Object.getOwnPropertyDescriptor(r, "lastIndex").writable, false); |
|
136 try { r.exec("aabbbba"); } catch (e) { /* swallow error if thrown */ } |
|
137 assertEq(Object.getOwnPropertyDescriptor(r, "lastIndex").writable, false); |
|
138 assertEq(Object.getOwnPropertyDescriptor(r, "source").writable, false); |
|
139 assertEq(Object.getOwnPropertyDescriptor(r, "global").value, true); |
|
140 assertEq(Object.getOwnPropertyDescriptor(r, "global").writable, false); |
|
141 assertEq(Object.getOwnPropertyDescriptor(r, "ignoreCase").value, false); |
|
142 assertEq(Object.getOwnPropertyDescriptor(r, "ignoreCase").writable, false); |
|
143 assertEq(Object.getOwnPropertyDescriptor(r, "multiline").value, false); |
|
144 assertEq(Object.getOwnPropertyDescriptor(r, "multiline").writable, false); |
|
145 } |
|
146 while (Math.random() > 17); // fake loop to discourage RegExp object caching |
|
147 |
|
148 /******************************************************************************/ |
|
149 |
|
150 if (typeof reportCompare === "function") |
|
151 reportCompare(true, true); |
|
152 |
|
153 print("All tests passed!"); |