summaryrefslogtreecommitdiffstats
path: root/js/src/tests/ecma_6/extensions
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/tests/ecma_6/extensions')
-rw-r--r--js/src/tests/ecma_6/extensions/ArrayBuffer-slice-arguments-detaching.js81
-rw-r--r--js/src/tests/ecma_6/extensions/DataView-construct-arguments-detaching.js81
-rw-r--r--js/src/tests/ecma_6/extensions/DataView-set-arguments-detaching.js85
-rw-r--r--js/src/tests/ecma_6/extensions/RegExp-replace-lastParen.js12
-rw-r--r--js/src/tests/ecma_6/extensions/String-match-flags.js27
-rw-r--r--js/src/tests/ecma_6/extensions/TypedArray-set-object-funky-length-detaches.js66
-rw-r--r--js/src/tests/ecma_6/extensions/TypedArray-subarray-arguments-detaching.js112
-rw-r--r--js/src/tests/ecma_6/extensions/array-isArray-proxy-recursion.js41
-rw-r--r--js/src/tests/ecma_6/extensions/browser.js0
-rw-r--r--js/src/tests/ecma_6/extensions/element-setting-ToNumber-detaches.js36
-rw-r--r--js/src/tests/ecma_6/extensions/for-loop-with-lexical-declaration-and-nested-function-statement.js130
-rw-r--r--js/src/tests/ecma_6/extensions/keyword-unescaped-requirement-modules.js99
-rw-r--r--js/src/tests/ecma_6/extensions/keyword-unescaped-requirement.js43
-rw-r--r--js/src/tests/ecma_6/extensions/new-cross-compartment.js42
-rw-r--r--js/src/tests/ecma_6/extensions/reentrant-RegExp-creation-and-gc-during-new-RegExp-pattern-ToString.js41
-rw-r--r--js/src/tests/ecma_6/extensions/setImmutablePrototype.js195
-rw-r--r--js/src/tests/ecma_6/extensions/shell.js5
17 files changed, 1096 insertions, 0 deletions
diff --git a/js/src/tests/ecma_6/extensions/ArrayBuffer-slice-arguments-detaching.js b/js/src/tests/ecma_6/extensions/ArrayBuffer-slice-arguments-detaching.js
new file mode 100644
index 000000000..1ff5c1ad5
--- /dev/null
+++ b/js/src/tests/ecma_6/extensions/ArrayBuffer-slice-arguments-detaching.js
@@ -0,0 +1,81 @@
+// |reftest| skip-if(!xulRuntime.shell) -- needs detachArrayBuffer()
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+
+var gTestfile = "ArrayBuffer-slice-arguments-detaching.js";
+//-----------------------------------------------------------------------------
+var BUGNUMBER = 991981;
+var summary =
+ "ArrayBuffer.prototype.slice shouldn't misbehave horribly if " +
+ "index-argument conversion detaches the ArrayBuffer being sliced";
+
+print(BUGNUMBER + ": " + summary);
+
+/**************
+ * BEGIN TEST *
+ **************/
+
+function testStart()
+{
+ var ab = new ArrayBuffer(0x1000);
+
+ var start =
+ {
+ valueOf: function()
+ {
+ detachArrayBuffer(ab);
+ gc();
+ return 0x800;
+ }
+ };
+
+ var ok = false;
+ try
+ {
+ ab.slice(start);
+ }
+ catch (e)
+ {
+ ok = true;
+ }
+ assertEq(ok, true, "start weirdness should have thrown");
+ assertEq(ab.byteLength, 0, "detaching should work for start weirdness");
+}
+testStart();
+
+function testEnd()
+{
+ var ab = new ArrayBuffer(0x1000);
+
+ var end =
+ {
+ valueOf: function()
+ {
+ detachArrayBuffer(ab);
+ gc();
+ return 0x1000;
+ }
+ };
+
+ var ok = false;
+ try
+ {
+ ab.slice(0x800, end);
+ }
+ catch (e)
+ {
+ ok = true;
+ }
+ assertEq(ok, true, "byteLength weirdness should have thrown");
+ assertEq(ab.byteLength, 0, "detaching should work for byteLength weirdness");
+}
+testEnd();
+
+/******************************************************************************/
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
+
+print("Tests complete");
diff --git a/js/src/tests/ecma_6/extensions/DataView-construct-arguments-detaching.js b/js/src/tests/ecma_6/extensions/DataView-construct-arguments-detaching.js
new file mode 100644
index 000000000..14659f1d2
--- /dev/null
+++ b/js/src/tests/ecma_6/extensions/DataView-construct-arguments-detaching.js
@@ -0,0 +1,81 @@
+// |reftest| skip-if(!xulRuntime.shell) -- needs detachArrayBuffer()
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+
+var gTestfile = "DataView-construct-arguments-detaching.js";
+//-----------------------------------------------------------------------------
+var BUGNUMBER = 991981;
+var summary =
+ "new DataView(...) shouldn't misbehave horribly if index-argument " +
+ "conversion detaches the ArrayBuffer to be viewed";
+
+print(BUGNUMBER + ": " + summary);
+
+/**************
+ * BEGIN TEST *
+ **************/
+
+function testByteOffset()
+{
+ var ab = new ArrayBuffer(0x1000);
+
+ var start =
+ {
+ valueOf: function()
+ {
+ detachArrayBuffer(ab);
+ gc();
+ return 0x800;
+ }
+ };
+
+ var ok = false;
+ try
+ {
+ new DataView(ab, start);
+ }
+ catch (e)
+ {
+ ok = true;
+ }
+ assertEq(ok, true, "byteOffset weirdness should have thrown");
+ assertEq(ab.byteLength, 0, "detaching should work for byteOffset weirdness");
+}
+testByteOffset();
+
+function testByteLength()
+{
+ var ab = new ArrayBuffer(0x1000);
+
+ var len =
+ {
+ valueOf: function()
+ {
+ detachArrayBuffer(ab);
+ gc();
+ return 0x800;
+ }
+ };
+
+ var ok = false;
+ try
+ {
+ new DataView(ab, 0x800, len);
+ }
+ catch (e)
+ {
+ ok = true;
+ }
+ assertEq(ok, true, "byteLength weirdness should have thrown");
+ assertEq(ab.byteLength, 0, "detaching should work for byteLength weirdness");
+}
+testByteLength();
+
+/******************************************************************************/
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
+
+print("Tests complete");
diff --git a/js/src/tests/ecma_6/extensions/DataView-set-arguments-detaching.js b/js/src/tests/ecma_6/extensions/DataView-set-arguments-detaching.js
new file mode 100644
index 000000000..b05ec480d
--- /dev/null
+++ b/js/src/tests/ecma_6/extensions/DataView-set-arguments-detaching.js
@@ -0,0 +1,85 @@
+// |reftest| skip-if(!xulRuntime.shell) -- needs detachArrayBuffer()
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+
+var gTestfile = "DataView-set-arguments-detaching.js";
+//-----------------------------------------------------------------------------
+var BUGNUMBER = 991981;
+var summary =
+ "DataView.prototype.set* methods shouldn't misbehave horribly if " +
+ "index-argument conversion detaches the ArrayBuffer being modified";
+
+print(BUGNUMBER + ": " + summary);
+
+/**************
+ * BEGIN TEST *
+ **************/
+
+function testIndex()
+{
+ var ab = new ArrayBuffer(0x1000);
+
+ var dv = new DataView(ab);
+
+ var start =
+ {
+ valueOf: function()
+ {
+ detachArrayBuffer(ab);
+ gc();
+ return 0xFFF;
+ }
+ };
+
+ var ok = false;
+ try
+ {
+ dv.setUint8(start, 0x42);
+ }
+ catch (e)
+ {
+ ok = true;
+ }
+ assertEq(ok, true, "should have thrown");
+ assertEq(ab.byteLength, 0, "should have been detached correctly");
+}
+testIndex();
+
+function testValue()
+{
+ var ab = new ArrayBuffer(0x100000);
+
+ var dv = new DataView(ab);
+
+ var value =
+ {
+ valueOf: function()
+ {
+ detachArrayBuffer(ab);
+ gc();
+ return 0x42;
+ }
+ };
+
+ var ok = false;
+ try
+ {
+ dv.setUint8(0xFFFFF, value);
+ }
+ catch (e)
+ {
+ ok = true;
+ }
+ assertEq(ok, true, "should have thrown");
+ assertEq(ab.byteLength, 0, "should have been detached correctly");
+}
+testValue();
+
+/******************************************************************************/
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
+
+print("Tests complete");
diff --git a/js/src/tests/ecma_6/extensions/RegExp-replace-lastParen.js b/js/src/tests/ecma_6/extensions/RegExp-replace-lastParen.js
new file mode 100644
index 000000000..d06bfe7cd
--- /dev/null
+++ b/js/src/tests/ecma_6/extensions/RegExp-replace-lastParen.js
@@ -0,0 +1,12 @@
+var BUGNUMBER = 1263118;
+var summary = "RegExp.prototype[@@replace] with non-standard $+ substitution.";
+
+print(BUGNUMBER + ": " + summary);
+
+assertEq(/(a)(b)(c)/[Symbol.replace]("abc", "[$+]"), "[c]");
+assertEq(/(a)(b)c/[Symbol.replace]("abc", "[$+]"), "[b]");
+assertEq(/(a)bc/[Symbol.replace]("abc", "[$+]"), "[a]");
+assertEq(/abc/[Symbol.replace]("abc", "[$+]"), "[]");
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/ecma_6/extensions/String-match-flags.js b/js/src/tests/ecma_6/extensions/String-match-flags.js
new file mode 100644
index 000000000..b1a382fdf
--- /dev/null
+++ b/js/src/tests/ecma_6/extensions/String-match-flags.js
@@ -0,0 +1,27 @@
+var BUGNUMBER = 1263139;
+var summary = "String.prototype.match with non-string non-standard flags argument.";
+
+print(BUGNUMBER + ": " + summary);
+
+var called;
+var flags = {
+ toString() {
+ called = true;
+ return "";
+ }
+};
+
+called = false;
+"a".match("a", flags);
+assertEq(called, false);
+
+called = false;
+"a".search("a", flags);
+assertEq(called, false);
+
+called = false;
+"a".replace("a", "b", flags);
+assertEq(called, false);
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/ecma_6/extensions/TypedArray-set-object-funky-length-detaches.js b/js/src/tests/ecma_6/extensions/TypedArray-set-object-funky-length-detaches.js
new file mode 100644
index 000000000..7379bf9a4
--- /dev/null
+++ b/js/src/tests/ecma_6/extensions/TypedArray-set-object-funky-length-detaches.js
@@ -0,0 +1,66 @@
+// |reftest| skip-if(!xulRuntime.shell) -- needs detachArrayBuffer()
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+
+var gTestfile = "set-object-funky-length-detaches.js";
+//-----------------------------------------------------------------------------
+var BUGNUMBER = 991981;
+var summary =
+ "%TypedArray%.prototype.set(object w/funky length property, offset) " +
+ "shouldn't misbehave if the funky length property detaches this typed " +
+ "array's buffer";
+
+print(BUGNUMBER + ": " + summary);
+
+/**************
+ * BEGIN TEST *
+ **************/
+
+var ctors = [Int8Array, Uint8Array, Uint8ClampedArray,
+ Int16Array, Uint16Array,
+ Int32Array, Uint32Array,
+ Float32Array, Float64Array];
+ctors.forEach(function(TypedArray) {
+ var buf = new ArrayBuffer(512 * 1024);
+ var ta = new TypedArray(buf);
+
+ var arraylike =
+ {
+ 0: 17,
+ 1: 42,
+ 2: 3,
+ 3: 99,
+ 4: 37,
+ 5: 9,
+ 6: 72,
+ 7: 31,
+ 8: 22,
+ 9: 0,
+ get length()
+ {
+ detachArrayBuffer(buf);
+ return 10;
+ }
+ };
+
+ var passed = false;
+ try
+ {
+ ta.set(arraylike, 0x1234);
+ }
+ catch (e)
+ {
+ passed = true;
+ }
+
+ assertEq(passed, true);
+});
+
+/******************************************************************************/
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
+
+print("Tests complete");
diff --git a/js/src/tests/ecma_6/extensions/TypedArray-subarray-arguments-detaching.js b/js/src/tests/ecma_6/extensions/TypedArray-subarray-arguments-detaching.js
new file mode 100644
index 000000000..a6349657c
--- /dev/null
+++ b/js/src/tests/ecma_6/extensions/TypedArray-subarray-arguments-detaching.js
@@ -0,0 +1,112 @@
+// |reftest| skip-if(!xulRuntime.shell) -- needs detachArrayBuffer()
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+
+var gTestfile = "TypedArray-subarray-arguments-detaching.js";
+//-----------------------------------------------------------------------------
+var BUGNUMBER = 991981;
+var summary =
+ "%TypedArray.prototype.subarray shouldn't misbehave horribly if " +
+ "index-argument conversion detaches the underlying ArrayBuffer";
+
+print(BUGNUMBER + ": " + summary);
+
+/**************
+ * BEGIN TEST *
+ **************/
+
+function testBegin()
+{
+ var ab = new ArrayBuffer(0x1000);
+
+ var begin =
+ {
+ valueOf: function()
+ {
+ detachArrayBuffer(ab);
+ return 0x800;
+ }
+ };
+
+ var ta = new Uint8Array(ab);
+
+ var ok = false;
+ try
+ {
+ ta.subarray(begin);
+ }
+ catch (e)
+ {
+ ok = true;
+ }
+ assertEq(ok, true, "start weirdness should have thrown");
+ assertEq(ab.byteLength, 0, "detaching should work for start weirdness");
+}
+testBegin();
+
+function testBeginWithEnd()
+{
+ var ab = new ArrayBuffer(0x1000);
+
+ var begin =
+ {
+ valueOf: function()
+ {
+ detachArrayBuffer(ab);
+ return 0x800;
+ }
+ };
+
+ var ta = new Uint8Array(ab);
+
+ var ok = false;
+ try
+ {
+ ta.subarray(begin, 0x1000);
+ }
+ catch (e)
+ {
+ ok = true;
+ }
+ assertEq(ok, true, "start weirdness should have thrown");
+ assertEq(ab.byteLength, 0, "detaching should work for start weirdness");
+}
+testBeginWithEnd();
+
+function testEnd()
+{
+ var ab = new ArrayBuffer(0x1000);
+
+ var end =
+ {
+ valueOf: function()
+ {
+ detachArrayBuffer(ab);
+ return 0x1000;
+ }
+ };
+
+ var ta = new Uint8Array(ab);
+
+ var ok = false;
+ try
+ {
+ ta.subarray(0x800, end);
+ }
+ catch (e)
+ {
+ ok = true;
+ }
+ assertEq(ok, true, "start weirdness should have thrown");
+ assertEq(ab.byteLength, 0, "detaching should work for start weirdness");
+}
+testEnd();
+
+/******************************************************************************/
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
+
+print("Tests complete");
diff --git a/js/src/tests/ecma_6/extensions/array-isArray-proxy-recursion.js b/js/src/tests/ecma_6/extensions/array-isArray-proxy-recursion.js
new file mode 100644
index 000000000..ca2907a99
--- /dev/null
+++ b/js/src/tests/ecma_6/extensions/array-isArray-proxy-recursion.js
@@ -0,0 +1,41 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+
+//-----------------------------------------------------------------------------
+var BUGNUMBER = 1282047;
+var summary = 'Infinite recursion via Array.isArray on a proxy';
+
+print(BUGNUMBER + ": " + summary);
+
+/**************
+ * BEGIN TEST *
+ **************/
+
+var proxy = Proxy.revocable([], {}).proxy;
+
+// A depth of 100000 ought to be enough for any platform to consume its entire
+// stack, hopefully without making any recalcitrant platforms time out. If no
+// timeout happens, the assertEq checks for the proper expected value.
+for (var i = 0; i < 1e5; i++)
+ proxy = new Proxy(proxy, {});
+
+try
+{
+ assertEq(Array.isArray(proxy), true);
+
+ // If we reach here, it's cool, we just didn't consume the entire stack.
+}
+catch (e)
+{
+ assertEq(e instanceof InternalError, true,
+ "should have thrown for over-recursion");
+}
+
+/******************************************************************************/
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
+
+print("Tests complete");
diff --git a/js/src/tests/ecma_6/extensions/browser.js b/js/src/tests/ecma_6/extensions/browser.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/ecma_6/extensions/browser.js
diff --git a/js/src/tests/ecma_6/extensions/element-setting-ToNumber-detaches.js b/js/src/tests/ecma_6/extensions/element-setting-ToNumber-detaches.js
new file mode 100644
index 000000000..82e0c0d87
--- /dev/null
+++ b/js/src/tests/ecma_6/extensions/element-setting-ToNumber-detaches.js
@@ -0,0 +1,36 @@
+// |reftest| skip-if(!xulRuntime.shell) -- needs detachArrayBuffer()
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+"use strict"; // make test fail when limitation below is fixed
+
+var gTestfile = 'element-setting-ToNumber-detaches.js';
+//-----------------------------------------------------------------------------
+var BUGNUMBER = 1001547;
+var summary =
+ "Don't assert assigning into memory detached while converting the value to " +
+ "assign into a number";
+
+print(BUGNUMBER + ": " + summary);
+
+/**************
+ * BEGIN TEST *
+ **************/
+
+// Technically per current spec the element-sets should throw in strict mode,
+// but we just silently do nothing for now, somewhat due to limitations of our
+// internal MOP (which can't easily say "try this special behavior, else fall
+// back on normal logic"), somewhat because it's consistent with current
+// behavior (as of this test's addition) for out-of-bounds sets.
+
+var ab = new ArrayBuffer(64);
+var ta = new Uint32Array(ab);
+ta[4] = { valueOf() { detachArrayBuffer(ab); return 5; } };
+
+/******************************************************************************/
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
+
+print("Tests complete");
diff --git a/js/src/tests/ecma_6/extensions/for-loop-with-lexical-declaration-and-nested-function-statement.js b/js/src/tests/ecma_6/extensions/for-loop-with-lexical-declaration-and-nested-function-statement.js
new file mode 100644
index 000000000..9f6fd6467
--- /dev/null
+++ b/js/src/tests/ecma_6/extensions/for-loop-with-lexical-declaration-and-nested-function-statement.js
@@ -0,0 +1,130 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+
+var gTestfile =
+ "for-loop-with-lexical-declaration-and-nested-function-statement.js";
+//-----------------------------------------------------------------------------
+var BUGNUMBER = 1149797;
+var summary =
+ "Don't assert when freshening the scope chain for a for-loop whose head " +
+ "contains a lexical declaration, where the loop body might add more " +
+ "bindings at runtime";
+
+print(BUGNUMBER + ": " + summary);
+
+/**************
+ * BEGIN TEST *
+ **************/
+
+for (let x = 0; x < 9; ++x) {
+ function q1() {}
+}
+
+{
+ for (let x = 0; x < 9; ++x) {
+ function q2() {}
+ }
+}
+
+function f1()
+{
+ for (let x = 0; x < 9; ++x) {
+ function q3() {}
+ }
+}
+f1();
+
+function f2()
+{
+ {
+ for (let x = 0; x < 9; ++x) {
+ function q4() {}
+ }
+ }
+}
+f2();
+
+for (let x = 0; x < 9; ++x)
+{
+ // deliberately inside a block statement
+ function q5() {}
+}
+
+{
+ for (let x = 0; x < 9; ++x)
+ {
+ // deliberately inside a block statement
+ function q6() {}
+ }
+}
+
+function g1()
+{
+ for (let x = 0; x < 9; ++x)
+ {
+ // deliberately inside a block statement
+ function q7() {}
+ }
+}
+g1();
+
+function g2()
+{
+ {
+ for (let x = 0; x < 9; ++x)
+ {
+ // deliberately inside a block statement
+ function q8() {}
+ }
+ }
+}
+g2();
+
+for (let x = 0; x < 9; ++x) {
+ (function() {
+ eval("function q9() {}");
+ })();
+}
+
+{
+ for (let x = 0; x < 9; ++x)
+ {
+ // deliberately inside a block statement
+ (function() {
+ eval("function q10() {}");
+ })();
+ }
+}
+
+function h1()
+{
+ for (let x = 0; x < 9; ++x)
+ {
+ // deliberately inside a block statement
+ (function() {
+ eval("function q11() {}");
+ })();
+ }
+}
+h1();
+
+function h2()
+{
+ {
+ for (let x = 0; x < 9; ++x)
+ {
+ // deliberately inside a block statement
+ (function() { eval("function q12() {}"); })();
+ }
+ }
+}
+h2();
+
+/******************************************************************************/
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
+
+print("Tests complete");
diff --git a/js/src/tests/ecma_6/extensions/keyword-unescaped-requirement-modules.js b/js/src/tests/ecma_6/extensions/keyword-unescaped-requirement-modules.js
new file mode 100644
index 000000000..260948cfe
--- /dev/null
+++ b/js/src/tests/ecma_6/extensions/keyword-unescaped-requirement-modules.js
@@ -0,0 +1,99 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+
+//-----------------------------------------------------------------------------
+var BUGNUMBER = 1204027;
+var summary =
+ "Escape sequences aren't allowed in bolded grammar tokens (that is, in " +
+ "keywords, possibly contextual keywords)";
+
+print(BUGNUMBER + ": " + summary);
+
+/**************
+ * BEGIN TEST *
+ **************/
+
+var badModules =
+ [
+ "\\u0069mport f from 'g'",
+ "i\\u006dport g from 'h'",
+ "import * \\u0061s foo",
+ "import {} fro\\u006d 'bar'",
+ "import { x \\u0061s y } from 'baz'",
+
+ "\\u0065xport function f() {}",
+ "e\\u0078port function g() {}",
+ "export * fro\\u006d 'fnord'",
+ "export d\\u0065fault var x = 3;",
+ "export { q } fro\\u006d 'qSupplier';",
+
+ ];
+
+if (typeof parseModule === "function")
+{
+ for (var module of badModules)
+ {
+ assertThrowsInstanceOf(() => parseModule(module), SyntaxError,
+ "bad behavior for: " + module);
+ }
+}
+
+if (typeof Reflect.parse === "function")
+{
+ var twoStatementAST =
+ Reflect.parse(`let x = 0;
+ export { x } /* ASI should trigger here */
+ fro\\u006D`,
+ { target: "module" });
+
+ var statements = twoStatementAST.body;
+ assertEq(statements.length, 3,
+ "should have two items in the module, not one ExportDeclaration");
+ assertEq(statements[0].type, "VariableDeclaration");
+ assertEq(statements[1].type, "ExportDeclaration");
+ assertEq(statements[2].type, "ExpressionStatement");
+ assertEq(statements[2].expression.name, "from");
+
+ var oneStatementAST =
+ Reflect.parse(`export { x } /* no ASI here */
+ from 'foo'`,
+ { target: "module" });
+
+ assertEq(oneStatementAST.body.length, 1);
+ assertEq(oneStatementAST.body[0].type, "ExportDeclaration");
+
+ twoStatementAST =
+ Reflect.parse(`export { x } from "bar"
+ /bar/g`,
+ { target: "module" });
+
+ statements = twoStatementAST.body;
+ assertEq(statements.length, 2,
+ "should have two items in the module, not one ExportDeclaration");
+ assertEq(statements[0].type, "ExportDeclaration");
+ assertEq(statements[1].type, "ExpressionStatement");
+ assertEq(statements[1].expression.type, "Literal");
+ assertEq(statements[1].expression.value.toString(), "/bar/g");
+
+ twoStatementAST =
+ Reflect.parse(`export * from "bar"
+ /bar/g`,
+ { target: "module" });
+
+ statements = twoStatementAST.body;
+ assertEq(statements.length, 2,
+ "should have two items in the module, not one ExportDeclaration");
+ assertEq(statements[0].type, "ExportDeclaration");
+ assertEq(statements[1].type, "ExpressionStatement");
+ assertEq(statements[1].expression.type, "Literal");
+ assertEq(statements[1].expression.value.toString(), "/bar/g");
+}
+
+/******************************************************************************/
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
+
+print("Tests complete");
diff --git a/js/src/tests/ecma_6/extensions/keyword-unescaped-requirement.js b/js/src/tests/ecma_6/extensions/keyword-unescaped-requirement.js
new file mode 100644
index 000000000..20d3555e3
--- /dev/null
+++ b/js/src/tests/ecma_6/extensions/keyword-unescaped-requirement.js
@@ -0,0 +1,43 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+
+//-----------------------------------------------------------------------------
+var BUGNUMBER = 1204027;
+var summary =
+ "Escape sequences aren't allowed in bolded grammar tokens (that is, in " +
+ "keywords, possibly contextual keywords)";
+
+print(BUGNUMBER + ": " + summary);
+
+/**************
+ * BEGIN TEST *
+ **************/
+
+var randomExtensions =
+ [
+ "for \\u0065ach (var x in []);",
+ "for e\\u0061ch (var x in []);",
+ "[0 for \\u0065ach (var x in [])]",
+ "[0 for e\\u0061ch (var x in [])]",
+ "(0 for \\u0065ach (var x in []))",
+ "(0 for e\\u0061ch (var x in []))",
+
+ // Soon to be not an extension, maybe...
+ "(for (x \\u006ff [1]) x)",
+ "(for (x o\\u0066 [1]) x)",
+ ];
+
+for (var extension of randomExtensions)
+{
+ assertThrowsInstanceOf(() => Function(extension), SyntaxError,
+ "bad behavior for: " + extension);
+}
+
+/******************************************************************************/
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
+
+print("Tests complete");
diff --git a/js/src/tests/ecma_6/extensions/new-cross-compartment.js b/js/src/tests/ecma_6/extensions/new-cross-compartment.js
new file mode 100644
index 000000000..5df437520
--- /dev/null
+++ b/js/src/tests/ecma_6/extensions/new-cross-compartment.js
@@ -0,0 +1,42 @@
+// Any copyright is dedicated to the Public Domain.
+// http://creativecommons.org/licenses/publicdomain/
+
+//-----------------------------------------------------------------------------
+var BUGNUMBER = 1178653;
+var summary =
+ "|new| on a cross-compartment wrapper to a non-constructor shouldn't assert";
+
+print(BUGNUMBER + ": " + summary);
+
+/**************
+ * BEGIN TEST *
+ **************/
+
+var g = newGlobal();
+
+var otherStr = new g.String("foo");
+assertEq(otherStr instanceof g.String, true);
+assertEq(otherStr.valueOf(), "foo");
+
+// THIS IS WRONG. |new| itself should throw if !IsConstructor(constructor),
+// meaning this global's TypeError should be used. The problem ultimately is
+// that wrappers conflate callable/constructible, so any old function from
+// another global appears to be both. Somebody fix bug XXXXXX!
+try
+{
+ var constructor = g.parseInt;
+ new constructor();
+ throw new Error("no error thrown");
+}
+catch (e)
+{
+ assertEq(e instanceof g.TypeError, true,
+ "THIS REALLY SHOULD BE |e instanceof TypeError|");
+}
+
+/******************************************************************************/
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
+
+print("Tests complete");
diff --git a/js/src/tests/ecma_6/extensions/reentrant-RegExp-creation-and-gc-during-new-RegExp-pattern-ToString.js b/js/src/tests/ecma_6/extensions/reentrant-RegExp-creation-and-gc-during-new-RegExp-pattern-ToString.js
new file mode 100644
index 000000000..0ec0b493e
--- /dev/null
+++ b/js/src/tests/ecma_6/extensions/reentrant-RegExp-creation-and-gc-during-new-RegExp-pattern-ToString.js
@@ -0,0 +1,41 @@
+// |reftest| skip-if(!xulRuntime.shell) -- needs gc (newGlobal/evaluate are shimmed)
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+
+var gTestfile =
+ "reentrant-RegExp-creation-and-gc-during-new-RegExp-pattern-ToString.js";
+//-----------------------------------------------------------------------------
+var BUGNUMBER = 1253099;
+var summary =
+ "Don't assert when, in |new RegExp(pat)|, stringifying |pat| creates " +
+ "another RegExp and then performs a GC";
+
+print(BUGNUMBER + ": " + summary);
+
+/**************
+ * BEGIN TEST *
+ **************/
+
+// The fresh global object is required to ensure that the outer |new RegExp|
+// is the first RegExp created in the global (other than RegExp.prototype).
+newGlobal().evaluate(`
+var createsRegExpAndCallsGCWhenStringified =
+ {
+ toString: function() {
+ new RegExp("a");
+ gc();
+ return "q";
+ }
+ };
+
+assertEq(new RegExp(createsRegExpAndCallsGCWhenStringified).source, "q");
+`);
+
+/******************************************************************************/
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
+
+print("Tests complete");
diff --git a/js/src/tests/ecma_6/extensions/setImmutablePrototype.js b/js/src/tests/ecma_6/extensions/setImmutablePrototype.js
new file mode 100644
index 000000000..9226dcce2
--- /dev/null
+++ b/js/src/tests/ecma_6/extensions/setImmutablePrototype.js
@@ -0,0 +1,195 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+var gTestfile = "setImmutablePrototype.js";
+//-----------------------------------------------------------------------------
+var BUGNUMBER = 1052139;
+var summary =
+ "Implement JSAPI and a shell function to prevent modifying an extensible " +
+ "object's [[Prototype]]";
+
+print(BUGNUMBER + ": " + summary);
+
+/**************
+ * BEGIN TEST *
+ **************/
+
+if (typeof evaluate !== "function")
+{
+ // Not totally faithful semantics, but approximately close enough for this
+ // test's purposes.
+ evaluate = eval;
+}
+
+var usingRealSetImmutablePrototype = true;
+
+if (typeof setImmutablePrototype !== "function")
+{
+ usingRealSetImmutablePrototype = false;
+
+ if (typeof SpecialPowers !== "undefined")
+ {
+ setImmutablePrototype =
+ SpecialPowers.Cu.getJSTestingFunctions().setImmutablePrototype;
+ }
+}
+
+if (typeof wrap !== "function")
+{
+ // good enough
+ wrap = function(x) { return x; };
+}
+
+function setViaProtoSetter(obj, newProto)
+{
+ var setter =
+ Object.getOwnPropertyDescriptor(Object.prototype, "__proto__").set;
+ setter.call(obj, newProto);
+}
+
+function checkPrototypeMutationFailure(obj, desc)
+{
+ var initialProto = Object.getPrototypeOf(obj);
+
+ // disconnected from any [[Prototype]] chains for use on any object at all
+ var newProto = Object.create(null);
+
+ function tryMutate(func, method)
+ {
+ try
+ {
+ func(obj, newProto);
+ throw new Error(desc + ": no error thrown, prototype " +
+ (Object.getPrototypeOf(obj) === initialProto
+ ? "wasn't"
+ : "was") +
+ " changed");
+ }
+ catch (e)
+ {
+ // Note: This is always a TypeError from *this* global object, because
+ // Object.setPrototypeOf and the __proto__ setter come from *this*
+ // global object.
+ assertEq(e instanceof TypeError, true,
+ desc + ": should have thrown TypeError setting [[Prototype]] " +
+ "via " + method + ", got " + e);
+ assertEq(Object.getPrototypeOf(obj), initialProto,
+ desc + ": shouldn't observe [[Prototype]] change");
+ }
+ }
+
+ tryMutate(Object.setPrototypeOf, "Object.setPrototypeOf");
+ tryMutate(setViaProtoSetter, "__proto__ setter");
+}
+
+function runNormalTests(global)
+{
+ if (typeof setImmutablePrototype !== "function")
+ {
+ print("no testable setImmutablePrototype function available, skipping tests");
+ return;
+ }
+
+ // regular old object, non-null [[Prototype]]
+
+ var emptyLiteral = global.evaluate("({})");
+ assertEq(setImmutablePrototype(emptyLiteral), true);
+ checkPrototypeMutationFailure(emptyLiteral, "empty literal");
+
+ // regular old object, null [[Prototype]]
+
+ var nullProto = global.Object.create(null);
+ assertEq(setImmutablePrototype(nullProto), true);
+ checkPrototypeMutationFailure(nullProto, "nullProto");
+
+ // Shocker: SpecialPowers's little mind doesn't understand proxies. Abort.
+ if (!usingRealSetImmutablePrototype)
+ return;
+
+ // direct proxies
+
+ var emptyTarget = global.evaluate("({})");
+ var directProxy = new global.Proxy(emptyTarget, {});
+ assertEq(setImmutablePrototype(directProxy), true);
+ checkPrototypeMutationFailure(directProxy, "direct proxy to empty target");
+ checkPrototypeMutationFailure(emptyTarget, "empty target");
+
+ var anotherTarget = global.evaluate("({})");
+ var anotherDirectProxy = new global.Proxy(anotherTarget, {});
+ assertEq(setImmutablePrototype(anotherTarget), true);
+ checkPrototypeMutationFailure(anotherDirectProxy, "another direct proxy to empty target");
+ checkPrototypeMutationFailure(anotherTarget, "another empty target");
+
+ var nestedTarget = global.evaluate("({})");
+ var nestedProxy = new global.Proxy(new Proxy(nestedTarget, {}), {});
+ assertEq(setImmutablePrototype(nestedProxy), true);
+ checkPrototypeMutationFailure(nestedProxy, "nested proxy to empty target");
+ checkPrototypeMutationFailure(nestedTarget, "nested target");
+
+ // revocable proxies
+
+ var revocableTarget = global.evaluate("({})");
+ var revocable = global.Proxy.revocable(revocableTarget, {});
+ assertEq(setImmutablePrototype(revocable.proxy), true);
+ checkPrototypeMutationFailure(revocableTarget, "revocable target");
+ checkPrototypeMutationFailure(revocable.proxy, "revocable proxy");
+
+ assertEq(revocable.revoke(), undefined);
+ try
+ {
+ setImmutablePrototype(revocable.proxy);
+ throw new Error("expected to throw on revoked proxy");
+ }
+ catch (e)
+ {
+ // Note: This is a TypeError from |global|, because the proxy's
+ // |setImmutablePrototype| method is what actually throws here.
+ // (Usually the method simply sets |*succeeded| to false and the
+ // caller handles or throws as needed after that. But not here.)
+ assertEq(e instanceof global.TypeError, true,
+ "expected TypeError, instead threw " + e);
+ }
+
+ var anotherRevocableTarget = global.evaluate("({})");
+ assertEq(setImmutablePrototype(anotherRevocableTarget), true);
+ checkPrototypeMutationFailure(anotherRevocableTarget, "another revocable target");
+
+ var anotherRevocable = global.Proxy.revocable(anotherRevocableTarget, {});
+ checkPrototypeMutationFailure(anotherRevocable.proxy, "another revocable target");
+
+ assertEq(anotherRevocable.revoke(), undefined);
+ try
+ {
+ var rv = setImmutablePrototype(anotherRevocable.proxy);
+ throw new Error("expected to throw on another revoked proxy, returned " + rv);
+ }
+ catch (e)
+ {
+ // NOTE: Again from |global|, as above.
+ assertEq(e instanceof global.TypeError, true,
+ "expected TypeError, instead threw " + e);
+ }
+}
+
+var global = this;
+runNormalTests(global); // same-global
+
+if (typeof newGlobal === "function")
+{
+ var otherGlobal = newGlobal();
+ var subsumingNothing = newGlobal({ principal: 0 });
+ var subsumingEverything = newGlobal({ principal: ~0 });
+
+ runNormalTests(otherGlobal); // cross-global
+ runNormalTests(subsumingNothing);
+ runNormalTests(subsumingEverything);
+}
+
+/******************************************************************************/
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
+
+print("Tests complete");
diff --git a/js/src/tests/ecma_6/extensions/shell.js b/js/src/tests/ecma_6/extensions/shell.js
new file mode 100644
index 000000000..4d731295d
--- /dev/null
+++ b/js/src/tests/ecma_6/extensions/shell.js
@@ -0,0 +1,5 @@
+// NOTE: This only turns on 1.8.5 in shell builds. The browser requires the
+// futzing in js/src/tests/browser.js (which only turns on 1.8, the most
+// the browser supports).
+if (typeof version != 'undefined')
+ version(185);