summaryrefslogtreecommitdiffstats
path: root/js/src/tests/test
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/tests/test')
-rw-r--r--js/src/tests/test/expected/export/multi-header.js25
-rw-r--r--js/src/tests/test/expected/export/reftest-and-frontmatter-error.js22
-rw-r--r--js/src/tests/test/expected/export/reftest-error-syntaxerror.js21
-rw-r--r--js/src/tests/test/expected/export/regular.js18
-rw-r--r--js/src/tests/test/expected/export/reportCompare.js23
-rw-r--r--js/src/tests/test/expected/import/files/local/smTempBranch/browser.js0
-rw-r--r--js/src/tests/test/expected/import/files/local/smTempBranch/language/browser.js0
-rw-r--r--js/src/tests/test/expected/import/files/local/smTempBranch/language/export/browser.js0
-rw-r--r--js/src/tests/test/expected/import/files/local/smTempBranch/language/export/escaped-foobarbaz.js25
-rw-r--r--js/src/tests/test/expected/import/files/local/smTempBranch/language/export/shell.js0
-rw-r--r--js/src/tests/test/expected/import/files/local/smTempBranch/language/shell.js0
-rw-r--r--js/src/tests/test/expected/import/files/local/smTempBranch/shell.js561
-rw-r--r--js/src/tests/test/expected/import/files/local/smTempBranch/temp42/bar.js2
-rw-r--r--js/src/tests/test/expected/import/files/local/smTempBranch/temp42/baz.js2
-rw-r--r--js/src/tests/test/expected/import/files/local/smTempBranch/temp42/browser.js0
-rw-r--r--js/src/tests/test/expected/import/files/local/smTempBranch/temp42/foo.js2
-rw-r--r--js/src/tests/test/expected/import/files/local/smTempBranch/temp42/shell.js0
-rw-r--r--js/src/tests/test/expected/import/output.txt14
-rw-r--r--js/src/tests/test/fixtures/export/.ignore.js1
-rw-r--r--js/src/tests/test/fixtures/export/browser.js1
-rw-r--r--js/src/tests/test/fixtures/export/empty.js0
-rw-r--r--js/src/tests/test/fixtures/export/multi-header.js20
-rw-r--r--js/src/tests/test/fixtures/export/reftest-and-frontmatter-error.js19
-rw-r--r--js/src/tests/test/fixtures/export/reftest-error-syntaxerror.js15
-rw-r--r--js/src/tests/test/fixtures/export/regular.js18
-rw-r--r--js/src/tests/test/fixtures/export/reportCompare.js38
-rw-r--r--js/src/tests/test/fixtures/export/shell.js1
-rw-r--r--js/src/tests/test/fixtures/import/files/bar.js0
-rw-r--r--js/src/tests/test/fixtures/import/files/baz.js0
-rw-r--r--js/src/tests/test/fixtures/import/files/foo.js0
-rwxr-xr-xjs/src/tests/test/run.py139
31 files changed, 967 insertions, 0 deletions
diff --git a/js/src/tests/test/expected/export/multi-header.js b/js/src/tests/test/expected/export/multi-header.js
new file mode 100644
index 0000000000..477395713d
--- /dev/null
+++ b/js/src/tests/test/expected/export/multi-header.js
@@ -0,0 +1,25 @@
+// Copyright (C) 2017 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+info: |
+ foo bar baz
+description: |
+ Outside AsyncFunction, |await| is a perfectly cromulent LexicalDeclaration variable
+ name. Therefore ASI doesn't apply, and so the |0| where a |=| was expected is a
+ syntax error.
+author: Jeff Walden <jwalden+code@mit.edu>
+negative:
+ phase: early
+ type: SyntaxError
+flags:
+- module
+esid: sec-let-and-const-declarations
+features:
+- foobar
+---*/
+
+function f() {
+ let
+ await 0;
+}
diff --git a/js/src/tests/test/expected/export/reftest-and-frontmatter-error.js b/js/src/tests/test/expected/export/reftest-and-frontmatter-error.js
new file mode 100644
index 0000000000..4966385662
--- /dev/null
+++ b/js/src/tests/test/expected/export/reftest-and-frontmatter-error.js
@@ -0,0 +1,22 @@
+// Copyright (C) 2017 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+
+/*---
+esid: sec-let-and-const-declarations
+features: []
+negative:
+ phase: runtime
+ type: SyntaxError
+description: |
+ Outside AsyncFunction, |await| is a perfectly cromulent LexicalDeclaration variable
+ name. Therefore ASI doesn't apply, and so the |0| where a |=| was expected is a
+ syntax error.
+---*/
+
+eval(`
+ function f() {
+ let
+ await 0;
+ }
+`);
diff --git a/js/src/tests/test/expected/export/reftest-error-syntaxerror.js b/js/src/tests/test/expected/export/reftest-error-syntaxerror.js
new file mode 100644
index 0000000000..5cd5759f66
--- /dev/null
+++ b/js/src/tests/test/expected/export/reftest-error-syntaxerror.js
@@ -0,0 +1,21 @@
+// Copyright (C) 2017 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+
+/*---
+negative:
+ phase: early
+ type: SyntaxError
+author: Jeff Walden <jwalden+code@mit.edu>
+features: []
+description: |
+ Outside AsyncFunction, |await| is a perfectly cromulent LexicalDeclaration variable
+ name. Therefore ASI doesn't apply, and so the |0| where a |=| was expected is a
+ syntax error.
+esid: sec-let-and-const-declarations
+---*/
+
+function f() {
+ let
+ await 0;
+}
diff --git a/js/src/tests/test/expected/export/regular.js b/js/src/tests/test/expected/export/regular.js
new file mode 100644
index 0000000000..b920a66a3c
--- /dev/null
+++ b/js/src/tests/test/expected/export/regular.js
@@ -0,0 +1,18 @@
+// Copyright (C) 2017 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+author: Jeff Walden <jwalden+code@mit.edu>
+description: |
+ '|await| is excluded from LexicalDeclaration by grammar parameter, in AsyncFunction. Therefore
+ |let| followed by |await| inside AsyncFunction is an ASI opportunity, and this code
+ must parse without error.'
+esid: sec-let-and-const-declarations
+---*/
+
+async function f() {
+ let
+ await 0;
+}
+
+assert.sameValue(true, f instanceof Function);
diff --git a/js/src/tests/test/expected/export/reportCompare.js b/js/src/tests/test/expected/export/reportCompare.js
new file mode 100644
index 0000000000..a71ca73b21
--- /dev/null
+++ b/js/src/tests/test/expected/export/reportCompare.js
@@ -0,0 +1,23 @@
+// Copyright (C) 2017 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: |
+ assert.sameValue
+esid: pending
+---*/
+
+
+var a = 42;
+
+// comment
+assert.sameValue(trueish, true, "ok");
+
+assert.sameValue ( true, /*lol*/true, "ok");
+
+assert.sameValue(true, f instanceof Function);
+assert.sameValue(true, true, "don't crash");
+assert.sameValue(42, foo);
+
+ // this was a assert.sameValue Line
+
diff --git a/js/src/tests/test/expected/import/files/local/smTempBranch/browser.js b/js/src/tests/test/expected/import/files/local/smTempBranch/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test/expected/import/files/local/smTempBranch/browser.js
diff --git a/js/src/tests/test/expected/import/files/local/smTempBranch/language/browser.js b/js/src/tests/test/expected/import/files/local/smTempBranch/language/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test/expected/import/files/local/smTempBranch/language/browser.js
diff --git a/js/src/tests/test/expected/import/files/local/smTempBranch/language/export/browser.js b/js/src/tests/test/expected/import/files/local/smTempBranch/language/export/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test/expected/import/files/local/smTempBranch/language/export/browser.js
diff --git a/js/src/tests/test/expected/import/files/local/smTempBranch/language/export/escaped-foobarbaz.js b/js/src/tests/test/expected/import/files/local/smTempBranch/language/export/escaped-foobarbaz.js
new file mode 100644
index 0000000000..8f923637f3
--- /dev/null
+++ b/js/src/tests/test/expected/import/files/local/smTempBranch/language/export/escaped-foobarbaz.js
@@ -0,0 +1,25 @@
+// |reftest| error:SyntaxError module
+// Copyright (C) 2017 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-grammar-notation
+description: >
+ The `default` keyword must not contain Unicode escape sequences.
+info: >
+ Terminal symbols of the lexical, RegExp, and numeric string grammars are shown
+ in fixed width font, both in the productions of the grammars and throughout this
+ specification whenever the text directly refers to such a terminal symbol. These
+ are to appear in a script exactly as written. All terminal symbol code points
+ specified in this way are to be understood as the appropriate Unicode code points
+ from the Basic Latin range, as opposed to any similar-looking code points from
+ other Unicode ranges.
+negative:
+ phase: early
+ type: SyntaxError
+flags: [module]
+---*/
+
+throw "Test262: This statement should not be evaluated.";
+
+export d\u0065fault 0;
diff --git a/js/src/tests/test/expected/import/files/local/smTempBranch/language/export/shell.js b/js/src/tests/test/expected/import/files/local/smTempBranch/language/export/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test/expected/import/files/local/smTempBranch/language/export/shell.js
diff --git a/js/src/tests/test/expected/import/files/local/smTempBranch/language/shell.js b/js/src/tests/test/expected/import/files/local/smTempBranch/language/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test/expected/import/files/local/smTempBranch/language/shell.js
diff --git a/js/src/tests/test/expected/import/files/local/smTempBranch/shell.js b/js/src/tests/test/expected/import/files/local/smTempBranch/shell.js
new file mode 100644
index 0000000000..ee1cf95742
--- /dev/null
+++ b/js/src/tests/test/expected/import/files/local/smTempBranch/shell.js
@@ -0,0 +1,561 @@
+// file: assert.js
+// Copyright (C) 2017 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ Collection of assertion functions used throughout test262
+---*/
+
+function assert(mustBeTrue, message) {
+ if (mustBeTrue === true) {
+ return;
+ }
+
+ if (message === undefined) {
+ message = 'Expected true but got ' + String(mustBeTrue);
+ }
+ $ERROR(message);
+}
+
+assert._isSameValue = function (a, b) {
+ if (a === b) {
+ // Handle +/-0 vs. -/+0
+ return a !== 0 || 1 / a === 1 / b;
+ }
+
+ // Handle NaN vs. NaN
+ return a !== a && b !== b;
+};
+
+assert.sameValue = function (actual, expected, message) {
+ if (assert._isSameValue(actual, expected)) {
+ return;
+ }
+
+ if (message === undefined) {
+ message = '';
+ } else {
+ message += ' ';
+ }
+
+ message += 'Expected SameValue(«' + String(actual) + '», «' + String(expected) + '») to be true';
+
+ $ERROR(message);
+};
+
+assert.notSameValue = function (actual, unexpected, message) {
+ if (!assert._isSameValue(actual, unexpected)) {
+ return;
+ }
+
+ if (message === undefined) {
+ message = '';
+ } else {
+ message += ' ';
+ }
+
+ message += 'Expected SameValue(«' + String(actual) + '», «' + String(unexpected) + '») to be false';
+
+ $ERROR(message);
+};
+
+assert.throws = function (expectedErrorConstructor, func, message) {
+ if (typeof func !== "function") {
+ $ERROR('assert.throws requires two arguments: the error constructor ' +
+ 'and a function to run');
+ return;
+ }
+ if (message === undefined) {
+ message = '';
+ } else {
+ message += ' ';
+ }
+
+ try {
+ func();
+ } catch (thrown) {
+ if (typeof thrown !== 'object' || thrown === null) {
+ message += 'Thrown value was not an object!';
+ $ERROR(message);
+ } else if (thrown.constructor !== expectedErrorConstructor) {
+ message += 'Expected a ' + expectedErrorConstructor.name + ' but got a ' + thrown.constructor.name;
+ $ERROR(message);
+ }
+ return;
+ }
+
+ message += 'Expected a ' + expectedErrorConstructor.name + ' to be thrown but no exception was thrown at all';
+ $ERROR(message);
+};
+
+assert.throws.early = function(err, code) {
+ let wrappedCode = `function wrapperFn() { ${code} }`;
+ let ieval = eval;
+
+ assert.throws(err, () => { Function(wrappedCode); }, `Function: ${code}`);
+};
+
+// file: compareArray.js
+// Copyright (C) 2017 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ Compare the contents of two arrays
+---*/
+
+function compareArray(a, b) {
+ if (b.length !== a.length) {
+ return false;
+ }
+
+ for (var i = 0; i < a.length; i++) {
+ if (b[i] !== a[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+assert.compareArray = function(actual, expected, message) {
+ assert(compareArray(actual, expected),
+ `Expected [${actual.join(", ")}] and [${expected.join(", ")}] to have the same contents. ${message}`);
+};
+
+// file: propertyHelper.js
+// Copyright (C) 2017 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ Collection of functions used to safely verify the correctness of
+ property descriptors.
+---*/
+
+function verifyProperty(obj, name, desc, options) {
+ assert(
+ arguments.length > 2,
+ 'verifyProperty should receive at least 3 arguments: obj, name, and descriptor'
+ );
+
+ var originalDesc = Object.getOwnPropertyDescriptor(obj, name);
+ var nameStr = String(name);
+
+ // Allows checking for undefined descriptor if it's explicitly given.
+ if (desc === undefined) {
+ assert.sameValue(
+ originalDesc,
+ undefined,
+ `obj['${nameStr}'] descriptor should be undefined`
+ );
+
+ // desc and originalDesc are both undefined, problem solved;
+ return true;
+ }
+
+ assert(
+ Object.prototype.hasOwnProperty.call(obj, name),
+ `obj should have an own property ${nameStr}`
+ );
+
+ assert.notSameValue(
+ desc,
+ null,
+ `The desc argument should be an object or undefined, null`
+ );
+
+ assert.sameValue(
+ typeof desc,
+ "object",
+ `The desc argument should be an object or undefined, ${String(desc)}`
+ );
+
+ var failures = [];
+
+ if (Object.prototype.hasOwnProperty.call(desc, 'value')) {
+ if (desc.value !== originalDesc.value) {
+ failures.push(`descriptor value should be ${desc.value}`);
+ }
+ }
+
+ if (Object.prototype.hasOwnProperty.call(desc, 'enumerable')) {
+ if (desc.enumerable !== originalDesc.enumerable ||
+ desc.enumerable !== isEnumerable(obj, name)) {
+ failures.push(`descriptor should ${desc.enumerable ? '' : 'not '}be enumerable`);
+ }
+ }
+
+ if (Object.prototype.hasOwnProperty.call(desc, 'writable')) {
+ if (desc.writable !== originalDesc.writable ||
+ desc.writable !== isWritable(obj, name)) {
+ failures.push(`descriptor should ${desc.writable ? '' : 'not '}be writable`);
+ }
+ }
+
+ if (Object.prototype.hasOwnProperty.call(desc, 'configurable')) {
+ if (desc.configurable !== originalDesc.configurable ||
+ desc.configurable !== isConfigurable(obj, name)) {
+ failures.push(`descriptor should ${desc.configurable ? '' : 'not '}be configurable`);
+ }
+ }
+
+ assert.sameValue(failures.length, 0, failures.join('; '));
+
+ if (options && options.restore) {
+ Object.defineProperty(obj, name, originalDesc);
+ }
+
+ return true;
+}
+
+function isConfigurable(obj, name) {
+ try {
+ delete obj[name];
+ } catch (e) {
+ if (!(e instanceof TypeError)) {
+ $ERROR("Expected TypeError, got " + e);
+ }
+ }
+ return !Object.prototype.hasOwnProperty.call(obj, name);
+}
+
+function isEnumerable(obj, name) {
+ var stringCheck = false;
+
+ if (typeof name === "string") {
+ for (var x in obj) {
+ if (x === name) {
+ stringCheck = true;
+ break;
+ }
+ }
+ } else {
+ // skip it if name is not string, works for Symbol names.
+ stringCheck = true;
+ }
+
+ return stringCheck &&
+ Object.prototype.hasOwnProperty.call(obj, name) &&
+ Object.prototype.propertyIsEnumerable.call(obj, name);
+}
+
+function isEqualTo(obj, name, expectedValue) {
+ var actualValue = obj[name];
+
+ return assert._isSameValue(actualValue, expectedValue);
+}
+
+function isWritable(obj, name, verifyProp, value) {
+ var newValue = value || "unlikelyValue";
+ var hadValue = Object.prototype.hasOwnProperty.call(obj, name);
+ var oldValue = obj[name];
+ var writeSucceeded;
+
+ try {
+ obj[name] = newValue;
+ } catch (e) {
+ if (!(e instanceof TypeError)) {
+ $ERROR("Expected TypeError, got " + e);
+ }
+ }
+
+ writeSucceeded = isEqualTo(obj, verifyProp || name, newValue);
+
+ // Revert the change only if it was successful (in other cases, reverting
+ // is unnecessary and may trigger exceptions for certain property
+ // configurations)
+ if (writeSucceeded) {
+ if (hadValue) {
+ obj[name] = oldValue;
+ } else {
+ delete obj[name];
+ }
+ }
+
+ return writeSucceeded;
+}
+
+function verifyEqualTo(obj, name, value) {
+ if (!isEqualTo(obj, name, value)) {
+ $ERROR("Expected obj[" + String(name) + "] to equal " + value +
+ ", actually " + obj[name]);
+ }
+}
+
+function verifyWritable(obj, name, verifyProp, value) {
+ if (!verifyProp) {
+ assert(Object.getOwnPropertyDescriptor(obj, name).writable,
+ "Expected obj[" + String(name) + "] to have writable:true.");
+ }
+ if (!isWritable(obj, name, verifyProp, value)) {
+ $ERROR("Expected obj[" + String(name) + "] to be writable, but was not.");
+ }
+}
+
+function verifyNotWritable(obj, name, verifyProp, value) {
+ if (!verifyProp) {
+ assert(!Object.getOwnPropertyDescriptor(obj, name).writable,
+ "Expected obj[" + String(name) + "] to have writable:false.");
+ }
+ if (isWritable(obj, name, verifyProp)) {
+ $ERROR("Expected obj[" + String(name) + "] NOT to be writable, but was.");
+ }
+}
+
+function verifyEnumerable(obj, name) {
+ assert(Object.getOwnPropertyDescriptor(obj, name).enumerable,
+ "Expected obj[" + String(name) + "] to have enumerable:true.");
+ if (!isEnumerable(obj, name)) {
+ $ERROR("Expected obj[" + String(name) + "] to be enumerable, but was not.");
+ }
+}
+
+function verifyNotEnumerable(obj, name) {
+ assert(!Object.getOwnPropertyDescriptor(obj, name).enumerable,
+ "Expected obj[" + String(name) + "] to have enumerable:false.");
+ if (isEnumerable(obj, name)) {
+ $ERROR("Expected obj[" + String(name) + "] NOT to be enumerable, but was.");
+ }
+}
+
+function verifyConfigurable(obj, name) {
+ assert(Object.getOwnPropertyDescriptor(obj, name).configurable,
+ "Expected obj[" + String(name) + "] to have configurable:true.");
+ if (!isConfigurable(obj, name)) {
+ $ERROR("Expected obj[" + String(name) + "] to be configurable, but was not.");
+ }
+}
+
+function verifyNotConfigurable(obj, name) {
+ assert(!Object.getOwnPropertyDescriptor(obj, name).configurable,
+ "Expected obj[" + String(name) + "] to have configurable:false.");
+ if (isConfigurable(obj, name)) {
+ $ERROR("Expected obj[" + String(name) + "] NOT to be configurable, but was.");
+ }
+}
+
+// file: sta.js
+// Copyright (c) 2012 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ Provides both:
+
+ - An error class to avoid false positives when testing for thrown exceptions
+ - A function to explicitly throw an exception using the Test262Error class
+---*/
+
+
+function Test262Error(message) {
+ this.message = message || "";
+}
+
+Test262Error.prototype.toString = function () {
+ return "Test262Error: " + this.message;
+};
+
+var $ERROR;
+$ERROR = function $ERROR(message) {
+ throw new Test262Error(message);
+};
+
+// file: test262-host.js
+// 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/.
+
+// https://github.com/tc39/test262/blob/main/INTERPRETING.md#host-defined-functions
+;(function createHostObject(global) {
+ var FunctionToString = global.Function.prototype.toString;
+ var ReflectApply = global.Reflect.apply;
+ var NewGlobal = global.newGlobal;
+ var Atomics = global.Atomics;
+ var SharedArrayBuffer = global.SharedArrayBuffer;
+ var Int32Array = global.Int32Array;
+ var setSharedArrayBuffer = global.setSharedArrayBuffer;
+ var getSharedArrayBuffer = global.getSharedArrayBuffer;
+ var evalInWorker = global.evalInWorker;
+ var hasThreads = ("helperThreadCount" in global ? global.helperThreadCount() > 0 : true);
+ var hasMailbox = typeof setSharedArrayBuffer == "function" && typeof getSharedArrayBuffer == "function";
+ var hasEvalInWorker = typeof evalInWorker == "function";
+
+ // The $262.agent framework is not appropriate for browsers yet, and some
+ // test cases can't work in browsers (they block the main thread).
+
+ var shellCode = hasMailbox && hasEvalInWorker;
+ var sabTestable = Atomics && SharedArrayBuffer && hasThreads && shellCode;
+
+ global.$262 = {
+ __proto__: null,
+ createRealm() {
+ var newGlobalObject = NewGlobal();
+ var createHostObjectFn = ReflectApply(FunctionToString, createHostObject, []);
+ newGlobalObject.Function(`${createHostObjectFn} createHostObject(this);`)();
+ return newGlobalObject.$262;
+ },
+ detachArrayBuffer: global.detachArrayBuffer,
+ evalScript: global.evaluateScript || global.evaluate,
+ global,
+ agent: (function () {
+
+ // SpiderMonkey complication: With run-time argument --no-threads
+ // our test runner will not properly filter test cases that can't be
+ // run because agents can't be started, and so we do a little
+ // filtering here: We will quietly succeed and exit if an agent test
+ // should not have been run because threads cannot be started.
+ //
+ // Firefox complication: The test cases that use $262.agent can't
+ // currently work in the browser, so for now we rely on them not
+ // being run at all.
+
+ if (!sabTestable) {
+ return {
+ _notAvailable() {
+ // See comment above.
+ if (!hasThreads && shellCode) {
+ global.reportCompare(0,0);
+ global.quit(0);
+ }
+ throw new Error("Agents not available");
+ },
+ start(script) { this._notAvailable() },
+ broadcast(sab, id) { this._notAvailable() },
+ getReport() { this._notAvailable() },
+ sleep(s) { this._notAvailable() }
+ }
+ }
+
+ // The SpiderMonkey implementation uses a designated shared buffer _ia
+ // for coordination, and spinlocks for everything except sleeping.
+
+ var _MSG_LOC = 0; // Low bit set: broadcast available; High bits: seq #
+ var _ID_LOC = 1; // ID sent with broadcast
+ var _ACK_LOC = 2; // Worker increments this to ack that broadcast was received
+ var _RDY_LOC = 3; // Worker increments this to ack that worker is up and running
+ var _LOCKTXT_LOC = 4; // Writer lock for the text buffer: 0=open, 1=closed
+ var _NUMTXT_LOC = 5; // Count of messages in text buffer
+ var _NEXT_LOC = 6; // First free location in the buffer
+ var _SLEEP_LOC = 7; // Used for sleeping
+
+ var _FIRST = 10; // First location of first message
+
+ var _ia = new Int32Array(new SharedArrayBuffer(65536));
+ _ia[_NEXT_LOC] = _FIRST;
+
+ var _worker_prefix =
+// BEGIN WORKER PREFIX
+`if (typeof $262 == 'undefined')
+ $262 = {};
+$262.agent = (function () {
+ var _ia = new Int32Array(getSharedArrayBuffer());
+ var agent = {
+ receiveBroadcast(receiver) {
+ var k;
+ while (((k = Atomics.load(_ia, ${_MSG_LOC})) & 1) == 0)
+ ;
+ var received_sab = getSharedArrayBuffer();
+ var received_id = Atomics.load(_ia, ${_ID_LOC});
+ Atomics.add(_ia, ${_ACK_LOC}, 1);
+ while (Atomics.load(_ia, ${_MSG_LOC}) == k)
+ ;
+ receiver(received_sab, received_id);
+ },
+
+ report(msg) {
+ while (Atomics.compareExchange(_ia, ${_LOCKTXT_LOC}, 0, 1) == 1)
+ ;
+ msg = "" + msg;
+ var i = _ia[${_NEXT_LOC}];
+ _ia[i++] = msg.length;
+ for ( let j=0 ; j < msg.length ; j++ )
+ _ia[i++] = msg.charCodeAt(j);
+ _ia[${_NEXT_LOC}] = i;
+ Atomics.add(_ia, ${_NUMTXT_LOC}, 1);
+ Atomics.store(_ia, ${_LOCKTXT_LOC}, 0);
+ },
+
+ sleep(s) {
+ Atomics.wait(_ia, ${_SLEEP_LOC}, 0, s);
+ },
+
+ leaving() {}
+ };
+ Atomics.add(_ia, ${_RDY_LOC}, 1);
+ return agent;
+})();`;
+// END WORKER PREFIX
+
+ return {
+ _numWorkers: 0,
+ _numReports: 0,
+ _reportPtr: _FIRST,
+
+ _bailIfNotAvailable() {
+ if (!sabTestable) {
+ // See comment above.
+ if (!hasThreads && shellCode) {
+ global.reportCompare(0,0);
+ global.quit(0);
+ }
+ throw new Error("Agents not available");
+ }
+ },
+
+ start(script) {
+ this._bailIfNotAvailable();
+ setSharedArrayBuffer(_ia.buffer);
+ var oldrdy = Atomics.load(_ia, _RDY_LOC);
+ evalInWorker(_worker_prefix + script);
+ while (Atomics.load(_ia, _RDY_LOC) == oldrdy)
+ ;
+ this._numWorkers++;
+ },
+
+ broadcast(sab, id) {
+ this._bailIfNotAvailable();
+ setSharedArrayBuffer(sab);
+ Atomics.store(_ia, _ID_LOC, id);
+ Atomics.store(_ia, _ACK_LOC, 0);
+ Atomics.add(_ia, _MSG_LOC, 1);
+ while (Atomics.load(_ia, _ACK_LOC) < this._numWorkers)
+ ;
+ Atomics.add(_ia, _MSG_LOC, 1);
+ },
+
+ getReport() {
+ this._bailIfNotAvailable();
+ if (this._numReports == Atomics.load(_ia, _NUMTXT_LOC))
+ return null;
+ var s = "";
+ var i = this._reportPtr;
+ var len = _ia[i++];
+ for ( let j=0 ; j < len ; j++ )
+ s += String.fromCharCode(_ia[i++]);
+ this._reportPtr = i;
+ this._numReports++;
+ return s;
+ },
+
+ sleep(s) {
+ this._bailIfNotAvailable();
+ Atomics.wait(_ia, _SLEEP_LOC, 0, s);
+ },
+ };
+ })()
+ };
+})(this);
+
+var $mozAsyncTestDone = false;
+function $DONE(failure) {
+ // This function is generally called from within a Promise handler, so any
+ // exception thrown by this method will be swallowed and most likely
+ // ignored by the Promise machinery.
+ if ($mozAsyncTestDone) {
+ reportFailure("$DONE() already called");
+ return;
+ }
+ $mozAsyncTestDone = true;
+
+ if (failure)
+ reportFailure(failure);
+ else
+ reportCompare(0, 0);
+}
diff --git a/js/src/tests/test/expected/import/files/local/smTempBranch/temp42/bar.js b/js/src/tests/test/expected/import/files/local/smTempBranch/temp42/bar.js
new file mode 100644
index 0000000000..c22331fd51
--- /dev/null
+++ b/js/src/tests/test/expected/import/files/local/smTempBranch/temp42/bar.js
@@ -0,0 +1,2 @@
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test/expected/import/files/local/smTempBranch/temp42/baz.js b/js/src/tests/test/expected/import/files/local/smTempBranch/temp42/baz.js
new file mode 100644
index 0000000000..c22331fd51
--- /dev/null
+++ b/js/src/tests/test/expected/import/files/local/smTempBranch/temp42/baz.js
@@ -0,0 +1,2 @@
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test/expected/import/files/local/smTempBranch/temp42/browser.js b/js/src/tests/test/expected/import/files/local/smTempBranch/temp42/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test/expected/import/files/local/smTempBranch/temp42/browser.js
diff --git a/js/src/tests/test/expected/import/files/local/smTempBranch/temp42/foo.js b/js/src/tests/test/expected/import/files/local/smTempBranch/temp42/foo.js
new file mode 100644
index 0000000000..c22331fd51
--- /dev/null
+++ b/js/src/tests/test/expected/import/files/local/smTempBranch/temp42/foo.js
@@ -0,0 +1,2 @@
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test/expected/import/files/local/smTempBranch/temp42/shell.js b/js/src/tests/test/expected/import/files/local/smTempBranch/temp42/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test/expected/import/files/local/smTempBranch/temp42/shell.js
diff --git a/js/src/tests/test/expected/import/output.txt b/js/src/tests/test/expected/import/output.txt
new file mode 100644
index 0000000000..e4f76f6132
--- /dev/null
+++ b/js/src/tests/test/expected/import/output.txt
@@ -0,0 +1,14 @@
+From the branch smTempBranch in {{folder}}
+
+Files being copied to the local folder:
+test/language/export/escaped-foobarbaz.js
+test/temp42/bar.js
+test/temp42/baz.js
+test/temp42/foo.js
+
+Deleted files (use this list to update the skip list):
+test/language/export/escaped-from.js
+
+Renamed files (already added with the new names):
+ rename test/language/export/{escaped-default.js => escaped-foobarbaz.js} (100%)
+
diff --git a/js/src/tests/test/fixtures/export/.ignore.js b/js/src/tests/test/fixtures/export/.ignore.js
new file mode 100644
index 0000000000..945c9b46d6
--- /dev/null
+++ b/js/src/tests/test/fixtures/export/.ignore.js
@@ -0,0 +1 @@
+. \ No newline at end of file
diff --git a/js/src/tests/test/fixtures/export/browser.js b/js/src/tests/test/fixtures/export/browser.js
new file mode 100644
index 0000000000..d18a19cb28
--- /dev/null
+++ b/js/src/tests/test/fixtures/export/browser.js
@@ -0,0 +1 @@
+// not an empty file
diff --git a/js/src/tests/test/fixtures/export/empty.js b/js/src/tests/test/fixtures/export/empty.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test/fixtures/export/empty.js
diff --git a/js/src/tests/test/fixtures/export/multi-header.js b/js/src/tests/test/fixtures/export/multi-header.js
new file mode 100644
index 0000000000..c1f46f4e4f
--- /dev/null
+++ b/js/src/tests/test/fixtures/export/multi-header.js
@@ -0,0 +1,20 @@
+// |reftest| skip-if(!this.hasOwnProperty('foobar')||outro()) error:SyntaxError module -- foo bar baz
+// Copyright (C) 2017 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+author: Jeff Walden <jwalden+code@mit.edu>
+esid: sec-let-and-const-declarations
+description: >
+ Outside AsyncFunction, |await| is a perfectly cromulent LexicalDeclaration
+ variable name. Therefore ASI doesn't apply, and so the |0| where a |=| was
+ expected is a syntax error.
+negative:
+ phase: early
+ type: SyntaxError
+---*/
+
+function f() {
+ let
+ await 0;
+}
diff --git a/js/src/tests/test/fixtures/export/reftest-and-frontmatter-error.js b/js/src/tests/test/fixtures/export/reftest-and-frontmatter-error.js
new file mode 100644
index 0000000000..38e98283d7
--- /dev/null
+++ b/js/src/tests/test/fixtures/export/reftest-and-frontmatter-error.js
@@ -0,0 +1,19 @@
+// |reftest| error:SyntaxError
+
+/*---
+esid: sec-let-and-const-declarations
+description: >
+ Outside AsyncFunction, |await| is a perfectly cromulent LexicalDeclaration
+ variable name. Therefore ASI doesn't apply, and so the |0| where a |=| was
+ expected is a syntax error.
+negative:
+ phase: runtime
+ type: SyntaxError
+---*/
+
+eval(`
+ function f() {
+ let
+ await 0;
+ }
+`);
diff --git a/js/src/tests/test/fixtures/export/reftest-error-syntaxerror.js b/js/src/tests/test/fixtures/export/reftest-error-syntaxerror.js
new file mode 100644
index 0000000000..718778ddf7
--- /dev/null
+++ b/js/src/tests/test/fixtures/export/reftest-error-syntaxerror.js
@@ -0,0 +1,15 @@
+// |reftest| error:SyntaxError
+
+/*---
+author: Jeff Walden <jwalden+code@mit.edu>
+esid: sec-let-and-const-declarations
+description: >
+ Outside AsyncFunction, |await| is a perfectly cromulent LexicalDeclaration
+ variable name. Therefore ASI doesn't apply, and so the |0| where a |=| was
+ expected is a syntax error.
+---*/
+
+function f() {
+ let
+ await 0;
+}
diff --git a/js/src/tests/test/fixtures/export/regular.js b/js/src/tests/test/fixtures/export/regular.js
new file mode 100644
index 0000000000..c43a5b2745
--- /dev/null
+++ b/js/src/tests/test/fixtures/export/regular.js
@@ -0,0 +1,18 @@
+// Copyright (C) 2017 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+author: Jeff Walden <jwalden+code@mit.edu>
+esid: sec-let-and-const-declarations
+description: >
+ |await| is excluded from LexicalDeclaration by grammar parameter, in
+ AsyncFunction. Therefore |let| followed by |await| inside AsyncFunction is
+ an ASI opportunity, and this code must parse without error.
+---*/
+
+async function f() {
+ let
+ await 0;
+}
+
+reportCompare(true, f instanceof Function);
diff --git a/js/src/tests/test/fixtures/export/reportCompare.js b/js/src/tests/test/fixtures/export/reportCompare.js
new file mode 100644
index 0000000000..7b5af60053
--- /dev/null
+++ b/js/src/tests/test/fixtures/export/reportCompare.js
@@ -0,0 +1,38 @@
+// Copyright (C) 2017 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: reportCompare
+---*/
+
+
+var a = 42;
+
+reportCompare(0, 0)
+reportCompare(0, 0);
+reportCompare(0, 0, "ok")
+reportCompare(true, true, "ok"); // comment
+reportCompare(trueish, true, "ok");
+
+reportCompare ( 0 , 0 ) ;
+reportCompare ( 0 , 0, "ok")
+reportCompare ( true, /*lol*/true, "ok");
+
+reportCompare(null, null, "test");
+reportCompare(true, f instanceof Function);
+reportCompare(true, true)
+reportCompare(true, true);
+reportCompare(true, true, "don't crash");
+reportCompare(true,true);
+this.reportCompare && reportCompare(0, 0, "ok");
+this.reportCompare && reportCompare(true, true);
+this.reportCompare && reportCompare(true,true);
+
+reportCompare(42, foo);
+
+ reportCompare(0, 0); // this was a reportCompare Line
+
+reportCompare(
+ true,
+ true
+);
diff --git a/js/src/tests/test/fixtures/export/shell.js b/js/src/tests/test/fixtures/export/shell.js
new file mode 100644
index 0000000000..d18a19cb28
--- /dev/null
+++ b/js/src/tests/test/fixtures/export/shell.js
@@ -0,0 +1 @@
+// not an empty file
diff --git a/js/src/tests/test/fixtures/import/files/bar.js b/js/src/tests/test/fixtures/import/files/bar.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test/fixtures/import/files/bar.js
diff --git a/js/src/tests/test/fixtures/import/files/baz.js b/js/src/tests/test/fixtures/import/files/baz.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test/fixtures/import/files/baz.js
diff --git a/js/src/tests/test/fixtures/import/files/foo.js b/js/src/tests/test/fixtures/import/files/foo.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test/fixtures/import/files/foo.js
diff --git a/js/src/tests/test/run.py b/js/src/tests/test/run.py
new file mode 100755
index 0000000000..a6f7a94932
--- /dev/null
+++ b/js/src/tests/test/run.py
@@ -0,0 +1,139 @@
+#!/usr/bin/env python
+# Adapted from https://github.com/tc39/test262/blob/main/tools/generation/test/run.py
+
+import contextlib
+import os
+import shutil
+import subprocess
+import tempfile
+import unittest
+
+testDir = os.path.dirname(os.path.relpath(__file__))
+OUT_DIR = os.path.join(testDir, "out")
+EXPECTED_DIR = os.path.join(testDir, "expected")
+ex = os.path.join(testDir, "..", "test262-export.py")
+importExec = os.path.join(testDir, "..", "test262-update.py")
+test262Url = "git://github.com/tc39/test262.git"
+
+
+@contextlib.contextmanager
+def TemporaryDirectory():
+ tmpDir = tempfile.mkdtemp()
+ try:
+ yield tmpDir
+ finally:
+ shutil.rmtree(tmpDir)
+
+
+class TestExport(unittest.TestCase):
+ maxDiff = None
+
+ def exportScript(self):
+ relpath = os.path.relpath(os.path.join(testDir, "fixtures", "export"))
+ sp = subprocess.Popen([ex, relpath, "--out", OUT_DIR], stdout=subprocess.PIPE)
+ stdout, stderr = sp.communicate()
+ return dict(stdout=stdout, stderr=stderr, returncode=sp.returncode)
+
+ def importLocal(self):
+ with TemporaryDirectory() as cloneDir:
+ branch = "smTempBranch"
+ # Clone Test262 to a local branch
+ subprocess.check_call(["git", "clone", "--depth=1", test262Url, cloneDir])
+ # Checkout to a new branch
+ subprocess.check_call(["git", "-C", cloneDir, "checkout", "-b", branch])
+ # Make changes on the new branch
+ # Remove test/language/export/escaped-from.js
+ subprocess.check_call(
+ ["git", "-C", cloneDir, "rm", "test/language/export/escaped-from.js"]
+ )
+ # Rename test/language/export/escaped-default.js
+ subprocess.check_call(
+ [
+ "git",
+ "-C",
+ cloneDir,
+ "mv",
+ "test/language/export/escaped-default.js",
+ "test/language/export/escaped-foobarbaz.js",
+ ]
+ )
+ # Copy fixtures files
+ fixturesDir = os.path.join(testDir, "fixtures", "import", "files")
+ shutil.copytree(fixturesDir, os.path.join(cloneDir, "test", "temp42"))
+ # Stage and Commit changes
+ subprocess.check_call(["git", "-C", cloneDir, "add", "."])
+ subprocess.check_call(
+ ["git", "-C", cloneDir, "commit", "-m", '"local foo"']
+ )
+
+ # Run import script
+ print("%s --local %s --out %s" % (importExec, cloneDir, OUT_DIR))
+ sp = subprocess.Popen(
+ [importExec, "--local", cloneDir, "--out", OUT_DIR],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ )
+ stdoutdata, _ = sp.communicate()
+
+ return stdoutdata, sp.returncode, cloneDir
+
+ def isTestFile(self, filename):
+ return not (
+ filename.startswith(".")
+ or filename.startswith("#")
+ or filename.endswith("~")
+ )
+
+ def getFiles(self, path):
+ names = []
+ for root, _, fileNames in os.walk(path):
+ for fileName in filter(self.isTestFile, fileNames):
+ names.append(os.path.join(root, fileName))
+ names.sort()
+ return names
+
+ def compareTrees(self, targetName):
+ expectedPath = os.path.join(EXPECTED_DIR, targetName)
+ actualPath = OUT_DIR
+
+ expectedFiles = self.getFiles(expectedPath)
+ actualFiles = self.getFiles(actualPath)
+
+ self.assertListEqual(
+ map(lambda x: os.path.relpath(x, expectedPath), expectedFiles),
+ map(lambda x: os.path.relpath(x, actualPath), actualFiles),
+ )
+
+ for expectedFile, actualFile in zip(expectedFiles, actualFiles):
+ with open(expectedFile) as expectedHandle:
+ with open(actualFile) as actualHandle:
+ self.assertMultiLineEqual(
+ expectedHandle.read(), actualHandle.read()
+ )
+
+ def compareContents(self, output, filePath, folder):
+ with open(filePath, "rb") as file:
+ expected = file.read()
+
+ expected = expected.replace("{{folder}}", folder)
+ self.assertMultiLineEqual(output, expected)
+
+ def tearDown(self):
+ shutil.rmtree(OUT_DIR, ignore_errors=True)
+
+ def test_export(self):
+ result = self.exportScript()
+ self.assertEqual(result["returncode"], 0)
+ self.compareTrees("export")
+
+ def test_import_local(self):
+ output, returncode, folder = self.importLocal()
+ self.assertEqual(returncode, 0)
+ self.compareTrees(os.path.join("import", "files"))
+ self.compareContents(
+ output, os.path.join(testDir, "expected", "import", "output.txt"), folder
+ )
+
+
+if __name__ == "__main__":
+ unittest.main()