267 lines
8.9 KiB
JavaScript
267 lines
8.9 KiB
JavaScript
"use strict";
|
|
|
|
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"); } }; }();
|
|
|
|
/**
|
|
* 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 construct_realm = require("../lib/construct_realm.js").default;
|
|
var initializeGlobals = require("../lib/globals.js").default;
|
|
var AbruptCompletion = require("../lib/completions.js").AbruptCompletion;
|
|
var ThrowCompletion = require("../lib/completions.js").ThrowCompletion;
|
|
var FatalError = require("../lib/errors.js").FatalError;
|
|
|
|
var chalk = require("chalk");
|
|
var path = require("path");
|
|
var fs = require("fs");
|
|
var vm = require("vm");
|
|
|
|
function search(dir, relative) {
|
|
var tests = [];
|
|
|
|
var _iteratorNormalCompletion = true;
|
|
var _didIteratorError = false;
|
|
var _iteratorError = undefined;
|
|
|
|
try {
|
|
for (var _iterator = fs.readdirSync(dir)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
|
var name = _step.value;
|
|
|
|
var loc = path.join(dir, name);
|
|
var stat = fs.statSync(loc);
|
|
|
|
if (stat.isFile()) {
|
|
tests.push({
|
|
file: fs.readFileSync(loc, "utf8"),
|
|
name: path.join(relative, name)
|
|
});
|
|
} else if (stat.isDirectory()) {
|
|
tests = tests.concat(search(loc, path.join(relative, name)));
|
|
}
|
|
}
|
|
} catch (err) {
|
|
_didIteratorError = true;
|
|
_iteratorError = err;
|
|
} finally {
|
|
try {
|
|
if (!_iteratorNormalCompletion && _iterator.return) {
|
|
_iterator.return();
|
|
}
|
|
} finally {
|
|
if (_didIteratorError) {
|
|
throw _iteratorError;
|
|
}
|
|
}
|
|
}
|
|
|
|
return tests;
|
|
}
|
|
|
|
var tests = search(__dirname + "/../test/residual", "test/residual");
|
|
|
|
function exec(code) {
|
|
var script = new vm.Script("var global = this; var self = this; var __result = " + code + " // keep newline here as code may end with comment\n; report(__result);", { cachedDataProduced: false });
|
|
|
|
var result = "";
|
|
var logOutput = "";
|
|
|
|
function write(prefix, values) {
|
|
logOutput += "\n" + prefix + values.join("");
|
|
}
|
|
|
|
script.runInNewContext({
|
|
setTimeout: setTimeout,
|
|
setInterval: setInterval,
|
|
clearTimeout: clearTimeout,
|
|
clearInterval: clearInterval,
|
|
report: function report(s) {
|
|
result = s;
|
|
},
|
|
console: {
|
|
log: function log() {
|
|
for (var _len = arguments.length, s = Array(_len), _key = 0; _key < _len; _key++) {
|
|
s[_key] = arguments[_key];
|
|
}
|
|
|
|
write("", s);
|
|
},
|
|
warn: function warn() {
|
|
for (var _len2 = arguments.length, s = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
|
|
s[_key2] = arguments[_key2];
|
|
}
|
|
|
|
write("WARN:", s);
|
|
},
|
|
error: function error() {
|
|
for (var _len3 = arguments.length, s = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
|
|
s[_key3] = arguments[_key3];
|
|
}
|
|
|
|
write("ERROR:", s);
|
|
}
|
|
}
|
|
});
|
|
return result + logOutput;
|
|
}
|
|
|
|
function runTest(name, code) {
|
|
var realmOptions = { residual: true };
|
|
var sources = [{ filePath: name, fileContents: code }];
|
|
console.log(chalk.inverse(name));
|
|
if (code.includes("// throws introspection error")) {
|
|
try {
|
|
var realm = construct_realm(realmOptions);
|
|
initializeGlobals(realm);
|
|
var result = realm.$GlobalEnv.executePartialEvaluator(sources);
|
|
if (result instanceof ThrowCompletion) throw result.value;
|
|
} catch (err) {
|
|
if (err instanceof FatalError) return true;
|
|
console.error(err);
|
|
}
|
|
return false;
|
|
} else {
|
|
var expected = void 0,
|
|
actual = void 0;
|
|
var codeIterations = [];
|
|
var markersToFind = [];
|
|
var _arr = [[true, "// does contain:"], [false, "// does not contain:"]];
|
|
for (var _i = 0; _i < _arr.length; _i++) {
|
|
var _ref = _arr[_i];
|
|
|
|
var _ref2 = _slicedToArray(_ref, 2);
|
|
|
|
var positive = _ref2[0];
|
|
var marker = _ref2[1];
|
|
|
|
if (code.includes(marker)) {
|
|
var _i3 = code.indexOf(marker);
|
|
var _value = code.substring(_i3 + marker.length, code.indexOf("\n", _i3));
|
|
markersToFind.push({ positive: positive, value: _value, start: _i3 + marker.length });
|
|
}
|
|
}
|
|
try {
|
|
expected = exec("(function () { " + code + "; // keep newline here as code may end with comment\nreturn __result; }).call(this);");
|
|
|
|
var i = 0;
|
|
var max = 4;
|
|
var oldCode = code;
|
|
for (; i < max; i++) {
|
|
var _realm = construct_realm(realmOptions);
|
|
initializeGlobals(_realm);
|
|
var _result = _realm.$GlobalEnv.executePartialEvaluator(sources);
|
|
if (_result instanceof ThrowCompletion) throw _result.value;
|
|
if (_result instanceof AbruptCompletion) throw _result;
|
|
var newCode = _result.code;
|
|
codeIterations.push(newCode);
|
|
var markersIssue = false;
|
|
var _iteratorNormalCompletion2 = true;
|
|
var _didIteratorError2 = false;
|
|
var _iteratorError2 = undefined;
|
|
|
|
try {
|
|
for (var _iterator2 = markersToFind[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
|
|
var _ref3 = _step2.value;
|
|
var _positive = _ref3.positive,
|
|
value = _ref3.value,
|
|
start = _ref3.start;
|
|
|
|
var found = newCode.indexOf(value, start) !== -1;
|
|
if (found !== _positive) {
|
|
console.error(chalk.red("Output " + (_positive ? "does not contain" : "contains") + " forbidden string: " + value));
|
|
markersIssue = true;
|
|
}
|
|
}
|
|
} catch (err) {
|
|
_didIteratorError2 = true;
|
|
_iteratorError2 = err;
|
|
} finally {
|
|
try {
|
|
if (!_iteratorNormalCompletion2 && _iterator2.return) {
|
|
_iterator2.return();
|
|
}
|
|
} finally {
|
|
if (_didIteratorError2) {
|
|
throw _iteratorError2;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (markersIssue) break;
|
|
actual = exec("(function () { " + newCode + "; // keep newline here as code may end with comment\n return __result; }).call(this);");
|
|
if (expected !== actual) {
|
|
console.error(chalk.red("Output mismatch!"));
|
|
break;
|
|
}
|
|
if (oldCode === newCode) {
|
|
// The generated code reached a fixed point!
|
|
return true;
|
|
}
|
|
oldCode = newCode;
|
|
}
|
|
if (i === max) {
|
|
console.error(chalk.red("Code generation did not reach fixed point after " + max + " iterations!"));
|
|
}
|
|
} catch (err) {
|
|
console.error(err);
|
|
}
|
|
console.log(chalk.underline("original code"));
|
|
console.log(code);
|
|
console.log(chalk.underline("output of inspect() on original code"));
|
|
console.log(expected);
|
|
for (var _i2 = 0; _i2 < codeIterations.length; _i2++) {
|
|
console.log(chalk.underline("generated code in iteration " + _i2));
|
|
console.log(codeIterations[_i2]);
|
|
}
|
|
console.log(chalk.underline("output of inspect() on last generated code iteration"));
|
|
console.log(actual);
|
|
return false;
|
|
}
|
|
}
|
|
function run() {
|
|
var failed = 0;
|
|
var passed = 0;
|
|
var total = 0;
|
|
|
|
var _iteratorNormalCompletion3 = true;
|
|
var _didIteratorError3 = false;
|
|
var _iteratorError3 = undefined;
|
|
|
|
try {
|
|
for (var _iterator3 = tests[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
|
|
var test = _step3.value;
|
|
|
|
// filter hidden files
|
|
if (path.basename(test.name)[0] === ".") continue;
|
|
if (test.name.endsWith("~")) continue;
|
|
if (test.file.includes("// skip")) continue;
|
|
|
|
total++;
|
|
if (runTest(test.name, test.file)) passed++;else failed++;
|
|
}
|
|
} catch (err) {
|
|
_didIteratorError3 = true;
|
|
_iteratorError3 = err;
|
|
} finally {
|
|
try {
|
|
if (!_iteratorNormalCompletion3 && _iterator3.return) {
|
|
_iterator3.return();
|
|
}
|
|
} finally {
|
|
if (_didIteratorError3) {
|
|
throw _iteratorError3;
|
|
}
|
|
}
|
|
}
|
|
|
|
console.log("Passed:", passed + "/" + total, (Math.floor(passed / total * 100) || 0) + "%");
|
|
return failed === 0;
|
|
}
|
|
|
|
if (!run()) process.exit(1);
|
|
//# sourceMappingURL=test-residual.js.map
|