summaryrefslogtreecommitdiffstats
path: root/js/src/tests/ecma_6/Reflect
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/tests/ecma_6/Reflect')
-rw-r--r--js/src/tests/ecma_6/Reflect/apply.js130
-rw-r--r--js/src/tests/ecma_6/Reflect/argumentsList.js164
-rw-r--r--js/src/tests/ecma_6/Reflect/browser.js0
-rw-r--r--js/src/tests/ecma_6/Reflect/construct.js107
-rw-r--r--js/src/tests/ecma_6/Reflect/defineProperty.js164
-rw-r--r--js/src/tests/ecma_6/Reflect/deleteProperty.js80
-rw-r--r--js/src/tests/ecma_6/Reflect/get.js72
-rw-r--r--js/src/tests/ecma_6/Reflect/getOwnPropertyDescriptor.js21
-rw-r--r--js/src/tests/ecma_6/Reflect/getPrototypeOf.js17
-rw-r--r--js/src/tests/ecma_6/Reflect/has.js41
-rw-r--r--js/src/tests/ecma_6/Reflect/isExtensible.js57
-rw-r--r--js/src/tests/ecma_6/Reflect/ownKeys.js66
-rw-r--r--js/src/tests/ecma_6/Reflect/preventExtensions.js56
-rw-r--r--js/src/tests/ecma_6/Reflect/propertyKeys.js84
-rw-r--r--js/src/tests/ecma_6/Reflect/set.js280
-rw-r--r--js/src/tests/ecma_6/Reflect/setPrototypeOf.js72
-rw-r--r--js/src/tests/ecma_6/Reflect/shell.js9
-rw-r--r--js/src/tests/ecma_6/Reflect/surfaces.js59
-rw-r--r--js/src/tests/ecma_6/Reflect/target.js44
19 files changed, 1523 insertions, 0 deletions
diff --git a/js/src/tests/ecma_6/Reflect/apply.js b/js/src/tests/ecma_6/Reflect/apply.js
new file mode 100644
index 000000000..fbd9db2a4
--- /dev/null
+++ b/js/src/tests/ecma_6/Reflect/apply.js
@@ -0,0 +1,130 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/ */
+
+// Reflect.apply calls functions.
+assertEq(Reflect.apply(Math.floor, undefined, [1.75]), 1);
+
+// Reflect.apply requires a target object that's callable.
+var nonCallable = [{}, [], (class clsX { constructor() {} })];
+for (var value of nonCallable) {
+ assertThrowsInstanceOf(() => Reflect.apply(nonCallable), TypeError);
+}
+
+// When target is not callable, Reflect.apply does not try to get argumentList.length before throwing.
+var hits = 0;
+var bogusArgumentList = {get length() { hit++; throw "FAIL";}};
+assertThrowsInstanceOf(() => Reflect.apply({callable: false}, null, bogusArgumentList),
+ TypeError);
+assertEq(hits, 0);
+
+// Reflect.apply works on a range of different callable objects.
+// Builtin functions (we also tested Math.floor above):
+assertEq(Reflect.apply(String.fromCharCode,
+ undefined,
+ [104, 101, 108, 108, 111]),
+ "hello");
+
+// Builtin methods:
+assertEq(Reflect.apply(RegExp.prototype.exec,
+ /ab/,
+ ["confabulation"]).index,
+ 4);
+
+// Builtin methods of primitive objects:
+assertEq(Reflect.apply("".charAt,
+ "ponies",
+ [3]),
+ "i");
+
+// Bound functions:
+assertEq(Reflect.apply(function () { return this; }.bind(Math),
+ Function,
+ []),
+ Math);
+assertEq(Reflect.apply(Array.prototype.concat.bind([1, 2], [3]),
+ [4, 5],
+ [[6, 7, 8]]).join(),
+ "1,2,3,6,7,8");
+
+// Generator functions:
+function* g(arg) { yield "pass" + arg; }
+assertEq(Reflect.apply(g,
+ undefined,
+ ["word"]).next().value,
+ "password");
+
+// Proxies:
+function f() { return 13; }
+assertEq(Reflect.apply(new Proxy(f, {}),
+ undefined,
+ []),
+ 13);
+
+// Cross-compartment wrappers:
+var gw = newGlobal();
+assertEq(Reflect.apply(gw.parseInt,
+ undefined,
+ ["45"]),
+ 45);
+assertEq(Reflect.apply(gw.Symbol.for,
+ undefined,
+ ["moon"]),
+ Symbol.for("moon"));
+
+gw.eval("function q() { return q; }");
+assertEq(Reflect.apply(gw.q,
+ undefined,
+ []),
+ gw.q);
+
+
+// Exceptions are propagated.
+var nope = new Error("nope");
+function fail() {
+ throw nope;
+}
+assertThrowsValue(() => Reflect.apply(fail, undefined, []),
+ nope);
+
+// Exceptions thrown by cross-compartment wrappers are re-wrapped for the
+// calling compartment.
+var gxw = gw.eval("var x = new Error('x'); x");
+gw.eval("function fail() { throw x; }");
+assertThrowsValue(() => Reflect.apply(gw.fail, undefined, []),
+ gxw);
+
+// The thisArgument is passed to the target function as the 'this' value.
+var obj = {};
+hits = 0;
+assertEq(Reflect.apply(function () { hits++; assertEq(this, obj); },
+ obj,
+ []),
+ undefined);
+assertEq(hits, 1);
+
+// Primitive values can be thisArgument.
+function strictThis() { "use strict"; return this; }
+for (var value of [null, undefined, 0, -0, NaN, Symbol("moon")]) {
+ assertEq(Reflect.apply(strictThis, value, []),
+ value);
+}
+
+// If the target is a non-strict function and thisArgument is a primitive value
+// other than null or undefined, then thisArgument is converted to a wrapper
+// object.
+var testValues = [true, 1e9, "ok", Symbol("ok")];
+function nonStrictThis(expected) {
+ assertEq(typeof this, "object");
+ assertEq(Reflect.apply(Object.prototype.toString, this, []).toLowerCase(), expected);
+ return "ok";
+}
+for (var value of testValues) {
+ assertEq(Reflect.apply(nonStrictThis,
+ value,
+ ["[object " + typeof value + "]"]),
+ "ok");
+}
+
+// For more Reflect.apply tests, see target.js and argumentsList.js.
+
+reportCompare(0, 0);
diff --git a/js/src/tests/ecma_6/Reflect/argumentsList.js b/js/src/tests/ecma_6/Reflect/argumentsList.js
new file mode 100644
index 000000000..1cd5984f0
--- /dev/null
+++ b/js/src/tests/ecma_6/Reflect/argumentsList.js
@@ -0,0 +1,164 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/ */
+
+// Tests for the argumentList argument to Reflect.apply and Reflect.construct.
+
+// Reflect.apply and Reflect.construct require an argumentList argument that must be an object.
+assertThrowsInstanceOf(() => Reflect.apply(Math.min, undefined), // missing
+ TypeError);
+assertThrowsInstanceOf(() => Reflect.construct(Object), // missing
+ TypeError);
+for (var primitive of SOME_PRIMITIVE_VALUES) {
+ assertThrowsInstanceOf(() => Reflect.apply(Math.min, undefined, primitive),
+ TypeError);
+ assertThrowsInstanceOf(() => Reflect.construct(Object, primitive),
+ TypeError);
+}
+
+// Array used by several tests below.
+var BOTH = [
+ Reflect.apply,
+ // Adapt Reflect.construct to accept the same arguments as Reflect.apply.
+ (target, thisArgument, argumentList) => Reflect.construct(target, argumentList)
+];
+
+// The argumentList is copied and becomes the list of arguments passed to the function.
+function getRest(...x) { return x; }
+var args = [1, 2, 3];
+for (var method of BOTH) {
+ var result = method(getRest, undefined, args);
+ assertEq(result.join(), args.join());
+ assertEq(result !== args, true);
+}
+
+// argumentList.length can be less than func.length.
+function testLess(a, b, c, d, e) {
+ assertEq(a, 1);
+ assertEq(b, true);
+ assertEq(c, "three");
+ assertEq(d, Symbol.for);
+ assertEq(e, undefined);
+
+ assertEq(arguments.length, 4);
+ assertEq(arguments !== args, true);
+ return "ok";
+}
+args = [1, true, "three", Symbol.for];
+assertEq(Reflect.apply(testLess, undefined, args), "ok");
+assertEq(Reflect.construct(testLess, args) instanceof testLess, true);
+
+// argumentList.length can be more than func.length.
+function testMoar(a) {
+ assertEq(a, args[0]);
+ return "good";
+}
+assertEq(Reflect.apply(testMoar, undefined, args), "good");
+assertEq(Reflect.construct(testMoar, args) instanceof testMoar, true);
+
+// argumentList can be any object with a .length property.
+function getArgs(...args) {
+ return args;
+}
+for (var method of BOTH) {
+ assertDeepEq(method(getArgs, undefined, {length: 0}),
+ []);
+ assertDeepEq(method(getArgs, undefined, {length: 1, "0": "zero"}),
+ ["zero"]);
+ assertDeepEq(method(getArgs, undefined, {length: 2}),
+ [undefined, undefined]);
+ assertDeepEq(method(getArgs, undefined, function (a, b, c) {}),
+ [undefined, undefined, undefined]);
+}
+
+// The Iterable/Iterator interfaces are not used.
+var funnyArgs = {
+ 0: "zero",
+ 1: "one",
+ length: 2,
+ [Symbol.iterator]() { throw "FAIL 1"; },
+ next() { throw "FAIL 2"; }
+};
+for (var method of BOTH) {
+ assertDeepEq(method(getArgs, undefined, funnyArgs),
+ ["zero", "one"]);
+}
+
+// If argumentList has no .length property, no arguments are passed.
+function count() { return {numArgsReceived: arguments.length}; }
+for (var method of BOTH) {
+ assertEq(method(count, undefined, {"0": 0, "1": 1}).numArgsReceived,
+ 0);
+ function* g() { yield 1; yield 2; }
+ assertEq(method(count, undefined, g()).numArgsReceived,
+ 0);
+}
+
+// If argumentsList.length has a getter, it is called.
+var log;
+args = {
+ get length() { log += "L"; return 1; },
+ get "0"() { log += "0"; return "zero"; },
+ get "1"() { log += "1"; return "one"; }
+};
+for (var method of BOTH) {
+ log = "";
+ assertDeepEq(method(getArgs, undefined, args),
+ ["zero"]);
+ assertEq(log, "L0");
+}
+
+// The argumentsList.length getter can throw; the exception is propagated.
+var exc = {status: "bad"};
+args = {
+ get length() { throw exc; }
+};
+for (var method of BOTH) {
+ assertThrowsValue(() => method(count, undefined, args), exc);
+}
+
+// If argumentsList.length is unreasonably huge, we get an error.
+// (This is an implementation limit.)
+for (var method of BOTH) {
+ for (var value of [1e12, 1e240, Infinity]) {
+ assertThrowsInstanceOf(() => method(count, undefined, {length: value}),
+ Error);
+ }
+}
+
+// argumentsList.length is converted to an integer.
+for (var value of [1.7, "1", {valueOf() { return "1"; }}]) {
+ args = {
+ length: value,
+ "0": "ponies"
+ };
+ for (var method of BOTH) {
+ var result = method(getArgs, undefined, args);
+ assertEq(result.length, 1);
+ assertEq(result[0], "ponies");
+ }
+}
+
+// If argumentsList.length is negative or NaN, no arguments are passed.
+for (var method of BOTH) {
+ for (var num of [-1, -0.1, -0, -1e99, -Infinity, NaN]) {
+ assertEq(method(count, undefined, {length: num}).numArgsReceived,
+ 0);
+ }
+}
+
+// Many arguments can be passed.
+var many = 65537;
+var args = {length: many, 0: "zero", [many - 1]: "last"};
+function testMany(...args) {
+ for (var i = 0; i < many; i++) {
+ assertEq(i in args, true);
+ assertEq(args[i], i === 0 ? "zero" : i === many - 1 ? "last" : undefined);
+ }
+ return this;
+}
+assertEq(Reflect.apply(testMany, "pass", args).toString(), "pass");
+assertEq(Reflect.construct(testMany, args) instanceof testMany, true);
+assertEq(Reflect.apply(new Proxy(testMany, {}), "pass", args).toString(), "pass");
+assertEq(Reflect.construct(new Proxy(testMany, {}), args) instanceof testMany, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/ecma_6/Reflect/browser.js b/js/src/tests/ecma_6/Reflect/browser.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/ecma_6/Reflect/browser.js
diff --git a/js/src/tests/ecma_6/Reflect/construct.js b/js/src/tests/ecma_6/Reflect/construct.js
new file mode 100644
index 000000000..7dbb9bfa7
--- /dev/null
+++ b/js/src/tests/ecma_6/Reflect/construct.js
@@ -0,0 +1,107 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/ */
+
+// Reflect.construct invokes constructors.
+
+assertDeepEq(Reflect.construct(Object, []), {});
+assertDeepEq(Reflect.construct(String, ["hello"]), new String("hello"));
+
+// Constructing Date creates a real Date object.
+var d = Reflect.construct(Date, [1776, 6, 4]);
+assertEq(d instanceof Date, true);
+assertEq(d.getFullYear(), 1776); // non-generic method requires real Date object
+
+// [[Construct]] methods don't necessarily create new objects.
+var obj = {};
+assertEq(Reflect.construct(Object, [obj]), obj);
+
+
+// === Various kinds of constructors
+// We've already seen some builtin constructors.
+//
+// JS functions:
+function f(x) { this.x = x; }
+assertDeepEq(Reflect.construct(f, [3]), new f(3));
+f.prototype = Array.prototype;
+assertDeepEq(Reflect.construct(f, [3]), new f(3));
+
+// Bound functions:
+var bound = f.bind(null, "carrot");
+assertDeepEq(Reflect.construct(bound, []), new bound);
+
+// Classes:
+class Base {
+ constructor(...args) {
+ this.args = args;
+ this.newTarget = new.target;
+ }
+}
+class Derived extends Base {
+ constructor(...args) { super(...args); }
+}
+
+assertDeepEq(Reflect.construct(Base, []), new Base);
+assertDeepEq(Reflect.construct(Derived, [7]), new Derived(7));
+g = Derived.bind(null, "q");
+assertDeepEq(Reflect.construct(g, [8, 9]), new g(8, 9));
+
+// Cross-compartment wrappers:
+var g = newGlobal();
+var local = {here: this};
+g.eval("function F(arg) { this.arg = arg }");
+assertDeepEq(Reflect.construct(g.F, [local]), new g.F(local));
+
+// If first argument to Reflect.construct isn't a constructor, it throws a
+// TypeError.
+var nonConstructors = [
+ {},
+ Reflect.construct, // builtin functions aren't constructors
+ x => x + 1,
+ Math.max.bind(null, 0), // bound non-constructors aren't constructors
+ ((x, y) => x > y).bind(null, 0),
+
+ // A Proxy to a non-constructor function isn't a constructor, even if a
+ // construct handler is present.
+ new Proxy(Reflect.construct, {construct(){}}),
+];
+for (var obj of nonConstructors) {
+ assertThrowsInstanceOf(() => Reflect.construct(obj, []), TypeError);
+ assertThrowsInstanceOf(() => Reflect.construct(obj, [], Object), TypeError);
+}
+
+
+// === new.target tests
+
+// If the newTarget argument to Reflect.construct is missing, the target is used.
+function checkNewTarget() {
+ assertEq(new.target, expected);
+ expected = undefined;
+}
+var expected = checkNewTarget;
+Reflect.construct(checkNewTarget, []);
+
+// The newTarget argument is correctly passed to the constructor.
+var constructors = [Object, Function, f, bound];
+for (var ctor of constructors) {
+ expected = ctor;
+ Reflect.construct(checkNewTarget, [], ctor);
+ assertEq(expected, undefined);
+}
+
+// The newTarget argument must be a constructor.
+for (var v of SOME_PRIMITIVE_VALUES.concat(nonConstructors)) {
+ assertThrowsInstanceOf(() => Reflect.construct(checkNewTarget, [], v), TypeError);
+}
+
+// The builtin Array constructor uses new.target.prototype and always
+// creates a real array object.
+function someConstructor() {}
+var result = Reflect.construct(Array, [], someConstructor);
+assertEq(Reflect.getPrototypeOf(result), someConstructor.prototype);
+assertEq(result.length, 0);
+assertEq(Array.isArray(result), true);
+
+
+// For more Reflect.construct tests, see target.js and argumentsList.js.
+
+reportCompare(0, 0);
diff --git a/js/src/tests/ecma_6/Reflect/defineProperty.js b/js/src/tests/ecma_6/Reflect/defineProperty.js
new file mode 100644
index 000000000..c3b1e8600
--- /dev/null
+++ b/js/src/tests/ecma_6/Reflect/defineProperty.js
@@ -0,0 +1,164 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/ */
+
+// Reflect.defineProperty defines properties.
+var obj = {};
+assertEq(Reflect.defineProperty(obj, "x", {value: 7}), true);
+assertEq(obj.x, 7);
+var desc = Reflect.getOwnPropertyDescriptor(obj, "x");
+assertDeepEq(desc, {value: 7,
+ writable: false,
+ enumerable: false,
+ configurable: false});
+
+// Reflect.defineProperty can define a symbol-keyed property.
+var key = Symbol(":o)");
+assertEq(Reflect.defineProperty(obj, key, {value: 8}), true);
+assertEq(obj[key], 8);
+
+// array .length property
+obj = [1, 2, 3, 4, 5];
+assertEq(Reflect.defineProperty(obj, "length", {value: 4}), true);
+assertDeepEq(obj, [1, 2, 3, 4]);
+
+// The target can be a proxy.
+obj = {};
+var proxy = new Proxy(obj, {
+ defineProperty(t, id, desc) {
+ t[id] = 1;
+ return true;
+ }
+});
+assertEq(Reflect.defineProperty(proxy, "prop", {value: 7}), true);
+assertEq(obj.prop, 1);
+assertEq(delete obj.prop, true);
+assertEq("prop" in obj, false);
+
+// The attributes object is re-parsed, not passed through to the
+// handler.defineProperty method.
+obj = {};
+var attributes = {
+ configurable: 17,
+ enumerable: undefined,
+ value: null
+};
+proxy = new Proxy(obj, {
+ defineProperty(t, id, desc) {
+ assertEq(desc !== attributes, true);
+ assertEq(desc.configurable, true);
+ assertEq(desc.enumerable, false);
+ assertEq(desc.value, null);
+ assertEq("writable" in desc, false);
+ return 15; // and the return value here is coerced to boolean
+ }
+});
+assertEq(Reflect.defineProperty(proxy, "prop", attributes), true);
+
+
+// === Failure and error cases
+//
+// Reflect.defineProperty behaves much like Object.defineProperty, which has
+// extremely thorough tests elsewhere, and the implementation is largely
+// shared. Duplicating those tests with Reflect.defineProperty would be a
+// big waste.
+//
+// However, certain failures cause Reflect.defineProperty to return false
+// without throwing a TypeError (unlike Object.defineProperty). So here we test
+// many error cases to check that behavior.
+
+// missing attributes argument
+assertThrowsInstanceOf(() => Reflect.defineProperty(obj, "y"),
+ TypeError);
+
+// non-object attributes argument
+for (var attributes of SOME_PRIMITIVE_VALUES) {
+ assertThrowsInstanceOf(() => Reflect.defineProperty(obj, "y", attributes),
+ TypeError);
+}
+
+// inextensible object
+obj = Object.preventExtensions({});
+assertEq(Reflect.defineProperty(obj, "prop", {value: 4}), false);
+
+// inextensible object with irrelevant inherited property
+obj = Object.preventExtensions(Object.create({"prop": 3}));
+assertEq(Reflect.defineProperty(obj, "prop", {value: 4}), false);
+
+// redefine nonconfigurable to configurable
+obj = Object.freeze({prop: 1});
+assertEq(Reflect.defineProperty(obj, "prop", {configurable: true}), false);
+
+// redefine enumerability of nonconfigurable property
+obj = Object.freeze(Object.defineProperties({}, {
+ x: {enumerable: true, configurable: false, value: 0},
+ y: {enumerable: false, configurable: false, value: 0},
+}));
+assertEq(Reflect.defineProperty(obj, "x", {enumerable: false}), false);
+assertEq(Reflect.defineProperty(obj, "y", {enumerable: true}), false);
+
+// redefine nonconfigurable data to accessor property, or vice versa
+obj = Object.seal({x: 1, get y() { return 2; }});
+assertEq(Reflect.defineProperty(obj, "x", {get() { return 2; }}), false);
+assertEq(Reflect.defineProperty(obj, "y", {value: 1}), false);
+
+// redefine nonwritable, nonconfigurable property as writable
+obj = Object.freeze({prop: 0});
+assertEq(Reflect.defineProperty(obj, "prop", {writable: true}), false);
+assertEq(Reflect.defineProperty(obj, "prop", {writable: false}), true); // no-op
+
+// change value of nonconfigurable nonwritable property
+obj = Object.freeze({prop: 0});
+assertEq(Reflect.defineProperty(obj, "prop", {value: -0}), false);
+assertEq(Reflect.defineProperty(obj, "prop", {value: +0}), true); // no-op
+
+// change getter or setter
+function g() {}
+function s(x) {}
+obj = {};
+Object.defineProperty(obj, "prop", {get: g, set: s, configurable: false});
+assertEq(Reflect.defineProperty(obj, "prop", {get: s}), false);
+assertEq(Reflect.defineProperty(obj, "prop", {get: g}), true); // no-op
+assertEq(Reflect.defineProperty(obj, "prop", {set: g}), false);
+assertEq(Reflect.defineProperty(obj, "prop", {set: s}), true); // no-op
+
+// Proxy defineProperty handler method that returns false
+var falseValues = [false, 0, -0, "", NaN, null, undefined];
+if (typeof objectEmulatingUndefined === "function")
+ falseValues.push(objectEmulatingUndefined());
+var value;
+proxy = new Proxy({}, {
+ defineProperty(t, id, desc) {
+ return value;
+ }
+});
+for (value of falseValues) {
+ assertEq(Reflect.defineProperty(proxy, "prop", {value: 1}), false);
+}
+
+// Proxy defineProperty handler method returns true, in violation of invariants.
+// Per spec, this is a TypeError, not a false return.
+obj = Object.freeze({x: 1});
+proxy = new Proxy(obj, {
+ defineProperty(t, id, desc) {
+ return true;
+ }
+});
+assertThrowsInstanceOf(() => Reflect.defineProperty(proxy, "x", {value: 2}), TypeError);
+assertThrowsInstanceOf(() => Reflect.defineProperty(proxy, "y", {value: 0}), TypeError);
+assertEq(Reflect.defineProperty(proxy, "x", {value: 1}), true);
+
+// The second argument is converted ToPropertyKey before any internal methods
+// are called on the first argument.
+var poison =
+ (counter => new Proxy({}, new Proxy({}, { get() { throw counter++; } })))(42);
+assertThrowsValue(() => {
+ Reflect.defineProperty(poison, {
+ toString() { throw 17; },
+ valueOf() { throw 8675309; }
+ }, poison);
+}, 17);
+
+
+// For more Reflect.defineProperty tests, see target.js and propertyKeys.js.
+
+reportCompare(0, 0);
diff --git a/js/src/tests/ecma_6/Reflect/deleteProperty.js b/js/src/tests/ecma_6/Reflect/deleteProperty.js
new file mode 100644
index 000000000..744e0f571
--- /dev/null
+++ b/js/src/tests/ecma_6/Reflect/deleteProperty.js
@@ -0,0 +1,80 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/ */
+
+// Reflect.deleteProperty deletes properties.
+var obj = {x: 1, y: 2};
+assertEq(Reflect.deleteProperty(obj, "x"), true);
+assertDeepEq(obj, {y: 2});
+
+var arr = [1, 1, 2, 3, 5];
+assertEq(Reflect.deleteProperty(arr, "3"), true);
+assertDeepEq(arr, [1, 1, 2, , 5]);
+
+
+// === Failure and error cases
+// Since Reflect.deleteProperty is almost exactly identical to the non-strict
+// `delete` operator, there is not much to test that would not be redundant.
+
+// Returns true if no such property exists.
+assertEq(Reflect.deleteProperty({}, "q"), true);
+
+// Or if it's inherited.
+var proto = {x: 1};
+assertEq(Reflect.deleteProperty(Object.create(proto), "x"), true);
+assertEq(proto.x, 1);
+
+// Return false if asked to delete a non-configurable property.
+var arr = [];
+assertEq(Reflect.deleteProperty(arr, "length"), false);
+assertEq(arr.hasOwnProperty("length"), true);
+assertEq(Reflect.deleteProperty(this, "undefined"), false);
+assertEq(this.undefined, void 0);
+
+// Return false if a Proxy's deleteProperty handler returns a false-y value.
+var value;
+var proxy = new Proxy({}, {
+ deleteProperty(t, k) {
+ return value;
+ }
+});
+for (value of [true, false, 0, "something", {}]) {
+ assertEq(Reflect.deleteProperty(proxy, "q"), !!value);
+}
+
+// If a Proxy's handler method throws, the error is propagated.
+proxy = new Proxy({}, {
+ deleteProperty(t, k) { throw "vase"; }
+});
+assertThrowsValue(() => Reflect.deleteProperty(proxy, "prop"), "vase");
+
+// Throw a TypeError if a Proxy's handler method returns true in violation of
+// the object invariants.
+proxy = new Proxy(Object.freeze({prop: 1}), {
+ deleteProperty(t, k) { return true; }
+});
+assertThrowsInstanceOf(() => Reflect.deleteProperty(proxy, "prop"), TypeError);
+
+
+// === Deleting elements from `arguments`
+
+// Non-strict arguments element becomes unmapped
+function f(x, y, z) {
+ assertEq(Reflect.deleteProperty(arguments, "0"), true);
+ arguments.x = 33;
+ return x;
+}
+assertEq(f(17, 19, 23), 17);
+
+// Frozen non-strict arguments element
+function testFrozenArguments() {
+ Object.freeze(arguments);
+ assertEq(Reflect.deleteProperty(arguments, "0"), false);
+ assertEq(arguments[0], "zero");
+ assertEq(arguments[1], "one");
+}
+testFrozenArguments("zero", "one");
+
+
+// For more Reflect.deleteProperty tests, see target.js and propertyKeys.js.
+
+reportCompare(0, 0);
diff --git a/js/src/tests/ecma_6/Reflect/get.js b/js/src/tests/ecma_6/Reflect/get.js
new file mode 100644
index 000000000..b38b188b0
--- /dev/null
+++ b/js/src/tests/ecma_6/Reflect/get.js
@@ -0,0 +1,72 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/ */
+
+// Reflect.get gets the value of a property.
+
+var x = {p: 1};
+assertEq(Reflect.get(x, "p"), 1);
+assertEq(Reflect.get(x, "toString"), Object.prototype.toString);
+assertEq(Reflect.get(x, "missing"), undefined);
+
+
+// === Various targets
+
+// Array
+assertEq(Reflect.get([], 700), undefined);
+assertEq(Reflect.get(["zero", "one"], 1), "one");
+
+// TypedArray
+assertEq(Reflect.get(new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7]), 7), 7);
+
+// Treatment of NaN
+var f = new Float64Array([NaN]);
+var u = new Uint32Array(f.buffer);
+u[0]++;
+u[1]++;
+assertEq(f[0], NaN);
+assertEq(Reflect.get(f, 0), NaN);
+
+// Proxy with no get handler
+assertEq(Reflect.get(new Proxy(x, {}), "p"), 1);
+
+// Proxy with a get handler
+var obj = new Proxy(x, {
+ get(t, k, r) { return k + "ful"; }
+});
+assertEq(Reflect.get(obj, "mood"), "moodful");
+
+// Exceptions thrown by a proxy's get handler are propagated.
+assertThrowsInstanceOf(() => Reflect.get(obj, Symbol()), TypeError);
+
+// Ordinary object, property has a setter and no getter
+obj = {set name(x) {}};
+assertEq(Reflect.get(obj, "name"), undefined);
+
+
+// === Receiver
+
+// Receiver argument is passed to getters as the this-value.
+obj = { get x() { return this; }};
+assertEq(Reflect.get(obj, "x", Math), Math);
+assertEq(Reflect.get(Object.create(obj), "x", JSON), JSON);
+
+// If missing, target is passed instead.
+assertEq(Reflect.get(obj, "x"), obj);
+
+// Receiver argument is passed to the proxy get handler.
+obj = new Proxy({}, {
+ get(t, k, r) {
+ assertEq(k, "itself");
+ return r;
+ }
+});
+assertEq(Reflect.get(obj, "itself"), obj);
+assertEq(Reflect.get(obj, "itself", Math), Math);
+assertEq(Reflect.get(Object.create(obj), "itself", Math), Math);
+
+// The receiver shouldn't have to be an object
+assertEq(Reflect.get(obj, "itself", 37.2), 37.2);
+
+// For more Reflect.get tests, see target.js and propertyKeys.js.
+
+reportCompare(0, 0);
diff --git a/js/src/tests/ecma_6/Reflect/getOwnPropertyDescriptor.js b/js/src/tests/ecma_6/Reflect/getOwnPropertyDescriptor.js
new file mode 100644
index 000000000..aa7329778
--- /dev/null
+++ b/js/src/tests/ecma_6/Reflect/getOwnPropertyDescriptor.js
@@ -0,0 +1,21 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/ */
+
+// Reflect.getOwnPropertyDescriptor inspects object properties.
+assertDeepEq(
+ Reflect.getOwnPropertyDescriptor({x: "hello"}, "x"),
+ {value: "hello", writable: true, enumerable: true, configurable: true});
+assertEq(
+ Reflect.getOwnPropertyDescriptor({x: "hello"}, "y"),
+ undefined);
+assertDeepEq(
+ Reflect.getOwnPropertyDescriptor([], "length"),
+ {value: 0, writable: true, enumerable: false, configurable: false});
+
+// Reflect.getOwnPropertyDescriptor shares its implementation with
+// Object.getOwnPropertyDescriptor. The only difference is how non-object
+// targets are handled.
+//
+// For more Reflect.getOwnPropertyDescriptor tests, see target.js and propertyKeys.js.
+
+reportCompare(0, 0);
diff --git a/js/src/tests/ecma_6/Reflect/getPrototypeOf.js b/js/src/tests/ecma_6/Reflect/getPrototypeOf.js
new file mode 100644
index 000000000..6a29d4a9b
--- /dev/null
+++ b/js/src/tests/ecma_6/Reflect/getPrototypeOf.js
@@ -0,0 +1,17 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/ */
+
+// Reflect.getPrototypeOf returns an object's prototype.
+assertEq(Reflect.getPrototypeOf({}), Object.prototype);
+assertEq(Reflect.getPrototypeOf(Object.prototype), null);
+assertEq(Reflect.getPrototypeOf(Object.create(null)), null);
+
+var proxy = new Proxy({}, {
+ getPrototypeOf(t) { return Math; }
+});
+
+assertEq(Reflect.getPrototypeOf(proxy), Math);
+
+// For more Reflect.getPrototypeOf tests, see target.js.
+
+reportCompare(0, 0);
diff --git a/js/src/tests/ecma_6/Reflect/has.js b/js/src/tests/ecma_6/Reflect/has.js
new file mode 100644
index 000000000..6019a61ed
--- /dev/null
+++ b/js/src/tests/ecma_6/Reflect/has.js
@@ -0,0 +1,41 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/ */
+
+// Reflect.has is identical to the `in` operator.
+assertEq(Reflect.has({x: 0}, "x"), true);
+assertEq(Reflect.has({x: 0}, "y"), false);
+assertEq(Reflect.has({x: 0}, "toString"), true);
+
+// The target can be an array; Reflect.has works on array elements.
+var arr = ["zero"];
+arr[10000] = 0;
+assertEq(Reflect.has(arr, "10000"), true);
+assertEq(Reflect.has(arr, 10000), true);
+assertEq(Reflect.has(arr, "-0"), false);
+assertEq(Reflect.has(arr, -0), true);
+
+// And string objects (though not string primitives; see target.js).
+var str = new String("hello");
+assertEq(Reflect.has(str, "4"), true);
+assertEq(Reflect.has(str, "-0"), false);
+assertEq(Reflect.has(str, -0), true);
+
+// Proxy without .has() handler method
+var obj = {get prop() {}};
+for (var i = 0; i < 2; i++) {
+ obj = new Proxy(obj, {});
+ assertEq(Reflect.has(obj, "prop"), true);
+ assertEq(Reflect.has(obj, "nope"), false);
+}
+
+// Proxy with .has() handler method
+obj = new Proxy({}, {
+ has(t, k) { return k.startsWith("door"); }
+});
+assertEq(Reflect.has(obj, "doorbell"), true);
+assertEq(Reflect.has(obj, "dormitory"), false);
+
+
+// For more Reflect.has tests, see target.js and propertyKeys.js.
+
+reportCompare(0, 0);
diff --git a/js/src/tests/ecma_6/Reflect/isExtensible.js b/js/src/tests/ecma_6/Reflect/isExtensible.js
new file mode 100644
index 000000000..f38724875
--- /dev/null
+++ b/js/src/tests/ecma_6/Reflect/isExtensible.js
@@ -0,0 +1,57 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/ */
+
+// Reflect.isExtensible behaves just like Object.extensible except when the
+// target argument is missing or is not an object (and that behavior is tested
+// in target.js).
+
+// Test basic functionality.
+var someObjects = [
+ {},
+ {a: "a"},
+ [0, 1],
+ new Uint8Array(64),
+ Object(Symbol("table")),
+ new Proxy({}, {})
+];
+if (typeof SharedArrayBuffer != "undefined")
+ someObjects.push(new Uint8Array(new SharedArrayBuffer(64)));
+
+for (var obj of someObjects) {
+ assertEq(Reflect.isExtensible(obj), true);
+ assertEq(Reflect.preventExtensions(obj), true);
+ assertEq(Reflect.isExtensible(obj), false);
+}
+
+// Array with nonwritable length.
+var arr = [0, 1, 2, 3];
+Object.defineProperty(arr, "length", {writable: false});
+assertEq(Reflect.isExtensible(arr), true);
+
+// Proxy case.
+for (var ext of [true, false]) {
+ var obj = {};
+ if (!ext)
+ Object.preventExtensions(obj);
+ var proxy = new Proxy(obj, {
+ isExtensible() { return ext; }
+ });
+ assertEq(Reflect.isExtensible(proxy), ext);
+}
+
+// If a Proxy's isExtensible method throws, the exception is propagated.
+proxy = new Proxy({}, {
+ isExtensible() { throw "oops"; }
+});
+assertThrowsValue(() => Reflect.isExtensible(proxy), "oops");
+
+// If an invariant is broken, [[IsExtensible]] does not return false. It throws
+// a TypeError.
+proxy = new Proxy({}, {
+ isExtensible() { return false; }
+});
+assertThrowsInstanceOf(() => Reflect.isExtensible(proxy), TypeError);
+
+// For more Reflect.isExtensible tests, see target.js.
+
+reportCompare(0, 0);
diff --git a/js/src/tests/ecma_6/Reflect/ownKeys.js b/js/src/tests/ecma_6/Reflect/ownKeys.js
new file mode 100644
index 000000000..5433562eb
--- /dev/null
+++ b/js/src/tests/ecma_6/Reflect/ownKeys.js
@@ -0,0 +1,66 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/ */
+
+// Reflect.ownKeys(obj) returns an array of an object's own property keys.
+
+// Test that Reflect.ownKeys gets the expected result when applied to various
+// objects. (These tests also check the basics: that the result is an array,
+// that its prototype is correct, etc.)
+var sym = Symbol.for("comet");
+var sym2 = Symbol.for("meteor");
+var cases = [
+ {object: {z: 3, y: 2, x: 1},
+ keys: ["z", "y", "x"]},
+ {object: [],
+ keys: ["length"]},
+ {object: new Int8Array(4),
+ keys: ["0", "1", "2", "3"]},
+ {object: new Proxy({a: 7}, {}),
+ keys: ["a"]},
+ {object: {[sym]: "ok"},
+ keys: [sym]},
+ {object: {[sym]: 0, // test 9.1.12 ordering
+ "str": 0,
+ "773": 0,
+ "0": 0,
+ [sym2]: 0,
+ "-1": 0,
+ "8": 0,
+ "second str": 0},
+ keys: ["0", "8", "773", // indexes in numeric order
+ "str", "-1", "second str", // strings in insertion order
+ sym, sym2]}, // symbols in insertion order
+ {object: newGlobal().Math, // cross-compartment wrapper
+ keys: Reflect.ownKeys(Math)}
+];
+for (var {object, keys} of cases)
+ assertDeepEq(Reflect.ownKeys(object), keys);
+
+// Reflect.ownKeys() creates a new array each time it is called.
+var object = {}, keys = [];
+for (var i = 0; i < 3; i++) {
+ var newKeys = Reflect.ownKeys(object);
+ assertEq(newKeys !== keys, true);
+ keys = newKeys;
+}
+
+// Proxy behavior with successful ownKeys() handler
+keys = ["str", "0"];
+obj = {};
+proxy = new Proxy(obj, {
+ ownKeys() { return keys; }
+});
+var actual = Reflect.ownKeys(proxy);
+assertDeepEq(actual, keys); // we get correct answers
+assertEq(actual !== keys, true); // but not the same object
+
+// If a proxy breaks invariants, a TypeError is thrown.
+var obj = Object.preventExtensions({});
+var proxy = new Proxy(obj, {
+ ownKeys() { return ["something"]; }
+});
+assertThrowsInstanceOf(() => Reflect.ownKeys(proxy), TypeError);
+
+// For more Reflect.ownKeys tests, see target.js.
+
+reportCompare(0, 0);
diff --git a/js/src/tests/ecma_6/Reflect/preventExtensions.js b/js/src/tests/ecma_6/Reflect/preventExtensions.js
new file mode 100644
index 000000000..63ca2545b
--- /dev/null
+++ b/js/src/tests/ecma_6/Reflect/preventExtensions.js
@@ -0,0 +1,56 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/ */
+
+// Reflect.preventExtensions is the same as Object.preventExtensions, except
+// for the return value and the behavior in error cases.
+
+var someObjects = [
+ {},
+ new Int32Array(7),
+ Object(Symbol("table")),
+ new Proxy({}, {})
+];
+
+for (var obj of someObjects) {
+ assertEq(Reflect.preventExtensions(obj), true);
+ // [[PreventExtensions]] on an already-inextensible object is a no-op.
+ assertEq(Reflect.preventExtensions(obj), true);
+}
+
+// Error cases.
+assertThrowsInstanceOf(() => Reflect.isExtensible(), TypeError);
+for (var value of [undefined, null, true, 1, NaN, "Phaedo", Symbol("good")]) {
+ assertThrowsInstanceOf(() => Reflect.isExtensible(value), TypeError);
+}
+
+// A proxy's preventExtensions handler can return false without doing anything.
+obj = {};
+var proxy = new Proxy(obj, {
+ preventExtensions() { return false; }
+});
+assertEq(Reflect.preventExtensions(proxy), false);
+assertEq(Reflect.isExtensible(obj), true);
+assertEq(Reflect.isExtensible(proxy), true);
+
+// If a proxy's preventExtensions handler throws, the exception is propagated.
+obj = {};
+proxy = new Proxy(obj, {
+ preventExtensions() { throw "fit"; }
+});
+assertThrowsValue(() => Reflect.preventExtensions(proxy), "fit");
+assertEq(Reflect.isExtensible(obj), true);
+assertEq(Reflect.isExtensible(proxy), true);
+
+// If a proxy's preventExtensions handler returns true while leaving the target
+// extensible, that's a TypeError.
+obj = {};
+proxy = new Proxy(obj, {
+ preventExtensions() { return true; }
+});
+assertThrowsInstanceOf(() => Reflect.preventExtensions(proxy), TypeError);
+assertEq(Reflect.isExtensible(obj), true);
+assertEq(Reflect.isExtensible(proxy), true);
+
+// For more Reflect.preventExtensions tests, see target.js.
+
+reportCompare(0, 0);
diff --git a/js/src/tests/ecma_6/Reflect/propertyKeys.js b/js/src/tests/ecma_6/Reflect/propertyKeys.js
new file mode 100644
index 000000000..6495a96fd
--- /dev/null
+++ b/js/src/tests/ecma_6/Reflect/propertyKeys.js
@@ -0,0 +1,84 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/ */
+
+// Test corner cases involving Reflect methods' propertyKey arguments.
+
+// keys - Array of propertyKey values to be tested.
+//
+// Each element of this array is a record with these properties:
+//
+// * value: a value that will be passed as a property key
+// to the various Reflect methods;
+//
+// * expected: (optional) the string or symbol that ToPropertyKey(value)
+// should return. If this is omitted, ToPropertyKey(value) === value.
+//
+var keys = [
+ {value: null, expected: "null"},
+ {value: undefined, expected: "undefined"},
+ {value: true, expected: "true"},
+ {value: 42, expected: "42"},
+ {value: "string"},
+ {value: ""},
+ {value: "string with \0"},
+ {value: new String("ok"), expected: "ok"},
+ {value: Symbol("sym")},
+ {value: Symbol.iterator},
+ {value: Object(Symbol.for("comet")), expected: Symbol.for("comet")},
+ {
+ value: {
+ toString() { return "key"; },
+ valueOf() { return "bad"; }
+ },
+ expected: "key"
+ },
+ {
+ value: {
+ toString: undefined,
+ valueOf() { return "fallback"; }
+ },
+ expected: "fallback"
+ },
+ {
+ value: {
+ [Symbol.toPrimitive](hint) { return hint; }
+ },
+ expected: "string"
+ },
+ {
+ value: {
+ [Symbol.toPrimitive](hint) { return Symbol.for(hint); }
+ },
+ expected: Symbol.for("string")
+ }
+];
+
+for (var {value, expected} of keys) {
+ if (expected === undefined)
+ expected = value;
+
+ var obj = {};
+ assertEq(Reflect.defineProperty(obj, value, {value: 1, configurable: true}), true);
+ assertDeepEq(Reflect.ownKeys(obj), [expected]);
+ assertDeepEq(Reflect.getOwnPropertyDescriptor(obj, value),
+ {value: 1,
+ writable: false,
+ enumerable: false,
+ configurable: true});
+ assertEq(Reflect.deleteProperty(obj, value), true);
+ assertEq(Reflect.has(obj, value), false);
+ assertEq(Reflect.set(obj, value, 113), true);
+ assertEq(obj[expected], 113);
+ assertEq(Reflect.has(obj, value), true);
+ assertEq(Reflect.get(obj, value), 113);
+}
+
+// ToPropertyKey can throw.
+var exc = {};
+var badKey = {toString() { throw exc; }};
+var methodNames = ["defineProperty", "deleteProperty", "has", "get", "getOwnPropertyDescriptor", "set"];
+for (var name of methodNames) {
+ assertThrowsValue(() => Reflect[name]({}, badKey), exc);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/ecma_6/Reflect/set.js b/js/src/tests/ecma_6/Reflect/set.js
new file mode 100644
index 000000000..83cd98b69
--- /dev/null
+++ b/js/src/tests/ecma_6/Reflect/set.js
@@ -0,0 +1,280 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/ */
+
+// Reflect.set does property assignment.
+// With three arguments, this is pretty straightforward.
+var obj = {};
+assertEq(Reflect.set(obj, "prop", "value"), true);
+assertEq(obj.prop, "value");
+
+
+// === Various targets
+
+// It can assign array elements.
+var arr = ["duck", "duck", "duck"];
+assertEq(Reflect.set(arr, 2, "goose"), true);
+assertEq(arr[2], "goose");
+
+// It can extend an array.
+assertEq(Reflect.set(arr, 3, "Model T"), true);
+assertEq(arr.length, 4);
+
+// It can truncate an array.
+assertEq(Reflect.set(arr, "length", 1), true);
+assertDeepEq(arr, ["duck"]);
+
+// It won't assign to non-writable properties of String objects.
+var str = new String("hello");
+assertEq(Reflect.set(str, "0", "y"), false);
+assertEq(str[0], "h");
+assertEq(Reflect.set(str, "length", 700), false);
+assertEq(str.length, 5);
+
+
+// === Receivers
+// The optional fourth argument is the receiver, which [[Set]] methods use for
+// various things.
+
+// On ordinary objects, if the property has a setter, the receiver is passed as
+// the this-value to the setter.
+var expected;
+var obj = {
+ set prop(v) {
+ "use strict";
+ assertEq(v, 32);
+ assertEq(this, expected);
+ }
+};
+for (expected of [obj, {}, [], 37.3]) {
+ assertEq(Reflect.set(obj, "prop", 32, expected), true);
+}
+
+// If the property doesn't already exist, it is defined on the receiver.
+obj = {};
+var obj2 = {};
+assertEq(Reflect.set(obj, "prop", 47, obj2), true);
+assertDeepEq(obj, {});
+assertDeepEq(Reflect.getOwnPropertyDescriptor(obj2, "prop"),
+ {value: 47, writable: true, enumerable: true, configurable: true});
+
+// If the property doesn't already exist, and the receiver isn't an object, return false.
+for (var v of SOME_PRIMITIVE_VALUES) {
+ assertEq(Reflect.set({}, "x", 0, v), false);
+}
+
+// Receiver defaults to the target.
+obj = {};
+var hits;
+var expectedReceiver;
+var proxy = new Proxy(obj, {
+ set(t, k, v, r) {
+ assertEq(t, obj);
+ assertEq(k, "key");
+ assertEq(v, "value");
+ assertEq(r, expectedReceiver); // not obj
+ hits++;
+ return true;
+ }
+});
+hits = 0;
+expectedReceiver = proxy;
+assertEq(Reflect.set(proxy, "key", "value"), true);
+assertEq(hits, 1);
+
+// But not if explicitly present and undefined.
+hits = 0;
+expectedReceiver = undefined;
+assertEq(Reflect.set(proxy, "key", "value", undefined), true);
+assertEq(hits, 1);
+
+// Reflect.set can be used as fallback behavior in a proxy handler .set()
+// method.
+var log;
+obj = {
+ set prop(v) {
+ log += "p";
+ assertEq(v, "value");
+ assertEq(this, proxy); // not obj!
+ }
+};
+proxy = new Proxy(obj, {
+ set(t, k, v, r) {
+ assertEq(t, obj);
+ assertEq(r, proxy);
+ log += "s";
+ return Reflect.set(t, k, v, r);
+ }
+});
+log = "";
+assertEq(Reflect.set(proxy, "prop", "value"), true);
+assertEq(log, "sp");
+
+
+// === Cross-compartment wrapper behavior.
+
+// When calling a cross-compartment wrapper, receiver is rewrapped for the
+// target compartment.
+var g = newGlobal();
+if (!("assertEq" in g))
+ g.assertEq = assertEq; // necessary in the browser
+g.eval(`
+ var hits;
+ var obj = {
+ set x(v) {
+ "use strict";
+ assertEq(this, receiver);
+ assertEq(v, "xyzzy");
+ hits++;
+ }
+ };
+ var receiver = {};
+`);
+g.hits = 0;
+assertEq(Reflect.set(g.obj, "x", "xyzzy", g.receiver), true);
+assertEq(g.hits, 1);
+
+// ...even when receiver is from a different compartment than target.
+var receiver = {};
+g.receiver = receiver;
+g.hits = 0;
+assertEq(Reflect.set(g.obj, "x", "xyzzy", receiver), true);
+assertEq(g.hits, 1);
+
+// ...even when receiver is a primtive value, even undefined.
+for (receiver of SOME_PRIMITIVE_VALUES) {
+ g.receiver = receiver;
+ g.hits = 0;
+ assertEq(Reflect.set(g.obj, "x", "xyzzy", receiver), true);
+ assertEq(g.hits, 1);
+}
+
+
+// === Less than 3 arguments
+
+// With two arguments, the value is assumed to be undefined.
+obj = {};
+assertEq(Reflect.set(obj, "size"), true);
+assertDeepEq(Reflect.getOwnPropertyDescriptor(obj, "size"),
+ {value: undefined, writable: true, enumerable: true, configurable: true});
+
+// With just one argument, the key is "undefined".
+obj = {};
+assertEq(Reflect.set(obj), true);
+assertDeepEq(Reflect.getOwnPropertyDescriptor(obj, "undefined"),
+ {value: undefined, writable: true, enumerable: true, configurable: true});
+
+// For the no argument-case, see target.js.
+
+
+// === Failure cases
+
+// Non-writable data property
+obj = {};
+Reflect.defineProperty(obj, "x", {value: 0, writable: false});
+assertEq(Reflect.set(obj, "x", 1), false);
+assertEq(obj.x, 0);
+
+// The same, but inherited from a prototype
+var obj2 = Object.create(obj);
+assertEq(Reflect.set(obj2, "x", 1), false);
+assertEq(obj2.hasOwnProperty("x"), false);
+assertEq(obj2.x, 0);
+
+// Getter, no setter
+obj = {};
+var desc = {get: () => 12, set: undefined, enumerable: false, configurable: true};
+Reflect.defineProperty(obj, "y", desc);
+assertEq(Reflect.set(obj, "y", 13), false);
+assertDeepEq(Reflect.getOwnPropertyDescriptor(obj, "y"), desc);
+
+// The same, but inherited from a prototype
+obj2 = Object.create(obj);
+assertEq(Reflect.set(obj2, "y", 1), false);
+assertEq(obj2.hasOwnProperty("y"), false);
+assertDeepEq(Reflect.getOwnPropertyDescriptor(obj, "y"), desc);
+
+// Proxy set handler returns a false value
+for (var no of [false, ""]) {
+ var hits = 0;
+ obj = {};
+ var proxy = new Proxy(obj, {
+ set(t, k, v, r) {
+ assertEq(t, obj);
+ assertEq(k, "x");
+ assertEq(v, 33);
+ assertEq(r, proxy);
+ hits++;
+ return no;
+ }
+ });
+ assertEq(Reflect.set(proxy, "x", 33), false);
+ assertEq(hits, 1);
+ assertEq("x" in obj, false);
+}
+
+// Proxy handler method throws
+obj = {};
+proxy = new Proxy(obj, {
+ set(t, k, v, r) { throw "i don't like " + v; }
+});
+assertThrowsValue(() => Reflect.set(proxy, "food", "cheese"), "i don't like cheese");
+
+// If a Proxy set handler breaks the object invariants, it's a TypeError.
+for (obj of [{a: 0}, {get a() { return 0; }}]) {
+ Object.freeze(obj);
+ proxy = new Proxy(obj, {
+ set(t, k, v, r) { return true; }
+ });
+ assertThrowsInstanceOf(() => Reflect.set(proxy, "a", "b"), TypeError);
+}
+
+// Per spec, this should first call p.[[Set]]("0", 42, a) and
+// then (since p has no own properties) a.[[Set]]("0", 42, a).
+// The latter should not define a property on p.
+var a = [0, 1, 2, 3];
+var p = Object.create(a);
+Reflect.set(p, "0", 42, a);
+assertEq(p.hasOwnProperty("0"), false);
+assertDeepEq(Reflect.getOwnPropertyDescriptor(a, "0"),
+ {value: 42, writable: true, enumerable: true, configurable: true});
+
+// Test behavior of ordinary objects' [[Set]] method (ES6 9.1.9).
+// On an ordinary object, if the property key isn't present, [[Set]] calls
+// receiver.[[GetOwnProperty]]() and then receiver.[[DefineProperty]]().
+var log;
+obj = {};
+var proxyTarget = {};
+var existingDescriptor, expected, defineResult;
+var receiver = new Proxy(proxyTarget, {
+ getOwnPropertyDescriptor(t, k) {
+ log += "g";
+ return existingDescriptor;
+ },
+ defineProperty(t, k, desc) {
+ log += "d";
+ assertEq(t, proxyTarget);
+ assertEq(k, "prop");
+ assertDeepEq(desc, expected);
+ return defineResult;
+ }
+});
+existingDescriptor = undefined;
+expected = {value: 5, writable: true, enumerable: true, configurable: true};
+for (var defineResult of [true, false]) {
+ log = "";
+ assertEq(Reflect.set(obj, "prop", 5, receiver), defineResult);
+ assertEq(log, "gd");
+}
+
+existingDescriptor = {value: 7, writable: true, enumerable: false, configurable: true};
+expected = {value: 4};
+for (var defineResult of [true, false]) {
+ log = "";
+ assertEq(Reflect.set(obj, "prop", 4, receiver), defineResult);
+ assertEq(log, "gd");
+}
+
+
+// For more Reflect.set tests, see target.js and propertyKeys.js.
+
+reportCompare(0, 0);
diff --git a/js/src/tests/ecma_6/Reflect/setPrototypeOf.js b/js/src/tests/ecma_6/Reflect/setPrototypeOf.js
new file mode 100644
index 000000000..ed7857a02
--- /dev/null
+++ b/js/src/tests/ecma_6/Reflect/setPrototypeOf.js
@@ -0,0 +1,72 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/ */
+
+// Reflect.setPrototypeOf changes an object's [[Prototype]].
+var obj = {};
+assertEq(Object.getPrototypeOf(obj), Object.prototype);
+var proto = {};
+assertEq(Reflect.setPrototypeOf(obj, proto), true);
+assertEq(Object.getPrototypeOf(obj), proto);
+
+// It can change an object's [[Prototype]] to null.
+obj = {};
+assertEq(Reflect.setPrototypeOf(obj, null), true);
+assertEq(Object.getPrototypeOf(obj), null);
+
+// The proto argument is required too.
+obj = {};
+assertThrowsInstanceOf(() => Reflect.setPrototypeOf(obj), TypeError);
+
+// The proto argument must be either null or an object.
+for (proto of [undefined, false, 0, 1.6, "that", Symbol.iterator]) {
+ assertThrowsInstanceOf(() => Reflect.setPrototypeOf(obj, proto), TypeError);
+}
+
+// Return false if the target isn't extensible.
+proto = {};
+obj = Object.preventExtensions(Object.create(proto));
+assertEq(Reflect.setPrototypeOf(obj, {}), false);
+assertEq(Reflect.setPrototypeOf(obj, null), false);
+assertEq(Reflect.setPrototypeOf(obj, proto), true); // except if not changing anything
+
+// Return false rather than create a [[Prototype]] cycle.
+obj = {};
+assertEq(Reflect.setPrototypeOf(obj, obj), false);
+
+// Don't create a [[Prototype]] cycle involving 2 objects.
+obj = Object.create(proto);
+assertEq(Reflect.setPrototypeOf(proto, obj), false);
+
+// Don't create a longish [[Prototype]] cycle.
+for (var i = 0; i < 256; i++)
+ obj = Object.create(obj);
+assertEq(Reflect.setPrototypeOf(proto, obj), false);
+
+// The spec claims we should allow creating cycles involving proxies. (The
+// cycle check quietly exits on encountering the proxy.)
+obj = {};
+var proxy = new Proxy(Object.create(obj), {});
+
+assertEq(Reflect.setPrototypeOf(obj, proxy), true);
+assertEq(Reflect.getPrototypeOf(obj), proxy);
+assertEq(Reflect.getPrototypeOf(proxy), obj);
+
+// If a proxy handler returns a false-y value, return false.
+var hits = 0;
+proto = {name: "proto"};
+obj = {name: "obj"};
+proxy = new Proxy(obj, {
+ setPrototypeOf(t, p) {
+ assertEq(t, obj);
+ assertEq(p, proto);
+ hits++;
+ return 0;
+ }
+});
+
+assertEq(Reflect.setPrototypeOf(proxy, proto), false);
+assertEq(hits, 1);
+
+// For more Reflect.setPrototypeOf tests, see target.js.
+
+reportCompare(0, 0);
diff --git a/js/src/tests/ecma_6/Reflect/shell.js b/js/src/tests/ecma_6/Reflect/shell.js
new file mode 100644
index 000000000..2aa5397ed
--- /dev/null
+++ b/js/src/tests/ecma_6/Reflect/shell.js
@@ -0,0 +1,9 @@
+// List of a few values that are not objects.
+var SOME_PRIMITIVE_VALUES = [
+ undefined, null,
+ false,
+ -Infinity, -1.6e99, -1, -0, 0, Math.pow(2, -1074), 1, 4294967295,
+ Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER + 1, 1.6e99, Infinity, NaN,
+ "", "Phaedo",
+ Symbol(), Symbol("iterator"), Symbol.for("iterator"), Symbol.iterator
+];
diff --git a/js/src/tests/ecma_6/Reflect/surfaces.js b/js/src/tests/ecma_6/Reflect/surfaces.js
new file mode 100644
index 000000000..d8486363a
--- /dev/null
+++ b/js/src/tests/ecma_6/Reflect/surfaces.js
@@ -0,0 +1,59 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/ */
+
+// Check surface features of the Reflect object.
+assertEq(typeof Reflect, 'object');
+assertEq(Object.getPrototypeOf(Reflect), Object.prototype);
+assertEq(Reflect.toString(), '[object Object]');
+assertThrowsInstanceOf(() => new Reflect, TypeError);
+
+var desc = Object.getOwnPropertyDescriptor(this, "Reflect");
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+assertEq(desc.writable, true);
+
+for (var name in Reflect)
+ throw new Error("Reflect should not have any enumerable properties");
+
+// The name and length of all the standard Reflect methods.
+var methods = {
+ apply: 3,
+ construct: 2,
+ defineProperty: 3,
+ deleteProperty: 2,
+ get: 2,
+ getOwnPropertyDescriptor: 2,
+ getPrototypeOf: 1,
+ has: 2,
+ isExtensible: 1,
+ ownKeys: 1,
+ preventExtensions: 1,
+ set: 3,
+ setPrototypeOf: 2
+};
+
+// Check that all Reflect properties are listed above.
+for (var name of Reflect.ownKeys(Reflect)) {
+ // If this assertion fails, congratulations on implementing a new Reflect feature!
+ // Add it to the list of methods above.
+ if (name !== "parse")
+ assertEq(name in methods, true, `unexpected property found: Reflect.${name}`);
+}
+
+// Check the .length and property attributes of each Reflect method.
+for (var name of Object.keys(methods)) {
+ var desc = Object.getOwnPropertyDescriptor(Reflect, name);
+ assertEq(desc.enumerable, false);
+ assertEq(desc.configurable, true);
+ assertEq(desc.writable, true);
+ var f = desc.value;
+ assertEq(typeof f, "function");
+ assertEq(f.length, methods[name]);
+}
+
+// Check that the SpiderMonkey "resolve hook" mechanism does not resurrect the
+// Reflect property once it is deleted.
+delete this.Reflect;
+assertEq("Reflect" in this, false);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/ecma_6/Reflect/target.js b/js/src/tests/ecma_6/Reflect/target.js
new file mode 100644
index 000000000..8d18ce99a
--- /dev/null
+++ b/js/src/tests/ecma_6/Reflect/target.js
@@ -0,0 +1,44 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/ */
+
+// Check correct handling of the `target` argument shared by every Reflect method.
+
+// For each standard Reflect method, an array of arguments
+// that would be OK after a suitable target argument.
+var methodInfo = {
+ apply: [undefined, []],
+ construct: [[]],
+ defineProperty: ["x", {}],
+ deleteProperty: ["x"],
+ get: ["x", {}],
+ getOwnPropertyDescriptor: ["x"],
+ getPrototypeOf: [],
+ has: ["x"],
+ isExtensible: [],
+ ownKeys: [],
+ preventExtensions: [],
+ set: ["x", 0],
+ setPrototypeOf: [{}]
+};
+
+// Check that all Reflect properties are listed above.
+for (var name of Reflect.ownKeys(Reflect)) {
+ // If this assertion fails, congratulations on implementing a new Reflect feature!
+ // Add it to methodInfo above.
+ if (name !== "parse")
+ assertEq(name in methodInfo, true);
+}
+
+for (var name of Object.keys(methodInfo)) {
+ var args = methodInfo[name];
+
+ // The target argument is required.
+ assertThrowsInstanceOf(Reflect[name], TypeError);
+
+ // Throw if the target argument is not an object.
+ for (var value of SOME_PRIMITIVE_VALUES) {
+ assertThrowsInstanceOf(() => Reflect[name](value, ...args), TypeError);
+ }
+}
+
+reportCompare(0, 0);