summaryrefslogtreecommitdiffstats
path: root/js/src/tests/non262/Proxy
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
commit6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch)
treea68f146d7fa01f0134297619fbe7e33db084e0aa /js/src/tests/non262/Proxy
parentInitial commit. (diff)
downloadthunderbird-upstream.tar.xz
thunderbird-upstream.zip
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/tests/non262/Proxy')
-rw-r--r--js/src/tests/non262/Proxy/browser.js0
-rw-r--r--js/src/tests/non262/Proxy/define-writable-as-non-writable.js19
-rw-r--r--js/src/tests/non262/Proxy/delete-non-extensible.js18
-rw-r--r--js/src/tests/non262/Proxy/getPrototypeOf.js285
-rw-r--r--js/src/tests/non262/Proxy/global-receiver.js35
-rw-r--r--js/src/tests/non262/Proxy/hasInstance.js13
-rw-r--r--js/src/tests/non262/Proxy/json-stringify-replacer-array-revocable-proxy.js39
-rw-r--r--js/src/tests/non262/Proxy/ownkeys-allowed-types.js20
-rw-r--r--js/src/tests/non262/Proxy/ownkeys-linear.js70
-rw-r--r--js/src/tests/non262/Proxy/ownkeys-trap-duplicates.js33
-rw-r--r--js/src/tests/non262/Proxy/proxy-__proto__.js59
-rw-r--r--js/src/tests/non262/Proxy/proxy-constructNonObject.js18
-rw-r--r--js/src/tests/non262/Proxy/proxy-for-in.js37
-rw-r--r--js/src/tests/non262/Proxy/proxy-no-receiver-overwrite.js23
-rw-r--r--js/src/tests/non262/Proxy/proxy-proto-lazy-props.js61
-rw-r--r--js/src/tests/non262/Proxy/proxy-with-revoked-arguments.js53
-rw-r--r--js/src/tests/non262/Proxy/regress-bug1037770.js7
-rw-r--r--js/src/tests/non262/Proxy/regress-bug1062349.js31
-rw-r--r--js/src/tests/non262/Proxy/regress-bug950407.js7
-rw-r--r--js/src/tests/non262/Proxy/report-writable-as-non-writable.js20
-rw-r--r--js/src/tests/non262/Proxy/revocable-proxy-prototype.js40
-rw-r--r--js/src/tests/non262/Proxy/revoke-as-side-effect.js73
-rw-r--r--js/src/tests/non262/Proxy/revoke-no-name.js2
-rw-r--r--js/src/tests/non262/Proxy/revoked-get-function-realm-typeerror.js119
-rw-r--r--js/src/tests/non262/Proxy/setPrototypeOf.js258
-rw-r--r--js/src/tests/non262/Proxy/shell.js0
-rw-r--r--js/src/tests/non262/Proxy/trap-null.js103
27 files changed, 1443 insertions, 0 deletions
diff --git a/js/src/tests/non262/Proxy/browser.js b/js/src/tests/non262/Proxy/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/non262/Proxy/browser.js
diff --git a/js/src/tests/non262/Proxy/define-writable-as-non-writable.js b/js/src/tests/non262/Proxy/define-writable-as-non-writable.js
new file mode 100644
index 0000000000..f764d278f0
--- /dev/null
+++ b/js/src/tests/non262/Proxy/define-writable-as-non-writable.js
@@ -0,0 +1,19 @@
+"use strict";
+
+var target = {};
+Object.defineProperty(target, "test", {configurable: false, writable: true, value: 5});
+
+var proxy = new Proxy(target, {
+ defineProperty(target, property) {
+ assertEq(property, "test");
+ return true;
+ }
+});
+
+assertThrowsInstanceOf(
+ () => Object.defineProperty(proxy, "test", {writable: false}), TypeError);
+
+assertThrowsInstanceOf(
+ () => Reflect.defineProperty(proxy, "test", {writable: false}), TypeError);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Proxy/delete-non-extensible.js b/js/src/tests/non262/Proxy/delete-non-extensible.js
new file mode 100644
index 0000000000..b31216bb65
--- /dev/null
+++ b/js/src/tests/non262/Proxy/delete-non-extensible.js
@@ -0,0 +1,18 @@
+"use strict";
+
+var target = { test: true };
+Object.preventExtensions(target);
+
+var proxy = new Proxy(target, {
+ deleteProperty(target, property) {
+ return true;
+ }
+});
+
+assertEq(delete proxy.missing, true);
+assertEq(Reflect.deleteProperty(proxy, "missing"), true);
+
+assertThrowsInstanceOf(() => { delete proxy.test; }, TypeError);
+assertThrowsInstanceOf(() => Reflect.deleteProperty(proxy, "test"), TypeError);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Proxy/getPrototypeOf.js b/js/src/tests/non262/Proxy/getPrototypeOf.js
new file mode 100644
index 0000000000..a0676c0c91
--- /dev/null
+++ b/js/src/tests/non262/Proxy/getPrototypeOf.js
@@ -0,0 +1,285 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+
+var gTestfile = "getPrototypeOf.js";
+var BUGNUMBER = 888969;
+var summary = "Scripted proxies' [[GetPrototypeOf]] behavior";
+
+print(BUGNUMBER + ": " + summary);
+
+/**************
+ * BEGIN TEST *
+ **************/
+
+const log = [];
+
+function observe(obj)
+{
+ var observingHandler = new Proxy({}, {
+ get(target, p, receiver) {
+ log.push(p);
+ return Reflect.get(target, p, receiver);
+ }
+ });
+
+ return new Proxy(obj, observingHandler);
+}
+
+function nop() {}
+
+var p, h;
+
+// 1. Let handler be the value of the [[ProxyHandler]] internal slot of O.
+// 2. If handler is null, throw a TypeError exception.
+// 3. Assert: Type(handler) is Object.
+var rev = Proxy.revocable({}, {});
+p = rev.proxy;
+
+assertEq(Object.getPrototypeOf(p), Object.prototype);
+rev.revoke();
+assertThrowsInstanceOf(() => Object.getPrototypeOf(p), TypeError);
+
+// 4. Let target be the value of the [[ProxyTarget]] internal slot of O.
+// 5. Let trap be ? GetMethod(handler, "getPrototypeOf").
+
+// Getting handler.getPrototypeOf might throw.
+assertThrowsValue(() => Object.getPrototypeOf(new Proxy({},
+ { get getPrototypeOf() {
+ throw 17;
+ } })),
+ 17);
+
+// The handler's getPrototypeOf, once gotten, might throw.
+p = new Proxy({}, { getPrototypeOf() { throw 42; } });
+
+assertThrowsValue(() => Object.getPrototypeOf(p), 42);
+
+// The trap might not be callable.
+p = new Proxy({}, { getPrototypeOf: 17 });
+
+assertThrowsInstanceOf(() => Object.getPrototypeOf(p),
+ TypeError);
+
+// 6. If trap is undefined, then
+// a. Return ? target.[[GetPrototypeOf]]().
+
+var x, tp;
+
+tp =
+ new Proxy(new Number(8675309), // behavior overridden by getPrototypeOf
+ { getPrototypeOf() { x = "getPrototypeOf trap"; return null; } });
+
+// The target's [[GetPrototypeOf]] should be invoked if the handler's
+// .getPrototypeOf is undefined.
+p = new Proxy(tp, { getPrototypeOf: undefined });
+x = "unset";
+assertEq(Object.getPrototypeOf(p), null);
+assertEq(x, "getPrototypeOf trap");
+
+// Likewise if the handler's .getPrototypeOf is null.
+p = new Proxy(tp, { getPrototypeOf: null });
+x = "unset";
+assertEq(Object.getPrototypeOf(p), null);
+assertEq(x, "getPrototypeOf trap");
+
+// Now the target is an empty object with a Number object as its [[Prototype]].
+var customProto = new Number(8675309);
+tp =
+ new Proxy({},
+ { getPrototypeOf() {
+ x = "getPrototypeOf trap";
+ return customProto;
+ } });
+
+// The target's [[GetPrototypeOf]] should be invoked if the handler's
+// .getPrototypeOf is undefined.
+p = new Proxy(tp, { getPrototypeOf: undefined });
+x = "unset";
+assertEq(Object.getPrototypeOf(p), customProto);
+assertEq(x, "getPrototypeOf trap");
+
+// Likewise if the handler's .getPrototypeOf is null.
+p = new Proxy(tp, { getPrototypeOf: null });
+x = "unset";
+assertEq(Object.getPrototypeOf(p), customProto);
+assertEq(x, "getPrototypeOf trap");
+
+// 7. Let handlerProto be ? Call(trap, handler, « target »).
+
+// The trap callable might throw.
+p = new Proxy({}, { getPrototypeOf() { throw "ohai"; } });
+
+assertThrowsValue(() => Object.getPrototypeOf(p),
+ "ohai");
+
+var throwingTrap =
+ new Proxy(function() { throw "not called"; },
+ { apply() { throw 37; } });
+
+p = new Proxy({}, { getPrototypeOf: throwingTrap });
+
+assertThrowsValue(() => Object.getPrototypeOf(p),
+ 37);
+
+// The trap callable must *only* be called.
+p = new Proxy({},
+ {
+ getPrototypeOf: observe(function() { throw "boo-urns"; })
+ });
+
+log.length = 0;
+assertThrowsValue(() => Object.getPrototypeOf(p),
+ "boo-urns");
+
+assertEq(log.length, 1);
+assertEq(log[0], "apply");
+
+// 8. If Type(handlerProto) is neither Object nor Null, throw a TypeError exception.
+
+var rval;
+
+var typeTestingTarget = {};
+p = new Proxy(typeTestingTarget, { getPrototypeOf() { return rval; } });
+
+function returnsPrimitives()
+{
+ rval = undefined;
+ assertThrowsInstanceOf(() => Object.getPrototypeOf(p),
+ TypeError);
+
+ rval = true;
+ assertThrowsInstanceOf(() => Object.getPrototypeOf(p),
+ TypeError);
+
+ rval = false;
+ assertThrowsInstanceOf(() => Object.getPrototypeOf(p),
+ TypeError);
+
+ rval = 0.0;
+ assertThrowsInstanceOf(() => Object.getPrototypeOf(p),
+ TypeError);
+
+ rval = -0.0;
+ assertThrowsInstanceOf(() => Object.getPrototypeOf(p),
+ TypeError);
+
+ rval = 3.141592654;
+ assertThrowsInstanceOf(() => Object.getPrototypeOf(p),
+ TypeError);
+
+ rval = NaN;
+ assertThrowsInstanceOf(() => Object.getPrototypeOf(p),
+ TypeError);
+
+ rval = -Infinity;
+ assertThrowsInstanceOf(() => Object.getPrototypeOf(p),
+ TypeError);
+
+ rval = "[[Prototype]] FOR REALZ";
+ assertThrowsInstanceOf(() => Object.getPrototypeOf(p),
+ TypeError);
+
+ rval = Symbol("[[Prototype]] FOR REALZ");
+ assertThrowsInstanceOf(() => Object.getPrototypeOf(p),
+ TypeError);
+}
+
+returnsPrimitives();
+Object.preventExtensions(typeTestingTarget);
+returnsPrimitives();
+
+// 9. Let extensibleTarget be ? IsExtensible(target).
+
+var act, extens;
+
+var typeTestingProxyTarget =
+ new Proxy({}, { isExtensible() {
+ seen = act();
+ return extens;
+ } });
+
+p = new Proxy(typeTestingProxyTarget, { getPrototypeOf() { return rval; } });
+
+rval = null;
+act = () => { throw "fnord" };
+assertThrowsValue(() => Object.getPrototypeOf(p),
+ "fnord");
+
+rval = /abc/;
+act = () => { throw "fnord again" };
+assertThrowsValue(() => Object.getPrototypeOf(p),
+ "fnord again");
+
+rval = Object.prototype;
+act = () => { throw "fnord" };
+assertThrowsValue(() => Object.getPrototypeOf(p),
+ "fnord");
+
+// 10. If extensibleTarget is true, return handlerProto.
+
+p = new Proxy({}, { getPrototypeOf() { return rval; } });
+
+rval = Number.prototype;
+assertEq(Object.getPrototypeOf(p), Number.prototype);
+
+// 11. Let targetProto be ? target.[[GetPrototypeOf]]().
+
+var targetProto;
+
+var targetWithProto =
+ new Proxy(Object.preventExtensions(Object.create(null)),
+ { getPrototypeOf() { act2(); return targetProto; } });
+
+p = new Proxy(targetWithProto,
+ { getPrototypeOf() { act1(); return rval; } });
+
+rval = null;
+targetProto = null;
+
+var regex = /targetProto/;
+
+act1 = () => log.push("act1");
+act2 = () => log.push("act2");
+
+log.length = 0;
+assertEq(Object.getPrototypeOf(p), null);
+assertEq(log.length, 2);
+assertEq(log[0], "act1");
+assertEq(log[1], "act2");
+
+act1 = () => log.push("act1 again");
+act2 = () => { throw "target throw"; };
+
+log.length = 0;
+assertThrowsValue(() => Object.getPrototypeOf(p),
+ "target throw");
+assertEq(log.length, 1);
+assertEq(log[0], "act1 again");
+
+// 12. If SameValue(handlerProto, targetProto) is false, throw a TypeError exception.
+
+act1 = act2 = nop;
+rval = /a/;
+assertThrowsInstanceOf(() => Object.getPrototypeOf(p),
+ TypeError);
+
+// 13. Return handlerProto.
+
+rval = null;
+targetProto = null;
+
+assertEq(Object.getPrototypeOf(p), null);
+
+p = new Proxy(Object.preventExtensions(new Number(55)),
+ { getPrototypeOf() { return Number.prototype; } });
+
+assertEq(Object.getPrototypeOf(p), Number.prototype);
+
+/******************************************************************************/
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
+
+print("Tests complete");
diff --git a/js/src/tests/non262/Proxy/global-receiver.js b/js/src/tests/non262/Proxy/global-receiver.js
new file mode 100644
index 0000000000..b2d160c0dd
--- /dev/null
+++ b/js/src/tests/non262/Proxy/global-receiver.js
@@ -0,0 +1,35 @@
+// The global object can be the receiver passed to the get and set traps of a Proxy.
+var global = this;
+var proto = Object.getPrototypeOf(global);
+var gets = 0, sets = 0;
+
+try {
+ Object.setPrototypeOf(global, new Proxy(proto, {
+ has(t, id) {
+ return id === "bareword" || Reflect.has(t, id);
+ },
+ get(t, id, r) {
+ gets++;
+ assertEq(r, global);
+ return Reflect.get(t, id, r);
+ },
+ set(t, id, v, r) {
+ sets++;
+ assertEq(r, global);
+ return Reflect.set(t, id, v, r);
+ }
+ }));
+} catch (e) {
+ global.bareword = undefined;
+ gets = 1;
+ sets = 1;
+}
+
+assertEq(bareword, undefined);
+assertEq(gets, 1);
+
+bareword = 12;
+assertEq(sets, 1);
+assertEq(global.bareword, 12);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Proxy/hasInstance.js b/js/src/tests/non262/Proxy/hasInstance.js
new file mode 100644
index 0000000000..bbdffb2273
--- /dev/null
+++ b/js/src/tests/non262/Proxy/hasInstance.js
@@ -0,0 +1,13 @@
+var get = [];
+var fun = function() {}
+var p = new Proxy(fun, {
+ get(target, key) {
+ get.push(key);
+ return target[key];
+ }
+});
+
+assertEq(new fun instanceof p, true);
+assertDeepEq(get, [Symbol.hasInstance, "prototype"]);
+
+reportCompare(true, true);
diff --git a/js/src/tests/non262/Proxy/json-stringify-replacer-array-revocable-proxy.js b/js/src/tests/non262/Proxy/json-stringify-replacer-array-revocable-proxy.js
new file mode 100644
index 0000000000..5d667e353a
--- /dev/null
+++ b/js/src/tests/non262/Proxy/json-stringify-replacer-array-revocable-proxy.js
@@ -0,0 +1,39 @@
+// Any copyright is dedicated to the Public Domain.
+// http://creativecommons.org/licenses/publicdomain/
+
+var gTestfile = "json-stringify-replacer-array-revocable-proxy.js";
+//-----------------------------------------------------------------------------
+var BUGNUMBER = 1196497;
+var summary =
+ "Don't assert when JSON.stringify is passed a revocable proxy to an array, " +
+ "then that proxy is revoked midflight during stringification";
+
+print(BUGNUMBER + ": " + summary);
+
+/**************
+ * BEGIN TEST *
+ **************/
+
+var arr = [];
+var { proxy, revoke } = Proxy.revocable(arr, {
+ get(thisv, prop, receiver) {
+ // First (and only) get will be for "length", to determine the length of the
+ // list of properties to serialize. Returning 0 uses the empty list,
+ // resulting in |a: 0| being ignored below.
+ assertEq(thisv, arr);
+ assertEq(prop, "length");
+ assertEq(receiver, proxy);
+
+ revoke();
+ return 0;
+ }
+});
+
+assertEq(JSON.stringify({a: 0}, proxy), "{}");
+
+/******************************************************************************/
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
+
+print("Tests complete");
diff --git a/js/src/tests/non262/Proxy/ownkeys-allowed-types.js b/js/src/tests/non262/Proxy/ownkeys-allowed-types.js
new file mode 100644
index 0000000000..028ab85128
--- /dev/null
+++ b/js/src/tests/non262/Proxy/ownkeys-allowed-types.js
@@ -0,0 +1,20 @@
+function makeProxy(type) {
+ return new Proxy({}, { ownKeys() { return [type]; } });
+}
+
+for (var type of [123, 12.5, true, false, undefined, null, {}, []]) {
+ var proxy = makeProxy(type);
+ assertThrowsInstanceOf(() => Object.ownKeys(proxy), TypeError);
+ assertThrowsInstanceOf(() => Object.getOwnPropertyNames(proxy), TypeError);
+}
+
+type = Symbol();
+proxy = makeProxy(type);
+assertEq(Object.getOwnPropertySymbols(proxy)[0], type);
+
+type = "abc";
+proxy = makeProxy(type);
+assertEq(Object.getOwnPropertyNames(proxy)[0], type);
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Proxy/ownkeys-linear.js b/js/src/tests/non262/Proxy/ownkeys-linear.js
new file mode 100644
index 0000000000..7b05a93846
--- /dev/null
+++ b/js/src/tests/non262/Proxy/ownkeys-linear.js
@@ -0,0 +1,70 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+
+var gTestfile = 'ownkeys-linear.js';
+var BUGNUMBER = 1257779;
+var summary =
+ "Scripted proxies' [[OwnPropertyKeys]] should have linear complexity";
+
+print(BUGNUMBER + ": " + summary);
+
+/**************
+ * BEGIN TEST *
+ **************/
+
+// Making this 50k makes cgc builds time out on tbpl. 5k takes 28s locally.
+// 10k takes 84s locally. So pick an intermediate number, with a generous
+// constant factor in case cgc-on-tbpl is much slower.
+const HALF_COUNT = 7500;
+
+var configurables = [];
+for (var i = 0; i < HALF_COUNT; i++)
+ configurables.push("conf" + i);
+
+var nonconfigurables = [];
+for (var i = 0; i < HALF_COUNT; i++)
+ nonconfigurables.push("nonconf" + i);
+
+var target = {};
+for (var name of configurables)
+ Object.defineProperty(target, name, { configurable: false, value: 0 });
+for (var name of nonconfigurables)
+ Object.defineProperty(target, name, { configurable: true, value: 0 });
+
+var handler = {
+ ownKeys(t) {
+ assertEq(t, target, "target mismatch!");
+
+ var trapResult = [];
+
+ // Append all nonconfigurables in reverse order of presence.
+ for (var i = nonconfigurables.length; i > 0; i--)
+ trapResult.push(nonconfigurables[i - 1]);
+
+ // Then the same for all configurables.
+ for (var i = configurables.length; i > 0; i--)
+ trapResult.push(configurables[i - 1]);
+
+ // The end consequence is that this ordering is exactly opposite the
+ // ordering they'll have on the target, and so worst-case performance will
+ // occur if the spec's |uncheckedResultKeys| structure is a vector having
+ // the same order as |trapResult|, searched from beginning to end in the
+ // presence-checks in the last few steps of the [[OwnPropertyKeys]]
+ // algorithm.
+ return trapResult;
+ }
+};
+
+var p = new Proxy(target, handler);
+
+// The test passes if it doesn't time out.
+assertEq(Object.getOwnPropertyNames(p).length, HALF_COUNT * 2);
+
+/******************************************************************************/
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
+
+print("Tests complete");
diff --git a/js/src/tests/non262/Proxy/ownkeys-trap-duplicates.js b/js/src/tests/non262/Proxy/ownkeys-trap-duplicates.js
new file mode 100644
index 0000000000..d525662657
--- /dev/null
+++ b/js/src/tests/non262/Proxy/ownkeys-trap-duplicates.js
@@ -0,0 +1,33 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+
+var gTestfile = 'ownkeys-trap-duplicates.js';
+var BUGNUMBER = 1293995;
+var summary =
+ "Scripted proxies' [[OwnPropertyKeys]] should not throw if the trap " +
+ "implementation returns duplicate properties and the object is " +
+ "non-extensible or has non-configurable properties." +
+ "Revised (bug 1389752): Throw TypeError for duplicate properties.";
+
+print(BUGNUMBER + ": " + summary);
+
+/**************
+ * BEGIN TEST *
+ **************/
+
+var target = Object.preventExtensions({ a: 1 });
+var proxy = new Proxy(target, { ownKeys(t) { return ["a", "a"]; } });
+assertThrowsInstanceOf(() => Object.getOwnPropertyNames(proxy), TypeError);
+
+target = Object.freeze({ a: 1 });
+proxy = new Proxy(target, { ownKeys(t) { return ["a", "a"]; } });
+assertThrowsInstanceOf(() => Object.getOwnPropertyNames(proxy), TypeError);
+
+/******************************************************************************/
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
+
+print("Tests complete");
diff --git a/js/src/tests/non262/Proxy/proxy-__proto__.js b/js/src/tests/non262/Proxy/proxy-__proto__.js
new file mode 100644
index 0000000000..f68bea489b
--- /dev/null
+++ b/js/src/tests/non262/Proxy/proxy-__proto__.js
@@ -0,0 +1,59 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+
+var gTestfile = 'proxy-__proto__.js';
+var BUGNUMBER = 950407;
+var summary = "Behavior of __proto__ on ES6 proxies";
+
+print(BUGNUMBER + ": " + summary);
+
+/**************
+ * BEGIN TEST *
+ **************/
+
+var protoDesc = Object.getOwnPropertyDescriptor(Object.prototype, "__proto__");
+var protoGetter = protoDesc.get;
+var protoSetter = protoDesc.set;
+
+function testProxy(target, initialProto)
+{
+ print("Now testing behavior for new Proxy(" + ("" + target) + ", {})");
+
+ var pobj = new Proxy(target, {});
+
+ // Check [[Prototype]] before attempted mutation
+ assertEq(Object.getPrototypeOf(pobj), initialProto);
+ assertEq(protoGetter.call(pobj), initialProto);
+
+ // Attempt [[Prototype]] mutation
+ protoSetter.call(pobj, null);
+
+ // Check [[Prototype]] after attempted mutation
+ assertEq(Object.getPrototypeOf(pobj), null);
+ assertEq(protoGetter.call(pobj), null);
+ assertEq(Object.getPrototypeOf(target), null);
+}
+
+// Proxy object with non-null [[Prototype]]
+var nonNullProto = { toString: function() { return "non-null prototype"; } };
+var target = Object.create(nonNullProto);
+testProxy(target, nonNullProto);
+
+// Proxy object with null [[Prototype]]
+target = Object.create(null);
+target.toString = function() { return "null prototype" };
+testProxy(target, null);
+
+// Proxy function with [[Call]]
+var callForCallOnly = function () { };
+callForCallOnly.toString = function() { return "callable target"; };
+testProxy(callForCallOnly, Function.prototype);
+
+/******************************************************************************/
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
+
+print("Tests complete");
diff --git a/js/src/tests/non262/Proxy/proxy-constructNonObject.js b/js/src/tests/non262/Proxy/proxy-constructNonObject.js
new file mode 100644
index 0000000000..04cee11e96
--- /dev/null
+++ b/js/src/tests/non262/Proxy/proxy-constructNonObject.js
@@ -0,0 +1,18 @@
+function bogusConstruct(target) { return 4; }
+function bogusConstructUndefined(target) { }
+
+var handler = { construct: bogusConstruct }
+
+function callable() {}
+
+var p = new Proxy(callable, handler);
+
+assertThrowsInstanceOf(function () { new p(); }, TypeError,
+ "[[Construct must throw if an object is not returned.");
+
+handler.construct = bogusConstructUndefined;
+assertThrowsInstanceOf(function () { new p(); }, TypeError,
+ "[[Construct must throw if an object is not returned.");
+
+if (typeof reportCompare === "function")
+ reportCompare(0,0, "OK");
diff --git a/js/src/tests/non262/Proxy/proxy-for-in.js b/js/src/tests/non262/Proxy/proxy-for-in.js
new file mode 100644
index 0000000000..4332bfbbad
--- /dev/null
+++ b/js/src/tests/non262/Proxy/proxy-for-in.js
@@ -0,0 +1,37 @@
+// Any copyright is dedicated to the Public Domain.
+// http://creativecommons.org/licenses/publicdomain/
+"use strict";
+
+let steps = [];
+
+const object = {
+ __proto__: {
+ "xyz": 42
+ }
+};
+const proxy = new Proxy(object, {
+ ownKeys(target) {
+ steps.push("ownKeys")
+ return ["a", "b"];
+ },
+
+ getOwnPropertyDescriptor(target, property) {
+ steps.push("getOwn-" + property);
+ return {
+ value: undefined,
+ configurable: true,
+ writable: true,
+ enumerable: (property === "a")
+ };
+ }
+});
+
+let iterated = [];
+for (let x in proxy)
+ iterated.push(x);
+
+assertEq(iterated.toString(), "a,xyz");
+assertEq(steps.toString(), "ownKeys,getOwn-a,getOwn-b");
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Proxy/proxy-no-receiver-overwrite.js b/js/src/tests/non262/Proxy/proxy-no-receiver-overwrite.js
new file mode 100644
index 0000000000..86d352d454
--- /dev/null
+++ b/js/src/tests/non262/Proxy/proxy-no-receiver-overwrite.js
@@ -0,0 +1,23 @@
+"use strict";
+
+var y = new Proxy({}, {
+ getOwnPropertyDescriptor(target, key) {
+ if (key === "a") {
+ return { configurable: true, get: function(v) {} };
+ } else {
+ assertEq(key, "b");
+ return { configurable: true, writable: false, value: 15 };
+ }
+ },
+
+ defineProperty() {
+ throw "not invoked";
+ }
+})
+
+// This will invoke [[Set]] on the target, with the proxy as receiver.
+assertThrowsInstanceOf(() => y.a = 1, TypeError);
+assertThrowsInstanceOf(() => y.b = 2, TypeError);
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Proxy/proxy-proto-lazy-props.js b/js/src/tests/non262/Proxy/proxy-proto-lazy-props.js
new file mode 100644
index 0000000000..c82c0f935b
--- /dev/null
+++ b/js/src/tests/non262/Proxy/proxy-proto-lazy-props.js
@@ -0,0 +1,61 @@
+function makeProxyPrototype(target) {
+ return Object.setPrototypeOf(target, new Proxy({}, new Proxy({
+ getPrototypeOf() {
+ return null;
+ },
+ ownKeys() {
+ return [];
+ },
+ get(t, pk, r) {
+ throw new Error("Unexpected [[Get]]: " + String(pk));
+ }
+ }, {
+ get(t, pk, r) {
+ if (pk in t)
+ return Reflect.get(t, pk, r);
+ throw new Error("Unexpected trap called: " + pk);
+ }
+ })));
+}
+
+function enumerateMappedArgs(x) {
+ var a = makeProxyPrototype(arguments);
+
+ // Delete all lazy properties and ensure no [[Has]] trap is called for them
+ // on the prototype chain.
+ delete a.length;
+ delete a.callee;
+ delete a[Symbol.iterator];
+ delete a[0];
+
+ for (var k in a);
+}
+enumerateMappedArgs(0);
+
+function enumerateUnmappedArgs(x) {
+ "use strict";
+ var a = makeProxyPrototype(arguments);
+
+ delete a.length;
+ // delete a.callee; // .callee is non-configurable
+ delete a[Symbol.iterator];
+ delete a[0];
+
+ for (var k in a);
+}
+enumerateUnmappedArgs(0);
+
+function enumerateFunction() {
+ var f = makeProxyPrototype(function named() {});
+
+ // delete f.prototype; // .prototype is non-configurable
+ delete f.length;
+ delete f.name;
+
+ for (var k in f);
+}
+enumerateFunction();
+
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Proxy/proxy-with-revoked-arguments.js b/js/src/tests/non262/Proxy/proxy-with-revoked-arguments.js
new file mode 100644
index 0000000000..a60dddbea6
--- /dev/null
+++ b/js/src/tests/non262/Proxy/proxy-with-revoked-arguments.js
@@ -0,0 +1,53 @@
+var BUGNUMBER = 1151149;
+var summary = "Proxy constructor should not throw if either the target or handler is a revoked proxy.";
+
+print(BUGNUMBER + ": " + summary);
+
+var p = new Proxy({}, {});
+
+new Proxy(p, {});
+new Proxy({}, p);
+
+var r = Proxy.revocable({}, {});
+p = r.proxy;
+
+new Proxy(p, {});
+new Proxy({}, p);
+
+r.revoke();
+
+new Proxy(p, {});
+new Proxy({}, p);
+
+
+var r2 = Proxy.revocable({}, {});
+r = Proxy.revocable(r2.proxy, {});
+p = r.proxy;
+
+new Proxy(p, {});
+new Proxy({}, p);
+
+r2.revoke();
+
+new Proxy(p, {});
+new Proxy({}, p);
+
+r.revoke();
+
+new Proxy(p, {});
+new Proxy({}, p);
+
+
+var g = newGlobal();
+p = g.eval(`var r = Proxy.revocable({}, {}); r.proxy;`);
+
+new Proxy(p, {});
+new Proxy({}, p);
+
+g.eval(`r.revoke();`);
+
+new Proxy(p, {});
+new Proxy({}, p);
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Proxy/regress-bug1037770.js b/js/src/tests/non262/Proxy/regress-bug1037770.js
new file mode 100644
index 0000000000..240b04f32e
--- /dev/null
+++ b/js/src/tests/non262/Proxy/regress-bug1037770.js
@@ -0,0 +1,7 @@
+foo = 1;
+Object.defineProperty(this, "foo", {writable:false, configurable:true});
+foo = 2;
+assertEq(foo, 1);
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Proxy/regress-bug1062349.js b/js/src/tests/non262/Proxy/regress-bug1062349.js
new file mode 100644
index 0000000000..fe0ad3d9a9
--- /dev/null
+++ b/js/src/tests/non262/Proxy/regress-bug1062349.js
@@ -0,0 +1,31 @@
+// Adapted from a test case contributed by André Bargull in bug 1062349.
+
+var log = [];
+var hh = {
+ get(t, pk) {
+ log.push("trap: " + pk);
+ return t[pk];
+ }
+};
+var h = new Proxy({
+ get set() {
+ log.push("called set()");
+ Object.defineProperty(o, "prop", {value: 0});
+ log.push("o.prop:", Object.getOwnPropertyDescriptor(o, "prop"));
+ }
+}, hh);
+var p = new Proxy({}, h);
+var o = {__proto__: p};
+
+o.prop = 1;
+
+var expectedDesc = {value: 0, writable: false, enumerable: false, configurable: false};
+assertDeepEq(log, [
+ "trap: set",
+ "called set()",
+ "o.prop:",
+ expectedDesc
+]);
+assertDeepEq(Object.getOwnPropertyDescriptor(o, "prop"), expectedDesc);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Proxy/regress-bug950407.js b/js/src/tests/non262/Proxy/regress-bug950407.js
new file mode 100644
index 0000000000..d253c75fc2
--- /dev/null
+++ b/js/src/tests/non262/Proxy/regress-bug950407.js
@@ -0,0 +1,7 @@
+var ab = new ArrayBuffer(5);
+var p = new Proxy(ab, {});
+var ps = Object.getOwnPropertyDescriptor(Object.prototype, "__proto__").set;
+var new_proto = {};
+ps.call(p, new_proto);
+
+reportCompare(ab.__proto__, new_proto);
diff --git a/js/src/tests/non262/Proxy/report-writable-as-non-writable.js b/js/src/tests/non262/Proxy/report-writable-as-non-writable.js
new file mode 100644
index 0000000000..c0facd1057
--- /dev/null
+++ b/js/src/tests/non262/Proxy/report-writable-as-non-writable.js
@@ -0,0 +1,20 @@
+"use strict";
+
+var target = {};
+Object.defineProperty(target, "test",
+ {configurable: false, writable: true, value: 1});
+
+var proxy = new Proxy(target, {
+ getOwnPropertyDescriptor(target, property) {
+ assertEq(property, "test");
+ return {configurable: false, writable: false, value: 1};
+ }
+});
+
+assertThrowsInstanceOf(() => Object.getOwnPropertyDescriptor(proxy, "test"),
+ TypeError);
+
+assertThrowsInstanceOf(() => Reflect.getOwnPropertyDescriptor(proxy, "test"),
+ TypeError);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Proxy/revocable-proxy-prototype.js b/js/src/tests/non262/Proxy/revocable-proxy-prototype.js
new file mode 100644
index 0000000000..7afbc15d2a
--- /dev/null
+++ b/js/src/tests/non262/Proxy/revocable-proxy-prototype.js
@@ -0,0 +1,40 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+
+var gTestfile = 'revocable-proxy-prototype.js';
+var BUGNUMBER = 1052139;
+var summary = "Accessing a revocable proxy's [[Prototype]] shouldn't crash";
+
+print(BUGNUMBER + ": " + summary);
+
+/**************
+ * BEGIN TEST *
+ **************/
+function checkFunctionAppliedToRevokedProxy(fun)
+{
+ var p = Proxy.revocable({}, {});
+ p.revoke();
+
+ try
+ {
+ fun(p.proxy);
+ throw "didn't throw";
+ }
+ catch (e)
+ {
+ assertEq(e instanceof TypeError, true,
+ "expected TypeError, got " + e);
+ }
+}
+
+checkFunctionAppliedToRevokedProxy(proxy => Object.getPrototypeOf(proxy));
+checkFunctionAppliedToRevokedProxy(proxy => Object.setPrototypeOf(proxy, null));
+
+/******************************************************************************/
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
+
+print("Tests complete");
diff --git a/js/src/tests/non262/Proxy/revoke-as-side-effect.js b/js/src/tests/non262/Proxy/revoke-as-side-effect.js
new file mode 100644
index 0000000000..25d4c9bf91
--- /dev/null
+++ b/js/src/tests/non262/Proxy/revoke-as-side-effect.js
@@ -0,0 +1,73 @@
+function createProxy(proxyTarget) {
+ var {proxy, revoke} = Proxy.revocable(proxyTarget, new Proxy({}, {
+ get(target, propertyKey, receiver) {
+ print("trap get:", propertyKey);
+ revoke();
+ }
+ }));
+ return proxy;
+}
+
+var obj;
+
+// [[GetPrototypeOf]]
+assertEq(Object.getPrototypeOf(createProxy({})), Object.prototype);
+assertEq(Object.getPrototypeOf(createProxy([])), Array.prototype);
+
+// [[SetPrototypeOf]]
+obj = {};
+Object.setPrototypeOf(createProxy(obj), Array.prototype);
+assertEq(Object.getPrototypeOf(obj), Array.prototype);
+
+// [[IsExtensible]]
+assertEq(Object.isExtensible(createProxy({})), true);
+assertEq(Object.isExtensible(createProxy(Object.preventExtensions({}))), false);
+
+// [[PreventExtensions]]
+obj = {};
+Object.preventExtensions(createProxy(obj));
+assertEq(Object.isExtensible(obj), false);
+
+// [[GetOwnProperty]]
+assertEq(Object.getOwnPropertyDescriptor(createProxy({}), "a"), undefined);
+assertEq(Object.getOwnPropertyDescriptor(createProxy({a: 5}), "a").value, 5);
+
+// [[DefineOwnProperty]]
+obj = {};
+Object.defineProperty(createProxy(obj), "a", {value: 5});
+assertEq(obj.a, 5);
+
+// [[HasProperty]]
+assertEq("a" in createProxy({}), false);
+assertEq("a" in createProxy({a: 5}), true);
+
+// [[Get]]
+assertEq(createProxy({}).a, undefined);
+assertEq(createProxy({a: 5}).a, 5);
+
+// [[Set]]
+assertThrowsInstanceOf(() => createProxy({}).a = 0, TypeError);
+assertThrowsInstanceOf(() => createProxy({a: 5}).a = 0, TypeError);
+
+// [[Delete]]
+assertEq(delete createProxy({}).a, true);
+assertEq(delete createProxy(Object.defineProperty({}, "a", {configurable: false})).a, false);
+
+// [[OwnPropertyKeys]]
+assertEq(Object.getOwnPropertyNames(createProxy({})).length, 0);
+assertEq(Object.getOwnPropertyNames(createProxy({a: 5})).length, 1);
+
+// [[Call]]
+assertEq(createProxy(function() { return "ok" })(), "ok");
+
+// [[Construct]]
+// This throws because after the "construct" trap on the proxy is consulted,
+// OrdinaryCreateFromConstructor (called because the |q| function's
+// [[ConstructorKind]] is "base" per FunctionAllocate) accesses
+// |new.target.prototype| to create the |this| for the construct operation, that
+// would be returned if |return obj;| didn't override it.
+assertThrowsInstanceOf(() => new (createProxy(function q(){ return obj; })),
+ TypeError);
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Proxy/revoke-no-name.js b/js/src/tests/non262/Proxy/revoke-no-name.js
new file mode 100644
index 0000000000..59ea80bd5d
--- /dev/null
+++ b/js/src/tests/non262/Proxy/revoke-no-name.js
@@ -0,0 +1,2 @@
+var revocationFunction = Proxy.revocable({}, {}).revoke;
+reportCompare(revocationFunction.name, "");
diff --git a/js/src/tests/non262/Proxy/revoked-get-function-realm-typeerror.js b/js/src/tests/non262/Proxy/revoked-get-function-realm-typeerror.js
new file mode 100644
index 0000000000..8214b3c9a7
--- /dev/null
+++ b/js/src/tests/non262/Proxy/revoked-get-function-realm-typeerror.js
@@ -0,0 +1,119 @@
+var constructors = [
+ // 19.1 Object Objects
+ {constructor: Object},
+
+ // 19.2 Function Objects
+ {constructor: Function},
+
+ // 19.3 Boolean Objects
+ {constructor: Boolean},
+
+ // 19.5 Error Objects
+ {constructor: Error},
+
+ // 19.5.5 Native Error Types Used in This Standard
+ {constructor: EvalError},
+ {constructor: RangeError},
+ {constructor: ReferenceError},
+ {constructor: SyntaxError},
+ {constructor: TypeError},
+ {constructor: URIError},
+
+ // 20.1 Number Objects
+ {constructor: Number},
+
+ // 20.3 Date Objects
+ {constructor: Date},
+
+ // 21.1 String Objects
+ {constructor: String},
+
+ // 21.2 RegExp (Regular Expression) Objects
+ {constructor: RegExp},
+
+ // 22.1 Array Objects
+ {constructor: Array},
+
+ // 22.2 TypedArray Objects
+ {constructor: Int8Array},
+
+ // 23.1 Map Objects
+ {constructor: Map},
+
+ // 23.2 Set Objects
+ {constructor: Set},
+
+ // 23.3 WeakMap Objects
+ {constructor: WeakMap},
+
+ // 23.4 WeakSet Objects
+ {constructor: WeakSet},
+
+ // 24.1 ArrayBuffer Objects
+ {constructor: ArrayBuffer},
+
+ // 24.2 SharedArrayBuffer Objects
+ ...(typeof SharedArrayBuffer === "function" ? [{constructor: SharedArrayBuffer}] : []),
+
+ // 24.3 DataView Objects
+ {constructor: DataView, args: [new ArrayBuffer(0)]},
+
+ // 25.2 GeneratorFunction Objects
+ {constructor: function*(){}.constructor},
+
+ // 25.3 AsyncGeneratorFunction Objects
+ {constructor: async function*(){}.constructor},
+
+ // 25.6 Promise Objects
+ {constructor: Promise, args: [function(){}]},
+
+ // 25.7 AsyncFunction Objects
+ {constructor: async function(){}.constructor},
+
+ // 9.2 ECMAScript Function Objects
+ {constructor: function(){}},
+
+ // Intl can be disabled at compile-time.
+ ...(typeof Intl !== "undefined" ? [
+ // 10 Collator Objects
+ {constructor: Intl.Collator},
+
+ // 11 NumberFormat Objects
+ {constructor: Intl.NumberFormat},
+
+ // 12 DateTimeFormat Objects
+ {constructor: Intl.DateTimeFormat},
+
+ // 13 PluralRules Objects
+ {constructor: Intl.PluralRules},
+
+ // Intl.RelativeTimeFormat proposal
+ {constructor: Intl.RelativeTimeFormat},
+
+ // Intl.Locale is not yet enabled by default.
+ ...(Intl.Locale ? [Intl.Locale] : []),
+ ] : []),
+];
+
+for (let {constructor, args = []} of constructors) {
+ let revoked = 0;
+ let {proxy, revoke} = Proxy.revocable(function(){}, {
+ get(t, pk, r) {
+ if (pk === "prototype") {
+ revoked++;
+ revoke();
+ return undefined;
+ }
+ return Reflect.get(t, pk, r);
+ }
+ });
+
+ assertThrowsInstanceOf(() => {
+ Reflect.construct(constructor, args, proxy);
+ }, TypeError);
+
+ assertEq(revoked, 1);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Proxy/setPrototypeOf.js b/js/src/tests/non262/Proxy/setPrototypeOf.js
new file mode 100644
index 0000000000..d79c53fd96
--- /dev/null
+++ b/js/src/tests/non262/Proxy/setPrototypeOf.js
@@ -0,0 +1,258 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+
+var gTestfile = "setPrototypeOf.js";
+var BUGNUMBER = 888969;
+var summary = "Scripted proxies' [[SetPrototypeOf]] behavior";
+
+print(BUGNUMBER + ": " + summary);
+
+/**************
+ * BEGIN TEST *
+ **************/
+
+const log = [];
+
+function observe(obj)
+{
+ var observingHandler = new Proxy({}, {
+ get(target, p, receiver) {
+ log.push(p);
+ return Reflect.get(target, p, receiver);
+ }
+ });
+
+ return new Proxy(obj, observingHandler);
+}
+
+var p, h;
+
+// 1. Assert: Either Type(V) is Object or Type(V) is Null.
+// 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
+// 3. If handler is null, throw a TypeError exception.
+// 4. Assert: Type(handler) is Object.
+// 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
+
+var rev = Proxy.revocable({}, {});
+p = rev.proxy;
+
+var originalProto = Reflect.getPrototypeOf(p);
+assertEq(originalProto, Object.prototype);
+
+rev.revoke();
+assertThrowsInstanceOf(() => Reflect.setPrototypeOf(p, originalProto),
+ TypeError);
+assertThrowsInstanceOf(() => Reflect.setPrototypeOf(p, null),
+ TypeError);
+
+// 6. Let trap be ? GetMethod(handler, "setPrototypeOf").
+
+// handler has uncallable (and not null/undefined) property
+p = new Proxy({}, { setPrototypeOf: 9 });
+assertThrowsInstanceOf(() => Reflect.setPrototypeOf(p, null),
+ TypeError);
+
+p = new Proxy({}, { setPrototypeOf: -3.7 });
+assertThrowsInstanceOf(() => Reflect.setPrototypeOf(p, null),
+ TypeError);
+
+p = new Proxy({}, { setPrototypeOf: NaN });
+assertThrowsInstanceOf(() => Reflect.setPrototypeOf(p, null),
+ TypeError);
+
+p = new Proxy({}, { setPrototypeOf: Infinity });
+assertThrowsInstanceOf(() => Reflect.setPrototypeOf(p, null),
+ TypeError);
+
+p = new Proxy({}, { setPrototypeOf: true });
+assertThrowsInstanceOf(() => Reflect.setPrototypeOf(p, null),
+ TypeError);
+
+p = new Proxy({}, { setPrototypeOf: /x/ });
+assertThrowsInstanceOf(() => Reflect.setPrototypeOf(p, null),
+ TypeError);
+
+p = new Proxy({}, { setPrototypeOf: Symbol(42) });
+assertThrowsInstanceOf(() => Reflect.setPrototypeOf(p, null),
+ TypeError);
+
+p = new Proxy({}, { setPrototypeOf: class X {} });
+assertThrowsInstanceOf(() => Reflect.setPrototypeOf(p, null),
+ TypeError);
+
+p = new Proxy({}, observe({}));
+
+assertEq(Reflect.setPrototypeOf(p, Object.prototype), true);
+assertEq(log.length, 1);
+assertEq(log[0], "get");
+
+h = observe({ setPrototypeOf() { throw 3.14; } });
+p = new Proxy(Object.create(Object.prototype), h);
+
+// "setting" without change
+log.length = 0;
+assertThrowsValue(() => Reflect.setPrototypeOf(p, Object.prototype),
+ 3.14);
+assertEq(log.length, 1);
+assertEq(log[0], "get");
+
+// "setting" with change
+log.length = 0;
+assertThrowsValue(() => Reflect.setPrototypeOf(p, /foo/),
+ 3.14);
+assertEq(log.length, 1);
+assertEq(log[0], "get");
+
+// 7. If trap is undefined, then
+// a. Return ? target.[[SetPrototypeOf]](V).
+
+var settingProtoThrows =
+ new Proxy({}, { setPrototypeOf() { throw "agnizes"; } });
+
+p = new Proxy(settingProtoThrows, { setPrototypeOf: undefined });
+assertThrowsValue(() => Reflect.setPrototypeOf(p, null),
+ "agnizes");
+
+p = new Proxy(settingProtoThrows, { setPrototypeOf: null });
+assertThrowsValue(() => Reflect.setPrototypeOf(p, null),
+ "agnizes");
+
+var anotherProto =
+ new Proxy({},
+ { setPrototypeOf(t, p) {
+ log.push("reached");
+ return Reflect.setPrototypeOf(t, p);
+ } });
+
+p = new Proxy(anotherProto, { setPrototypeOf: undefined });
+
+log.length = 0;
+assertEq(Reflect.setPrototypeOf(p, null), true);
+assertEq(log.length, 1);
+assertEq(log[0], "reached");
+
+p = new Proxy(anotherProto, { setPrototypeOf: null });
+
+log.length = 0;
+assertEq(Reflect.setPrototypeOf(p, null), true);
+assertEq(log.length, 1);
+assertEq(log[0], "reached");
+
+// 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler, « target, V »)).
+
+// The trap callable might throw.
+p = new Proxy({}, { setPrototypeOf() { throw "ohai"; } });
+
+assertThrowsValue(() => Reflect.setPrototypeOf(p, /x/),
+ "ohai");
+
+var throwingTrap =
+ new Proxy(function() { throw "not called"; },
+ { apply() { throw 37; } });
+
+p = new Proxy({}, { setPrototypeOf: throwingTrap });
+
+assertThrowsValue(() => Reflect.setPrototypeOf(p, Object.prototype),
+ 37);
+
+// The trap callable must *only* be called.
+p = new Proxy({},
+ {
+ setPrototypeOf: observe(function() { throw "boo-urns"; })
+ });
+
+log.length = 0;
+assertThrowsValue(() => Reflect.setPrototypeOf(p, Object.prototype),
+ "boo-urns");
+
+assertEq(log.length, 1);
+assertEq(log[0], "apply");
+
+// 9. If booleanTrapResult is false, return false.
+
+p = new Proxy({}, { setPrototypeOf() { return false; } });
+assertEq(Reflect.setPrototypeOf(p, Object.prototype), false);
+
+p = new Proxy({}, { setPrototypeOf() { return +0; } });
+assertEq(Reflect.setPrototypeOf(p, Object.prototype), false);
+
+p = new Proxy({}, { setPrototypeOf() { return -0; } });
+assertEq(Reflect.setPrototypeOf(p, Object.prototype), false);
+
+p = new Proxy({}, { setPrototypeOf() { return NaN; } });
+assertEq(Reflect.setPrototypeOf(p, Object.prototype), false);
+
+p = new Proxy({}, { setPrototypeOf() { return ""; } });
+assertEq(Reflect.setPrototypeOf(p, Object.prototype), false);
+
+p = new Proxy({}, { setPrototypeOf() { return undefined; } });
+assertEq(Reflect.setPrototypeOf(p, Object.prototype), false);
+
+// 10. Let extensibleTarget be ? IsExtensible(target).
+
+var targetThrowIsExtensible =
+ new Proxy({}, { isExtensible() { throw "psych!"; } });
+
+p = new Proxy(targetThrowIsExtensible, { setPrototypeOf() { return true; } });
+assertThrowsValue(() => Reflect.setPrototypeOf(p, Object.prototype),
+ "psych!");
+
+// 11. If extensibleTarget is true, return true.
+
+var targ = {};
+
+p = new Proxy(targ, { setPrototypeOf() { return true; } });
+assertEq(Reflect.setPrototypeOf(p, /x/), true);
+assertEq(Reflect.getPrototypeOf(targ), Object.prototype);
+assertEq(Reflect.getPrototypeOf(p), Object.prototype);
+
+p = new Proxy(targ, { setPrototypeOf() { return /x/; } });
+assertEq(Reflect.setPrototypeOf(p, /x/), true);
+assertEq(Reflect.getPrototypeOf(targ), Object.prototype);
+assertEq(Reflect.getPrototypeOf(p), Object.prototype);
+
+p = new Proxy(targ, { setPrototypeOf() { return Infinity; } });
+assertEq(Reflect.setPrototypeOf(p, /x/), true);
+assertEq(Reflect.getPrototypeOf(targ), Object.prototype);
+assertEq(Reflect.getPrototypeOf(p), Object.prototype);
+
+p = new Proxy(targ, { setPrototypeOf() { return Symbol(true); } });
+assertEq(Reflect.setPrototypeOf(p, /x/), true);
+assertEq(Reflect.getPrototypeOf(targ), Object.prototype);
+assertEq(Reflect.getPrototypeOf(p), Object.prototype);
+
+// 12. Let targetProto be ? target.[[GetPrototypeOf]]().
+
+var targetNotExtensibleGetProtoThrows =
+ new Proxy(Object.preventExtensions({}),
+ { getPrototypeOf() { throw NaN; } });
+
+p = new Proxy(targetNotExtensibleGetProtoThrows,
+ { setPrototypeOf() { log.push("goober"); return true; } });
+
+log.length = 0;
+assertThrowsValue(() => Reflect.setPrototypeOf(p, /abcd/),
+ NaN);
+
+// 13. If SameValue(V, targetProto) is false, throw a TypeError exception.
+
+var newProto;
+
+p = new Proxy(Object.preventExtensions(Object.create(Math)),
+ { setPrototypeOf(t, p) { return true; } });
+
+assertThrowsInstanceOf(() => Reflect.setPrototypeOf(p, null),
+ TypeError);
+
+// 14. Return true.
+
+assertEq(Reflect.setPrototypeOf(p, Math), true);
+
+/******************************************************************************/
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
+
+print("Tests complete");
diff --git a/js/src/tests/non262/Proxy/shell.js b/js/src/tests/non262/Proxy/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/non262/Proxy/shell.js
diff --git a/js/src/tests/non262/Proxy/trap-null.js b/js/src/tests/non262/Proxy/trap-null.js
new file mode 100644
index 0000000000..703649e7c8
--- /dev/null
+++ b/js/src/tests/non262/Proxy/trap-null.js
@@ -0,0 +1,103 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+
+var gTestfile = 'trap-null.js';
+var BUGNUMBER = 1257102;
+var summary = "null as a trap value on a handler should operate on the target";
+
+print(BUGNUMBER + ": " + summary);
+
+/**************
+ * BEGIN TEST *
+ **************/
+
+// This might seem like overkill, but this proxying trick caught typos of
+// several trap names before this test landed. \o/ /o\
+var allTraps = {
+ getPrototypeOf: null,
+ setPrototypeOf: null,
+ isExtensible: null,
+ preventExtensions: null,
+ getOwnPropertyDescriptor: null,
+ defineProperty: null,
+ has: null,
+ get: null,
+ set: null,
+ deleteProperty: null,
+ ownKeys: null,
+ apply: null,
+ construct: null,
+};
+
+var complainingHandler = new Proxy(allTraps, {
+ get(target, p, receiver) {
+ var v = Reflect.get(target, p, receiver);
+ if (v !== null)
+ throw new TypeError("failed to set one of the traps to null? " + p);
+
+ return v;
+ }
+});
+
+var proxyTarget = function(x) {
+ "use strict";
+ var str = this + x;
+ str += new.target ? "constructing" : "calling";
+ return new.target ? new String(str) : str;
+};
+proxyTarget.prototype.toString = () => "###";
+proxyTarget.prototype.valueOf = () => "@@@";
+
+var proxy = new Proxy(proxyTarget, complainingHandler);
+
+assertEq(Reflect.getPrototypeOf(proxy), Function.prototype);
+
+assertEq(Object.getPrototypeOf(proxyTarget), Function.prototype);
+assertEq(Reflect.setPrototypeOf(proxy, null), true);
+assertEq(Object.getPrototypeOf(proxyTarget), null);
+
+assertEq(Reflect.isExtensible(proxy), true);
+
+assertEq(Reflect.isExtensible(proxyTarget), true);
+assertEq(Reflect.preventExtensions(proxy), true);
+assertEq(Reflect.isExtensible(proxy), false);
+assertEq(Reflect.isExtensible(proxyTarget), false);
+
+var desc = Reflect.getOwnPropertyDescriptor(proxy, "length");
+assertEq(desc.value, 1);
+
+assertEq(desc.configurable, true);
+assertEq(Reflect.defineProperty(proxy, "length", { value: 3, configurable: false }), true);
+desc = Reflect.getOwnPropertyDescriptor(proxy, "length");
+assertEq(desc.configurable, false);
+
+assertEq(Reflect.has(proxy, "length"), true);
+
+assertEq(Reflect.get(proxy, "length"), 3);
+
+assertEq(Reflect.set(proxy, "length", 3), false);
+
+assertEq(Reflect.deleteProperty(proxy, "length"), false);
+
+var keys = Reflect.ownKeys(proxy);
+assertEq(keys.length, 3);
+keys.sort();
+assertEq(keys[0], "length");
+assertEq(keys[1], "name");
+assertEq(keys[2], "prototype");
+
+assertEq(Reflect.apply(proxy, "hi!", [" "]), "hi! calling");
+
+var res = Reflect.construct(proxy, [" - "]);
+assertEq(typeof res, "object");
+assertEq(res instanceof String, true);
+assertEq(res.valueOf(), "@@@ - constructing");
+
+/******************************************************************************/
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
+
+print("Tests complete");