UNPKG

shift-interpreter

Version:

Shift-interpreter is an experimental JavaScript meta-interpreter useful for reverse engineering and analysis. One notable difference from other projects is that shift-interpreter retains state over an entire script but can be fed expressions and statement

114 lines 4.09 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.compare = exports.assertError = exports.assertResult = void 0; const chai_1 = require("chai"); const shift_parser_1 = require("shift-parser"); const interpreter_1 = require("../src/interpreter"); const deep_equal_1 = __importDefault(require("deep-equal")); const debug_1 = __importDefault(require("debug")); const debug = debug_1.default('shift:interpreter:test'); const evaluate = require('./nostrict-eval.js').eval; function assertResult(result) { const message = result.expectedError ? `${result.src}: Actual "${result.actualError.message}", Expected "${result.expectedError.message}"` : `${result.src}: Actual ${JSON.stringify(result.actual)}, Expected ${JSON.stringify(result.expected)}`; chai_1.expect(result.success).to.equal(true, message); } exports.assertResult = assertResult; function assertError(src, error) { debug(`assertError(\`${src}\`)`); const interpreter = new interpreter_1.Interpreter(); let expected = 'No error', actual = 'No error'; try { evaluate(src); } catch (e) { expected = e.message; } try { interpreter.run(shift_parser_1.parseScript(src)); } catch (e) { actual = e.message; } if (actual) debug(`Interpreter error: ${actual}`); if (expected) debug(`Native error: ${expected}`); chai_1.expect(actual).to.equal(expected); } exports.assertError = assertError; function funcify(fn) { const src = fn.toString(); return `(${src})()`; } function compare(src, context) { const interpreter = new interpreter_1.Interpreter(); let nativeExpectedValue, nativeExpectedError; debug(`compare(\`${src}\`)`); try { nativeExpectedValue = evaluate(src, context); } catch (e) { nativeExpectedError = e; } let interpreterActualValue, interpreterActualError; let finalSrc = typeof src === 'string' ? src : funcify(src); try { interpreter.load(shift_parser_1.parseScript(finalSrc), context); interpreterActualValue = interpreter.run(); } catch (e) { interpreterActualError = e; } debug(`== Interpreter result: ${interpreterActualValue}`); debug(`== Native result : ${nativeExpectedValue}`); if (interpreterActualError) debug(`!! Interpreter error: ${interpreterActualError.message}`); else debug(`!! Interpreter error: <none>`); if (nativeExpectedError) debug(`!! Native error : ${nativeExpectedError.message}`); else debug(`!! Native error : <none>`); let success = false; if (Number.isNaN(nativeExpectedValue)) { success = Number.isNaN(interpreterActualValue); debug(`Interpreter produced NaN, Native produced ${interpreterActualValue}`); } else if (nativeExpectedError) { if (!interpreterActualError) { debug(`Failure: Native produced error, Interpreter did not`); interpreterActualError = { message: '<<Did not throw an error>>' }; success = false; } else { success = interpreterActualError.message === nativeExpectedError.message; debug(`Both produced errors (same===${success})`); } } else { if (interpreterActualError) { debug(`Failure: Interpreter produced error, Native did not`); console.log(interpreterActualError); success = false; } else { success = deep_equal_1.default(nativeExpectedValue, interpreterActualValue); } } return { actual: interpreterActualValue, actualError: interpreterActualError, expected: nativeExpectedValue, expectedError: nativeExpectedError, src: finalSrc, success, interpreter, }; } exports.compare = compare; //# sourceMappingURL=util.js.map