|
1 // Any copyright is dedicated to the Public Domain. |
|
2 // http://creativecommons.org/licenses/publicdomain/ |
|
3 |
|
4 //----------------------------------------------------------------------------- |
|
5 var BUGNUMBER = 715821; |
|
6 var summary = "Implement __define[GS]etter__ using Object.defineProperty"; |
|
7 |
|
8 print(BUGNUMBER + ": " + summary); |
|
9 |
|
10 /************* |
|
11 * UTILITIES * |
|
12 *************/ |
|
13 |
|
14 function s(desc) |
|
15 { |
|
16 if (typeof desc === "undefined") |
|
17 return "<undefined>"; |
|
18 assertEq(typeof desc, "object"); |
|
19 assertEq(desc !== null, true); |
|
20 |
|
21 var str = "<enumerable: <" + desc.enumerable + ">, " + |
|
22 " configurable: <" + desc.configurable + ">,"; |
|
23 |
|
24 if (desc.hasOwnProperty("value")) |
|
25 { |
|
26 return str + |
|
27 " value: <" + desc.value + ">," + |
|
28 " writable: <" + desc.writable + ">>"; |
|
29 } |
|
30 |
|
31 return str + |
|
32 " get: <" + desc.get + ">," + |
|
33 " set: <" + desc.set + ">>"; |
|
34 } |
|
35 |
|
36 function checkField(field, desc, expected) |
|
37 { |
|
38 var present = desc.hasOwnProperty(field); |
|
39 assertEq(present, expected.hasOwnProperty(field), |
|
40 field + " presence mismatch (got " + s(desc) + ", expected " + s(expected) + ")"); |
|
41 if (present) |
|
42 { |
|
43 assertEq(desc[field], expected[field], |
|
44 field + " value mismatch (got " + s(desc) + ", expected " + s(expected) + ")"); |
|
45 } |
|
46 } |
|
47 |
|
48 function check(obj, prop, expected) |
|
49 { |
|
50 var desc = Object.getOwnPropertyDescriptor(obj, prop); |
|
51 assertEq(typeof desc, typeof expected, |
|
52 "type mismatch (got " + s(desc) + ", expected " + s(expected) + ")"); |
|
53 |
|
54 assertEq(desc.hasOwnProperty("get"), desc.hasOwnProperty("set"), |
|
55 "bad descriptor: " + s(desc)); |
|
56 assertEq(desc.hasOwnProperty("value"), desc.hasOwnProperty("writable"), |
|
57 "bad descriptor: " + s(desc)); |
|
58 |
|
59 assertEq(desc.hasOwnProperty("get"), !desc.hasOwnProperty("value"), |
|
60 "bad descriptor: " + s(desc)); |
|
61 |
|
62 checkField("get", desc, expected); |
|
63 checkField("set", desc, expected); |
|
64 checkField("value", desc, expected); |
|
65 checkField("writable", desc, expected); |
|
66 checkField("enumerable", desc, expected); |
|
67 checkField("configurable", desc, expected); |
|
68 } |
|
69 |
|
70 function expectTypeError(f) |
|
71 { |
|
72 try |
|
73 { |
|
74 f(); |
|
75 throw new Error("no error thrown"); |
|
76 } |
|
77 catch (e) |
|
78 { |
|
79 assertEq(e instanceof TypeError, true, |
|
80 "wrong error thrown: got " + e + ", not a TypeError"); |
|
81 } |
|
82 } |
|
83 |
|
84 /************** |
|
85 * BEGIN TEST * |
|
86 **************/ |
|
87 |
|
88 // Adding a new getter, overwriting an existing one |
|
89 |
|
90 function g1() { } |
|
91 var gobj = {}; |
|
92 gobj.__defineGetter__("foo", g1); |
|
93 check(gobj, "foo", { get: g1, set: undefined, enumerable: true, configurable: true }); |
|
94 |
|
95 function g2() { } |
|
96 gobj.__defineGetter__("foo", g2); |
|
97 check(gobj, "foo", { get: g2, set: undefined, enumerable: true, configurable: true }); |
|
98 |
|
99 /******************************************************************************/ |
|
100 |
|
101 // Adding a new setter, overwriting an existing one |
|
102 |
|
103 function s1() { } |
|
104 var sobj = {}; |
|
105 sobj.__defineSetter__("bar", s1); |
|
106 check(sobj, "bar", { get: undefined, set: s1, enumerable: true, configurable: true }); |
|
107 |
|
108 function s2() { } |
|
109 sobj.__defineSetter__("bar", s2); |
|
110 check(sobj, "bar", { get: undefined, set: s2, enumerable: true, configurable: true }); |
|
111 |
|
112 /******************************************************************************/ |
|
113 |
|
114 // Adding a new getter, then adding a setter |
|
115 // Changing an existing accessor's enumerability, then "null"-changing the accessor |
|
116 // Changing an accessor's configurability, then "null"-changing and real-changing the accessor |
|
117 |
|
118 function g3() { } |
|
119 var gsobj = {}; |
|
120 gsobj.__defineGetter__("baz", g3); |
|
121 check(gsobj, "baz", { get: g3, set: undefined, enumerable: true, configurable: true }); |
|
122 |
|
123 function s3() { } |
|
124 gsobj.__defineSetter__("baz", s3); |
|
125 check(gsobj, "baz", { get: g3, set: s3, enumerable: true, configurable: true }); |
|
126 |
|
127 Object.defineProperty(gsobj, "baz", { enumerable: false }); |
|
128 check(gsobj, "baz", { get: g3, set: s3, enumerable: false, configurable: true }); |
|
129 |
|
130 gsobj.__defineGetter__("baz", g3); |
|
131 check(gsobj, "baz", { get: g3, set: s3, enumerable: true, configurable: true }); |
|
132 |
|
133 Object.defineProperty(gsobj, "baz", { enumerable: false }); |
|
134 check(gsobj, "baz", { get: g3, set: s3, enumerable: false, configurable: true }); |
|
135 |
|
136 gsobj.__defineSetter__("baz", s3); |
|
137 check(gsobj, "baz", { get: g3, set: s3, enumerable: true, configurable: true }); |
|
138 |
|
139 Object.defineProperty(gsobj, "baz", { configurable: false }); |
|
140 expectTypeError(function() { gsobj.__defineSetter__("baz", s2); }); |
|
141 expectTypeError(function() { gsobj.__defineSetter__("baz", s3); }); |
|
142 check(gsobj, "baz", { get: g3, set: s3, enumerable: true, configurable: false }); |
|
143 |
|
144 /******************************************************************************/ |
|
145 |
|
146 // Adding a new setter, then adding a getter |
|
147 // Changing an existing accessor's enumerability, then "null"-changing the accessor |
|
148 // Changing an accessor's configurability, then "null"-changing and real-changing the accessor |
|
149 |
|
150 function s4() { } |
|
151 var sgobj = {}; |
|
152 sgobj.__defineSetter__("baz", s4); |
|
153 check(sgobj, "baz", { get: undefined, set: s4, enumerable: true, configurable: true }); |
|
154 |
|
155 function g4() { } |
|
156 sgobj.__defineGetter__("baz", g4); |
|
157 check(sgobj, "baz", { get: g4, set: s4, enumerable: true, configurable: true }); |
|
158 |
|
159 Object.defineProperty(sgobj, "baz", { enumerable: false }); |
|
160 check(sgobj, "baz", { get: g4, set: s4, enumerable: false, configurable: true }); |
|
161 |
|
162 sgobj.__defineSetter__("baz", s4); |
|
163 check(sgobj, "baz", { get: g4, set: s4, enumerable: true, configurable: true }); |
|
164 |
|
165 Object.defineProperty(sgobj, "baz", { enumerable: false }); |
|
166 check(sgobj, "baz", { get: g4, set: s4, enumerable: false, configurable: true }); |
|
167 |
|
168 sgobj.__defineSetter__("baz", s4); |
|
169 check(sgobj, "baz", { get: g4, set: s4, enumerable: true, configurable: true }); |
|
170 |
|
171 Object.defineProperty(sgobj, "baz", { configurable: false }); |
|
172 expectTypeError(function() { sgobj.__defineGetter__("baz", g3); }); |
|
173 expectTypeError(function() { sgobj.__defineSetter__("baz", s4); }); |
|
174 check(sgobj, "baz", { get: g4, set: s4, enumerable: true, configurable: false }); |
|
175 |
|
176 /******************************************************************************/ |
|
177 |
|
178 // Adding a getter over a writable data property |
|
179 |
|
180 function g5() { } |
|
181 var gover = { quux: 17 }; |
|
182 check(gover, "quux", { value: 17, writable: true, enumerable: true, configurable: true }); |
|
183 |
|
184 gover.__defineGetter__("quux", g5); |
|
185 check(gover, "quux", { get: g5, set: undefined, enumerable: true, configurable: true }); |
|
186 |
|
187 /******************************************************************************/ |
|
188 |
|
189 // Adding a setter over a writable data property |
|
190 |
|
191 function s5() { } |
|
192 var sover = { quux: 17 }; |
|
193 check(sover, "quux", { value: 17, writable: true, enumerable: true, configurable: true }); |
|
194 |
|
195 sover.__defineSetter__("quux", s5); |
|
196 check(sover, "quux", { get: undefined, set: s5, enumerable: true, configurable: true }); |
|
197 |
|
198 /******************************************************************************/ |
|
199 |
|
200 // Adding a getter over a non-writable data property |
|
201 |
|
202 function g6() { } |
|
203 var gnover = { eit: 17 }; |
|
204 check(gnover, "eit", { value: 17, writable: true, enumerable: true, configurable: true }); |
|
205 Object.defineProperty(gnover, "eit", { writable: false }); |
|
206 check(gnover, "eit", { value: 17, writable: false, enumerable: true, configurable: true }); |
|
207 |
|
208 gnover.__defineGetter__("eit", g6); |
|
209 check(gnover, "eit", { get: g6, set: undefined, enumerable: true, configurable: true }); |
|
210 |
|
211 /******************************************************************************/ |
|
212 |
|
213 // Adding a setter over a non-writable data property |
|
214 |
|
215 function s6() { } |
|
216 var snover = { eit: 17 }; |
|
217 check(snover, "eit", { value: 17, writable: true, enumerable: true, configurable: true }); |
|
218 Object.defineProperty(snover, "eit", { writable: false }); |
|
219 check(snover, "eit", { value: 17, writable: false, enumerable: true, configurable: true }); |
|
220 |
|
221 snover.__defineSetter__("eit", s6); |
|
222 check(snover, "eit", { get: undefined, set: s6, enumerable: true, configurable: true }); |
|
223 |
|
224 /******************************************************************************/ |
|
225 |
|
226 // Adding a getter over a non-configurable, writable data property |
|
227 |
|
228 function g7() { } |
|
229 var gncover = { moo: 17 }; |
|
230 check(gncover, "moo", { value: 17, writable: true, enumerable: true, configurable: true }); |
|
231 Object.defineProperty(gncover, "moo", { configurable: false }); |
|
232 check(gncover, "moo", { value: 17, writable: true, enumerable: true, configurable: false }); |
|
233 |
|
234 expectTypeError(function() { gncover.__defineGetter__("moo", g7); }); |
|
235 check(gncover, "moo", { value: 17, writable: true, enumerable: true, configurable: false }); |
|
236 |
|
237 /******************************************************************************/ |
|
238 |
|
239 // Adding a setter over a non-configurable, writable data property |
|
240 |
|
241 function s7() { } |
|
242 var sncover = { moo: 17 }; |
|
243 check(sncover, "moo", { value: 17, writable: true, enumerable: true, configurable: true }); |
|
244 Object.defineProperty(sncover, "moo", { configurable: false }); |
|
245 check(sncover, "moo", { value: 17, writable: true, enumerable: true, configurable: false }); |
|
246 |
|
247 expectTypeError(function() { sncover.__defineSetter__("moo", s7); }); |
|
248 check(sncover, "moo", { value: 17, writable: true, enumerable: true, configurable: false }); |
|
249 |
|
250 /******************************************************************************/ |
|
251 |
|
252 // Adding a getter over a non-configurable, non-writable data property |
|
253 |
|
254 function g8() { } |
|
255 var gncwover = { fwoosh: 17 }; |
|
256 check(gncwover, "fwoosh", { value: 17, writable: true, enumerable: true, configurable: true }); |
|
257 Object.defineProperty(gncwover, "fwoosh", { writable: false, configurable: false }); |
|
258 check(gncwover, "fwoosh", { value: 17, writable: false, enumerable: true, configurable: false }); |
|
259 |
|
260 expectTypeError(function() { gncwover.__defineGetter__("fwoosh", g7); }); |
|
261 check(gncwover, "fwoosh", { value: 17, writable: false, enumerable: true, configurable: false }); |
|
262 |
|
263 /******************************************************************************/ |
|
264 |
|
265 // Adding a setter over a non-configurable, non-writable data property |
|
266 |
|
267 function s8() { } |
|
268 var sncwover = { fwoosh: 17 }; |
|
269 check(sncwover, "fwoosh", { value: 17, writable: true, enumerable: true, configurable: true }); |
|
270 Object.defineProperty(sncwover, "fwoosh", { writable: false, configurable: false }); |
|
271 check(sncwover, "fwoosh", { value: 17, writable: false, enumerable: true, configurable: false }); |
|
272 |
|
273 expectTypeError(function() { sncwover.__defineSetter__("fwoosh", s7); }); |
|
274 check(sncwover, "fwoosh", { value: 17, writable: false, enumerable: true, configurable: false }); |
|
275 |
|
276 /******************************************************************************/ |
|
277 |
|
278 if (typeof reportCompare === "function") |
|
279 reportCompare(true, true); |
|
280 |
|
281 print("Tests complete"); |