summaryrefslogtreecommitdiffstats
path: root/js/src/tests/ecma_6/Object
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/tests/ecma_6/Object')
-rw-r--r--js/src/tests/ecma_6/Object/accessor-arguments-rest.js24
-rw-r--r--js/src/tests/ecma_6/Object/accessor-name.js36
-rw-r--r--js/src/tests/ecma_6/Object/accessor-non-constructor.js20
-rw-r--r--js/src/tests/ecma_6/Object/assign.js303
-rw-r--r--js/src/tests/ecma_6/Object/browser.js0
-rw-r--r--js/src/tests/ecma_6/Object/bug-1150906.js13
-rw-r--r--js/src/tests/ecma_6/Object/bug-1206700.js10
-rw-r--r--js/src/tests/ecma_6/Object/defineProperties-order.js17
-rw-r--r--js/src/tests/ecma_6/Object/defineProperty-proxy.js54
-rw-r--r--js/src/tests/ecma_6/Object/destructuring-shorthand-defaults.js135
-rw-r--r--js/src/tests/ecma_6/Object/duplProps.js116
-rw-r--r--js/src/tests/ecma_6/Object/freeze-proxy.js27
-rw-r--r--js/src/tests/ecma_6/Object/freeze.js21
-rw-r--r--js/src/tests/ecma_6/Object/getOwnPropertyDescriptor.js35
-rw-r--r--js/src/tests/ecma_6/Object/getOwnPropertySymbols-proxy.js28
-rw-r--r--js/src/tests/ecma_6/Object/getOwnPropertySymbols.js46
-rw-r--r--js/src/tests/ecma_6/Object/getPrototypeOf.js22
-rw-r--r--js/src/tests/ecma_6/Object/getter-name.js10
-rw-r--r--js/src/tests/ecma_6/Object/isExtensible.js21
-rw-r--r--js/src/tests/ecma_6/Object/isFrozen.js21
-rw-r--r--js/src/tests/ecma_6/Object/isSealed.js21
-rw-r--r--js/src/tests/ecma_6/Object/keys.js23
-rw-r--r--js/src/tests/ecma_6/Object/method-non-constructor.js12
-rw-r--r--js/src/tests/ecma_6/Object/preventExtensions-proxy.js23
-rw-r--r--js/src/tests/ecma_6/Object/preventExtensions.js21
-rw-r--r--js/src/tests/ecma_6/Object/property-descriptor-order.js17
-rw-r--r--js/src/tests/ecma_6/Object/propertyIsEnumerable-proxy.js59
-rw-r--r--js/src/tests/ecma_6/Object/seal-proxy.js27
-rw-r--r--js/src/tests/ecma_6/Object/seal.js21
-rw-r--r--js/src/tests/ecma_6/Object/setPrototypeOf-cross-realm-cycle.js11
-rw-r--r--js/src/tests/ecma_6/Object/setPrototypeOf-cycle.js16
-rw-r--r--js/src/tests/ecma_6/Object/setPrototypeOf-same-value.js11
-rw-r--r--js/src/tests/ecma_6/Object/shell.js0
-rw-r--r--js/src/tests/ecma_6/Object/toLocaleString.js13
-rw-r--r--js/src/tests/ecma_6/Object/toPrimitive-callers.js57
-rw-r--r--js/src/tests/ecma_6/Object/toPrimitive.js101
36 files changed, 1392 insertions, 0 deletions
diff --git a/js/src/tests/ecma_6/Object/accessor-arguments-rest.js b/js/src/tests/ecma_6/Object/accessor-arguments-rest.js
new file mode 100644
index 000000000..82f37b62e
--- /dev/null
+++ b/js/src/tests/ecma_6/Object/accessor-arguments-rest.js
@@ -0,0 +1,24 @@
+assertThrowsInstanceOf(() => eval("({ get x(...a) { } })"), SyntaxError);
+assertThrowsInstanceOf(() => eval("({ get x(a, ...b) { } })"), SyntaxError);
+assertThrowsInstanceOf(() => eval("({ get x([a], ...b) { } })"), SyntaxError);
+assertThrowsInstanceOf(() => eval("({ get x({a}, ...b) { } })"), SyntaxError);
+assertThrowsInstanceOf(() => eval("({ get x({a: A}, ...b) { } })"), SyntaxError);
+
+assertThrowsInstanceOf(() => eval("({ set x(...a) { } })"), SyntaxError);
+assertThrowsInstanceOf(() => eval("({ set x(a, ...b) { } })"), SyntaxError);
+assertThrowsInstanceOf(() => eval("({ set x([a], ...b) { } })"), SyntaxError);
+assertThrowsInstanceOf(() => eval("({ set x({a: A}, ...b) { } })"), SyntaxError);
+
+({ get(...a) { } });
+({ get(a, ...b) { } });
+({ get([a], ...b) { } });
+({ get({a}, ...b) { } });
+({ get({a: A}, ...b) { } });
+
+({ set(...a) { } });
+({ set(a, ...b) { } });
+({ set([a], ...b) { } });
+({ set({a: A}, ...b) { } });
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/ecma_6/Object/accessor-name.js b/js/src/tests/ecma_6/Object/accessor-name.js
new file mode 100644
index 000000000..1b5268e07
--- /dev/null
+++ b/js/src/tests/ecma_6/Object/accessor-name.js
@@ -0,0 +1,36 @@
+function name(obj, property, get) {
+ let desc = Object.getOwnPropertyDescriptor(obj, property);
+ return (get ? desc.get : desc.set).name;
+}
+
+assertEq(name({get a() {}}, "a", true), "get a");
+assertEq(name({set a(v) {}}, "a", false), "set a");
+
+assertEq(name({get 123() {}}, "123", true), "get 123");
+assertEq(name({set 123(v) {}}, "123", false), "set 123");
+
+assertEq(name({get case() {}}, "case", true), "get case");
+assertEq(name({set case(v) {}}, "case", false), "set case");
+
+assertEq(name({get get() {}}, "get", true), "get get");
+assertEq(name({set set(v) {}}, "set", false), "set set");
+
+let o = {get a() { }, set a(v) {}};
+assertEq(name(o, "a", true), "get a");
+assertEq(name(o, "a", false), "set a");
+
+o = {get 123() { }, set 123(v) {}}
+assertEq(name(o, "123", true), "get 123");
+assertEq(name(o, "123", false), "set 123");
+
+o = {get case() { }, set case(v) {}}
+assertEq(name(o, "case", true), "get case");
+assertEq(name(o, "case", false), "set case");
+
+// Congratulations on implementing these!
+assertEq(name({get ["a"]() {}}, "a", true), "");
+assertEq(name({get [123]() {}}, "123", true), "");
+assertEq(name({set ["a"](v) {}}, "a", false), "");
+assertEq(name({set [123](v) {}}, "123", false), "");
+
+reportCompare(true, true);
diff --git a/js/src/tests/ecma_6/Object/accessor-non-constructor.js b/js/src/tests/ecma_6/Object/accessor-non-constructor.js
new file mode 100644
index 000000000..32d1d3467
--- /dev/null
+++ b/js/src/tests/ecma_6/Object/accessor-non-constructor.js
@@ -0,0 +1,20 @@
+var obj = { get a() { return 1; } };
+assertThrowsInstanceOf(() => {
+ new Object.getOwnPropertyDescriptor(obj, "a").get
+}, TypeError);
+
+obj = { set a(b) { } };
+assertThrowsInstanceOf(() => {
+ new Object.getOwnPropertyDescriptor(obj, "a").set
+}, TypeError);
+
+obj = { get a() { return 1; }, set a(b) { } };
+assertThrowsInstanceOf(() => {
+ new Object.getOwnPropertyDescriptor(obj, "a").get
+}, TypeError);
+assertThrowsInstanceOf(() => {
+ new Object.getOwnPropertyDescriptor(obj, "a").set
+}, TypeError);
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/ecma_6/Object/assign.js b/js/src/tests/ecma_6/Object/assign.js
new file mode 100644
index 000000000..5deb09c8e
--- /dev/null
+++ b/js/src/tests/ecma_6/Object/assign.js
@@ -0,0 +1,303 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+function checkDataProperty(object, propertyKey, value, writable, enumerable, configurable) {
+ var desc = Object.getOwnPropertyDescriptor(object, propertyKey);
+ assertEq(desc === undefined, false);
+ assertEq('value' in desc, true);
+ assertEq(desc.value, value);
+ assertEq(desc.writable, writable);
+ assertEq(desc.enumerable, enumerable);
+ assertEq(desc.configurable, configurable);
+}
+
+/* 19.1.2.1 Object.assign ( target, ...sources ) */
+assertEq(Object.assign.length, 2);
+
+// Basic functionality works with multiple sources
+function basicMultipleSources() {
+ var a = {};
+ var b = { bProp : 7 };
+ var c = { cProp : 8 };
+ Object.assign(a, b, c);
+ assertEq(a.bProp, 7);
+ assertEq(a.cProp, 8);
+}
+basicMultipleSources();
+
+// Basic functionality works with symbols (Bug 1052358)
+function basicSymbols() {
+ var a = {};
+ var b = { bProp : 7 };
+ var aSymbol = Symbol("aSymbol");
+ b[aSymbol] = 22;
+ Object.assign(a, b);
+ assertEq(a.bProp, 7);
+ assertEq(a[aSymbol], 22);
+}
+basicSymbols();
+
+// Calls ToObject() for target, skips null/undefined sources, uses
+// ToObject(source) otherwise.
+function testToObject() {
+ assertThrowsInstanceOf(() => Object.assign(null, null), TypeError);
+ assertThrowsInstanceOf(() => Object.assign(), TypeError);
+ assertThrowsInstanceOf(() => Object.assign(null, {}), TypeError);
+ assertEq(Object.assign({}, null) instanceof Object, true);
+ assertEq(Object.assign({}, undefined) instanceof Object, true);
+
+ // Technically an embedding could have this as extension acting differently
+ // from ours, so a feature-test is inadequate. We can move this subtest
+ // into extensions/ if that ever matters.
+ if (typeof objectEmulatingUndefined === "function") {
+ var falsyObject = objectEmulatingUndefined();
+ falsyObject.foo = 7;
+
+ var obj = Object.assign({}, falsyObject);
+ assertEq(obj instanceof Object, true);
+ assertEq(obj.foo, 7);
+ }
+
+ assertEq(Object.assign(true, {}) instanceof Boolean, true);
+ assertEq(Object.assign(1, {}) instanceof Number, true);
+ assertEq(Object.assign("string", {}) instanceof String, true);
+ var o = {};
+ assertEq(Object.assign(o, {}), o);
+}
+testToObject();
+
+// Invokes [[OwnPropertyKeys]] on ToObject(source)
+function testOwnPropertyKeys() {
+ assertThrowsInstanceOf(() => Object.assign(null, new Proxy({}, {
+ getOwnPropertyNames: () => { throw new Error("not called"); }
+ })), TypeError);
+
+ var ownKeysCalled = false;
+ Object.assign({}, new Proxy({}, {
+ ownKeys: function() {
+ ownKeysCalled = true;
+ return [];
+ }
+ }));
+ assertEq(ownKeysCalled, true);
+};
+testOwnPropertyKeys();
+
+// Ensure correct property traversal
+function correctPropertyTraversal() {
+ var log = "";
+ var source = new Proxy({a: 1, b: 2}, {
+ ownKeys: () => ["b", "c", "a"],
+ getOwnPropertyDescriptor: function(t, pk) {
+ log += "#" + pk;
+ return Object.getOwnPropertyDescriptor(t, pk);
+ },
+ get: function(t, pk, r) {
+ log += "-" + pk;
+ return t[pk];
+ },
+ });
+ Object.assign({}, source);
+ assertEq(log, "#b-b#c#a-a");
+}
+correctPropertyTraversal();
+
+// Only [[Enumerable]] properties are assigned to target
+function onlyEnumerablePropertiesAssigned() {
+ var source = Object.defineProperties({}, {
+ a: {value: 1, enumerable: true},
+ b: {value: 2, enumerable: false},
+ });
+ var target = Object.assign({}, source);
+ assertEq("a" in target, true);
+ assertEq("b" in target, false);
+}
+onlyEnumerablePropertiesAssigned();
+
+
+// Enumerability is decided on-time, not before main loop (1)
+function testEnumerabilityDeterminedInLoop1()
+{
+ var getterCalled = false;
+ var sourceTarget = {
+ get a() { getterCalled = true },
+ get b() { Object.defineProperty(sourceTarget, "a", {enumerable: false}) },
+ };
+ var source = new Proxy(sourceTarget, { ownKeys: () => ["b", "a"] });
+ Object.assign({}, source);
+ assertEq(getterCalled, false);
+}
+testEnumerabilityDeterminedInLoop1();
+
+// Enumerability is decided on-time, not before main loop (2)
+function testEnumerabilityDeterminedInLoop2()
+{
+ var getterCalled = false;
+ var sourceTarget = {
+ get a() { getterCalled = true },
+ get b() { Object.defineProperty(sourceTarget, "a", {enumerable: true}) },
+ };
+ var source = new Proxy(sourceTarget, {
+ ownKeys: () => ["b", "a"]
+ });
+ Object.defineProperty(sourceTarget, "a", {enumerable: false});
+ Object.assign({}, source);
+ assertEq(getterCalled, true);
+}
+testEnumerabilityDeterminedInLoop2();
+
+// Properties are retrieved through Get() and assigned onto
+// the target as data properties, not in any sense cloned over as descriptors
+function testPropertiesRetrievedThroughGet() {
+ var getterCalled = false;
+ Object.assign({}, {get a() { getterCalled = true }});
+ assertEq(getterCalled, true);
+}
+testPropertiesRetrievedThroughGet();
+
+// Properties are retrieved through Get()
+// Properties are assigned through Put()
+function testPropertiesAssignedThroughPut() {
+ var setterCalled = false;
+ Object.assign({set a(v) { setterCalled = v }}, {a: true});
+ assertEq(setterCalled, true);
+}
+testPropertiesAssignedThroughPut();
+
+// Properties are retrieved through Get()
+// Properties are assigned through Put(): Existing property attributes are not altered
+function propertiesAssignedExistingNotAltered() {
+ var source = {a: 1, b: 2, c: 3};
+ var target = {a: 0, b: 0, c: 0};
+ Object.defineProperty(target, "a", {enumerable: false});
+ Object.defineProperty(target, "b", {configurable: false});
+ Object.defineProperty(target, "c", {enumerable: false, configurable: false});
+ Object.assign(target, source);
+ checkDataProperty(target, "a", 1, true, false, true);
+ checkDataProperty(target, "b", 2, true, true, false);
+ checkDataProperty(target, "c", 3, true, false, false);
+}
+propertiesAssignedExistingNotAltered();
+
+// Properties are retrieved through Get()
+// Properties are assigned through Put(): Throws TypeError if non-writable
+function propertiesAssignedTypeErrorNonWritable() {
+ var source = {a: 1};
+ var target = {a: 0};
+ Object.defineProperty(target, "a", {writable: false});
+ assertThrowsInstanceOf(() => Object.assign(target, source), TypeError);
+ checkDataProperty(target, "a", 0, false, true, true);
+}
+propertiesAssignedTypeErrorNonWritable();
+
+// Properties are retrieved through Get()
+// Put() creates standard properties; Property attributes from source are ignored
+function createsStandardProperties() {
+ var source = {a: 1, b: 2, c: 3, get d() { return 4 }};
+ Object.defineProperty(source, "b", {writable: false});
+ Object.defineProperty(source, "c", {configurable: false});
+ var target = Object.assign({}, source);
+ checkDataProperty(target, "a", 1, true, true, true);
+ checkDataProperty(target, "b", 2, true, true, true);
+ checkDataProperty(target, "c", 3, true, true, true);
+ checkDataProperty(target, "d", 4, true, true, true);
+}
+createsStandardProperties();
+
+// Properties created during traversal are not copied
+function propertiesCreatedDuringTraversalNotCopied() {
+ var source = {get a() { this.b = 2 }};
+ var target = Object.assign({}, source);
+ assertEq("a" in target, true);
+ assertEq("b" in target, false);
+}
+propertiesCreatedDuringTraversalNotCopied();
+
+// Properties deleted during traversal are not copied
+function testDeletePropertiesNotCopied() {
+ var source = new Proxy({
+ get a() { delete this.b },
+ b: 2,
+ }, {
+ getOwnPropertyNames: () => ["a", "b"]
+ });
+ var target = Object.assign({}, source);
+ assertEq("a" in target, true);
+ assertEq("b" in target, false);
+}
+testDeletePropertiesNotCopied();
+
+function testDeletionExposingShadowedProperty()
+{
+ var srcProto = { b: 42 };
+ var src =
+ Object.create(srcProto,
+ { a: { enumerable: true, get: function() { delete this.b; } },
+ b: { value: 2, configurable: true, enumerable: true } });
+ var source = new Proxy(src, { getOwnPropertyNames: () => ["a", "b"] });
+ var target = Object.assign({}, source);
+ assertEq("a" in target, true);
+ assertEq("b" in target, false);
+}
+testDeletionExposingShadowedProperty();
+
+// Properties first deleted and then recreated during traversal are copied (1)
+function testDeletedAndRecreatedPropertiesCopied1() {
+ var source = new Proxy({
+ get a() { delete this.c },
+ get b() { this.c = 4 },
+ c: 3,
+ }, {
+ getOwnPropertyNames: () => ["a", "b", "c"]
+ });
+ var target = Object.assign({}, source);
+ assertEq("a" in target, true);
+ assertEq("b" in target, true);
+ assertEq("c" in target, true);
+ checkDataProperty(target, "c", 4, true, true, true);
+}
+testDeletedAndRecreatedPropertiesCopied1();
+
+// Properties first deleted and then recreated during traversal are copied (2)
+function testDeletedAndRecreatedPropertiesCopied2() {
+ var source = new Proxy({
+ get a() { delete this.c },
+ get b() { this.c = 4 },
+ c: 3,
+ }, {
+ ownKeys: () => ["a", "c", "b"]
+ });
+ var target = Object.assign({}, source);
+ assertEq("a" in target, true);
+ assertEq("b" in target, true);
+ assertEq("c" in target, false);
+}
+testDeletedAndRecreatedPropertiesCopied2();
+
+// String and Symbol valued properties are copied
+function testStringAndSymbolPropertiesCopied() {
+ var keyA = "str-prop";
+ var source = {"str-prop": 1};
+ var target = Object.assign({}, source);
+ checkDataProperty(target, keyA, 1, true, true, true);
+}
+testStringAndSymbolPropertiesCopied();
+
+// Intermediate exceptions stop traversal and throw exception
+function testExceptionsDoNotStopFirstReported1() {
+ var TestError = function TestError() {};
+ var source = new Proxy({}, {
+ getOwnPropertyDescriptor: function(t, pk) {
+ assertEq(pk, "b");
+ throw new TestError();
+ },
+ ownKeys: () => ["b", "a"]
+ });
+ assertThrowsInstanceOf(() => Object.assign({}, source), TestError);
+}
+testExceptionsDoNotStopFirstReported1();
+
+
+if (typeof reportCompare == "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/ecma_6/Object/browser.js b/js/src/tests/ecma_6/Object/browser.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/ecma_6/Object/browser.js
diff --git a/js/src/tests/ecma_6/Object/bug-1150906.js b/js/src/tests/ecma_6/Object/bug-1150906.js
new file mode 100644
index 000000000..27403cccf
--- /dev/null
+++ b/js/src/tests/ecma_6/Object/bug-1150906.js
@@ -0,0 +1,13 @@
+function f(x) {
+ Object.defineProperty(arguments, 0, {
+ get: function() {}
+ });
+ return arguments;
+}
+
+var obj = f(1);
+assertEq(obj[0], undefined);
+assertEq(Object.getOwnPropertyDescriptor(obj, 0).set, undefined);
+assertThrowsInstanceOf(() => { "use strict"; obj[0] = 1; }, TypeError);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/ecma_6/Object/bug-1206700.js b/js/src/tests/ecma_6/Object/bug-1206700.js
new file mode 100644
index 000000000..4918bcbec
--- /dev/null
+++ b/js/src/tests/ecma_6/Object/bug-1206700.js
@@ -0,0 +1,10 @@
+var x = {};
+Reflect.set(x, "prop", 5, Object.prototype);
+var y = {};
+Reflect.set(y, "prop", 6, Object.prototype);
+assertEq(x.hasOwnProperty("prop"), false);
+assertEq(y.hasOwnProperty("prop"), false);
+assertEq(Object.prototype.hasOwnProperty("prop"), true);
+assertEq(Object.prototype.prop, 6);
+
+reportCompare(0, 0, "ok");
diff --git a/js/src/tests/ecma_6/Object/defineProperties-order.js b/js/src/tests/ecma_6/Object/defineProperties-order.js
new file mode 100644
index 000000000..417d10183
--- /dev/null
+++ b/js/src/tests/ecma_6/Object/defineProperties-order.js
@@ -0,0 +1,17 @@
+// Based on testcases provided by André Bargull
+
+let log = [];
+let logger = new Proxy({}, {
+ get(target, key) {
+ log.push(key);
+ }
+});
+
+Object.create(null, new Proxy({a: {value: 0}, b: {value: 1}}, logger));
+assertEq(log.join(), "ownKeys,getOwnPropertyDescriptor,get,getOwnPropertyDescriptor,get");
+
+log = [];
+Object.defineProperties({}, new Proxy({a: {value: 0}, b: {value: 1}}, logger));
+assertEq(log.join(), "ownKeys,getOwnPropertyDescriptor,get,getOwnPropertyDescriptor,get");
+
+reportCompare(true, true);
diff --git a/js/src/tests/ecma_6/Object/defineProperty-proxy.js b/js/src/tests/ecma_6/Object/defineProperty-proxy.js
new file mode 100644
index 000000000..b5ece940b
--- /dev/null
+++ b/js/src/tests/ecma_6/Object/defineProperty-proxy.js
@@ -0,0 +1,54 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/ */
+
+// Test details of the implementation of ToPropertyDescriptor exposed to scripts
+// thanks to scriptable proxies.
+
+// A LoggingProxy object logs certain operations performed on it.
+var log = [];
+function LoggingProxy(target) {
+ return new Proxy(target, {
+ has: function (t, id) {
+ log.push("has " + id);
+ return id in t;
+ },
+ get: function (t, id) {
+ log.push("get " + id);
+ return t[id];
+ }
+ });
+}
+
+// Tragically, we use separate code to implement Object.defineProperty on
+// arrays and on proxies. So run the test three times.
+var testSubjects = [
+ {},
+ [],
+ new Proxy({}, {})
+];
+
+for (var obj of testSubjects) {
+ log = [];
+
+ // Object.defineProperty is one public method that performs a
+ // ToPropertyDescriptor call.
+ Object.defineProperty(obj, "x", new LoggingProxy({
+ enumerable: true,
+ configurable: true,
+ value: 3,
+ writable: true
+ }));
+
+ // It should have performed exactly these operations on the proxy, in this
+ // order. See ES6 rev 24 (2014 April 27) 6.2.4.5 ToPropertyDescriptor.
+ assertDeepEq(log, [
+ "has enumerable", "get enumerable",
+ "has configurable", "get configurable",
+ "has value", "get value",
+ "has writable", "get writable",
+ "has get",
+ "has set"
+ ]);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/ecma_6/Object/destructuring-shorthand-defaults.js b/js/src/tests/ecma_6/Object/destructuring-shorthand-defaults.js
new file mode 100644
index 000000000..a03dea2a2
--- /dev/null
+++ b/js/src/tests/ecma_6/Object/destructuring-shorthand-defaults.js
@@ -0,0 +1,135 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Ensure that the syntax used in shorthand destructuring with defaults
+// e.g. |{x=1, y=2} = {}| properly raises a syntax error within an object
+// literal. As per ES6 12.2.6 Object Initializer, "NOTE 3."
+
+const SYNTAX_ERROR_STMTS = [
+ // expressions
+ "({x={}={}}),",
+ "({y={x={}={}={}={}={}={}={}={}}={}}),",
+ "({a=1, b=2, c=3, x=({}={})}),",
+ "({x=1, y={z={1}}})",
+ "({x=1} = {y=1});",
+ "({x: y={z=1}}={})",
+ "({x=1}),",
+ "({z={x=1}})=>{};",
+ "({x = ({y=1}) => y})",
+ "(({x=1})) => x",
+ "({e=[]}==(;",
+ "({x=1}[-1]);",
+ "({x=y}[-9])",
+ "({x=y}.x.z[-9])",
+ "({x=y}`${-9}`)",
+ "(new {x=y}(-9))",
+ "new {x=1}",
+ "new {x=1}={}",
+ "typeof {x=1}",
+ "typeof ({x=1})",
+ "({x=y, [-9]:0})",
+ "((({w = x} >(-9)",
+ "++({x=1})",
+ "--{x=1}",
+ "!{x=1}={}",
+ "delete {x=1}",
+ "delete ({x=1})",
+ "delete {x=1} = {}",
+ "({x=1}.abc)",
+ "x > (0, {a = b} );",
+ // declarations
+ "var x = 0 + {a=1} = {}",
+ "let o = {x=1};",
+ "var j = {x=1};",
+ "var j = {x={y=1}}={};",
+ "const z = {x=1};",
+ "const z = {x={y=1}}={};",
+ "const {x=1};",
+ "const {x={y=33}}={};",
+ "var {x=1};",
+ "let {x=1};",
+ "let x, y, {z=1}={}, {w=2}, {e=3};",
+ // array initialization
+ "[{x=1, y = ({z=2} = {})}];",
+ // try/catch
+ "try {throw 'a';} catch ({x={y=1}}) {}",
+ // if/else
+ "if ({k: 1, x={y=2}={}}) {}",
+ "if (false) {} else if (true) { ({x=1}) }",
+ // switch
+ "switch ('c') { case 'c': ({x=1}); }",
+ // for
+ "for ({x=1}; 1;) {1}",
+ "for ({x={y=2}}; 1;) {1}",
+ "for (var x = 0; x < 2; x++) { ({x=1, y=2}) }",
+ "for (let x=1;{x=1};){}",
+ "for (let x=1;{x={y=2}};){}",
+ "for (let x=1;1;{x=1}){}",
+ "for (let x=1;1;{x={y=2}}){}",
+ // while
+ "while ({x=1}) {1};",
+ "while ({x={y=2}}={}) {1};",
+ // with
+ "with ({x=1}) {};",
+ "with ({x={y=3}={}}) {};",
+ "with (Math) { ({x=1}) };",
+ // ternary
+ "true ? {x=1} : 1;",
+ "false ? 1 : {x=1};",
+ "{x=1} ? 2 : 3;",
+]
+
+for (var stmt of SYNTAX_ERROR_STMTS) {
+ assertThrowsInstanceOf(() => {
+ eval(stmt);
+ }, SyntaxError);
+}
+
+const REFERENCE_ERROR_STMTS = [
+ "({x} += {});",
+ "({x = 1}) = {x: 2};",
+]
+
+for (var stmt of REFERENCE_ERROR_STMTS) {
+ assertThrowsInstanceOf(() => {
+ eval(stmt);
+ }, ReferenceError);
+}
+
+// A few tricky but acceptable cases:
+// see https://bugzilla.mozilla.org/show_bug.cgi?id=932080#c2
+
+assertEq((({a = 0}) => a)({}), 0);
+assertEq((({a = 0} = {}) => a)({}), 0);
+assertEq((({a = 0} = {}) => a)({a: 1}), 1);
+
+{
+ let x, y;
+ ({x=1} = {});
+ assertEq(x, 1);
+ ({x=1} = {x: 4});
+ assertEq(x, 4);
+ ({x=1, y=2} = {})
+ assertEq(x, 1);
+ assertEq(y, 2);
+}
+
+{
+ let {x={i=1, j=2}={}}={};
+ assertDeepEq(x, ({}));
+ assertEq(i, 1);
+ assertEq(j, 2);
+}
+
+// Default destructuring values, which are variables, should be defined
+// within closures (Bug 1255167).
+{
+ let f = function(a){
+ return (function({aa = a}){ return aa; })({});
+ };
+ assertEq(f(9999), 9999);
+}
+
+if (typeof reportCompare == "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/ecma_6/Object/duplProps.js b/js/src/tests/ecma_6/Object/duplProps.js
new file mode 100644
index 000000000..41b8d67fb
--- /dev/null
+++ b/js/src/tests/ecma_6/Object/duplProps.js
@@ -0,0 +1,116 @@
+/*
+ * ES6 allows duplicate property names in object literals, even in strict mode.
+ * These tests modify the tests in test262 to reflect this change.
+ */
+
+// test262/ch11/11.1/11.1.5/11.1.5-4-4-a-1-s.js
+a = function() { "use strict"; return { foo: 0, foo : 1 }};
+assertEq(a().foo, 1);
+a = function() { return { foo: 0, foo : 1 }};
+assertEq(a().foo, 1);
+
+// test262/ch11/11.1/11.1.5/11.1.5_4-4-b-1.js
+a = function() { "use strict"; return { foo : 1, get foo() { return 2; }}};
+assertEq(a().foo, 2);
+a = function() { return { foo : 1, get foo() { return 2;} }};
+assertEq(a().foo, 2);
+
+// test262/ch11/11.1/11.1.5/11.1.5_4-4-c-1.js
+a = function() { "use strict"; return { get foo() { return 2; }, foo : 1 }};
+assertEq(a().foo, 1);
+a = function() { return { get foo() { return 2; }, foo : 1 }};
+assertEq(a().foo, 1);
+
+// test262/ch11/11.1/11.1.5/11.1.5_4-4-b-2.js
+a = function() { "use strict"; return { foo : 1, set foo(a) { throw 2; }}};
+try {
+ a().foo = 5;
+ throw new Error("2 should be thrown here");
+} catch (e) {
+ if (e !== 2)
+ throw new Error("2 should be thrown here");
+}
+a = function() { return { foo : 1, set foo(a) { throw 2;} }};
+try {
+ a().foo = 5;
+ throw new Error("2 should be thrown here");
+} catch (e) {
+ if (e !== 2)
+ throw new Error("2 should be thrown here");
+}
+
+// test262/ch11/11.1/11.1.5/11.1.5_4-4-d-1.js
+a = function() { "use strict"; return { get foo() { return 2; }, get foo() { return 3; } }};
+assertEq(a().foo, 3);
+a = function() { return { get foo() { return 2; }, get foo() { return 3; } }};
+assertEq(a().foo, 3);
+
+// test262/ch11/11.1/11.1.5/11.1.5_4-4-c-2.js
+a = function() { "use strict"; return { set foo(a) { throw 2; }, foo : 1 }};
+assertEq(a().foo, 1);
+a = function() { return { set foo(a) { throw 2; }, foo : 1 }};
+assertEq(a().foo, 1);
+
+// test262/ch11/11.1/11.1.5/11.1.5_4-4-d-2.js
+a = function() { "use strict"; return { set foo(a) { throw 2; }, set foo(a) { throw 3; }}};
+try {
+ a().foo = 5;
+ throw new Error("3 should be thrown here");
+} catch (e) {
+ if (e !== 3)
+ throw new Error("3 should be thrown here");
+}
+a = function() { return { set foo(a) { throw 2; }, set foo(a) { throw 3; }}};
+try {
+ a().foo = 5;
+ throw new Error("3 should be thrown here");
+} catch (e) {
+ if (e !== 3)
+ throw new Error("3 should be thrown here");
+}
+
+// test262/ch11/11.1/11.1.5/11.1.5_4-4-d-3.js
+a = function() { "use strict"; return { get foo() { return 2; }, set foo(a) { throw 3; },
+ get foo() { return 4; }}};
+try {
+ assertEq(a().foo, 4);
+ a().foo = 5;
+ throw new Error("3 should be thrown here");
+} catch (e) {
+ if (e !== 3)
+ throw new Error("3 should be thrown here");
+}
+a = function() { return { get foo() { return 2; }, set foo(a) { throw 3; },
+ get foo() { return 4; }}};
+try {
+ assertEq(a().foo, 4);
+ a().foo = 5;
+ throw new Error("3 should be thrown here");
+} catch (e) {
+ if (e !== 3)
+ throw new Error("3 should be thrown here");
+}
+
+// test262/ch11/11.1/11.1.5/11.1.5_4-4-d-4.js
+a = function() { "use strict"; return { set foo(a) { throw 2; }, get foo() { return 4; },
+ set foo(a) { throw 3; }}};
+try {
+ assertEq(a().foo, 4);
+ a().foo = 5;
+ throw new Error("3 should be thrown here");
+} catch (e) {
+ if (e !== 3)
+ throw new Error("3 should be thrown here");
+}
+a = function() { return { set foo(a) { throw 2; }, get foo() { return 4; },
+ set foo(a) { throw 3; }}};
+try {
+ assertEq(a().foo, 4);
+ a().foo = 5;
+ throw new Error("3 should be thrown here");
+} catch (e) {
+ if (e !== 3)
+ throw new Error("3 should be thrown here");
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/ecma_6/Object/freeze-proxy.js b/js/src/tests/ecma_6/Object/freeze-proxy.js
new file mode 100644
index 000000000..3d95a28d4
--- /dev/null
+++ b/js/src/tests/ecma_6/Object/freeze-proxy.js
@@ -0,0 +1,27 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function logProxy(object = {}, handler = {}) {
+ var log = [];
+ var proxy = new Proxy(object, new Proxy(handler, {
+ get(target, propertyKey, receiver) {
+ log.push(propertyKey);
+ return target[propertyKey];
+ }
+ }));
+ return {proxy, log};
+}
+
+// The order of operations is backwards when compared to ES6 draft rev 27
+// (2014 August 24), but see https://bugs.ecmascript.org/show_bug.cgi?id=3215
+// for an explanation on why the spec version is clearly wrong.
+
+var {proxy, log} = logProxy();
+Object.freeze(proxy);
+assertDeepEq(log, ["preventExtensions", "ownKeys"]);
+
+var {proxy, log} = logProxy();
+Object.freeze(Object.freeze(proxy));
+assertDeepEq(log, ["preventExtensions", "ownKeys", "preventExtensions", "ownKeys"]);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/ecma_6/Object/freeze.js b/js/src/tests/ecma_6/Object/freeze.js
new file mode 100644
index 000000000..18f71f76d
--- /dev/null
+++ b/js/src/tests/ecma_6/Object/freeze.js
@@ -0,0 +1,21 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * https://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+var BUGNUMBER = 1076588;
+var summary = "Object.freeze() should return its argument with no conversion when the argument is a primitive value";
+
+print(BUGNUMBER + ": " + summary);
+assertEq(Object.freeze(), undefined);
+assertEq(Object.freeze(undefined), undefined);
+assertEq(Object.freeze(null), null);
+assertEq(Object.freeze(1), 1);
+assertEq(Object.freeze("foo"), "foo");
+assertEq(Object.freeze(true), true);
+if (typeof Symbol === "function") {
+ assertEq(Object.freeze(Symbol.for("foo")), Symbol.for("foo"));
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/ecma_6/Object/getOwnPropertyDescriptor.js b/js/src/tests/ecma_6/Object/getOwnPropertyDescriptor.js
new file mode 100644
index 000000000..7aaba7b5e
--- /dev/null
+++ b/js/src/tests/ecma_6/Object/getOwnPropertyDescriptor.js
@@ -0,0 +1,35 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * https://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+var BUGNUMBER = 1079188;
+var summary = "Coerce the argument passed to Object.getOwnPropertyDescriptor using ToObject";
+print(BUGNUMBER + ": " + summary);
+
+assertThrowsInstanceOf(() => Object.getOwnPropertyDescriptor(), TypeError);
+assertThrowsInstanceOf(() => Object.getOwnPropertyDescriptor(undefined), TypeError);
+assertThrowsInstanceOf(() => Object.getOwnPropertyDescriptor(null), TypeError);
+
+Object.getOwnPropertyDescriptor(1);
+Object.getOwnPropertyDescriptor(true);
+if (typeof Symbol === "function") {
+ Object.getOwnPropertyDescriptor(Symbol("foo"));
+}
+
+assertDeepEq(Object.getOwnPropertyDescriptor("foo", "length"), {
+ value: 3,
+ writable: false,
+ enumerable: false,
+ configurable: false
+});
+
+assertDeepEq(Object.getOwnPropertyDescriptor("foo", 0), {
+ value: "f",
+ writable: false,
+ enumerable: true,
+ configurable: false
+});
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/ecma_6/Object/getOwnPropertySymbols-proxy.js b/js/src/tests/ecma_6/Object/getOwnPropertySymbols-proxy.js
new file mode 100644
index 000000000..56f20afb3
--- /dev/null
+++ b/js/src/tests/ecma_6/Object/getOwnPropertySymbols-proxy.js
@@ -0,0 +1,28 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/ */
+
+// getOwnPropertySymbols(proxy) calls the getOwnPropertyNames hook (only).
+
+var symbols = [Symbol(), Symbol("moon"), Symbol.for("sun"), Symbol.iterator];
+var hits = 0;
+
+function HandlerProxy() {
+ return new Proxy({}, {
+ get: function (t, key) {
+ if (key !== "ownKeys")
+ throw new Error("tried to access handler[" + uneval(key) + "]");
+ hits++;
+ return t => symbols;
+ }
+ });
+}
+
+function OwnKeysProxy() {
+ return new Proxy({}, new HandlerProxy);
+}
+
+assertDeepEq(Object.getOwnPropertySymbols(new OwnKeysProxy), symbols);
+assertEq(hits, 1);
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/ecma_6/Object/getOwnPropertySymbols.js b/js/src/tests/ecma_6/Object/getOwnPropertySymbols.js
new file mode 100644
index 000000000..b92d14ef1
--- /dev/null
+++ b/js/src/tests/ecma_6/Object/getOwnPropertySymbols.js
@@ -0,0 +1,46 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/ */
+
+assertDeepEq(Object.getOwnPropertySymbols({}), []);
+
+// String keys are ignored.
+assertEq(Object.getOwnPropertySymbols({a: 1, b: 2}).length, 0);
+assertEq(Object.getOwnPropertySymbols([0, 1, 2, 3]).length, 0);
+
+// Symbol keys are observed.
+var iterable = {};
+Object.defineProperty(iterable, Symbol.iterator, {
+ value: () => [][Symbol.iterator]()
+});
+assertDeepEq(Object.getOwnPropertySymbols(iterable), [Symbol.iterator]);
+assertDeepEq(Object.getOwnPropertySymbols(new Proxy(iterable, {})), [Symbol.iterator]);
+
+// Test on an object with a thousand own properties.
+var obj = {};
+for (var i = 0; i < 1000; i++) {
+ obj[Symbol.for("x" + i)] = 1;
+}
+assertEq(Object.getOwnPropertyNames(obj).length, 0);
+var symbols = Object.getOwnPropertySymbols(obj);
+assertEq(symbols.length, 1000);
+assertEq(symbols.indexOf(Symbol.for("x0")) !== -1, true);
+assertEq(symbols.indexOf(Symbol.for("x241")) !== -1, true);
+assertEq(symbols.indexOf(Symbol.for("x999")) !== -1, true);
+assertEq(Object.getOwnPropertySymbols(new Proxy(obj, {})).length, 1000);
+
+// The prototype chain is not consulted.
+assertEq(Object.getOwnPropertySymbols(Object.create(obj)).length, 0);
+assertEq(Object.getOwnPropertySymbols(new Proxy(Object.create(obj), {})).length, 0);
+
+// Primitives are coerced to objects; but there are never any symbol-keyed
+// properties on the resulting wrapper objects.
+assertThrowsInstanceOf(() => Object.getOwnPropertySymbols(), TypeError);
+assertThrowsInstanceOf(() => Object.getOwnPropertySymbols(undefined), TypeError);
+assertThrowsInstanceOf(() => Object.getOwnPropertySymbols(null), TypeError);
+for (var primitive of [true, 1, 3.14, "hello", Symbol()])
+ assertEq(Object.getOwnPropertySymbols(primitive).length, 0);
+
+assertEq(Object.getOwnPropertySymbols.length, 1);
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/ecma_6/Object/getPrototypeOf.js b/js/src/tests/ecma_6/Object/getPrototypeOf.js
new file mode 100644
index 000000000..71cd30c62
--- /dev/null
+++ b/js/src/tests/ecma_6/Object/getPrototypeOf.js
@@ -0,0 +1,22 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * https://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+var BUGNUMBER = 1079090;
+var summary = "Coerce the argument passed to Object.getPrototypeOf using ToObject";
+print(BUGNUMBER + ": " + summary);
+
+assertThrowsInstanceOf(() => Object.getPrototypeOf(), TypeError);
+assertThrowsInstanceOf(() => Object.getPrototypeOf(undefined), TypeError);
+assertThrowsInstanceOf(() => Object.getPrototypeOf(null), TypeError);
+
+assertEq(Object.getPrototypeOf(1), Number.prototype);
+assertEq(Object.getPrototypeOf(true), Boolean.prototype);
+assertEq(Object.getPrototypeOf("foo"), String.prototype);
+if (typeof Symbol === "function") {
+ assertEq(Object.getPrototypeOf(Symbol("foo")), Symbol.prototype);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/ecma_6/Object/getter-name.js b/js/src/tests/ecma_6/Object/getter-name.js
new file mode 100644
index 000000000..601d6b477
--- /dev/null
+++ b/js/src/tests/ecma_6/Object/getter-name.js
@@ -0,0 +1,10 @@
+var BUGNUMBER = 1180290;
+var summary = 'Object accessors should have get prefix';
+
+print(BUGNUMBER + ": " + summary);
+
+assertEq(Object.getOwnPropertyDescriptor(Object.prototype, "__proto__").get.name, "get __proto__");
+assertEq(Object.getOwnPropertyDescriptor(Object.prototype, "__proto__").set.name, "set __proto__");
+
+if (typeof reportCompare === 'function')
+ reportCompare(true, true);
diff --git a/js/src/tests/ecma_6/Object/isExtensible.js b/js/src/tests/ecma_6/Object/isExtensible.js
new file mode 100644
index 000000000..f1fa00878
--- /dev/null
+++ b/js/src/tests/ecma_6/Object/isExtensible.js
@@ -0,0 +1,21 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+
+var BUGNUMBER = 1060873;
+var summary = "Object.isExtensible() should return false when given primitive values as input";
+
+print(BUGNUMBER + ": " + summary);
+assertEq(Object.isExtensible(), false);
+assertEq(Object.isExtensible(undefined), false);
+assertEq(Object.isExtensible(null), false);
+assertEq(Object.isExtensible(1), false);
+assertEq(Object.isExtensible("foo"), false);
+assertEq(Object.isExtensible(true), false);
+if (typeof Symbol === "function") {
+ assertEq(Object.isExtensible(Symbol()), false);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/ecma_6/Object/isFrozen.js b/js/src/tests/ecma_6/Object/isFrozen.js
new file mode 100644
index 000000000..02056802d
--- /dev/null
+++ b/js/src/tests/ecma_6/Object/isFrozen.js
@@ -0,0 +1,21 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * https://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+var BUGNUMBER = 1071464;
+var summary = "Object.isFrozen() should return true when given primitive values as input";
+
+print(BUGNUMBER + ": " + summary);
+assertEq(Object.isFrozen(), true);
+assertEq(Object.isFrozen(undefined), true);
+assertEq(Object.isFrozen(null), true);
+assertEq(Object.isFrozen(1), true);
+assertEq(Object.isFrozen("foo"), true);
+assertEq(Object.isFrozen(true), true);
+if (typeof Symbol === "function") {
+ assertEq(Object.isFrozen(Symbol()), true);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/ecma_6/Object/isSealed.js b/js/src/tests/ecma_6/Object/isSealed.js
new file mode 100644
index 000000000..cd363a87e
--- /dev/null
+++ b/js/src/tests/ecma_6/Object/isSealed.js
@@ -0,0 +1,21 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * https://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+var BUGNUMBER = 1062860;
+var summary = "Object.isSealed() should return true when given primitive values as input";
+
+print(BUGNUMBER + ": " + summary);
+assertEq(Object.isSealed(), true);
+assertEq(Object.isSealed(undefined), true);
+assertEq(Object.isSealed(null), true);
+assertEq(Object.isSealed(1), true);
+assertEq(Object.isSealed("foo"), true);
+assertEq(Object.isSealed(true), true);
+if (typeof Symbol === "function") {
+ assertEq(Object.isSealed(Symbol()), true);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/ecma_6/Object/keys.js b/js/src/tests/ecma_6/Object/keys.js
new file mode 100644
index 000000000..5766f16d1
--- /dev/null
+++ b/js/src/tests/ecma_6/Object/keys.js
@@ -0,0 +1,23 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * https://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+var BUGNUMBER = 1038545;
+var summary = "Coerce the argument passed to Object.keys using ToObject";
+print(BUGNUMBER + ": " + summary);
+
+assertThrowsInstanceOf(() => Object.keys(), TypeError);
+assertThrowsInstanceOf(() => Object.keys(undefined), TypeError);
+assertThrowsInstanceOf(() => Object.keys(null), TypeError);
+
+assertDeepEq(Object.keys(1), []);
+assertDeepEq(Object.keys(true), []);
+if (typeof Symbol === "function") {
+ assertDeepEq(Object.keys(Symbol("foo")), []);
+}
+
+assertDeepEq(Object.keys("foo"), ["0", "1", "2"]);
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/ecma_6/Object/method-non-constructor.js b/js/src/tests/ecma_6/Object/method-non-constructor.js
new file mode 100644
index 000000000..fd1d589b9
--- /dev/null
+++ b/js/src/tests/ecma_6/Object/method-non-constructor.js
@@ -0,0 +1,12 @@
+var obj = { method() { } };
+assertThrowsInstanceOf(() => {
+ new obj.method;
+}, TypeError);
+
+obj = { constructor() { } };
+assertThrowsInstanceOf(() => {
+ new obj.constructor;
+}, TypeError);
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/ecma_6/Object/preventExtensions-proxy.js b/js/src/tests/ecma_6/Object/preventExtensions-proxy.js
new file mode 100644
index 000000000..347a63bc3
--- /dev/null
+++ b/js/src/tests/ecma_6/Object/preventExtensions-proxy.js
@@ -0,0 +1,23 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function logProxy(object = {}, handler = {}) {
+ var log = [];
+ var proxy = new Proxy(object, new Proxy(handler, {
+ get(target, propertyKey, receiver) {
+ log.push(propertyKey);
+ return target[propertyKey];
+ }
+ }));
+ return {proxy, log};
+}
+
+var {proxy, log} = logProxy();
+Object.preventExtensions(proxy);
+assertDeepEq(log, ["preventExtensions"]);
+
+var {proxy, log} = logProxy();
+Object.preventExtensions(Object.preventExtensions(proxy));
+assertDeepEq(log, ["preventExtensions", "preventExtensions"]);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/ecma_6/Object/preventExtensions.js b/js/src/tests/ecma_6/Object/preventExtensions.js
new file mode 100644
index 000000000..75c8ed3db
--- /dev/null
+++ b/js/src/tests/ecma_6/Object/preventExtensions.js
@@ -0,0 +1,21 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * https://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+var BUGNUMBER = 1073446;
+var summary = "Object.preventExtensions() should return its argument with no conversion when the argument is a primitive value";
+
+print(BUGNUMBER + ": " + summary);
+assertEq(Object.preventExtensions(), undefined);
+assertEq(Object.preventExtensions(undefined), undefined);
+assertEq(Object.preventExtensions(null), null);
+assertEq(Object.preventExtensions(1), 1);
+assertEq(Object.preventExtensions("foo"), "foo");
+assertEq(Object.preventExtensions(true), true);
+if (typeof Symbol === "function") {
+ assertEq(Object.preventExtensions(Symbol.for("foo")), Symbol.for("foo"));
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/ecma_6/Object/property-descriptor-order.js b/js/src/tests/ecma_6/Object/property-descriptor-order.js
new file mode 100644
index 000000000..337d247da
--- /dev/null
+++ b/js/src/tests/ecma_6/Object/property-descriptor-order.js
@@ -0,0 +1,17 @@
+var names = Object.getOwnPropertyNames(Object.getOwnPropertyDescriptor({foo: 0}, "foo"));
+assertDeepEq(names, ["value", "writable", "enumerable", "configurable"]);
+
+names = Object.getOwnPropertyNames(Object.getOwnPropertyDescriptor({get foo(){}}, "foo"));
+assertDeepEq(names, ["get", "set", "enumerable", "configurable"]);
+
+var proxy = new Proxy({}, {
+ defineProperty(target, key, desc) {
+ var names = Object.getOwnPropertyNames(desc);
+ assertDeepEq(names, ["set", "configurable"]);
+ return true;
+ }
+});
+
+Object.defineProperty(proxy, "foo", {configurable: true, set: function() {}});
+
+reportCompare(true, true);
diff --git a/js/src/tests/ecma_6/Object/propertyIsEnumerable-proxy.js b/js/src/tests/ecma_6/Object/propertyIsEnumerable-proxy.js
new file mode 100644
index 000000000..a1dda90e0
--- /dev/null
+++ b/js/src/tests/ecma_6/Object/propertyIsEnumerable-proxy.js
@@ -0,0 +1,59 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function logProxy(object) {
+ var log = [];
+ var handler = {
+ getOwnPropertyDescriptor(target, propertyKey) {
+ log.push(propertyKey);
+ return Object.getOwnPropertyDescriptor(target, propertyKey);
+ }
+ };
+ var proxy = new Proxy(object, new Proxy(handler, {
+ get(target, propertyKey, receiver) {
+ if (!(propertyKey in target)) {
+ throw new Error(`Unexpected call to trap: "${propertyKey}"`);
+ }
+ return target[propertyKey];
+ }
+ }));
+ return {proxy, log};
+}
+
+var properties = ["string-property"];
+if (typeof Symbol === 'function')
+ properties.push(Symbol("symbol-property"));
+
+for (var property of properties) {
+ // Test 1: property is not present on object
+ var {proxy, log} = logProxy({});
+ var result = Object.prototype.propertyIsEnumerable.call(proxy, property);
+ assertEq(result, false);
+ assertDeepEq(log, [property]);
+
+ // Test 2: property is present on object and enumerable
+ var {proxy, log} = logProxy({[property]: 0});
+ var result = Object.prototype.propertyIsEnumerable.call(proxy, property);
+ assertEq(result, true);
+ assertDeepEq(log, [property]);
+
+ // Test 3: property is present on object, but not enumerable
+ var {proxy, log} = logProxy(Object.defineProperty({[property]: 0}, property, {enumerable: false}));
+ var result = Object.prototype.propertyIsEnumerable.call(proxy, property);
+ assertEq(result, false);
+ assertDeepEq(log, [property]);
+
+ // Test 4: property is present on prototype object
+ var {proxy, log} = logProxy(Object.create({[property]: 0}));
+ var result = Object.prototype.propertyIsEnumerable.call(proxy, property);
+ assertEq(result, false);
+ assertDeepEq(log, [property]);
+
+ // Test 5: property is present on prototype object, prototype is proxy object
+ var {proxy, log} = logProxy({[property]: 0});
+ var result = Object.prototype.propertyIsEnumerable.call(Object.create(proxy), property);
+ assertEq(result, false);
+ assertDeepEq(log, []);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/ecma_6/Object/seal-proxy.js b/js/src/tests/ecma_6/Object/seal-proxy.js
new file mode 100644
index 000000000..44bb685c8
--- /dev/null
+++ b/js/src/tests/ecma_6/Object/seal-proxy.js
@@ -0,0 +1,27 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function logProxy(object = {}, handler = {}) {
+ var log = [];
+ var proxy = new Proxy(object, new Proxy(handler, {
+ get(target, propertyKey, receiver) {
+ log.push(propertyKey);
+ return target[propertyKey];
+ }
+ }));
+ return {proxy, log};
+}
+
+// The order of operations is backwards when compared to ES6 draft rev 27
+// (2014 August 24), but see https://bugs.ecmascript.org/show_bug.cgi?id=3215
+// for an explanation on why the spec version is clearly wrong.
+
+var {proxy, log} = logProxy();
+Object.seal(proxy);
+assertDeepEq(log, ["preventExtensions", "ownKeys"]);
+
+var {proxy, log} = logProxy();
+Object.seal(Object.seal(proxy));
+assertDeepEq(log, ["preventExtensions", "ownKeys", "preventExtensions", "ownKeys"]);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/ecma_6/Object/seal.js b/js/src/tests/ecma_6/Object/seal.js
new file mode 100644
index 000000000..e325c80d9
--- /dev/null
+++ b/js/src/tests/ecma_6/Object/seal.js
@@ -0,0 +1,21 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * https://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+var BUGNUMBER = 1075294;
+var summary = "Object.seal() should return its argument with no conversion when the argument is a primitive value";
+
+print(BUGNUMBER + ": " + summary);
+assertEq(Object.seal(), undefined);
+assertEq(Object.seal(undefined), undefined);
+assertEq(Object.seal(null), null);
+assertEq(Object.seal(1), 1);
+assertEq(Object.seal("foo"), "foo");
+assertEq(Object.seal(true), true);
+if (typeof Symbol === "function") {
+ assertEq(Object.seal(Symbol.for("foo")), Symbol.for("foo"));
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/ecma_6/Object/setPrototypeOf-cross-realm-cycle.js b/js/src/tests/ecma_6/Object/setPrototypeOf-cross-realm-cycle.js
new file mode 100644
index 000000000..e2efe010e
--- /dev/null
+++ b/js/src/tests/ecma_6/Object/setPrototypeOf-cross-realm-cycle.js
@@ -0,0 +1,11 @@
+// The cycle check in 9.1.2 [[SetPrototypeOf]] prevents cross-realm cycles
+// involving only ordinary objects.
+
+var gw = newGlobal();
+
+var obj = {};
+var w = gw.Object.create(obj);
+assertThrowsInstanceOf(() => Object.setPrototypeOf(obj, w), TypeError);
+assertThrowsInstanceOf(() => gw.Object.setPrototypeOf(obj, w), gw.TypeError);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/ecma_6/Object/setPrototypeOf-cycle.js b/js/src/tests/ecma_6/Object/setPrototypeOf-cycle.js
new file mode 100644
index 000000000..a8b5aa75c
--- /dev/null
+++ b/js/src/tests/ecma_6/Object/setPrototypeOf-cycle.js
@@ -0,0 +1,16 @@
+// The cycle check in 9.1.2 [[SetPrototypeOf]] does not walk proxies.
+// Therefore it's very easy to create prototype chain cycles involving proxies,
+// and the spec requires us to accept this.
+
+var t = {};
+var p = new Proxy(t, {});
+Object.setPrototypeOf(t, p); // đŸ™ˆ
+
+// Actually doing anything that searches this object's prototype chain
+// technically should not terminate. We instead throw "too much recursion".
+for (var obj of [t, p]) {
+ assertThrowsInstanceOf(() => "x" in obj, InternalError);
+ assertThrowsInstanceOf(() => obj.x, InternalError);
+ assertThrowsInstanceOf(() => { obj.x = 1; }, InternalError);
+}
+reportCompare(0, 0);
diff --git a/js/src/tests/ecma_6/Object/setPrototypeOf-same-value.js b/js/src/tests/ecma_6/Object/setPrototypeOf-same-value.js
new file mode 100644
index 000000000..337550946
--- /dev/null
+++ b/js/src/tests/ecma_6/Object/setPrototypeOf-same-value.js
@@ -0,0 +1,11 @@
+// Setting a "new" prototype to the current [[Prototype]] value should never fail
+
+var x = {}, t = Object.create(x);
+Object.preventExtensions(t);
+// Should not fail, because it is the same [[Prototype]] value
+Object.setPrototypeOf(t, x);
+
+// Object.prototype's [[Prototype]] is immutable, make sure we can still set null
+Object.setPrototypeOf(Object.prototype, null);
+
+reportCompare(true, true);
diff --git a/js/src/tests/ecma_6/Object/shell.js b/js/src/tests/ecma_6/Object/shell.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/ecma_6/Object/shell.js
diff --git a/js/src/tests/ecma_6/Object/toLocaleString.js b/js/src/tests/ecma_6/Object/toLocaleString.js
new file mode 100644
index 000000000..3fa2acc74
--- /dev/null
+++ b/js/src/tests/ecma_6/Object/toLocaleString.js
@@ -0,0 +1,13 @@
+"use strict";
+
+Object.defineProperty(String.prototype, "toString", {
+ get() {
+ assertEq(typeof this, "string");
+
+ return function() { return typeof this; };
+ }
+})
+assertEq(Object.prototype.toLocaleString.call("test"), "string");
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/ecma_6/Object/toPrimitive-callers.js b/js/src/tests/ecma_6/Object/toPrimitive-callers.js
new file mode 100644
index 000000000..ffeef2225
--- /dev/null
+++ b/js/src/tests/ecma_6/Object/toPrimitive-callers.js
@@ -0,0 +1,57 @@
+// Check all the algorithms that call ToPrimitive. Confirm that they're passing
+// the correct hint, per spec.
+
+var STRING = "xyzzy";
+var NUMBER = 42;
+
+function assertCallsToPrimitive(f, expectedHint, expectedResult) {
+ var hint = undefined;
+ var testObj = {
+ [Symbol.toPrimitive](h) {
+ assertEq(hint, undefined);
+ hint = h;
+ return h === "number" ? NUMBER : STRING;
+ }
+ };
+ var result = f(testObj);
+ assertEq(hint, expectedHint, String(f));
+ assertEq(result, expectedResult, String(f));
+}
+
+// ToNumber
+assertCallsToPrimitive(Number, "number", NUMBER);
+
+// ToString
+assertCallsToPrimitive(String, "string", STRING);
+
+// ToPropertyKey
+var obj = {[STRING]: "pass"};
+assertCallsToPrimitive(key => obj[key], "string", "pass");
+
+// Abstract Relational Comparison
+assertCallsToPrimitive(x => x >= 42, "number", true);
+assertCallsToPrimitive(x => x > "42", "number", false);
+
+// Abstract Equality Comparison
+assertCallsToPrimitive(x => x != STRING, "default", false);
+assertCallsToPrimitive(x => STRING == x, "default", true);
+assertCallsToPrimitive(x => x == NUMBER, "default", false);
+assertCallsToPrimitive(x => NUMBER != x, "default", true);
+
+// Addition
+assertCallsToPrimitive(x => 1 + x, "default", "1" + STRING);
+assertCallsToPrimitive(x => "" + x, "default", STRING);
+
+// Date constructor
+assertCallsToPrimitive(x => (new Date(x)).valueOf(), "default", Number(STRING));
+
+// Date.prototype.toJSON
+var expected = "a suffusion of yellow";
+function testJSON(x) {
+ x.toJSON = Date.prototype.toJSON;
+ x.toISOString = function () { return expected; };
+ return JSON.stringify(x);
+}
+assertCallsToPrimitive(testJSON, "number", JSON.stringify(expected));
+
+reportCompare(0, 0);
diff --git a/js/src/tests/ecma_6/Object/toPrimitive.js b/js/src/tests/ecma_6/Object/toPrimitive.js
new file mode 100644
index 000000000..0904bd19a
--- /dev/null
+++ b/js/src/tests/ecma_6/Object/toPrimitive.js
@@ -0,0 +1,101 @@
+// ES6 7.1.1 ToPrimitive(input [, PreferredType]) specifies a new extension
+// point in the language. Objects can override the behavior of ToPrimitive
+// somewhat by supporting the method obj[@@toPrimitive](hint).
+//
+// (Rationale: ES5 had a [[DefaultValue]] internal method, overridden only by
+// Date objects. The change in ES6 is to make [[DefaultValue]] a plain old
+// method. This allowed ES6 to eliminate the [[DefaultValue]] internal method,
+// simplifying the meta-object protocol and thus proxies.)
+
+// obj[Symbol.toPrimitive]() is called whenever the ToPrimitive algorithm is invoked.
+var expectedThis, expectedHint;
+var obj = {
+ [Symbol.toPrimitive](hint, ...rest) {
+ assertEq(this, expectedThis);
+ assertEq(hint, expectedHint);
+ assertEq(rest.length, 0);
+ return 2015;
+ }
+};
+expectedThis = obj;
+expectedHint = "string";
+assertEq(String(obj), "2015");
+expectedHint = "number";
+assertEq(Number(obj), 2015);
+
+// It is called even through proxies.
+var proxy = new Proxy(obj, {});
+expectedThis = proxy;
+expectedHint = "default";
+assertEq("ES" + proxy, "ES2015");
+
+// It is called even through additional proxies and the prototype chain.
+proxy = new Proxy(Object.create(proxy), {});
+expectedThis = proxy;
+expectedHint = "default";
+assertEq("ES" + (proxy + 1), "ES2016");
+
+// It is not called if the operand is already a primitive.
+var ok = true;
+for (var constructor of [Boolean, Number, String, Symbol]) {
+ constructor.prototype[Symbol.toPrimitive] = function () {
+ ok = false;
+ throw "FAIL";
+ };
+}
+assertEq(Number(true), 1);
+assertEq(Number(77.7), 77.7);
+assertEq(Number("123"), 123);
+assertThrowsInstanceOf(() => Number(Symbol.iterator), TypeError);
+assertEq(String(true), "true");
+assertEq(String(77.7), "77.7");
+assertEq(String("123"), "123");
+assertEq(String(Symbol.iterator), "Symbol(Symbol.iterator)");
+assertEq(ok, true);
+
+// Converting a primitive symbol to another primitive type throws even if you
+// delete the @@toPrimitive method from Symbol.prototype.
+delete Symbol.prototype[Symbol.toPrimitive];
+var sym = Symbol("ok");
+assertThrowsInstanceOf(() => `${sym}`, TypeError);
+assertThrowsInstanceOf(() => Number(sym), TypeError);
+assertThrowsInstanceOf(() => "" + sym, TypeError);
+
+// However, having deleted that method, converting a Symbol wrapper object does
+// work: it calls Symbol.prototype.toString().
+obj = Object(sym);
+assertEq(String(obj), "Symbol(ok)");
+assertEq(`${obj}`, "Symbol(ok)");
+
+// Deleting valueOf as well makes numeric conversion also call toString().
+delete Symbol.prototype.valueOf;
+delete Object.prototype.valueOf;
+assertEq(Number(obj), NaN);
+Symbol.prototype.toString = function () { return "2060"; };
+assertEq(Number(obj), 2060);
+
+// Deleting Date.prototype[Symbol.toPrimitive] changes the result of addition
+// involving Date objects.
+var d = new Date;
+assertEq(0 + d, 0 + d.toString());
+delete Date.prototype[Symbol.toPrimitive];
+assertEq(0 + d, 0 + d.valueOf());
+
+// If @@toPrimitive, .toString, and .valueOf are all missing, we get a
+// particular sequence of property accesses, followed by a TypeError exception.
+var log = [];
+function doGet(target, propertyName, receiver) {
+ log.push(propertyName);
+}
+var handler = new Proxy({}, {
+ get(target, trapName, receiver) {
+ if (trapName !== "get")
+ throw `FAIL: system tried to access handler method: ${uneval(trapName)}`;
+ return doGet;
+ }
+});
+proxy = new Proxy(Object.create(null), handler);
+assertThrowsInstanceOf(() => proxy == 0, TypeError);
+assertDeepEq(log, [Symbol.toPrimitive, "valueOf", "toString"]);
+
+reportCompare(0, 0);