/ proof-of-concept / plate-dynamics-lab-2
Sign in
proof-of-concept / plate-dynamics-lab-2
plate-dynamics-lab-2 / packages / core / src / runner / execute.ts
89 lines · 2.7 KBBlameHistoryRaw
1import { executeCode, RuntimeError } from "numbl";
2import type { RuntimeValue } from "numbl";
3import type { RunRequest, RunResult, BackendInfo } from "./types";
4import { toPlain, toRuntime } from "./convert";
6const OPTIMIZATION = "1" as const;
8declare const __NUMBL_VERSION__: string | undefined;
10/**
11 * numbl's package version, injected at build time by the host's Vite config
12 * (see vite.shared.ts); numbl's own `version` builtin reports the MATLAB
13 * release it emulates, which is not what "which backend ran it" means.
14 */
15export function numblVersion(): string {
16 return typeof __NUMBL_VERSION__ === "string" ? __NUMBL_VERSION__ : "unknown";
19/**
20 * Run a bundle synchronously in the current thread. Both the Node runner and
21 * the worker call this, so the two hosts execute identically.
22 */
23export function executeBundle(
24 req: RunRequest,
25 backend: BackendInfo,
26 onOutput?: (text: string) => void,
27): RunResult {
28 const { bundle } = req;
29 const entry = bundle.files.find((f) => f.name === bundle.entry);
30 const output: string[] = [];
31 const t0 = performance.now();
32 if (!entry) {
33 return {
34 ok: false,
35 error: `entry file ${bundle.entry} is not in the bundle`,
36 output,
37 wallMs: 0,
38 backend,
39 };
40 }
41 const workspaceFiles = bundle.files
42 .filter((f) => f.name !== bundle.entry)
43 .map((f) => ({ name: f.name, source: f.source }));
44 const initialVariableValues: Record<string, RuntimeValue> = {};
45 for (const [name, v] of Object.entries(req.inputs ?? {}))
46 initialVariableValues[name] = toRuntime(v);
47 try {
48 const result = executeCode(
49 entry.source,
50 {
51 optimization: OPTIMIZATION,
52 displayResults: false,
53 initialVariableValues,
54 onOutput: (text: string) => {
55 output.push(text);
56 onOutput?.(text);
57 },
58 },
59 workspaceFiles,
60 bundle.entry,
61 );
62 const wallMs = performance.now() - t0;
63 const value = result.variableValues[bundle.resultVariable];
64 if (value === undefined) {
65 return {
66 ok: false,
67 error: `the script finished but did not define the variable "${bundle.resultVariable}"`,
68 output,
69 wallMs,
70 backend,
71 };
72 }
73 return { ok: true, value: toPlain(value), output, wallMs, backend };
74 } catch (e) {
75 const wallMs = performance.now() - t0;
76 return { ok: false, error: formatError(e), output, wallMs, backend };
77 }
80export function formatError(e: unknown): string {
81 if (e instanceof RuntimeError) {
82 const where = [e.file, e.line]
83 .filter((x) => x !== undefined && x !== null && x !== "")
84 .join(":");
85 return where ? `${where}: ${e.message}` : e.message;
86 }
87 if (e instanceof Error) return e.message;
88 return String(e);
↑↓ move↵openescclose