diff options
Diffstat (limited to 'js/src/tests/test')
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() |