"use strict"; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); var _path = require("path"); var _path2 = _interopRequireDefault(_path); var _fs = require("fs"); var _fs2 = _interopRequireDefault(_fs); var _jsYaml = require("js-yaml"); var _jsYaml2 = _interopRequireDefault(_jsYaml); var _test262Integrator = require("test262-integrator"); var _test262Integrator2 = _interopRequireDefault(_test262Integrator); var _tty = require("tty"); var _tty2 = _interopRequireDefault(_tty); var _minimist2 = require("minimist"); var _minimist3 = _interopRequireDefault(_minimist2); var _globals = require("../lib/globals.js"); var _globals2 = _interopRequireDefault(_globals); var _completions = require("../lib/completions.js"); var _arraybuffer = require("../lib/methods/arraybuffer.js"); var _construct_realm = require("../lib/construct_realm.js"); var _construct_realm2 = _interopRequireDefault(_construct_realm); var _index = require("../lib/values/index.js"); var _realm = require("../lib/realm.js"); var _singletons = require("../lib/singletons.js"); var _get = require("../lib/methods/get.js"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ var filters = _jsYaml2.default.safeLoad(_fs2.default.readFileSync(_path2.default.join(__dirname, "./test262-filters.yml"), "utf8")); var TestAttrs = function TestAttrs() { _classCallCheck(this, TestAttrs); }; var TestAttrsNegative = function TestAttrsNegative() { _classCallCheck(this, TestAttrsNegative); }; var TestFlags = function TestFlags() { _classCallCheck(this, TestFlags); }; var TestObject = function TestObject() { _classCallCheck(this, TestObject); }; var Result = function Result(pass, error, skip) { _classCallCheck(this, Result); this.pass = pass; this.error = error; this.skip = skip; }; var TestResult = function (_TestObject) { _inherits(TestResult, _TestObject); function TestResult() { _classCallCheck(this, TestResult); return _possibleConstructorReturn(this, (TestResult.__proto__ || Object.getPrototypeOf(TestResult)).apply(this, arguments)); } return TestResult; }(TestObject); function execute(timeout, test) { var contents = test.contents, attrs = test.attrs, file = test.file, scenario = test.scenario; var _createRealm = createRealm(timeout), realm = _createRealm.realm; var strict = scenario === "strict mode"; // Run the test. try { try { var completion = realm.$GlobalEnv.execute(contents, file); if (completion instanceof _completions.ThrowCompletion) throw completion; if (completion instanceof _completions.AbruptCompletion) { return new Result(false, new Error("Unexpected abrupt completion")); } } catch (err) { if (err.message === "Timed out") return new Result(false, err); if (!attrs.negative) { throw err; } } if (attrs.negative && attrs.negative.type) { throw new Error("Was supposed to error with type " + attrs.negative.type + " but passed"); } // succeeded return new Result(true); } catch (err) { if (err.value && err.value.$Prototype && err.value.$Prototype.intrinsicName === "SyntaxError.prototype") { // Skip test return new Result(false, null, true); } var stack = err.stack; if (attrs.negative && attrs.negative.type) { var type = attrs.negative.type; if (err && err instanceof _completions.ThrowCompletion && (0, _get.Get)(realm, err.value, "name").value === type) { // Expected an error and got one. return new Result(true); } else { // Expected an error, but got something else. if (err && err instanceof _completions.ThrowCompletion) { return new Result(false, err); } else { var err2 = new Error("Expected an error, but got something else: " + err.message); return new Result(false, err2); } } } else { // Not expecting an error, but got one. try { if (err && err instanceof _completions.ThrowCompletion) { var interpreterStack = void 0; if (err.value instanceof _index.ObjectValue) { if (err.value.$HasProperty("stack")) { interpreterStack = _singletons.To.ToStringPartial(realm, (0, _get.Get)(realm, err.value, "stack")); } else { interpreterStack = _singletons.To.ToStringPartial(realm, (0, _get.Get)(realm, err.value, "message")); } // filter out if the error stack is due to async if (interpreterStack.includes("async ")) { // Skip test return new Result(false, null, true); } } else if (err.value instanceof _index.StringValue) { interpreterStack = err.value.value; if (interpreterStack === "only plain identifiers are supported in parameter lists") { // Skip test return new Result(false, null, true); } } // Many strict-only tests involving eval check if certain SyntaxErrors are thrown. // Some of those would require changes to Babel to support properly, and some we should handle ourselves in Prepack some day. // But for now, ignore. if (contents.includes("eval(") && strict) { // Skip test return new Result(false, null, true); } if (interpreterStack) { stack = "Interpreter: " + interpreterStack + "\nNative: " + err.nativeStack; } } } catch (_err) { stack = _err.stack; } return new Result(false, new Error("Got an error, but was not expecting one:\n" + stack)); } } } function createRealm(timeout) { // Create a new realm. var realm = (0, _construct_realm2.default)({ strictlyMonotonicDateNow: true, timeout: timeout * 1000 }); (0, _globals2.default)(realm); var executionContext = new _realm.ExecutionContext(); executionContext.realm = realm; realm.pushContext(executionContext); // Create the Host-Defined functions. var $ = new _index.ObjectValue(realm); $.defineNativeMethod("createRealm", 0, function (context) { return createRealm(timeout).$; }); $.defineNativeMethod("detachArrayBuffer", 1, function (context, _ref) { var _ref2 = _slicedToArray(_ref, 1), buffer = _ref2[0]; return (0, _arraybuffer.DetachArrayBuffer)(realm, buffer); }); $.defineNativeMethod("evalScript", 1, function (context, _ref3) { var _ref4 = _slicedToArray(_ref3, 1), sourceText = _ref4[0]; // TODO: eval return realm.intrinsics.undefined; }); $.defineNativeProperty("global", realm.$GlobalObject); $.defineNativeMethod("destroy", 0, function () { return realm.intrinsics.undefined; }); var glob = realm.$GlobalObject; glob.defineNativeProperty("$262", $); glob.defineNativeMethod("print", 1, function (context, _ref5) { var _ref6 = _slicedToArray(_ref5, 1), arg = _ref6[0]; return realm.intrinsics.undefined; }); return { realm: realm, $: $ }; } var ReportResults = function () { function ReportResults(name) { _classCallCheck(this, ReportResults); this.skipped = 0; this.passed = 0; this.total = 0; this.name = name; } _createClass(ReportResults, [{ key: "report", value: function report(pass, skip) { if (skip) { this.skipped += 1; } else if (pass) { this.passed += 1; } this.total += 1; } }, { key: "percentage", value: function percentage(x, total) { if (total === 0) { return "100%"; } return (x / total * 100).toFixed(2) + "%"; } }, { key: "info", value: function info(title, x, y, force) { if (!force && x === 0) { return ""; } return title + " " + x + "/" + y + " (" + this.percentage(x, y) + ")"; } }, { key: "formatResult", value: function formatResult() { var subtotal = this.total - this.skipped; var failed = subtotal - this.passed; return [this.name + ": ", this.info("Ran", subtotal, this.total, true), this.info(", Passed", this.passed, subtotal, false), this.info(", Failed", failed, subtotal, false), this.info(", Skipped", this.skipped, this.total, false)].join(""); } }], [{ key: "safeTypeReturn", value: function safeTypeReturn(map, key) { var result = map.get(key); if (result instanceof ReportResults) { return result; } throw new Error("Wrong type set in a list of ReportResults"); } }]); return ReportResults; }(); function processResults(verbose, statusFile, results) { var status = "\n"; var foldersMap = new Map(); var featuresMap = new Map(); var allResults = new ReportResults("\nTotal"); console.log("\n"); results.forEach(function (_ref7) { var file = _ref7.file, scenario = _ref7.scenario, features = _ref7.attrs.features, _ref7$result = _ref7.result; _ref7$result = _ref7$result === undefined ? {} : _ref7$result; var pass = _ref7$result.pass, skip = _ref7$result.skip, error = _ref7$result.error; // Limits the report result in a max depth of 5 folders. // This fits most cases for built-ins prototype methods as e.g. // test/built-ins/Array/prototype/sort var folder = _path2.default.dirname(file).split(_path2.default.sep).slice(1, 5).join(_path2.default.sep); var folderResults = void 0; if (!foldersMap.has(folder)) { folderResults = new ReportResults(folder); foldersMap.set(folder, folderResults); } else { folderResults = ReportResults.safeTypeReturn(foldersMap, folder); } if (folderResults) { folderResults.report(!!pass, !!skip); } allResults.report(!!pass, !!skip); if (features) { var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = features[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var feature = _step.value; var featureResults = void 0; if (!featuresMap.has(feature)) { featureResults = new ReportResults(feature); featuresMap.set(feature, featureResults); } else { featureResults = ReportResults.safeTypeReturn(featuresMap, feature); } if (featureResults) { featureResults.report(!!pass, !!skip); } } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } } if (verbose && !skip && !pass) { var message = ""; if (error && error.message) { message = error.message; } status += "Failed: " + file + " (" + scenario + ")\n" + message + "\n\n"; } }); foldersMap.forEach(function (folderResults) { status += folderResults.formatResult(); status += "\n"; }); status += "\nFeatures:\n\n"; featuresMap.forEach(function (featureResults) { status += featureResults.formatResult(); status += "\n"; }); status += allResults.formatResult(); console.log(status); if (statusFile) { _fs2.default.writeFileSync(statusFile, status); } } var MasterProgramArgs = function MasterProgramArgs(verbose, timeout, statusFile, paths, testDir) { _classCallCheck(this, MasterProgramArgs); this.verbose = verbose; this.timeout = timeout; this.statusFile = statusFile; this.paths = paths; this.testDir = testDir; }; function masterArgsParse() { var _minimist = (0, _minimist3.default)(process.argv.slice(2), { string: ["statusFile", "testDir"], boolean: ["verbose"], default: { testDir: ["..", "test", "test262"].join(_path2.default.sep), verbose: process.stdout instanceof _tty2.default.WriteStream ? false : true, statusFile: "", timeout: 10 } }), _paths = _minimist._, verbose = _minimist.verbose, timeout = _minimist.timeout, statusFile = _minimist.statusFile, testDir = _minimist.testDir; // Test paths can be provided as "built-ins/Array", "language/statements/class", etc. var paths = _paths.map(function (p) { return _path2.default.join("test", p); }); if (typeof verbose !== "boolean") { throw new Error("verbose must be a boolean (either --verbose or not)"); } if (typeof timeout !== "number") { throw new Error("timeout must be a number (in seconds) (--timeout 10)"); } if (typeof statusFile !== "string") { throw new Error("statusFile must be a string (--statusFile file.txt)"); } if (typeof testDir !== "string") { throw new Error("testDir must be a string (--testDir ../test/test262)"); } return new MasterProgramArgs(verbose, timeout, statusFile, paths, testDir); } function usage(message) { console.error(["Illegal argument: " + message, "Usage: " + process.argv[0] + " " + process.argv[1], "[--verbose] (defaults to false)", "[--timeout ] (defaults to 10)", "[--statusFile ]", "[--testDir ] (defaults to ../test/test262)"].join("\n")); } function main() { try { var _masterArgsParse = masterArgsParse(), testDir = _masterArgsParse.testDir, verbose = _masterArgsParse.verbose, paths = _masterArgsParse.paths, statusFile = _masterArgsParse.statusFile, timeout = _masterArgsParse.timeout; // Execution (0, _test262Integrator2.default)({ filters: filters, execute: execute.bind(null, timeout), testDir: _path2.default.join(__dirname, testDir), verbose: verbose, paths: paths.length ? paths : null }).then(processResults.bind(null, verbose, statusFile), function (err) { console.error("Error running the tests: " + err); process.exit(1); }).then(function () { return process.exit(0); }); } catch (e) { usage(e.message); process.exit(2); } } main(); //# sourceMappingURL=test262.js.map