mirror of
				https://github.com/tc39/test262.git
				synced 2025-10-31 03:34:08 +01:00 
			
		
		
		
	sourceRevisionAtLastExport: 33f2fb0e53d135f0ee17cfccd9d993eb2a6f47de targetRevisionAtLastExport: 31340cbd9add103f586d501b0c3354b7b182abc0
		
			
				
	
	
		
			409 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			409 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| // Copyright 2015 the V8 project authors. All rights reserved.
 | |
| // Use of this source code is governed by a BSD-style license that can be
 | |
| // found in the LICENSE file.
 | |
| 
 | |
| 
 | |
| function sloppyDefaultSet(o, p, v) { return o[p] = v }
 | |
| function sloppyReflectSet(o, p, v) { return Reflect.set(o, p, v) }
 | |
| function strictDefaultSet(o, p, v) { "use strict"; return o[p] = v }
 | |
| function strictReflectSet(o, p, v) { "use strict"; return Reflect.set(o, p, v) }
 | |
| 
 | |
| sloppyDefaultSet.shouldThrow = false;
 | |
| sloppyReflectSet.shouldThrow = false;
 | |
| strictDefaultSet.shouldThrow = true;
 | |
| strictReflectSet.shouldThrow = false;
 | |
| 
 | |
| sloppyDefaultSet.returnsBool = false;
 | |
| sloppyReflectSet.returnsBool = true;
 | |
| strictDefaultSet.returnsBool = false;
 | |
| strictReflectSet.returnsBool = true;
 | |
| 
 | |
| 
 | |
| function assertTrueIf(flag, x) { if (flag) assertTrue(x) }
 | |
| function assertFalseIf(flag, x) { if (flag) assertFalse(x) }
 | |
| function assertSetFails(mySet, o, p, v) {
 | |
|   if (mySet.shouldThrow) {
 | |
|     assertThrows(() => mySet(o, p, v), TypeError);
 | |
|   } else {
 | |
|     assertFalseIf(mySet.returnsBool, mySet(o, p, v));
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| function dataDescriptor(x) {
 | |
|   return {value: x, writable: true, enumerable: true, configurable: true};
 | |
| }
 | |
| 
 | |
| 
 | |
| function toKey(x) {
 | |
|   if (typeof x === "symbol") return x;
 | |
|   return String(x);
 | |
| }
 | |
| 
 | |
| 
 | |
| var properties =
 | |
|     ["bla", "0", 1, Symbol(), {[Symbol.toPrimitive]() {return "a"}}];
 | |
| 
 | |
| 
 | |
| function TestForwarding(handler, mySet) {
 | |
|   assertTrue(undefined == handler.set);
 | |
|   assertTrue(undefined == handler.getOwnPropertyDescriptor);
 | |
|   assertTrue(undefined == handler.defineProperty);
 | |
| 
 | |
|   var target = {};
 | |
|   var proxy = new Proxy(target, handler);
 | |
| 
 | |
|   // Property does not exist on target.
 | |
|   for (var p of properties) {
 | |
|     assertTrueIf(mySet.returnsBool, mySet(proxy, p, 42));
 | |
|     assertSame(42, target[p]);
 | |
|   }
 | |
| 
 | |
|   // Property exists as writable data on target.
 | |
|   for (var p of properties) {
 | |
|     assertTrueIf(mySet.returnsBool, mySet(proxy, p, 0));
 | |
|     assertSame(0, target[p]);
 | |
|   }
 | |
| 
 | |
|   // Property exists as non-writable data on target.
 | |
|   for (var p of properties) {
 | |
|     Object.defineProperty(target, p,
 | |
|         {value: 42, configurable: true, writable: false});
 | |
|     assertSetFails(mySet, proxy, p, 42);
 | |
|     assertSetFails(mySet, proxy, p, 0);
 | |
|     assertEquals(42, target[p]);
 | |
|   }
 | |
| };
 | |
| 
 | |
| (function () {
 | |
|   // No trap.
 | |
|   var handler = {};
 | |
|   TestForwarding(handler, sloppyDefaultSet);
 | |
|   TestForwarding(handler, sloppyReflectSet);
 | |
|   TestForwarding(handler, strictDefaultSet);
 | |
|   TestForwarding(handler, strictReflectSet);
 | |
| })();
 | |
| 
 | |
| (function () {
 | |
|   // "Undefined" trap.
 | |
|   var handler = { set: null };
 | |
|   TestForwarding(handler, sloppyDefaultSet);
 | |
|   TestForwarding(handler, sloppyReflectSet);
 | |
|   TestForwarding(handler, strictDefaultSet);
 | |
|   TestForwarding(handler, strictReflectSet);
 | |
| })();
 | |
| 
 | |
| 
 | |
| function TestForwarding2(mySet) {
 | |
|   // Check that setting on a proxy without "set" trap correctly triggers its
 | |
|   // "getOwnProperty" trap and its "defineProperty" trap.
 | |
| 
 | |
|   var target = {};
 | |
|   var handler = {};
 | |
|   var observations = [];
 | |
|   var proxy = new Proxy(target, handler);
 | |
| 
 | |
|   handler.getOwnPropertyDescriptor = function() {
 | |
|       observations.push(arguments);
 | |
|       return Reflect.getOwnPropertyDescriptor(...arguments);
 | |
|   }
 | |
| 
 | |
|   handler.defineProperty = function() {
 | |
|       observations.push(arguments);
 | |
|       return Reflect.defineProperty(...arguments);
 | |
|   }
 | |
| 
 | |
|   for (var p of properties) {
 | |
|     mySet(proxy, p, 42);
 | |
|     assertEquals(2, observations.length)
 | |
|     assertArrayEquals([target, toKey(p)], observations[0]);
 | |
|     assertSame(target, observations[0][0]);
 | |
|     assertArrayEquals([target, toKey(p), dataDescriptor(42)], observations[1]);
 | |
|     assertSame(target, observations[1][0]);
 | |
|     observations = [];
 | |
| 
 | |
|     mySet(proxy, p, 42);
 | |
|     assertEquals(2, observations.length)
 | |
|     assertArrayEquals([target, toKey(p)], observations[0]);
 | |
|     assertSame(target, observations[0][0]);
 | |
|     assertArrayEquals([target, toKey(p), {value: 42}], observations[1]);
 | |
|     assertSame(target, observations[1][0]);
 | |
|     observations = [];
 | |
|   }
 | |
| }
 | |
| 
 | |
| TestForwarding2(sloppyDefaultSet);
 | |
| TestForwarding2(sloppyReflectSet);
 | |
| TestForwarding2(strictDefaultSet);
 | |
| TestForwarding2(strictReflectSet);
 | |
| 
 | |
| 
 | |
| function TestInvalidTrap(proxy, mySet) {
 | |
|   for (var p of properties) {
 | |
|     assertThrows(() => mySet(proxy, p, 42), TypeError);
 | |
|   }
 | |
| }
 | |
| 
 | |
| (function () {
 | |
|   var target = {};
 | |
|   var handler = { set: true };
 | |
|   var proxy = new Proxy(target, handler);
 | |
| 
 | |
|   TestInvalidTrap(proxy, sloppyDefaultSet);
 | |
|   TestInvalidTrap(proxy, sloppyReflectSet);
 | |
|   TestInvalidTrap(proxy, strictDefaultSet);
 | |
|   TestInvalidTrap(proxy, strictReflectSet);
 | |
| })();
 | |
| 
 | |
| 
 | |
| function TestTrappingFalsish(mySet) {
 | |
|   var target = {};
 | |
|   var handler = { set() {return ""} };
 | |
|   var proxy = new Proxy(target, handler);
 | |
| 
 | |
|   for (var p of properties) {
 | |
|     assertSetFails(mySet, proxy, p, 42);
 | |
|   }
 | |
| }
 | |
| 
 | |
| TestTrappingFalsish(sloppyDefaultSet);
 | |
| TestTrappingFalsish(sloppyReflectSet);
 | |
| TestTrappingFalsish(strictDefaultSet);
 | |
| TestTrappingFalsish(strictReflectSet);
 | |
| 
 | |
| 
 | |
| function TestTrappingTrueish(mySet) {
 | |
|   var target = {};
 | |
|   var handler = { set() {return 42} };
 | |
|   var proxy = new Proxy(target, handler);
 | |
| 
 | |
|   // Trap returns trueish and property does not exist in target.
 | |
|   for (var p of properties) {
 | |
|     assertTrueIf(mySet.returnsBool, mySet(proxy, p, 0));
 | |
|   }
 | |
| 
 | |
|   // Trap returns trueish and target property is configurable or writable data.
 | |
|   for (var p of properties) {
 | |
|     Object.defineProperty(target, p, {configurable: true, writable: true});
 | |
|     assertTrueIf(mySet.returnsBool, mySet(proxy, p, 0));
 | |
|     Object.defineProperty(target, p, {configurable: true, writable: false});
 | |
|     assertTrueIf(mySet.returnsBool, mySet(proxy, p, 0));
 | |
|     Object.defineProperty(target, p, {configurable: false, writable: true});
 | |
|     assertTrueIf(mySet.returnsBool, mySet(proxy, p, 0));
 | |
|   }
 | |
| }
 | |
| 
 | |
| TestTrappingTrueish(sloppyDefaultSet);
 | |
| TestTrappingTrueish(sloppyReflectSet);
 | |
| TestTrappingTrueish(strictDefaultSet);
 | |
| TestTrappingTrueish(strictReflectSet);
 | |
| 
 | |
| 
 | |
| function TestTrappingTrueish2(mySet) {
 | |
|   var target = {};
 | |
|   var handler = { set() {return 42} };
 | |
|   var proxy = new Proxy(target, handler);
 | |
| 
 | |
|   // Trap returns trueish but target property is frozen data.
 | |
|   for (var p of properties) {
 | |
|     Object.defineProperty(target, p, {
 | |
|         configurable: false, writable: false, value: 0
 | |
|     });
 | |
|     assertThrows(() => mySet(proxy, p, 666), TypeError);  // New value.
 | |
|     assertTrueIf(mySet.returnsBool, mySet(proxy, p, 0));  // Old value.
 | |
|   }
 | |
| };
 | |
| 
 | |
| TestTrappingTrueish2(sloppyDefaultSet);
 | |
| TestTrappingTrueish2(sloppyReflectSet);
 | |
| TestTrappingTrueish2(strictDefaultSet);
 | |
| TestTrappingTrueish2(strictReflectSet);
 | |
| 
 | |
| 
 | |
| function TestTrappingTrueish3(mySet) {
 | |
|   var target = {};
 | |
|   var handler = { set() {return 42} };
 | |
|   var proxy = new Proxy(target, handler);
 | |
| 
 | |
|   // Trap returns trueish and target property is configurable accessor.
 | |
|   for (var p of properties) {
 | |
|     Object.defineProperty(target, p, { configurable: true, set: undefined });
 | |
|     assertTrueIf(mySet.returnsBool, mySet(proxy, p, 0));
 | |
|   }
 | |
| 
 | |
|   // Trap returns trueish and target property is non-configurable accessor.
 | |
|   for (var p of properties) {
 | |
|     Object.defineProperty(target, p, { configurable: false, set: undefined });
 | |
|     assertThrows(() => mySet(proxy, p, 0));
 | |
|   }
 | |
| };
 | |
| 
 | |
| TestTrappingTrueish3(sloppyDefaultSet);
 | |
| TestTrappingTrueish3(sloppyReflectSet);
 | |
| TestTrappingTrueish3(strictDefaultSet);
 | |
| TestTrappingTrueish3(strictReflectSet);
 | |
| 
 | |
| 
 | |
| function TestTrapReceiverArgument(mySet) {
 | |
|   var target = {};
 | |
|   var handler = {};
 | |
|   var observations = [];
 | |
|   var proxy = new Proxy(target, handler);
 | |
|   var object = Object.create(proxy);
 | |
| 
 | |
|   handler.set = function() {
 | |
|       observations.push(arguments);
 | |
|       return Reflect.set(...arguments);
 | |
|   }
 | |
| 
 | |
|   for (var p of properties) {
 | |
|     mySet(object, p, 42);
 | |
|     assertEquals(1, observations.length)
 | |
|     assertArrayEquals([target, toKey(p), 42, object], observations[0]);
 | |
|     assertSame(target, observations[0][0]);
 | |
|     assertSame(object, observations[0][3]);
 | |
|     observations = [];
 | |
|   }
 | |
| };
 | |
| 
 | |
| TestTrapReceiverArgument(sloppyDefaultSet);
 | |
| TestTrapReceiverArgument(sloppyReflectSet);
 | |
| TestTrapReceiverArgument(strictDefaultSet);
 | |
| TestTrapReceiverArgument(strictReflectSet);
 | |
| 
 | |
| 
 | |
| (function TestTrapReceiverArgument2() {
 | |
|   // Check that non-object receiver is passed through as well.
 | |
| 
 | |
|   var target = {};
 | |
|   var handler = {};
 | |
|   var observations = [];
 | |
|   var proxy = new Proxy(target, handler);
 | |
| 
 | |
|   handler.set = function() {
 | |
|       observations.push(arguments);
 | |
|       return Reflect.set(...arguments);
 | |
|   }
 | |
| 
 | |
|   for (var p of properties) {
 | |
|     for (var receiver of [null, undefined, 1]) {
 | |
|       Reflect.set(proxy, p, 42, receiver);
 | |
|       assertEquals(1, observations.length)
 | |
|       assertArrayEquals([target, toKey(p), 42, receiver], observations[0]);
 | |
|       assertSame(target, observations[0][0]);
 | |
|       assertSame(receiver, observations[0][3]);
 | |
|       observations = [];
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   var object = Object.create(proxy);
 | |
|   for (var p of properties) {
 | |
|     for (var receiver of [null, undefined, 1]) {
 | |
|       Reflect.set(object, p, 42, receiver);
 | |
|       assertEquals(1, observations.length);
 | |
|       assertArrayEquals([target, toKey(p), 42, receiver], observations[0]);
 | |
|       assertSame(target, observations[0][0]);
 | |
|       assertSame(receiver, observations[0][3]);
 | |
|       observations = [];
 | |
|     }
 | |
|   }
 | |
| })();
 | |
| 
 | |
| 
 | |
| function TestTargetProxy(mySet) {
 | |
|   var q = new Proxy({}, {});
 | |
|   var proxy = new Proxy(q, {
 | |
|     set: function(t, k, v) {
 | |
|       return Reflect.set(t, k, v);
 | |
|     }
 | |
|   });
 | |
| 
 | |
|   for (var p of properties) {
 | |
|     assertTrueIf(mySet.returnsBool, mySet(proxy, p, 42));
 | |
|     assertSame(42, q[p]);
 | |
|   }
 | |
| };
 | |
| 
 | |
| TestTargetProxy(sloppyDefaultSet);
 | |
| TestTargetProxy(sloppyReflectSet);
 | |
| TestTargetProxy(strictDefaultSet);
 | |
| TestTargetProxy(strictReflectSet);
 | |
| 
 | |
| 
 | |
| (function TestAccessorNoSet() {
 | |
|   var target = {
 | |
|   };
 | |
|   Object.defineProperty(target, 'prop', {
 | |
|     get: function() {
 | |
|       return 42;
 | |
|     },
 | |
|     configurable: false
 | |
|   })
 | |
|   var handler = {
 | |
|     set: function() { return true; }
 | |
|   }
 | |
|   var proxy = new Proxy(target, handler);
 | |
|   assertThrows(function() { proxy.prop = 0; }, TypeError);
 | |
| })();
 | |
| 
 | |
| (function TestProxyInPrototype() {
 | |
|   var handler = {
 | |
|     set: function(t, k, v) {
 | |
|       Reflect.set(t, k, v);
 | |
|     }
 | |
|   };
 | |
|   var obj = {};
 | |
|   var proxy = new Proxy(obj, handler);
 | |
|   var o = Object.create(proxy);
 | |
| 
 | |
|   for (var i = 0; i < 3; ++i) {
 | |
|     o.prop = 42 + i;
 | |
|     assertEquals(42 + i, obj.prop);
 | |
|   }
 | |
| })();
 | |
| 
 | |
| (function TestProxyInPrototypeNoTrap() {
 | |
|   var handler = {
 | |
|   };
 | |
|   var obj = {};
 | |
|   var proxy = new Proxy(obj, handler);
 | |
|   var o = Object.create(proxy);
 | |
| 
 | |
|   for (var i = 0; i < 3; ++i) {
 | |
|     o.prop = 42 + i;
 | |
|     assertEquals(42 + i, o.prop);
 | |
|     assertEquals(undefined, obj.prop);
 | |
|   }
 | |
| })();
 | |
| 
 | |
| // Note: this case is currently handled by runtime.
 | |
| (function TestDifferentHolder() {
 | |
|   var obj = {
 | |
|     '1337': 100
 | |
|   };
 | |
|   var handler = {
 | |
|     set(target, name, value, receiver) {
 | |
|       if (name != '1337') return Reflect.set(target, name, value, receiver);
 | |
| 
 | |
|       assertSame(target, obj);
 | |
|       assertSame(receiver, p);
 | |
|       return target[name] = value;
 | |
|     }
 | |
|   };
 | |
|   var p = new Proxy(obj, handler);
 | |
|   for (var i = 0; i < 3; ++i) {
 | |
|     assertEquals(42, p[1337] = 42);
 | |
|   }
 | |
| })();
 | |
| 
 | |
| (function test32BitIndex() {
 | |
|   var index = (1 << 31) + 1;
 | |
|   var obj = {};
 | |
|   obj[index] = 42;
 | |
|   var p = new Proxy(obj, {});
 | |
|   for (var i = 0; i < 3; ++i) {
 | |
|     p[index] = 100;
 | |
|     assertEquals(100, obj[index]);
 | |
|   }
 | |
| })();
 |