diff --git a/src/logic/completionMapping.ts b/src/logic/completionMapping.ts new file mode 100644 index 0000000..4f06ecf --- /dev/null +++ b/src/logic/completionMapping.ts @@ -0,0 +1,49 @@ +import { Node } from "acorn"; +import { inspect } from "../../engine262/dist/engine262"; + +import { CompletionRecord, CompletionTypes } from "../types/engine262-stubs"; + +export interface ICompletionDetail { + start: number; + end: number; + completionType: CompletionTypes; + completionValueString: string; + completionTargetString: string | undefined; + completionValue: any; +} + +export const completionMapping: { + completionDetails: ICompletionDetail[]; + addCompletion(_: { node: Node; result: CompletionRecord }): void; + reset(): void; +} = { + completionDetails: [], + addCompletion({ node, result }) { + const { start, end } = node; + const { + Type: completionType, + Value: completionValue, + Target: completionTarget, + } = result; + + const completionValueString: string = inspect(completionValue); + const completionTargetString: string | undefined = + completionTarget !== undefined + ? inspect(completionTarget) + : completionTarget; + + const obj = { + start, + end, + completionType, + completionValueString, + completionTargetString, + completionValue, + }; + + this.completionDetails.push(obj); + }, + reset() { + this.completionDetails = []; + }, +}; diff --git a/src/logic/runEngine.ts b/src/logic/runEngine.ts new file mode 100644 index 0000000..a65859f --- /dev/null +++ b/src/logic/runEngine.ts @@ -0,0 +1,58 @@ +import { Node } from "acorn"; +import { + Agent, + setSurroundingAgent, + ManagedRealm, + Value, + CreateDataProperty, + inspect, +} from "../../engine262/dist/engine262"; + +import { CompletionRecord } from "../types/engine262-stubs"; +import { completionMapping } from "./completionMapping"; + +export function runEngine(code: string) { + completionMapping.reset(); + + const agent = new Agent({ + onNodeEvaluationComplete({ + node, + result, + }: { + node: Node; + result: CompletionRecord; + }) { + console.log({ node, result }); + completionMapping.addCompletion({ node, result }); + }, + // onDebugger() {}, + // ensureCanCompileStrings() {}, + // hasSourceTextAvailable() {}, + // onNodeEvaluation() {}, + // features: [], + }); + setSurroundingAgent(agent); + + const realm = new ManagedRealm({ + // promiseRejectionTracker() {}, + // resolveImportedModule() {}, + // getImportMetaProperties() {}, + // finalizeImportMeta() {}, + // randomSeed() {}, + }); + + realm.scope(() => { + // Add print function from host + + // @ts-ignore: new Value has type any + const print = new Value((args) => { + console.log(...args.map((tmp: any) => inspect(tmp))); + return (Value as any).undefined; + }); + + // @ts-ignore: new Value has type any + CreateDataProperty(realm.GlobalObject, new Value("print"), print); + }); + + realm.evaluateScript(code); +} diff --git a/src/types/engine262-stubs.ts b/src/types/engine262-stubs.ts new file mode 100644 index 0000000..1c295ce --- /dev/null +++ b/src/types/engine262-stubs.ts @@ -0,0 +1,14 @@ +export enum CompletionTypes { + Normal = "normal", + Return = "return", + Break = "break", + Continue = "continue", + Throw = "throw", +} + +export interface CompletionRecord { + Type: CompletionTypes; + Value: any; + // Target: Actually undefined or StringValue + Target: any; +}