/ proof-of-concept / plate-mechanics-sim
Sign in
proof-of-concept / plate-mechanics-sim
plate-mechanics-sim / packages / core / src / runner / execute.ts
74 lines · 2.6 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(req: RunRequest, backend: BackendInfo, onOutput?: (text: string) => void): RunResult {
24 const { bundle } = req;
25 const entry = bundle.files.find((f) => f.name === bundle.entry);
26 const output: string[] = [];
27 const t0 = performance.now();
28 if (!entry) {
29 return { ok: false, error: `entry file ${bundle.entry} is not in the bundle`, output, wallMs: 0, backend };
30 }
31 const workspaceFiles = bundle.files.filter((f) => f.name !== bundle.entry).map((f) => ({ name: f.name, source: f.source }));
32 const initialVariableValues: Record<string, RuntimeValue> = {};
33 for (const [name, v] of Object.entries(req.inputs ?? {})) initialVariableValues[name] = toRuntime(v);
34 try {
35 const result = executeCode(
36 entry.source,
37 {
38 optimization: OPTIMIZATION,
39 displayResults: false,
40 initialVariableValues,
41 onOutput: (text: string) => {
42 output.push(text);
43 onOutput?.(text);
44 },
45 },
46 workspaceFiles,
47 bundle.entry,
48 );
49 const wallMs = performance.now() - t0;
50 const value = result.variableValues[bundle.resultVariable];
51 if (value === undefined) {
52 return {
53 ok: false,
54 error: `the script finished but did not define the variable "${bundle.resultVariable}"`,
55 output,
56 wallMs,
57 backend,
58 };
59 }
60 return { ok: true, value: toPlain(value), output, wallMs, backend };
61 } catch (e) {
62 const wallMs = performance.now() - t0;
63 return { ok: false, error: formatError(e), output, wallMs, backend };
64 }
67export function formatError(e: unknown): string {
68 if (e instanceof RuntimeError) {
69 const where = [e.file, e.line].filter((x) => x !== undefined && x !== null && x !== "").join(":");
70 return where ? `${where}: ${e.message}` : e.message;
71 }
72 if (e instanceof Error) return e.message;
73 return String(e);
↑↓ move↵openescclose