| Index: test/mjsunit/harmony/proxies-set.js
|
| diff --git a/test/mjsunit/harmony/proxies-set.js b/test/mjsunit/harmony/proxies-set.js
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..2fec115a103ea05d0a49fa350381e157f679487a
|
| --- /dev/null
|
| +++ b/test/mjsunit/harmony/proxies-set.js
|
| @@ -0,0 +1,312 @@
|
| +// 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.
|
| +
|
| +// Flags: --harmony-proxies --harmony-reflect
|
| +
|
| +
|
| +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 = [];
|
| + }
|
| + }
|
| +})();
|
|
|