UNPKG

js-slang

Version:

Javascript-based implementations of Source, written in Typescript

107 lines 4.95 kB
"use strict"; 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