OLD | NEW |
| (Empty) |
1 // Copyright 2011 the V8 project authors. All rights reserved. | |
2 // Redistribution and use in source and binary forms, with or without | |
3 // modification, are permitted provided that the following conditions are | |
4 // met: | |
5 // | |
6 // * Redistributions of source code must retain the above copyright | |
7 // notice, this list of conditions and the following disclaimer. | |
8 // * Redistributions in binary form must reproduce the above | |
9 // copyright notice, this list of conditions and the following | |
10 // disclaimer in the documentation and/or other materials provided | |
11 // with the distribution. | |
12 // * Neither the name of Google Inc. nor the names of its | |
13 // contributors may be used to endorse or promote products derived | |
14 // from this software without specific prior written permission. | |
15 // | |
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
27 | |
28 // We change the stack size for the ARM64 simulator because at one point this | |
29 // test enters an infinite recursion which goes through the runtime and we | |
30 // overflow the system stack before the simulator stack. | |
31 | |
32 // Flags: --harmony-proxies --sim-stack-size=500 --allow-natives-syntax | |
33 | |
34 | |
35 // Helper. | |
36 | |
37 function TestWithProxies(test, x, y, z) { | |
38 // Separate function for nicer stack traces. | |
39 TestWithObjectProxy(test, x, y, z); | |
40 TestWithFunctionProxy(test, x, y, z); | |
41 } | |
42 | |
43 function TestWithObjectProxy(test, x, y, z) { | |
44 test((handler) => { return new Proxy({}, handler) }, x, y, z) | |
45 | |
46 } | |
47 | |
48 function TestWithFunctionProxy(test, x, y, z) { | |
49 test((handler) => { return new Proxy(() => {}, handler) }, x, y, z) | |
50 } | |
51 | |
52 // --------------------------------------------------------------------------- | |
53 // Getting property descriptors (Object.getOwnPropertyDescriptor). | |
54 | |
55 var key | |
56 | |
57 function TestGetOwnProperty(handler) { | |
58 TestWithProxies(TestGetOwnProperty2, handler) | |
59 } | |
60 | |
61 function TestGetOwnProperty2(create, handler) { | |
62 var p = create(handler) | |
63 assertEquals(42, Object.getOwnPropertyDescriptor(p, "a").value) | |
64 assertEquals("a", key) | |
65 assertEquals(42, Object.getOwnPropertyDescriptor(p, 99).value) | |
66 assertEquals("99", key) | |
67 } | |
68 | |
69 TestGetOwnProperty({ | |
70 getOwnPropertyDescriptor(target, k) { | |
71 key = k | |
72 return {value: 42, configurable: true} | |
73 } | |
74 }) | |
75 | |
76 TestGetOwnProperty({ | |
77 getOwnPropertyDescriptor(target, k) { | |
78 return this.getOwnPropertyDescriptor2(k) | |
79 }, | |
80 getOwnPropertyDescriptor2(k) { | |
81 key = k | |
82 return {value: 42, configurable: true} | |
83 } | |
84 }) | |
85 | |
86 TestGetOwnProperty({ | |
87 getOwnPropertyDescriptor(target, k) { | |
88 key = k | |
89 return {get value() { return 42 }, get configurable() { return true }} | |
90 } | |
91 }) | |
92 | |
93 TestGetOwnProperty(new Proxy({}, { | |
94 get(target, pk, receiver) { | |
95 return function(t, k) { key = k; return {value: 42, configurable: true} } | |
96 } | |
97 })) | |
98 | |
99 | |
100 // --------------------------------------------------------------------------- | |
101 function TestGetOwnPropertyThrow(handler) { | |
102 TestWithProxies(TestGetOwnPropertyThrow2, handler) | |
103 } | |
104 | |
105 function TestGetOwnPropertyThrow2(create, handler) { | |
106 var p = create(handler) | |
107 assertThrowsEquals(() => Object.getOwnPropertyDescriptor(p, "a"), "myexn") | |
108 assertThrowsEquals(() => Object.getOwnPropertyDescriptor(p, 77), "myexn") | |
109 } | |
110 | |
111 TestGetOwnPropertyThrow({ | |
112 getOwnPropertyDescriptor: function(k) { throw "myexn" } | |
113 }) | |
114 | |
115 TestGetOwnPropertyThrow({ | |
116 getOwnPropertyDescriptor: function(k) { | |
117 return this.getOwnPropertyDescriptor2(k) | |
118 }, | |
119 getOwnPropertyDescriptor2: function(k) { throw "myexn" } | |
120 }) | |
121 | |
122 TestGetOwnPropertyThrow({ | |
123 getOwnPropertyDescriptor: function(k) { | |
124 return {get value() { throw "myexn" }} | |
125 } | |
126 }) | |
127 | |
128 TestGetOwnPropertyThrow(new Proxy({}, { | |
129 get: function(pr, pk) { | |
130 return function(k) { throw "myexn" } | |
131 } | |
132 })) | |
133 | |
134 | |
135 // --------------------------------------------------------------------------- | |
136 // Getters (dot, brackets). | |
137 | |
138 var key | |
139 | |
140 function TestGet(handler) { | |
141 TestWithProxies(TestGet2, handler) | |
142 } | |
143 | |
144 function TestGet2(create, handler) { | |
145 var p = create(handler) | |
146 assertEquals(42, p.a) | |
147 assertEquals("a", key) | |
148 assertEquals(42, p["b"]) | |
149 assertEquals("b", key) | |
150 assertEquals(42, p[99]) | |
151 assertEquals("99", key) | |
152 assertEquals(42, (function(n) { return p[n] })("c")) | |
153 assertEquals("c", key) | |
154 assertEquals(42, (function(n) { return p[n] })(101)) | |
155 assertEquals("101", key) | |
156 | |
157 var o = Object.create(p, {x: {value: 88}}) | |
158 assertEquals(42, o.a) | |
159 assertEquals("a", key) | |
160 assertEquals(42, o["b"]) | |
161 assertEquals("b", key) | |
162 assertEquals(42, o[99]) | |
163 assertEquals("99", key) | |
164 assertEquals(88, o.x) | |
165 assertEquals(88, o["x"]) | |
166 assertEquals(42, (function(n) { return o[n] })("c")) | |
167 assertEquals("c", key) | |
168 assertEquals(42, (function(n) { return o[n] })(101)) | |
169 assertEquals("101", key) | |
170 assertEquals(88, (function(n) { return o[n] })("x")) | |
171 } | |
172 | |
173 TestGet({ | |
174 get(t, k, r) { key = k; return 42 } | |
175 }) | |
176 | |
177 TestGet({ | |
178 get(t, k, r) { return this.get2(r, k) }, | |
179 get2(r, k) { key = k; return 42 } | |
180 }) | |
181 | |
182 TestGet(new Proxy({}, { | |
183 get(pt, pk, pr) { | |
184 return function(t, k, r) { key = k; return 42 } | |
185 } | |
186 })) | |
187 | |
188 | |
189 // --------------------------------------------------------------------------- | |
190 function TestGetCall(handler) { | |
191 TestWithProxies(TestGetCall2, handler) | |
192 } | |
193 | |
194 function TestGetCall2(create, handler) { | |
195 var p = create(handler) | |
196 assertEquals(55, p.f()) | |
197 assertEquals(55, p["f"]()) | |
198 assertEquals(55, p.f("unused", "arguments")) | |
199 assertEquals(55, p.f.call(p)) | |
200 assertEquals(55, p["f"].call(p)) | |
201 assertEquals(55, p[101].call(p)) | |
202 assertEquals(55, p.withargs(45, 5)) | |
203 assertEquals(55, p.withargs.call(p, 11, 22)) | |
204 assertEquals(55, (function(n) { return p[n]() })("f")) | |
205 assertEquals(55, (function(n) { return p[n].call(p) })("f")) | |
206 assertEquals(55, (function(n) { return p[n](15, 20) })("withargs")) | |
207 assertEquals(55, (function(n) { return p[n].call(p, 13, 21) })("withargs")) | |
208 assertEquals("6655", "66" + p) // calls p.toString | |
209 | |
210 var o = Object.create(p, {g: {value: function(x) { return x + 88 }}}) | |
211 assertEquals(55, o.f()) | |
212 assertEquals(55, o["f"]()) | |
213 assertEquals(55, o.f("unused", "arguments")) | |
214 assertEquals(55, o.f.call(o)) | |
215 assertEquals(55, o.f.call(p)) | |
216 assertEquals(55, o["f"].call(p)) | |
217 assertEquals(55, o[101].call(p)) | |
218 assertEquals(55, o.withargs(45, 5)) | |
219 assertEquals(55, o.withargs.call(p, 11, 22)) | |
220 assertEquals(90, o.g(2)) | |
221 assertEquals(91, o.g.call(o, 3)) | |
222 assertEquals(92, o.g.call(p, 4)) | |
223 assertEquals(55, (function(n) { return o[n]() })("f")) | |
224 assertEquals(55, (function(n) { return o[n].call(o) })("f")) | |
225 assertEquals(55, (function(n) { return o[n](15, 20) })("withargs")) | |
226 assertEquals(55, (function(n) { return o[n].call(o, 13, 21) })("withargs")) | |
227 assertEquals(93, (function(n) { return o[n](5) })("g")) | |
228 assertEquals(94, (function(n) { return o[n].call(o, 6) })("g")) | |
229 assertEquals(95, (function(n) { return o[n].call(p, 7) })("g")) | |
230 assertEquals("6655", "66" + o) // calls o.toString | |
231 } | |
232 | |
233 TestGetCall({ | |
234 get(t, k, r) { return () => { return 55 } } | |
235 }) | |
236 | |
237 TestGetCall({ | |
238 get(t, k, r) { return this.get2(t, k, r) }, | |
239 get2(t, k, r) { return () => { return 55 } } | |
240 }) | |
241 | |
242 TestGetCall({ | |
243 get(t, k, r) { | |
244 if (k == "gg") { | |
245 return () => { return 55 } | |
246 } else if (k == "withargs") { | |
247 return (n, m) => { return n + m * 2 } | |
248 } else { | |
249 return () => { return r.gg() } | |
250 } | |
251 } | |
252 }) | |
253 | |
254 TestGetCall(new Proxy({}, { | |
255 get(pt, pk, pr) { | |
256 return (t, k, r) => { return () => { return 55 } } | |
257 } | |
258 })) | |
259 | |
260 | |
261 // --------------------------------------------------------------------------- | |
262 function TestGetThrow(handler) { | |
263 TestWithProxies(TestGetThrow2, handler) | |
264 } | |
265 | |
266 function TestGetThrow2(create, handler) { | |
267 var p = create(handler) | |
268 assertThrowsEquals(function(){ p.a }, "myexn") | |
269 assertThrowsEquals(function(){ p["b"] }, "myexn") | |
270 assertThrowsEquals(function(){ p[3] }, "myexn") | |
271 assertThrowsEquals(function(){ (function(n) { p[n] })("c") }, "myexn") | |
272 assertThrowsEquals(function(){ (function(n) { p[n] })(99) }, "myexn") | |
273 | |
274 var o = Object.create(p, {x: {value: 88}, '4': {value: 89}}) | |
275 assertThrowsEquals(function(){ o.a }, "myexn") | |
276 assertThrowsEquals(function(){ o["b"] }, "myexn") | |
277 assertThrowsEquals(function(){ o[3] }, "myexn") | |
278 assertThrowsEquals(function(){ (function(n) { o[n] })("c") }, "myexn") | |
279 assertThrowsEquals(function(){ (function(n) { o[n] })(99) }, "myexn") | |
280 } | |
281 | |
282 TestGetThrow({ | |
283 get(r, k) { throw "myexn" } | |
284 }) | |
285 | |
286 TestGetThrow({ | |
287 get(r, k) { return this.get2(r, k) }, | |
288 get2(r, k) { throw "myexn" } | |
289 }) | |
290 | |
291 TestGetThrow(new Proxy({}, { | |
292 get(pr, pk) { throw "myexn" } | |
293 })) | |
294 | |
295 TestGetThrow(new Proxy({}, { | |
296 get(pr, pk) { | |
297 return function(r, k) { throw "myexn" } | |
298 } | |
299 })) | |
300 | |
301 | |
302 // --------------------------------------------------------------------------- | |
303 // Setters. | |
304 | |
305 var key | |
306 var val | |
307 | |
308 function TestSet(handler) { | |
309 TestWithProxies(TestSet2, handler) | |
310 } | |
311 | |
312 function TestSet2(create, handler) { | |
313 var p = create(handler) | |
314 assertEquals(42, p.a = 42) | |
315 assertEquals("a", key) | |
316 assertEquals(42, val) | |
317 assertEquals(43, p["b"] = 43) | |
318 assertEquals("b", key) | |
319 assertEquals(43, val) | |
320 assertEquals(44, p[77] = 44) | |
321 assertEquals("77", key) | |
322 assertEquals(44, val) | |
323 | |
324 assertEquals(45, (function(n) { return p[n] = 45 })("c")) | |
325 assertEquals("c", key) | |
326 assertEquals(45, val) | |
327 assertEquals(46, (function(n) { return p[n] = 46 })(99)) | |
328 assertEquals("99", key) | |
329 assertEquals(46, val) | |
330 | |
331 assertEquals(47, p["0"] = 47) | |
332 assertEquals("0", key) | |
333 assertEquals(47, val) | |
334 } | |
335 | |
336 TestSet({ | |
337 set: function(r, k, v) { key = k; val = v; return true } | |
338 }) | |
339 | |
340 TestSet({ | |
341 set: function(r, k, v) { return this.set2(r, k, v) }, | |
342 set2: function(r, k, v) { key = k; val = v; return true } | |
343 }) | |
344 | |
345 TestSet(new Proxy({}, { | |
346 get(pk, pr) { | |
347 return (r, k, v) => { key = k; val = v; return true } | |
348 } | |
349 })) | |
350 | |
351 | |
352 // --------------------------------------------------------------------------- | |
353 function TestSetThrow(handler) { | |
354 TestWithProxies(TestSetThrow2, handler) | |
355 } | |
356 | |
357 function TestSetThrow2(create, handler) { | |
358 var p = create(handler) | |
359 assertThrowsEquals(function(){ p.a = 42 }, "myexn") | |
360 assertThrowsEquals(function(){ p["b"] = 42 }, "myexn") | |
361 assertThrowsEquals(function(){ p[22] = 42 }, "myexn") | |
362 assertThrowsEquals(function(){ (function(n) { p[n] = 45 })("c") }, "myexn") | |
363 assertThrowsEquals(function(){ (function(n) { p[n] = 46 })(99) }, "myexn") | |
364 } | |
365 | |
366 TestSetThrow({ | |
367 set: function(r, k, v) { throw "myexn" } | |
368 }) | |
369 | |
370 TestSetThrow({ | |
371 set: function(r, k, v) { return this.set2(r, k, v) }, | |
372 set2: function(r, k, v) { throw "myexn" } | |
373 }) | |
374 | |
375 TestSetThrow({ | |
376 getOwnPropertyDescriptor: function(k) { throw "myexn" }, | |
377 defineProperty: function(k, desc) { key = k; val = desc.value } | |
378 }) | |
379 | |
380 TestSetThrow({ | |
381 getOwnPropertyDescriptor: function(k) { | |
382 return {configurable: true, writable: true} | |
383 }, | |
384 defineProperty: function(k, desc) { throw "myexn" } | |
385 }) | |
386 | |
387 TestSetThrow({ | |
388 getOwnPropertyDescriptor: function(k) { | |
389 return this.getOwnPropertyDescriptor2(k) | |
390 }, | |
391 getOwnPropertyDescriptor2: function(k) { throw "myexn" }, | |
392 defineProperty: function(k, desc) { this.defineProperty2(k, desc) }, | |
393 defineProperty2: function(k, desc) { key = k; val = desc.value } | |
394 }) | |
395 | |
396 TestSetThrow({ | |
397 getOwnPropertyDescriptor: function(k) { | |
398 return this.getOwnPropertyDescriptor2(k) | |
399 }, | |
400 getOwnPropertyDescriptor2: function(k) { | |
401 return {configurable: true, writable: true} | |
402 }, | |
403 defineProperty: function(k, desc) { this.defineProperty2(k, desc) }, | |
404 defineProperty2: function(k, desc) { throw "myexn" } | |
405 }) | |
406 | |
407 TestSetThrow({ | |
408 getOwnPropertyDescriptor: function(k) { throw "myexn" }, | |
409 defineProperty: function(k, desc) { key = k; val = desc.value } | |
410 }) | |
411 | |
412 TestSetThrow({ | |
413 getOwnPropertyDescriptor: function(k) { | |
414 return { | |
415 get configurable() { return true }, | |
416 get writable() { return true } | |
417 } | |
418 }, | |
419 defineProperty: function(k, desc) { throw "myexn" } | |
420 }) | |
421 | |
422 TestSetThrow({ | |
423 getOwnPropertyDescriptor: function(k) { throw "myexn" } | |
424 }) | |
425 | |
426 TestSetThrow({ | |
427 getOwnPropertyDescriptor: function(k) { throw "myexn" }, | |
428 defineProperty: function(k, desc) { key = k; val = desc.value } | |
429 }) | |
430 | |
431 TestSetThrow(new Proxy({}, { | |
432 get: function(pr, pk) { throw "myexn" } | |
433 })) | |
434 | |
435 TestSetThrow(new Proxy({}, { | |
436 get: function(pr, pk) { | |
437 return function(r, k, v) { throw "myexn" } | |
438 } | |
439 })) | |
440 | |
441 // --------------------------------------------------------------------------- | |
442 | |
443 // Evil proxy-induced side-effects shouldn't crash. | |
444 TestWithProxies(function(create) { | |
445 var calls = 0 | |
446 var handler = { | |
447 getPropertyDescriptor: function() { | |
448 ++calls | |
449 return (calls % 2 == 1) | |
450 ? {get: function() { return 5 }, configurable: true} | |
451 : {set: function() { return false }, configurable: true} | |
452 } | |
453 } | |
454 var p = create(handler) | |
455 var o = Object.create(p) | |
456 // Make proxy prototype property read-only after CanPut check. | |
457 try { o.x = 4 } catch (e) { assertInstanceof(e, Error) } | |
458 }) | |
459 | |
460 TestWithProxies(function(create) { | |
461 var handler = { | |
462 getPropertyDescriptor: function() { | |
463 Object.defineProperty(o, "x", {get: function() { return 5 }}); | |
464 return {set: function() {}} | |
465 } | |
466 } | |
467 var p = create(handler) | |
468 var o = Object.create(p) | |
469 // Make object property read-only after CanPut check. | |
470 try { o.x = 4 } catch (e) { assertInstanceof(e, Error) } | |
471 }) | |
472 | |
473 | |
474 // --------------------------------------------------------------------------- | |
475 // Property definition (Object.defineProperty and Object.defineProperties). | |
476 | |
477 var key | |
478 var desc | |
479 | |
480 function TestDefine(handler) { | |
481 TestWithProxies(TestDefine2, handler) | |
482 } | |
483 | |
484 function TestDefine2(create, handler) { | |
485 var p = create(handler) | |
486 assertEquals(p, Object.defineProperty(p, "a", {value: 44})) | |
487 assertEquals("a", key) | |
488 assertEquals(1, Object.getOwnPropertyNames(desc).length) | |
489 assertEquals(44, desc.value) | |
490 | |
491 assertEquals(p, Object.defineProperty(p, "b", {value: 45, writable: false})) | |
492 assertEquals("b", key) | |
493 assertEquals(2, Object.getOwnPropertyNames(desc).length) | |
494 assertEquals(45, desc.value) | |
495 assertEquals(false, desc.writable) | |
496 | |
497 assertEquals(p, Object.defineProperty(p, "c", {value: 46, enumerable: false})) | |
498 assertEquals("c", key) | |
499 assertEquals(2, Object.getOwnPropertyNames(desc).length) | |
500 assertEquals(46, desc.value) | |
501 assertEquals(false, desc.enumerable) | |
502 | |
503 assertEquals(p, Object.defineProperty(p, 101, {value: 47, enumerable: false})) | |
504 assertEquals("101", key) | |
505 assertEquals(2, Object.getOwnPropertyNames(desc).length) | |
506 assertEquals(47, desc.value) | |
507 assertEquals(false, desc.enumerable) | |
508 | |
509 var attributes = {configurable: true, mine: 66, minetoo: 23} | |
510 assertEquals(p, Object.defineProperty(p, "d", attributes)) | |
511 assertEquals("d", key); | |
512 // Modifying the attributes object after the fact should have no effect. | |
513 attributes.configurable = false | |
514 attributes.mine = 77 | |
515 delete attributes.minetoo; | |
516 assertEquals(1, Object.getOwnPropertyNames(desc).length) | |
517 assertEquals(true, desc.configurable) | |
518 assertEquals(undefined, desc.mine) | |
519 assertEquals(undefined, desc.minetoo) | |
520 | |
521 assertEquals(p, Object.defineProperty(p, "e", {get: function(){ return 5 }})) | |
522 assertEquals("e", key) | |
523 assertEquals(1, Object.getOwnPropertyNames(desc).length) | |
524 assertEquals(5, desc.get()) | |
525 | |
526 assertEquals(p, Object.defineProperty(p, "zzz", {})) | |
527 assertEquals("zzz", key) | |
528 assertEquals(0, Object.getOwnPropertyNames(desc).length) | |
529 | |
530 var props = { | |
531 '11': {}, | |
532 blub: {get: function() { return true }}, | |
533 '': {get value() { return 20 }}, | |
534 last: {value: 21, configurable: true, mine: "eyes"} | |
535 } | |
536 Object.defineProperty(props, "hidden", {value: "hidden", enumerable: false}) | |
537 assertEquals(p, Object.defineProperties(p, props)) | |
538 assertEquals("last", key) | |
539 assertEquals(2, Object.getOwnPropertyNames(desc).length) | |
540 assertEquals(21, desc.value) | |
541 assertEquals(true, desc.configurable) | |
542 assertEquals(undefined, desc.mine) // Arguably a bug in the spec... | |
543 | |
544 var props = {bla: {get value() { throw "myexn" }}} | |
545 assertThrowsEquals(function(){ Object.defineProperties(p, props) }, "myexn") | |
546 } | |
547 | |
548 TestDefine({ | |
549 defineProperty(t, k, d) { key = k; desc = d; return true } | |
550 }) | |
551 | |
552 TestDefine({ | |
553 defineProperty(t, k, d) { return this.defineProperty2(k, d) }, | |
554 defineProperty2(k, d) { key = k; desc = d; return true } | |
555 }) | |
556 | |
557 | |
558 // --------------------------------------------------------------------------- | |
559 function TestDefineThrow(handler) { | |
560 TestWithProxies(TestDefineThrow2, handler) | |
561 } | |
562 | |
563 function TestDefineThrow2(create, handler) { | |
564 var p = create(handler) | |
565 assertThrowsEquals(() => Object.defineProperty(p, "a", {value: 44}), "myexn") | |
566 assertThrowsEquals(() => Object.defineProperty(p, 0, {value: 44}), "myexn") | |
567 | |
568 var d1 = create({ | |
569 get: function(r, k) { throw "myexn" }, | |
570 getOwnPropertyNames: function() { return ["value"] } | |
571 }) | |
572 assertThrowsEquals(function(){ Object.defineProperty(p, "p", d1) }, "myexn") | |
573 var d2 = create({ | |
574 get: function(r, k) { return 77 }, | |
575 getOwnPropertyNames: function() { throw "myexn" } | |
576 }) | |
577 assertThrowsEquals(function(){ Object.defineProperty(p, "p", d2) }, "myexn") | |
578 | |
579 var props = {bla: {get value() { throw "otherexn" }}} | |
580 assertThrowsEquals(() => Object.defineProperties(p, props), "otherexn") | |
581 } | |
582 | |
583 TestDefineThrow({ | |
584 defineProperty: function(k, d) { throw "myexn" } | |
585 }) | |
586 | |
587 TestDefineThrow({ | |
588 defineProperty: function(k, d) { return this.defineProperty2(k, d) }, | |
589 defineProperty2: function(k, d) { throw "myexn" } | |
590 }) | |
591 | |
592 TestDefineThrow(new Proxy({}, { | |
593 get: function(pr, pk) { throw "myexn" } | |
594 })) | |
595 | |
596 TestDefineThrow(new Proxy({}, { | |
597 get: function(pr, pk) { | |
598 return function(k, d) { throw "myexn" } | |
599 } | |
600 })) | |
601 | |
602 | |
603 | |
604 // --------------------------------------------------------------------------- | |
605 // Property deletion (delete). | |
606 | |
607 var key | |
608 | |
609 function TestDelete(handler) { | |
610 TestWithProxies(TestDelete2, handler) | |
611 } | |
612 | |
613 function TestDelete2(create, handler) { | |
614 var p = create(handler) | |
615 assertEquals(true, delete p.a) | |
616 assertEquals("a", key) | |
617 assertEquals(true, delete p["b"]) | |
618 assertEquals("b", key) | |
619 assertEquals(true, delete p[1]) | |
620 assertEquals("1", key) | |
621 | |
622 assertEquals(false, delete p.z1) | |
623 assertEquals("z1", key) | |
624 assertEquals(false, delete p["z2"]) | |
625 assertEquals("z2", key); | |
626 | |
627 (function() { | |
628 "use strict" | |
629 assertEquals(true, delete p.c) | |
630 assertEquals("c", key) | |
631 assertEquals(true, delete p["d"]) | |
632 assertEquals("d", key) | |
633 assertEquals(true, delete p[2]) | |
634 assertEquals("2", key) | |
635 | |
636 assertThrows(function(){ delete p.z3 }, TypeError) | |
637 assertEquals("z3", key) | |
638 assertThrows(function(){ delete p["z4"] }, TypeError) | |
639 assertEquals("z4", key) | |
640 })() | |
641 } | |
642 | |
643 TestDelete({ | |
644 deleteProperty(target, k) { key = k; return k < "z" } | |
645 }) | |
646 | |
647 TestDelete({ | |
648 deleteProperty(target, k) { return this.delete2(k) }, | |
649 delete2: function(k) { key = k; return k < "z" } | |
650 }) | |
651 | |
652 TestDelete(new Proxy({}, { | |
653 get(pt, pk, pr) { | |
654 return (target, k) => { key = k; return k < "z" } | |
655 } | |
656 })) | |
657 | |
658 | |
659 // --------------------------------------------------------------------------- | |
660 function TestDeleteThrow(handler) { | |
661 TestWithProxies(TestDeleteThrow2, handler) | |
662 } | |
663 | |
664 function TestDeleteThrow2(create, handler) { | |
665 var p = create(handler) | |
666 assertThrowsEquals(function(){ delete p.a }, "myexn") | |
667 assertThrowsEquals(function(){ delete p["b"] }, "myexn"); | |
668 assertThrowsEquals(function(){ delete p[3] }, "myexn"); | |
669 | |
670 (function() { | |
671 "use strict" | |
672 assertThrowsEquals(function(){ delete p.c }, "myexn") | |
673 assertThrowsEquals(function(){ delete p["d"] }, "myexn") | |
674 assertThrowsEquals(function(){ delete p[4] }, "myexn"); | |
675 })() | |
676 } | |
677 | |
678 TestDeleteThrow({ | |
679 deleteProperty(t, k) { throw "myexn" } | |
680 }) | |
681 | |
682 TestDeleteThrow({ | |
683 deleteProperty(t, k) { return this.delete2(k) }, | |
684 delete2(k) { throw "myexn" } | |
685 }) | |
686 | |
687 TestDeleteThrow(new Proxy({}, { | |
688 get(pt, pk, pr) { throw "myexn" } | |
689 })) | |
690 | |
691 TestDeleteThrow(new Proxy({}, { | |
692 get(pt, pk, pr) { | |
693 return (k) => { throw "myexn" } | |
694 } | |
695 })) | |
696 | |
697 | |
698 // --------------------------------------------------------------------------- | |
699 // Property descriptors (Object.getOwnPropertyDescriptor). | |
700 | |
701 function TestDescriptor(handler) { | |
702 TestWithProxies(TestDescriptor2, handler) | |
703 } | |
704 | |
705 function TestDescriptor2(create, handler) { | |
706 var p = create(handler) | |
707 var descs = [ | |
708 {configurable: true}, | |
709 {value: 34, enumerable: true, configurable: true}, | |
710 {value: 3, writable: false, mine: "eyes", configurable: true}, | |
711 {get value() { return 20 }, get configurable() { return true }}, | |
712 {get: function() { "get" }, set: function() { "set" }, configurable: true} | |
713 ] | |
714 for (var i = 0; i < descs.length; ++i) { | |
715 assertEquals(p, Object.defineProperty(p, i, descs[i])) | |
716 var desc = Object.getOwnPropertyDescriptor(p, i) | |
717 for (prop in descs[i]) { | |
718 // TODO(rossberg): Ignore user attributes as long as the spec isn't | |
719 // fixed suitably. | |
720 if (prop != "mine") assertEquals(descs[i][prop], desc[prop]) | |
721 } | |
722 assertEquals(undefined, Object.getOwnPropertyDescriptor(p, "absent")) | |
723 } | |
724 } | |
725 | |
726 TestDescriptor({ | |
727 defineProperty(t, k, d) { this["__" + k] = d; return true }, | |
728 getOwnPropertyDescriptor(t, k) { return this["__" + k] } | |
729 }) | |
730 | |
731 TestDescriptor({ | |
732 defineProperty(t, k, d) { this["__" + k] = d; return true }, | |
733 getOwnPropertyDescriptor(t, k) { | |
734 return this.getOwnPropertyDescriptor2(k) | |
735 }, | |
736 getOwnPropertyDescriptor2: function(k) { return this["__" + k] } | |
737 }) | |
738 | |
739 | |
740 // --------------------------------------------------------------------------- | |
741 function TestDescriptorThrow(handler) { | |
742 TestWithProxies(TestDescriptorThrow2, handler) | |
743 } | |
744 | |
745 function TestDescriptorThrow2(create, handler) { | |
746 var p = create(handler) | |
747 assertThrowsEquals(() => Object.getOwnPropertyDescriptor(p, "a"), "myexn") | |
748 } | |
749 | |
750 TestDescriptorThrow({ | |
751 getOwnPropertyDescriptor: function(k) { throw "myexn" } | |
752 }) | |
753 | |
754 TestDescriptorThrow({ | |
755 getOwnPropertyDescriptor: function(k) { | |
756 return this.getOwnPropertyDescriptor2(k) | |
757 }, | |
758 getOwnPropertyDescriptor2: function(k) { throw "myexn" } | |
759 }) | |
760 | |
761 | |
762 | |
763 // --------------------------------------------------------------------------- | |
764 // Comparison. | |
765 | |
766 function TestComparison(eq) { | |
767 TestWithProxies(TestComparison2, eq) | |
768 } | |
769 | |
770 function TestComparison2(create, eq) { | |
771 var p1 = create({}) | |
772 var p2 = create({}) | |
773 | |
774 assertTrue(eq(p1, p1)) | |
775 assertTrue(eq(p2, p2)) | |
776 assertTrue(!eq(p1, p2)) | |
777 assertTrue(!eq(p1, {})) | |
778 assertTrue(!eq({}, p2)) | |
779 assertTrue(!eq({}, {})) | |
780 } | |
781 | |
782 TestComparison(function(o1, o2) { return o1 == o2 }) | |
783 TestComparison(function(o1, o2) { return o1 === o2 }) | |
784 TestComparison(function(o1, o2) { return !(o1 != o2) }) | |
785 TestComparison(function(o1, o2) { return !(o1 !== o2) }) | |
786 | |
787 | |
788 | |
789 // Type (typeof). | |
790 | |
791 function TestTypeof() { | |
792 assertEquals("object", typeof new Proxy({},{})) | |
793 assertTrue(typeof new Proxy({}, {}) == "object") | |
794 assertTrue("object" == typeof new Proxy({},{})) | |
795 | |
796 assertEquals("function", typeof new Proxy(function() {}, {})) | |
797 assertTrue(typeof new Proxy(function() {}, {}) == "function") | |
798 assertTrue("function" == typeof new Proxy(function() {},{})) | |
799 } | |
800 | |
801 TestTypeof() | |
802 | |
803 | |
804 | |
805 // --------------------------------------------------------------------------- | |
806 // Membership test (in). | |
807 | |
808 var key | |
809 | |
810 function TestIn(handler) { | |
811 TestWithProxies(TestIn2, handler) | |
812 } | |
813 | |
814 function TestIn2(create, handler) { | |
815 var p = create(handler) | |
816 assertTrue("a" in p) | |
817 assertEquals("a", key) | |
818 assertTrue(99 in p) | |
819 assertEquals("99", key) | |
820 assertFalse("z" in p) | |
821 assertEquals("z", key) | |
822 | |
823 assertEquals(2, ("a" in p) ? 2 : 0) | |
824 assertEquals(0, !("a" in p) ? 2 : 0) | |
825 assertEquals(0, ("zzz" in p) ? 2 : 0) | |
826 assertEquals(2, !("zzz" in p) ? 2 : 0) | |
827 | |
828 // Test compilation in conditionals. | |
829 if ("b" in p) { | |
830 } else { | |
831 assertTrue(false) | |
832 } | |
833 assertEquals("b", key) | |
834 | |
835 if ("zz" in p) { | |
836 assertTrue(false) | |
837 } | |
838 assertEquals("zz", key) | |
839 | |
840 if (!("c" in p)) { | |
841 assertTrue(false) | |
842 } | |
843 assertEquals("c", key) | |
844 | |
845 if (!("zzz" in p)) { | |
846 } else { | |
847 assertTrue(false) | |
848 } | |
849 assertEquals("zzz", key) | |
850 } | |
851 | |
852 TestIn({ | |
853 has(t, k) { key = k; return k < "z" } | |
854 }) | |
855 | |
856 TestIn({ | |
857 has(t, k) { return this.has2(k) }, | |
858 has2(k) { key = k; return k < "z" } | |
859 }) | |
860 | |
861 TestIn(new Proxy({},{ | |
862 get(pt, pk, pr) { | |
863 return (t, k) => { key = k; return k < "z" } | |
864 } | |
865 })) | |
866 | |
867 | |
868 // --------------------------------------------------------------------------- | |
869 function TestInThrow(handler) { | |
870 TestWithProxies(TestInThrow2, handler) | |
871 } | |
872 | |
873 function TestInThrow2(create, handler) { | |
874 var p = create(handler) | |
875 assertThrowsEquals(function(){ return "a" in p }, "myexn") | |
876 assertThrowsEquals(function(){ return 99 in p }, "myexn") | |
877 assertThrowsEquals(function(){ return !("a" in p) }, "myexn") | |
878 assertThrowsEquals(function(){ return ("a" in p) ? 2 : 3 }, "myexn") | |
879 assertThrowsEquals(function(){ if ("b" in p) {} }, "myexn") | |
880 assertThrowsEquals(function(){ if (!("b" in p)) {} }, "myexn") | |
881 assertThrowsEquals(function(){ if ("zzz" in p) {} }, "myexn") | |
882 } | |
883 | |
884 TestInThrow({ | |
885 has: function(k) { throw "myexn" } | |
886 }) | |
887 | |
888 TestInThrow({ | |
889 has: function(k) { return this.has2(k) }, | |
890 has2: function(k) { throw "myexn" } | |
891 }) | |
892 | |
893 TestInThrow(new Proxy({},{ | |
894 get: function(pr, pk) { throw "myexn" } | |
895 })) | |
896 | |
897 TestInThrow(new Proxy({},{ | |
898 get: function(pr, pk) { | |
899 return function(k) { throw "myexn" } | |
900 } | |
901 })) | |
902 | |
903 | |
904 | |
905 // --------------------------------------------------------------------------- | |
906 // Own Properties (Object.prototype.hasOwnProperty). | |
907 | |
908 var key | |
909 | |
910 function TestHasOwn(handler) { | |
911 TestWithProxies(TestHasOwn2, handler) | |
912 } | |
913 | |
914 function TestHasOwn2(create, handler) { | |
915 var p = create(handler) | |
916 assertTrue(Object.prototype.hasOwnProperty.call(p, "a")) | |
917 assertEquals("a", key) | |
918 assertTrue(Object.prototype.hasOwnProperty.call(p, 99)) | |
919 assertEquals("99", key) | |
920 assertFalse(Object.prototype.hasOwnProperty.call(p, "z")) | |
921 assertEquals("z", key) | |
922 } | |
923 | |
924 TestHasOwn({ | |
925 getOwnPropertyDescriptor(t, k) { | |
926 key = k; if (k < "z") return {configurable: true} | |
927 }, | |
928 has() { assertUnreachable() } | |
929 }) | |
930 | |
931 TestHasOwn({ | |
932 getOwnPropertyDescriptor(t, k) { return this.getOwnPropertyDescriptor2(k) }, | |
933 getOwnPropertyDescriptor2(k) { | |
934 key = k; if (k < "z") return {configurable: true} | |
935 } | |
936 }) | |
937 | |
938 | |
939 | |
940 // --------------------------------------------------------------------------- | |
941 function TestHasOwnThrow(handler) { | |
942 TestWithProxies(TestHasOwnThrow2, handler) | |
943 } | |
944 | |
945 function TestHasOwnThrow2(create, handler) { | |
946 var p = create(handler) | |
947 assertThrowsEquals(function(){ Object.prototype.hasOwnProperty.call(p, "a")}, | |
948 "myexn") | |
949 assertThrowsEquals(function(){ Object.prototype.hasOwnProperty.call(p, 99)}, | |
950 "myexn") | |
951 } | |
952 | |
953 TestHasOwnThrow({ | |
954 getOwnPropertyDescriptor(t, k) { throw "myexn" } | |
955 }) | |
956 | |
957 TestHasOwnThrow({ | |
958 getOwnPropertyDescriptor(t, k) { return this.getOwnPropertyDescriptor2(k) }, | |
959 getOwnPropertyDescriptor2(k) { throw "myexn" } | |
960 }); | |
961 | |
962 | |
963 // --------------------------------------------------------------------------- | |
964 // Instanceof (instanceof) | |
965 | |
966 (function TestProxyInstanceof() { | |
967 var o1 = {} | |
968 var p1 = new Proxy({}, {}) | |
969 var p2 = new Proxy(o1, {}) | |
970 var p3 = new Proxy(p2, {}) | |
971 var o2 = Object.create(p2) | |
972 | |
973 var f0 = function() {} | |
974 f0.prototype = o1 | |
975 var f1 = function() {} | |
976 f1.prototype = p1 | |
977 var f2 = function() {} | |
978 f2.prototype = p2 | |
979 var f3 = function() {} | |
980 f3.prototype = o2 | |
981 | |
982 assertTrue(o1 instanceof Object) | |
983 assertFalse(o1 instanceof f0) | |
984 assertFalse(o1 instanceof f1) | |
985 assertFalse(o1 instanceof f2) | |
986 assertFalse(o1 instanceof f3) | |
987 assertTrue(p1 instanceof Object) | |
988 assertFalse(p1 instanceof f0) | |
989 assertFalse(p1 instanceof f1) | |
990 assertFalse(p1 instanceof f2) | |
991 assertFalse(p1 instanceof f3) | |
992 assertTrue(p2 instanceof Object) | |
993 assertFalse(p2 instanceof f0) | |
994 assertFalse(p2 instanceof f1) | |
995 assertFalse(p2 instanceof f2) | |
996 assertFalse(p2 instanceof f3) | |
997 assertTrue(p3 instanceof Object) | |
998 assertFalse(p3 instanceof f0) | |
999 assertFalse(p3 instanceof f1) | |
1000 assertFalse(p3 instanceof f2) | |
1001 assertFalse(p3 instanceof f3) | |
1002 assertTrue(o2 instanceof Object) | |
1003 assertFalse(o2 instanceof f0) | |
1004 assertFalse(o2 instanceof f1) | |
1005 assertTrue(o2 instanceof f2) | |
1006 assertFalse(o2 instanceof f3) | |
1007 | |
1008 var f = new Proxy(function() {}, {}) | |
1009 assertTrue(f instanceof Function) | |
1010 })(); | |
1011 | |
1012 | |
1013 (function TestInstanceofProxy() { | |
1014 var o0 = Object.create(null) | |
1015 var o1 = {} | |
1016 var o2 = Object.create(o0) | |
1017 var o3 = Object.create(o1) | |
1018 var o4 = Object.create(o2) | |
1019 var o5 = Object.create(o3) | |
1020 | |
1021 function handler(o) { | |
1022 return { | |
1023 get: function(r, p) { | |
1024 // We want to test prototype lookup, so ensure the proxy | |
1025 // offers OrdinaryHasInstance behavior. | |
1026 if (p === Symbol.hasInstance) { | |
1027 return undefined; | |
1028 } | |
1029 return o; | |
1030 } | |
1031 } | |
1032 } | |
1033 | |
1034 var f0 = new Proxy(function() {}, handler(o0)) | |
1035 var f1 = new Proxy(function() {}, handler(o1)) | |
1036 var f2 = new Proxy(function() {}, handler(o2)) | |
1037 var f3 = new Proxy(function() {}, handler(o3)) | |
1038 var f4 = new Proxy(function() {}, handler(o4)) | |
1039 var f5 = new Proxy(function() {}, handler(o4)) | |
1040 | |
1041 assertFalse(null instanceof f0) | |
1042 assertFalse(o0 instanceof f0) | |
1043 assertFalse(o0 instanceof f1) | |
1044 assertFalse(o0 instanceof f2) | |
1045 assertFalse(o0 instanceof f3) | |
1046 assertFalse(o0 instanceof f4) | |
1047 assertFalse(o0 instanceof f5) | |
1048 assertFalse(o1 instanceof f0) | |
1049 assertFalse(o1 instanceof f1) | |
1050 assertFalse(o1 instanceof f2) | |
1051 assertFalse(o1 instanceof f3) | |
1052 assertFalse(o1 instanceof f4) | |
1053 assertFalse(o1 instanceof f5) | |
1054 assertTrue(o2 instanceof f0) | |
1055 assertFalse(o2 instanceof f1) | |
1056 assertFalse(o2 instanceof f2) | |
1057 assertFalse(o2 instanceof f3) | |
1058 assertFalse(o2 instanceof f4) | |
1059 assertFalse(o2 instanceof f5) | |
1060 assertFalse(o3 instanceof f0) | |
1061 assertTrue(o3 instanceof f1) | |
1062 assertFalse(o3 instanceof f2) | |
1063 assertFalse(o3 instanceof f3) | |
1064 assertFalse(o3 instanceof f4) | |
1065 assertFalse(o3 instanceof f5) | |
1066 assertTrue(o4 instanceof f0) | |
1067 assertFalse(o4 instanceof f1) | |
1068 assertTrue(o4 instanceof f2) | |
1069 assertFalse(o4 instanceof f3) | |
1070 assertFalse(o4 instanceof f4) | |
1071 assertFalse(o4 instanceof f5) | |
1072 assertFalse(o5 instanceof f0) | |
1073 assertTrue(o5 instanceof f1) | |
1074 assertFalse(o5 instanceof f2) | |
1075 assertTrue(o5 instanceof f3) | |
1076 assertFalse(o5 instanceof f4) | |
1077 assertFalse(o5 instanceof f5) | |
1078 | |
1079 var f = new Proxy(function() {}, {}) | |
1080 var ff = new Proxy(function() {}, handler(Function)) | |
1081 assertTrue(f instanceof Function) | |
1082 assertFalse(f instanceof ff) | |
1083 })(); | |
1084 | |
1085 | |
1086 // --------------------------------------------------------------------------- | |
1087 // Prototype (Object.getPrototypeOf, Object.prototype.isPrototypeOf). | |
1088 | |
1089 (function TestPrototype() { | |
1090 var o1 = {} | |
1091 var p1 = new Proxy({}, {}) | |
1092 var p2 = new Proxy(o1, {}) | |
1093 var p3 = new Proxy(p2, {}) | |
1094 var o2 = Object.create(p3) | |
1095 | |
1096 assertSame(Object.getPrototypeOf(o1), Object.prototype) | |
1097 assertSame(Object.getPrototypeOf(p1), Object.prototype) | |
1098 assertSame(Object.getPrototypeOf(p2), Object.prototype) | |
1099 assertSame(Object.getPrototypeOf(p3), Object.prototype) | |
1100 assertSame(Object.getPrototypeOf(o2), p3) | |
1101 | |
1102 assertTrue(Object.prototype.isPrototypeOf(o1)) | |
1103 assertTrue(Object.prototype.isPrototypeOf(p1)) | |
1104 assertTrue(Object.prototype.isPrototypeOf(p2)) | |
1105 assertTrue(Object.prototype.isPrototypeOf(p3)) | |
1106 assertTrue(Object.prototype.isPrototypeOf(o2)) | |
1107 assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, o1)) | |
1108 assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, p1)) | |
1109 assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, p2)) | |
1110 assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, p3)) | |
1111 assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, o2)) | |
1112 assertFalse(Object.prototype.isPrototypeOf.call(o1, o1)) | |
1113 assertFalse(Object.prototype.isPrototypeOf.call(o1, p1)) | |
1114 assertFalse(Object.prototype.isPrototypeOf.call(o1, p2)) | |
1115 assertFalse(Object.prototype.isPrototypeOf.call(o1, p3)) | |
1116 assertFalse(Object.prototype.isPrototypeOf.call(o1, o2)) | |
1117 assertFalse(Object.prototype.isPrototypeOf.call(p1, p1)) | |
1118 assertFalse(Object.prototype.isPrototypeOf.call(p1, o1)) | |
1119 assertFalse(Object.prototype.isPrototypeOf.call(p1, p2)) | |
1120 assertFalse(Object.prototype.isPrototypeOf.call(p1, p3)) | |
1121 assertFalse(Object.prototype.isPrototypeOf.call(p1, o2)) | |
1122 assertFalse(Object.prototype.isPrototypeOf.call(p2, p1)) | |
1123 assertFalse(Object.prototype.isPrototypeOf.call(p2, p2)) | |
1124 assertFalse(Object.prototype.isPrototypeOf.call(p2, p3)) | |
1125 assertFalse(Object.prototype.isPrototypeOf.call(p2, o2)) | |
1126 assertFalse(Object.prototype.isPrototypeOf.call(p3, p2)) | |
1127 assertTrue(Object.prototype.isPrototypeOf.call(p3, o2)) | |
1128 assertFalse(Object.prototype.isPrototypeOf.call(o2, o1)) | |
1129 assertFalse(Object.prototype.isPrototypeOf.call(o2, p1)) | |
1130 assertFalse(Object.prototype.isPrototypeOf.call(o2, p2)) | |
1131 assertFalse(Object.prototype.isPrototypeOf.call(o2, p3)) | |
1132 assertFalse(Object.prototype.isPrototypeOf.call(o2, o2)) | |
1133 | |
1134 var f = new Proxy(function() {}, {}) | |
1135 assertSame(Object.getPrototypeOf(f), Function.prototype) | |
1136 assertTrue(Object.prototype.isPrototypeOf(f)) | |
1137 assertTrue(Object.prototype.isPrototypeOf.call(Function.prototype, f)) | |
1138 })(); | |
1139 | |
1140 | |
1141 // --------------------------------------------------------------------------- | |
1142 function TestPropertyNamesThrow(handler) { | |
1143 TestWithProxies(TestPropertyNamesThrow2, handler) | |
1144 } | |
1145 | |
1146 function TestPropertyNamesThrow2(create, handler) { | |
1147 var p = create(handler) | |
1148 assertThrowsEquals(function(){ Object.getOwnPropertyNames(p) }, "myexn") | |
1149 } | |
1150 | |
1151 TestPropertyNamesThrow({ | |
1152 ownKeys() { throw "myexn" } | |
1153 }) | |
1154 | |
1155 TestPropertyNamesThrow({ | |
1156 ownKeys() { return this.getOwnPropertyNames2() }, | |
1157 getOwnPropertyNames2() { throw "myexn" } | |
1158 }) | |
1159 | |
1160 // --------------------------------------------------------------------------- | |
1161 | |
1162 function TestKeys(names, handler) { | |
1163 var p = new Proxy({}, handler); | |
1164 assertArrayEquals(names, Object.keys(p)) | |
1165 } | |
1166 | |
1167 TestKeys([], { | |
1168 ownKeys() { return [] } | |
1169 }) | |
1170 | |
1171 TestKeys([], { | |
1172 ownKeys() { return ["a", "zz", " ", "0", "toString"] } | |
1173 }) | |
1174 | |
1175 TestKeys(["a", "zz", " ", "0", "toString"], { | |
1176 ownKeys() { return ["a", "zz", " ", "0", "toString"] }, | |
1177 getOwnPropertyDescriptor(t, p) { | |
1178 return {configurable: true, enumerable: true} | |
1179 } | |
1180 }) | |
1181 | |
1182 TestKeys([], { | |
1183 ownKeys() { return this.keys2() }, | |
1184 keys2() { return ["throw", "function "] } | |
1185 }) | |
1186 | |
1187 TestKeys(["throw", "function "], { | |
1188 ownKeys() { return this.keys2() }, | |
1189 keys2() { return ["throw", "function "] }, | |
1190 getOwnPropertyDescriptor(t, p) { | |
1191 return {configurable: true, enumerable: true} | |
1192 } | |
1193 }) | |
1194 | |
1195 TestKeys(["a", "0"], { | |
1196 ownKeys() { return ["a", "23", "zz", "", "0"] }, | |
1197 getOwnPropertyDescriptor(t, k) { | |
1198 return k == "" ? | |
1199 undefined : | |
1200 { configurable: true, enumerable: k.length == 1} | |
1201 } | |
1202 }) | |
1203 | |
1204 TestKeys(["23", "zz", ""], { | |
1205 ownKeys() { return this.getOwnPropertyNames2() }, | |
1206 getOwnPropertyNames2() { return ["a", "23", "zz", "", "0"] }, | |
1207 getOwnPropertyDescriptor(t, k) { | |
1208 return this.getOwnPropertyDescriptor2(k) | |
1209 }, | |
1210 getOwnPropertyDescriptor2(k) { | |
1211 return {configurable: true, enumerable: k.length != 1 } | |
1212 } | |
1213 }) | |
1214 | |
1215 TestKeys([], { | |
1216 get ownKeys() { | |
1217 return function() { return ["a", "b", "c"] } | |
1218 }, | |
1219 getOwnPropertyDescriptor: function(k) { return {configurable: true} } | |
1220 }) | |
1221 | |
1222 | |
1223 // --------------------------------------------------------------------------- | |
1224 function TestKeysThrow(handler) { | |
1225 TestWithProxies(TestKeysThrow2, handler) | |
1226 } | |
1227 | |
1228 function TestKeysThrow2(create, handler) { | |
1229 var p = create(handler); | |
1230 assertThrowsEquals(function(){ Object.keys(p) }, "myexn"); | |
1231 } | |
1232 | |
1233 TestKeysThrow({ | |
1234 ownKeys() { throw "myexn" } | |
1235 }) | |
1236 | |
1237 TestKeysThrow({ | |
1238 ownKeys() { return this.keys2() }, | |
1239 keys2() { throw "myexn" } | |
1240 }) | |
1241 | |
1242 TestKeysThrow({ | |
1243 ownKeys() { return ['1'] }, | |
1244 getOwnPropertyDescriptor: function() { throw "myexn" }, | |
1245 }) | |
1246 | |
1247 TestKeysThrow({ | |
1248 ownKeys() { return this.getOwnPropertyNames2() }, | |
1249 getOwnPropertyNames2() { return ['1', '2'] }, | |
1250 getOwnPropertyDescriptor(k) { | |
1251 return this.getOwnPropertyDescriptor2(k) | |
1252 }, | |
1253 getOwnPropertyDescriptor2(k) { throw "myexn" } | |
1254 }) | |
1255 | |
1256 TestKeysThrow({ | |
1257 get ownKeys() { throw "myexn" } | |
1258 }) | |
1259 | |
1260 TestKeysThrow({ | |
1261 get ownKeys() { | |
1262 return function() { throw "myexn" } | |
1263 }, | |
1264 }) | |
1265 | |
1266 TestKeysThrow({ | |
1267 get ownKeys() { | |
1268 return function() { return ['1', '2'] } | |
1269 }, | |
1270 getOwnPropertyDescriptor(k) { throw "myexn" } | |
1271 }) | |
1272 | |
1273 | |
1274 | |
1275 // --------------------------------------------------------------------------- | |
1276 // String conversion (Object.prototype.toString, | |
1277 // Object.prototype.toLocaleString, | |
1278 // Function.prototype.toString) | |
1279 | |
1280 var key | |
1281 | |
1282 function TestToString(handler) { | |
1283 var p = new Proxy({}, handler) | |
1284 key = "" | |
1285 assertEquals("[object Object]", Object.prototype.toString.call(p)) | |
1286 assertEquals(Symbol.toStringTag, key) | |
1287 assertEquals("my_proxy", Object.prototype.toLocaleString.call(p)) | |
1288 assertEquals("toString", key) | |
1289 | |
1290 var f = new Proxy(function() {}, handler) | |
1291 key = "" | |
1292 assertEquals("[object Function]", Object.prototype.toString.call(f)) | |
1293 assertEquals(Symbol.toStringTag, key) | |
1294 assertEquals("my_proxy", Object.prototype.toLocaleString.call(f)) | |
1295 assertEquals("toString", key) | |
1296 assertThrows(function(){ Function.prototype.toString.call(f) }) | |
1297 | |
1298 var o = Object.create(p) | |
1299 key = "" | |
1300 assertEquals("[object Object]", Object.prototype.toString.call(o)) | |
1301 assertEquals(Symbol.toStringTag, key) | |
1302 assertEquals("my_proxy", Object.prototype.toLocaleString.call(o)) | |
1303 assertEquals("toString", key) | |
1304 } | |
1305 | |
1306 TestToString({ | |
1307 get: function(r, k) { key = k; return function() { return "my_proxy" } } | |
1308 }) | |
1309 | |
1310 TestToString({ | |
1311 get: function(r, k) { return this.get2(r, k) }, | |
1312 get2: function(r, k) { key = k; return function() { return "my_proxy" } } | |
1313 }) | |
1314 | |
1315 TestToString(new Proxy({}, { | |
1316 get: function(pr, pk) { | |
1317 return function(r, k) { key = k; return function() { return "my_proxy" } } | |
1318 } | |
1319 })) | |
1320 | |
1321 | |
1322 function TestToStringThrow(handler) { | |
1323 var p = new Proxy({}, handler) | |
1324 assertThrowsEquals(() => Object.prototype.toString.call(p), "myexn") | |
1325 assertThrowsEquals(() => Object.prototype.toLocaleString.call(p), "myexn") | |
1326 | |
1327 var f = new Proxy(function(){}, handler) | |
1328 assertThrowsEquals(() => Object.prototype.toString.call(f), "myexn") | |
1329 assertThrowsEquals(() => Object.prototype.toLocaleString.call(f), "myexn") | |
1330 | |
1331 var o = Object.create(p) | |
1332 assertThrowsEquals(() => Object.prototype.toString.call(o), "myexn") | |
1333 assertThrowsEquals(() => Object.prototype.toLocaleString.call(o), "myexn") | |
1334 } | |
1335 | |
1336 TestToStringThrow({ | |
1337 get: function(r, k) { throw "myexn" } | |
1338 }) | |
1339 | |
1340 TestToStringThrow({ | |
1341 get: function(r, k) { return this.get2(r, k) }, | |
1342 get2: function(r, k) { throw "myexn" } | |
1343 }) | |
1344 | |
1345 TestToStringThrow(new Proxy({}, { | |
1346 get: function(pr, pk) { throw "myexn" } | |
1347 })) | |
1348 | |
1349 TestToStringThrow(new Proxy({}, { | |
1350 get: function(pr, pk) { | |
1351 return function(r, k) { throw "myexn" } | |
1352 } | |
1353 })) | |
1354 | |
1355 | |
1356 // --------------------------------------------------------------------------- | |
1357 // Value conversion (Object.prototype.toValue) | |
1358 | |
1359 function TestValueOf(handler) { | |
1360 TestWithProxies(TestValueOf2, handler) | |
1361 } | |
1362 | |
1363 function TestValueOf2(create, handler) { | |
1364 var p = create(handler) | |
1365 assertSame(p, Object.prototype.valueOf.call(p)) | |
1366 } | |
1367 | |
1368 TestValueOf({}) | |
1369 | |
1370 | |
1371 | |
1372 // --------------------------------------------------------------------------- | |
1373 // Enumerability (Object.prototype.propertyIsEnumerable) | |
1374 | |
1375 var key | |
1376 | |
1377 function TestIsEnumerable(handler) { | |
1378 TestWithProxies(TestIsEnumerable2, handler) | |
1379 } | |
1380 | |
1381 function TestIsEnumerable2(create, handler) { | |
1382 var p = create(handler) | |
1383 assertTrue(Object.prototype.propertyIsEnumerable.call(p, "a")) | |
1384 assertEquals("a", key) | |
1385 assertTrue(Object.prototype.propertyIsEnumerable.call(p, 2)) | |
1386 assertEquals("2", key) | |
1387 assertFalse(Object.prototype.propertyIsEnumerable.call(p, "z")) | |
1388 assertEquals("z", key) | |
1389 | |
1390 var o = Object.create(p) | |
1391 key = "" | |
1392 assertFalse(Object.prototype.propertyIsEnumerable.call(o, "a")) | |
1393 assertEquals("", key) // trap not invoked | |
1394 } | |
1395 | |
1396 TestIsEnumerable({ | |
1397 getOwnPropertyDescriptor(t, k) { | |
1398 key = k; | |
1399 return {enumerable: k < "z", configurable: true} | |
1400 }, | |
1401 }) | |
1402 | |
1403 TestIsEnumerable({ | |
1404 getOwnPropertyDescriptor: function(t, k) { | |
1405 return this.getOwnPropertyDescriptor2(k) | |
1406 }, | |
1407 getOwnPropertyDescriptor2: function(k) { | |
1408 key = k; | |
1409 return {enumerable: k < "z", configurable: true} | |
1410 }, | |
1411 }) | |
1412 | |
1413 TestIsEnumerable({ | |
1414 getOwnPropertyDescriptor: function(t, k) { | |
1415 key = k; | |
1416 return {get enumerable() { return k < "z" }, configurable: true} | |
1417 }, | |
1418 }) | |
1419 | |
1420 TestIsEnumerable(new Proxy({}, { | |
1421 get: function(pt, pk, pr) { | |
1422 return function(t, k) { | |
1423 key = k; | |
1424 return {enumerable: k < "z", configurable: true} | |
1425 } | |
1426 } | |
1427 })) | |
1428 | |
1429 | |
1430 // --------------------------------------------------------------------------- | |
1431 function TestIsEnumerableThrow(handler) { | |
1432 TestWithProxies(TestIsEnumerableThrow2, handler) | |
1433 } | |
1434 | |
1435 function TestIsEnumerableThrow2(create, handler) { | |
1436 var p = create(handler) | |
1437 assertThrowsEquals(() => Object.prototype.propertyIsEnumerable.call(p, "a"), | |
1438 "myexn") | |
1439 assertThrowsEquals(() => Object.prototype.propertyIsEnumerable.call(p, 11), | |
1440 "myexn") | |
1441 } | |
1442 | |
1443 TestIsEnumerableThrow({ | |
1444 getOwnPropertyDescriptor: function(k) { throw "myexn" } | |
1445 }) | |
1446 | |
1447 TestIsEnumerableThrow({ | |
1448 getOwnPropertyDescriptor: function(k) { | |
1449 return this.getOwnPropertyDescriptor2(k) | |
1450 }, | |
1451 getOwnPropertyDescriptor2: function(k) { throw "myexn" } | |
1452 }) | |
1453 | |
1454 TestIsEnumerableThrow({ | |
1455 getOwnPropertyDescriptor: function(k) { | |
1456 return {get enumerable() { throw "myexn" }, configurable: true} | |
1457 }, | |
1458 }) | |
1459 | |
1460 TestIsEnumerableThrow(new Proxy({}, { | |
1461 get: function(pr, pk) { throw "myexn" } | |
1462 })) | |
1463 | |
1464 TestIsEnumerableThrow(new Proxy({}, { | |
1465 get: function(pr, pk) { | |
1466 return function(k) { throw "myexn" } | |
1467 } | |
1468 })); | |
1469 | |
1470 | |
1471 | |
1472 // --------------------------------------------------------------------------- | |
1473 // Constructor functions with proxy prototypes. | |
1474 | |
1475 (function TestConstructorWithProxyPrototype() { | |
1476 TestWithProxies(TestConstructorWithProxyPrototype2, {}) | |
1477 })(); | |
1478 | |
1479 function TestConstructorWithProxyPrototype2(create, handler) { | |
1480 function C() {}; | |
1481 C.prototype = create(handler); | |
1482 | |
1483 var o = new C; | |
1484 assertSame(C.prototype, Object.getPrototypeOf(o)); | |
1485 }; | |
1486 | |
1487 | |
1488 (function TestOptWithProxyPrototype() { | |
1489 var handler = { | |
1490 get(t, k) { | |
1491 return 10; | |
1492 } | |
1493 }; | |
1494 | |
1495 function C() {}; | |
1496 C.prototype = new Proxy({}, handler); | |
1497 var o = new C(); | |
1498 | |
1499 function f() { | |
1500 return o.x; | |
1501 } | |
1502 assertEquals(10, f()); | |
1503 assertEquals(10, f()); | |
1504 %OptimizeFunctionOnNextCall(f); | |
1505 assertEquals(10, f()); | |
1506 })(); | |
OLD | NEW |