js-slang
Version:
Javascript-based implementations of Source, written in Typescript
107 lines • 4.95 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
const _ = require("lodash");
const constants_1 = require("../constants");
const interpreter_1 = require("../cse-machine/interpreter");
const errors_1 = require("../errors/errors");
const runtimeSourceError_1 = require("../errors/runtimeSourceError");
const timeoutErrors_1 = require("../errors/timeoutErrors");
const errors_2 = require("../infiniteLoops/errors");
const runtime_1 = require("../infiniteLoops/runtime");
const evalContainer_1 = require("../transpiler/evalContainer");
const transpiler_1 = require("../transpiler/transpiler");
const types_1 = require("../types");
const steppers_1 = require("../tracer/steppers");
const errors_3 = require("./errors");
const utils_1 = require("./utils");
const fullJSRunner_1 = require("./fullJSRunner");
let isPreviousCodeTimeoutError = false;
const runners = {
fulljs: fullJSRunner_1.default,
'cse-machine': (program, context, options) => {
const value = (0, interpreter_1.evaluate)(program, context, options);
return (0, interpreter_1.CSEResultPromise)(context, value);
},
substitution: (program, context, options) => {
const steps = (0, steppers_1.getSteps)(program, context, options);
if (context.errors.length > 0) {
return utils_1.resolvedErrorPromise;
}
return Promise.resolve({
status: 'finished',
context,
value: steps
});
},
native: async (program, context, options) => {
if (!options.isPrelude) {
if (context.shouldIncreaseEvaluationTimeout && isPreviousCodeTimeoutError) {
context.nativeStorage.maxExecTime *= constants_1.JSSLANG_PROPERTIES.factorToIncreaseBy;
}
else {
context.nativeStorage.maxExecTime = options.originalMaxExecTime;
}
}
// For whatever reason, the transpiler mutates the state of the AST as it is transpiling and inserts
// a bunch of global identifiers to it. Once that happens, the infinite loop detection instrumentation
// ends up generating code that has syntax errors. As such, we need to make a deep copy here to preserve
// the original AST for future use, such as with the infinite loop detector.
const transpiledProgram = _.cloneDeep(program);
let transpiled;
let sourceMapJson;
try {
;
({ transpiled, sourceMapJson } = (0, transpiler_1.transpile)(transpiledProgram, context));
let value = (0, evalContainer_1.sandboxedEval)(transpiled, context.nativeStorage);
if (!options.isPrelude) {
isPreviousCodeTimeoutError = false;
}
return {
status: 'finished',
context,
value
};
}
catch (error) {
const isDefaultVariant = options.variant === undefined || options.variant === types_1.Variant.DEFAULT;
if (isDefaultVariant && (0, errors_2.isPotentialInfiniteLoop)(error)) {
const detectedInfiniteLoop = (0, runtime_1.testForInfiniteLoop)(program, context.previousPrograms.slice(1), context.nativeStorage.loadedModules);
if (detectedInfiniteLoop !== undefined) {
if (options.throwInfiniteLoops) {
context.errors.push(detectedInfiniteLoop);
return utils_1.resolvedErrorPromise;
}
else {
error.infiniteLoopError = detectedInfiniteLoop;
if (error instanceof errors_1.ExceptionError) {
;
error.error.infiniteLoopError = detectedInfiniteLoop;
}
}
}
}
if (error instanceof runtimeSourceError_1.RuntimeSourceError) {
context.errors.push(error);
if (error instanceof timeoutErrors_1.TimeoutError) {
isPreviousCodeTimeoutError = true;
}
return utils_1.resolvedErrorPromise;
}
if (error instanceof errors_1.ExceptionError) {
// if we know the location of the error, just throw it
if (error.location.start.line !== -1) {
context.errors.push(error);
return utils_1.resolvedErrorPromise;
}
else {
error = error.error; // else we try to get the location from source map
}
}
const sourceError = await (0, errors_3.toSourceError)(error, sourceMapJson);
context.errors.push(sourceError);
return utils_1.resolvedErrorPromise;
}
}
};
exports.default = runners;
//# sourceMappingURL=sourceRunner.js.map
;