Files
2023-08-01 13:49:46 +02:00

501 lines
17 KiB
JavaScript

"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 <number>] (defaults to 10)", "[--statusFile <string>]", "[--testDir <string>] (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