@al8b/vm 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/context.ts","../src/extensions.ts","../src/l8bvm.ts","../src/index.ts"],"sourcesContent":["/**\n * VM Context creation utilities\n */\n\nimport { Random } from \"@al8b/lootiscript\";\nimport type { GlobalAPI, MetaFunctions, VMContext } from \"./types\";\n\n// Shared math lambdas — allocated once, reused across all VM instances\nconst _baseMeta = {\n\tround: (x: number) => Math.round(x),\n\tfloor: (x: number) => Math.floor(x),\n\tceil: (x: number) => Math.ceil(x),\n\tabs: (x: number) => Math.abs(x),\n\tmin: (x: number, y: number) => Math.min(x, y),\n\tmax: (x: number, y: number) => Math.max(x, y),\n\tsqrt: (x: number) => Math.sqrt(x),\n\tpow: (x: number, y: number) => x ** y,\n\tsin: (x: number) => Math.sin(x),\n\tcos: (x: number) => Math.cos(x),\n\ttan: (x: number) => Math.tan(x),\n\tasin: (x: number) => Math.asin(x),\n\tacos: (x: number) => Math.acos(x),\n\tatan: (x: number) => Math.atan(x),\n\tatan2: (y: number, x: number) => Math.atan2(y, x),\n\tsind: (x: number) => Math.sin((x / 180) * Math.PI),\n\tcosd: (x: number) => Math.cos((x / 180) * Math.PI),\n\ttand: (x: number) => Math.tan((x / 180) * Math.PI),\n\tasind: (x: number) => (Math.asin(x) * 180) / Math.PI,\n\tacosd: (x: number) => (Math.acos(x) * 180) / Math.PI,\n\tatand: (x: number) => (Math.atan(x) * 180) / Math.PI,\n\tatan2d: (y: number, x: number) => (Math.atan2(y, x) * 180) / Math.PI,\n\tlog: (x: number) => Math.log(x),\n\texp: (x: number) => Math.exp(x),\n\trandom: new Random(0),\n\tPI: Math.PI,\n\ttrue: 1 as const,\n\tfalse: 0 as const,\n};\n\nconst _defaultPrint = (text: any) => console.log(text);\n\n/**\n * Create meta functions (built-in functions)\n */\nexport function createMetaFunctions(customPrint?: (text: any) => void): MetaFunctions {\n\treturn {\n\t\t..._baseMeta,\n\t\tprint: customPrint ?? _defaultPrint,\n\t};\n}\n\n/**\n * Create VM context\n */\nexport function createVMContext(meta: Partial<MetaFunctions>, global: Partial<GlobalAPI>): VMContext {\n\tconst fullMeta: MetaFunctions = {\n\t\t..._baseMeta,\n\t\tprint: meta.print ?? _defaultPrint,\n\t\t...meta,\n\t};\n\n\treturn {\n\t\tmeta: fullMeta as MetaFunctions,\n\t\tglobal: global as GlobalAPI,\n\t\tlocal: global,\n\t\tobject: global,\n\t\tbreakable: 0,\n\t\tcontinuable: 0,\n\t\treturnable: 0,\n\t\tstack_size: 0,\n\t\ttimeout: Date.now() + 3000,\n\t\twarnings: {\n\t\t\tusing_undefined_variable: {},\n\t\t\tassigning_field_to_undefined: {},\n\t\t\tinvoking_non_function: {},\n\t\t\tassigning_api_variable: {},\n\t\t\tassignment_as_condition: {},\n\t\t},\n\t};\n}\n","/**\n * Array extensions\n */\n\n/**\n * Setup array extensions\n */\nexport function setupArrayExtensions(): void {\n\t// Insert element at beginning of array (returns the inserted element)\n\tif (!Array.prototype.insert) {\n\t\tArray.prototype.insert = function (element: any) {\n\t\t\tthis.splice(0, 0, element);\n\t\t\treturn element;\n\t\t};\n\t}\n\n\t// Insert element at specific index (returns the inserted element)\n\tif (!Array.prototype.insertAt) {\n\t\tArray.prototype.insertAt = function (element: any, index: number) {\n\t\t\tif (index >= 0 && index < this.length) {\n\t\t\t\tthis.splice(index, 0, element);\n\t\t\t} else {\n\t\t\t\tthis.push(element);\n\t\t\t}\n\t\t\treturn element;\n\t\t};\n\t}\n\n\t// Remove element at index (returns removed element or 0 if out of bounds)\n\tif (!Array.prototype.remove) {\n\t\tArray.prototype.remove = function (index: number) {\n\t\t\tif (index >= 0 && index < this.length) {\n\t\t\t\treturn this.splice(index, 1)[0];\n\t\t\t}\n\t\t\treturn 0;\n\t\t};\n\t}\n\n\t// Remove first occurrence of element (returns removed element or 0 if not found)\n\tif (!Array.prototype.removeElement) {\n\t\tArray.prototype.removeElement = function (element: any) {\n\t\t\tconst index = this.indexOf(element);\n\t\t\tif (index >= 0) {\n\t\t\t\treturn this.splice(index, 1)[0];\n\t\t\t}\n\t\t\treturn 0;\n\t\t};\n\t}\n\n\t// Check if array contains element (returns 1 if found, 0 if not found)\n\tif (!Array.prototype.contains) {\n\t\tArray.prototype.contains = function (element: any) {\n\t\t\treturn this.indexOf(element) >= 0 ? 1 : 0;\n\t\t};\n\t}\n\n\t// Sort array with optional comparator function\n\tif (!Array.prototype.sortList) {\n\t\tArray.prototype.sortList = function (fn?: (a: any, b: any) => number) {\n\t\t\tif (fn) {\n\t\t\t\treturn this.sort(fn);\n\t\t\t}\n\t\t\treturn this.sort();\n\t\t};\n\t}\n}\n\n// TypeScript type declarations for Array prototype extensions\ndeclare global {\n\tinterface Array<T> {\n\t\tinsert(element: T): T;\n\t\tinsertAt(element: T, index: number): T;\n\t\tremove(index: number): T | 0;\n\t\tremoveElement(element: T): T | 0;\n\t\tcontains(element: T): 0 | 1;\n\t\tsortList(fn?: (a: T, b: T) => number): T[];\n\t}\n}\n","/**\n * L8BVM - Virtual Machine wrapper for lootiscript\n *\n * High-level interface for the LootiScript virtual machine.\n * Wraps the core Compiler, Processor, and Runner into a usable engine component.\n * Handles context creation, storage persistence, and error formatting.\n *\n * Responsibilities:\n * - Create and manage VM execution context\n * - Provide clean API for running code and calling functions\n * - Handle storage persistence\n * - Format and normalize runtime errors\n *\n * @module vm\n */\n\nimport type { CompiledModuleArtifact, SerializedRoutineData } from \"@al8b/framework-shared\";\nimport { StorageService } from \"@al8b/io\";\nimport { Routine, Runner } from \"@al8b/lootiscript\";\nimport { createVMContext } from \"./context\";\nimport { setupArrayExtensions } from \"./extensions\";\nimport type { ErrorInfo, GlobalAPI, MetaFunctions, VMContext } from \"./types\";\n\n/**\n * Extract normalized ErrorInfo from a caught exception.\n * Centralizes the error-parsing logic shared across run(), call(), and loadRoutine().\n */\nfunction extractErrorInfo(err: any, fallbackFile: string, fallbackType: string, runner?: Runner): ErrorInfo {\n\tconst errorMessage =\n\t\ttypeof err === \"object\" && err !== null && \"error\" in err && typeof err.error === \"string\"\n\t\t\t? err.error\n\t\t\t: err?.message ?? String(err);\n\n\tlet stackTrace = err?.stackTrace;\n\tif (!stackTrace && (runner as any)?.main_thread?.processor?.generateStackTrace) {\n\t\tstackTrace = (runner as any).main_thread.processor.generateStackTrace();\n\t}\n\n\treturn {\n\t\terror: errorMessage,\n\t\ttype: err?.type ?? fallbackType,\n\t\tline: err?.line,\n\t\tcolumn: err?.column,\n\t\tfile: err?.file ?? fallbackFile,\n\t\tstack: err?.stack,\n\t\tstackTrace,\n\t};\n}\n\nexport class L8BVM {\n\tpublic context: VMContext;\n\tpublic runner: Runner;\n\tpublic storage_service: StorageService;\n\tpublic error_info: ErrorInfo | null = null;\n\n\tconstructor(\n\t\tmeta: Partial<MetaFunctions> = {},\n\t\tglobal: Partial<GlobalAPI> = {},\n\t\tnamespace = \"/l8b\",\n\t\tpreserve_ls = false,\n\t) {\n\t\t// Initialize VM execution context with meta functions and global API\n\t\tthis.context = createVMContext(meta, global);\n\n\t\t// Initialize storage service for persistent data (localStorage/sessionStorage)\n\t\tthis.storage_service = new StorageService(namespace, preserve_ls);\n\n\t\t// Inject storage API into global scope for LootiScript access\n\t\tthis.context.global.storage = this.storage_service.getInterface();\n\n\t\t// Create Runner instance with reference to this VM for bidirectional communication\n\t\tthis.runner = new Runner(this as any);\n\n\t\t// Initialize Runner and create main execution thread\n\t\tthis.runner.init();\n\n\t\t// Add custom array methods to Array.prototype for LootiScript\n\t\tsetupArrayExtensions();\n\t}\n\n\t/**\n\t * Run source code\n\t *\n\t * Compiles and executes a string of LootiScript code.\n\t *\n\t * @param {string} source - The source code to execute\n\t * @param {number} [timeout=3000] - Execution time limit in ms\n\t * @param {string} [filename=\"\"] - Filename for error reporting\n\t * @returns {any} The result of the last statement execution\n\t * @throws {ErrorInfo} If compilation or execution fails\n\t */\n\trun(source: string, timeout = 3000, filename = \"\"): any {\n\t\tthis.error_info = null;\n\t\tthis.context.timeout = Date.now() + timeout;\n\t\tthis.context.stack_size = 0;\n\n\t\ttry {\n\t\t\tconst result = this.runner.run(source, filename);\n\t\t\tthis.storage_service.check();\n\n\t\t\tif (result !== null && result !== undefined) {\n\t\t\t\treturn this.runner.toString(result);\n\t\t\t}\n\t\t\treturn null;\n\t\t} catch (err: any) {\n\t\t\tthis.error_info = extractErrorInfo(err, filename, \"runtime\", this.runner);\n\t\t\tthrow err;\n\t\t}\n\t}\n\n\t/**\n\t * Call a global function\n\t *\n\t * Executes a specific function defined in the global scope.\n\t * Useful for game loop hooks (update, draw) or event handlers.\n\t *\n\t * @param {string} name - Name of the function to call\n\t * @param {any[]} [args=[]] - Arguments to pass to the function\n\t * @param {number} [timeout=3000] - Execution time limit in ms\n\t * @returns {any} The return value of the function\n\t * @throws {ErrorInfo} If the function doesn't exist or execution fails\n\t */\n\tcall(name: string, args: any[] = [], timeout = 3000): any {\n\t\tthis.error_info = null;\n\t\tthis.context.timeout = Date.now() + timeout;\n\t\tthis.context.stack_size = 0;\n\n\t\ttry {\n\t\t\tconst result = this.runner.call(name, ...args);\n\t\t\tthis.storage_service.check();\n\t\t\treturn result;\n\t\t} catch (err: any) {\n\t\t\tthis.error_info = extractErrorInfo(err, name, \"call\", this.runner);\n\t\t\tthrow err;\n\t\t}\n\t}\n\n\t/**\n\t * Load a pre-compiled routine (for production builds)\n\t *\n\t * Loads bytecode directly into the VM, bypassing the compilation step.\n\t * Used in production to improve startup time and obfuscate source.\n\t *\n\t * @param {any} routineData - Either a Routine instance or serialized JSON\n\t * @param {string} [filename=\"\"] - Name of the file for error reporting\n\t * @throws {ErrorInfo} If loading fails\n\t */\n\tloadRoutine(routineData: any, filename: string = \"\"): void {\n\t\tthis.error_info = null;\n\n\t\ttry {\n\t\t\tlet routine: Routine;\n\n\t\t\t// Handle both Routine instances and serialized routine data\n\t\t\t// Serialized data needs to be imported first\n\t\t\tif (routineData instanceof Routine) {\n\t\t\t\troutine = routineData;\n\t\t\t} else {\n\t\t\t\troutine = new Routine(0).import(normalizeSerializedRoutine(routineData));\n\t\t\t}\n\n\t\t\t// Add to main thread for execution\n\t\t\tthis.runner.main_thread.addCall(routine);\n\t\t\tthis.runner.tick();\n\t\t} catch (err: any) {\n\t\t\tthis.error_info = extractErrorInfo(err, filename, \"compile\");\n\t\t\tthrow err;\n\t\t}\n\t}\n\n\t/**\n\t * Clear warnings\n\t */\n\tclearWarnings(): void {\n\t\tthis.context.warnings = {\n\t\t\tusing_undefined_variable: {},\n\t\t\tassigning_field_to_undefined: {},\n\t\t\tinvoking_non_function: {},\n\t\t\tassigning_api_variable: {},\n\t\t\tassignment_as_condition: {},\n\t\t};\n\t}\n\n\t/**\n\t * Get warnings\n\t */\n\tgetWarnings(): Record<string, any> {\n\t\treturn this.context.warnings || {};\n\t}\n\n\t/**\n\t * Convert value to string (for printing)\n\t */\n\ttoString(value: any): string {\n\t\treturn this.runner.toString(value);\n\t}\n}\n\nfunction normalizeSerializedRoutine(routineData: CompiledModuleArtifact | SerializedRoutineData): SerializedRoutineData {\n\tif (isCompiledModuleArtifact(routineData)) {\n\t\treturn routineData.routine;\n\t}\n\n\treturn routineData;\n}\n\nfunction isCompiledModuleArtifact(value: unknown): value is CompiledModuleArtifact {\n\treturn (\n\t\ttypeof value === \"object\" &&\n\t\tvalue !== null &&\n\t\t\"format\" in value &&\n\t\t(value as { format?: unknown }).format === \"l8b-compiled-routine\" &&\n\t\t\"routine\" in value\n\t);\n}\n","// VM public surface — StorageService is intentionally NOT re-exported here.\n// Import it directly from \"@al8b/io\" if you need it.\nexport { createMetaFunctions, createVMContext } from \"./context\";\nexport { setupArrayExtensions } from \"./extensions\";\nexport { L8BVM } from \"./l8bvm\";\nexport type {\n\tErrorInfo,\n\tGlobalAPI,\n\tMetaFunctions,\n\tPlayerAPI,\n\tSystemAPI,\n\tVMContext,\n\tVMWarnings,\n\tWarningInfo,\n} from \"./types\";\n\n// Re-export language primitives that runtime and host code legitimately need.\n// This keeps runtime from bypassing the vm layer and importing lootiscript directly.\nexport { Random, Routine } from \"@al8b/lootiscript\";\n"],"mappings":"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","names":["Random","_baseMeta","round","x","Math","floor","ceil","abs","min","y","max","sqrt","pow","sin","cos","tan","asin","acos","atan","atan2","sind","PI","cosd","tand","asind","acosd","atand","atan2d","log","exp","random","Random","true","false","_defaultPrint","text","console","createMetaFunctions","customPrint","print","createVMContext","meta","global","fullMeta","local","object","breakable","continuable","returnable","stack_size","timeout","Date","now","warnings","using_undefined_variable","assigning_field_to_undefined","invoking_non_function","assigning_api_variable","assignment_as_condition","setupArrayExtensions","Array","prototype","insert","element","splice","insertAt","index","length","push","remove","removeElement","indexOf","contains","sortList","fn","sort","StorageService","Routine","Runner","extractErrorInfo","err","fallbackFile","fallbackType","runner","errorMessage","error","message","String","stackTrace","main_thread","processor","generateStackTrace","type","line","column","file","stack","L8BVM","context","storage_service","error_info","meta","global","namespace","preserve_ls","createVMContext","StorageService","storage","getInterface","Runner","init","setupArrayExtensions","run","source","timeout","filename","Date","now","stack_size","result","check","undefined","toString","call","name","args","loadRoutine","routineData","routine","Routine","import","normalizeSerializedRoutine","addCall","tick","clearWarnings","warnings","using_undefined_variable","assigning_field_to_undefined","invoking_non_function","assigning_api_variable","assignment_as_condition","getWarnings","value","isCompiledModuleArtifact","format","Random","Routine"]}
@@ -0,0 +1,77 @@
1
+ import { StorageService } from '@al8b/io';
2
+ import { Runner } from '@al8b/lootiscript';
3
+ import { VMContext, ErrorInfo, MetaFunctions, GlobalAPI } from './types/index.mjs';
4
+
5
+ /**
6
+ * L8BVM - Virtual Machine wrapper for lootiscript
7
+ *
8
+ * High-level interface for the LootiScript virtual machine.
9
+ * Wraps the core Compiler, Processor, and Runner into a usable engine component.
10
+ * Handles context creation, storage persistence, and error formatting.
11
+ *
12
+ * Responsibilities:
13
+ * - Create and manage VM execution context
14
+ * - Provide clean API for running code and calling functions
15
+ * - Handle storage persistence
16
+ * - Format and normalize runtime errors
17
+ *
18
+ * @module vm
19
+ */
20
+
21
+ declare class L8BVM {
22
+ context: VMContext;
23
+ runner: Runner;
24
+ storage_service: StorageService;
25
+ error_info: ErrorInfo | null;
26
+ constructor(meta?: Partial<MetaFunctions>, global?: Partial<GlobalAPI>, namespace?: string, preserve_ls?: boolean);
27
+ /**
28
+ * Run source code
29
+ *
30
+ * Compiles and executes a string of LootiScript code.
31
+ *
32
+ * @param {string} source - The source code to execute
33
+ * @param {number} [timeout=3000] - Execution time limit in ms
34
+ * @param {string} [filename=""] - Filename for error reporting
35
+ * @returns {any} The result of the last statement execution
36
+ * @throws {ErrorInfo} If compilation or execution fails
37
+ */
38
+ run(source: string, timeout?: number, filename?: string): any;
39
+ /**
40
+ * Call a global function
41
+ *
42
+ * Executes a specific function defined in the global scope.
43
+ * Useful for game loop hooks (update, draw) or event handlers.
44
+ *
45
+ * @param {string} name - Name of the function to call
46
+ * @param {any[]} [args=[]] - Arguments to pass to the function
47
+ * @param {number} [timeout=3000] - Execution time limit in ms
48
+ * @returns {any} The return value of the function
49
+ * @throws {ErrorInfo} If the function doesn't exist or execution fails
50
+ */
51
+ call(name: string, args?: any[], timeout?: number): any;
52
+ /**
53
+ * Load a pre-compiled routine (for production builds)
54
+ *
55
+ * Loads bytecode directly into the VM, bypassing the compilation step.
56
+ * Used in production to improve startup time and obfuscate source.
57
+ *
58
+ * @param {any} routineData - Either a Routine instance or serialized JSON
59
+ * @param {string} [filename=""] - Name of the file for error reporting
60
+ * @throws {ErrorInfo} If loading fails
61
+ */
62
+ loadRoutine(routineData: any, filename?: string): void;
63
+ /**
64
+ * Clear warnings
65
+ */
66
+ clearWarnings(): void;
67
+ /**
68
+ * Get warnings
69
+ */
70
+ getWarnings(): Record<string, any>;
71
+ /**
72
+ * Convert value to string (for printing)
73
+ */
74
+ toString(value: any): string;
75
+ }
76
+
77
+ export { L8BVM };
@@ -0,0 +1,77 @@
1
+ import { StorageService } from '@al8b/io';
2
+ import { Runner } from '@al8b/lootiscript';
3
+ import { VMContext, ErrorInfo, MetaFunctions, GlobalAPI } from './types/index.js';
4
+
5
+ /**
6
+ * L8BVM - Virtual Machine wrapper for lootiscript
7
+ *
8
+ * High-level interface for the LootiScript virtual machine.
9
+ * Wraps the core Compiler, Processor, and Runner into a usable engine component.
10
+ * Handles context creation, storage persistence, and error formatting.
11
+ *
12
+ * Responsibilities:
13
+ * - Create and manage VM execution context
14
+ * - Provide clean API for running code and calling functions
15
+ * - Handle storage persistence
16
+ * - Format and normalize runtime errors
17
+ *
18
+ * @module vm
19
+ */
20
+
21
+ declare class L8BVM {
22
+ context: VMContext;
23
+ runner: Runner;
24
+ storage_service: StorageService;
25
+ error_info: ErrorInfo | null;
26
+ constructor(meta?: Partial<MetaFunctions>, global?: Partial<GlobalAPI>, namespace?: string, preserve_ls?: boolean);
27
+ /**
28
+ * Run source code
29
+ *
30
+ * Compiles and executes a string of LootiScript code.
31
+ *
32
+ * @param {string} source - The source code to execute
33
+ * @param {number} [timeout=3000] - Execution time limit in ms
34
+ * @param {string} [filename=""] - Filename for error reporting
35
+ * @returns {any} The result of the last statement execution
36
+ * @throws {ErrorInfo} If compilation or execution fails
37
+ */
38
+ run(source: string, timeout?: number, filename?: string): any;
39
+ /**
40
+ * Call a global function
41
+ *
42
+ * Executes a specific function defined in the global scope.
43
+ * Useful for game loop hooks (update, draw) or event handlers.
44
+ *
45
+ * @param {string} name - Name of the function to call
46
+ * @param {any[]} [args=[]] - Arguments to pass to the function
47
+ * @param {number} [timeout=3000] - Execution time limit in ms
48
+ * @returns {any} The return value of the function
49
+ * @throws {ErrorInfo} If the function doesn't exist or execution fails
50
+ */
51
+ call(name: string, args?: any[], timeout?: number): any;
52
+ /**
53
+ * Load a pre-compiled routine (for production builds)
54
+ *
55
+ * Loads bytecode directly into the VM, bypassing the compilation step.
56
+ * Used in production to improve startup time and obfuscate source.
57
+ *
58
+ * @param {any} routineData - Either a Routine instance or serialized JSON
59
+ * @param {string} [filename=""] - Name of the file for error reporting
60
+ * @throws {ErrorInfo} If loading fails
61
+ */
62
+ loadRoutine(routineData: any, filename?: string): void;
63
+ /**
64
+ * Clear warnings
65
+ */
66
+ clearWarnings(): void;
67
+ /**
68
+ * Get warnings
69
+ */
70
+ getWarnings(): Record<string, any>;
71
+ /**
72
+ * Convert value to string (for printing)
73
+ */
74
+ toString(value: any): string;
75
+ }
76
+
77
+ export { L8BVM };
package/dist/l8bvm.js ADDED
@@ -0,0 +1,293 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+
21
+ // src/l8bvm.ts
22
+ var l8bvm_exports = {};
23
+ __export(l8bvm_exports, {
24
+ L8BVM: () => L8BVM
25
+ });
26
+ module.exports = __toCommonJS(l8bvm_exports);
27
+ var import_io = require("@al8b/io");
28
+ var import_lootiscript2 = require("@al8b/lootiscript");
29
+
30
+ // src/context.ts
31
+ var import_lootiscript = require("@al8b/lootiscript");
32
+ var _baseMeta = {
33
+ round: /* @__PURE__ */ __name((x) => Math.round(x), "round"),
34
+ floor: /* @__PURE__ */ __name((x) => Math.floor(x), "floor"),
35
+ ceil: /* @__PURE__ */ __name((x) => Math.ceil(x), "ceil"),
36
+ abs: /* @__PURE__ */ __name((x) => Math.abs(x), "abs"),
37
+ min: /* @__PURE__ */ __name((x, y) => Math.min(x, y), "min"),
38
+ max: /* @__PURE__ */ __name((x, y) => Math.max(x, y), "max"),
39
+ sqrt: /* @__PURE__ */ __name((x) => Math.sqrt(x), "sqrt"),
40
+ pow: /* @__PURE__ */ __name((x, y) => x ** y, "pow"),
41
+ sin: /* @__PURE__ */ __name((x) => Math.sin(x), "sin"),
42
+ cos: /* @__PURE__ */ __name((x) => Math.cos(x), "cos"),
43
+ tan: /* @__PURE__ */ __name((x) => Math.tan(x), "tan"),
44
+ asin: /* @__PURE__ */ __name((x) => Math.asin(x), "asin"),
45
+ acos: /* @__PURE__ */ __name((x) => Math.acos(x), "acos"),
46
+ atan: /* @__PURE__ */ __name((x) => Math.atan(x), "atan"),
47
+ atan2: /* @__PURE__ */ __name((y, x) => Math.atan2(y, x), "atan2"),
48
+ sind: /* @__PURE__ */ __name((x) => Math.sin(x / 180 * Math.PI), "sind"),
49
+ cosd: /* @__PURE__ */ __name((x) => Math.cos(x / 180 * Math.PI), "cosd"),
50
+ tand: /* @__PURE__ */ __name((x) => Math.tan(x / 180 * Math.PI), "tand"),
51
+ asind: /* @__PURE__ */ __name((x) => Math.asin(x) * 180 / Math.PI, "asind"),
52
+ acosd: /* @__PURE__ */ __name((x) => Math.acos(x) * 180 / Math.PI, "acosd"),
53
+ atand: /* @__PURE__ */ __name((x) => Math.atan(x) * 180 / Math.PI, "atand"),
54
+ atan2d: /* @__PURE__ */ __name((y, x) => Math.atan2(y, x) * 180 / Math.PI, "atan2d"),
55
+ log: /* @__PURE__ */ __name((x) => Math.log(x), "log"),
56
+ exp: /* @__PURE__ */ __name((x) => Math.exp(x), "exp"),
57
+ random: new import_lootiscript.Random(0),
58
+ PI: Math.PI,
59
+ true: 1,
60
+ false: 0
61
+ };
62
+ var _defaultPrint = /* @__PURE__ */ __name((text) => console.log(text), "_defaultPrint");
63
+ function createVMContext(meta, global) {
64
+ const fullMeta = {
65
+ ..._baseMeta,
66
+ print: meta.print ?? _defaultPrint,
67
+ ...meta
68
+ };
69
+ return {
70
+ meta: fullMeta,
71
+ global,
72
+ local: global,
73
+ object: global,
74
+ breakable: 0,
75
+ continuable: 0,
76
+ returnable: 0,
77
+ stack_size: 0,
78
+ timeout: Date.now() + 3e3,
79
+ warnings: {
80
+ using_undefined_variable: {},
81
+ assigning_field_to_undefined: {},
82
+ invoking_non_function: {},
83
+ assigning_api_variable: {},
84
+ assignment_as_condition: {}
85
+ }
86
+ };
87
+ }
88
+ __name(createVMContext, "createVMContext");
89
+
90
+ // src/extensions.ts
91
+ function setupArrayExtensions() {
92
+ if (!Array.prototype.insert) {
93
+ Array.prototype.insert = function(element) {
94
+ this.splice(0, 0, element);
95
+ return element;
96
+ };
97
+ }
98
+ if (!Array.prototype.insertAt) {
99
+ Array.prototype.insertAt = function(element, index) {
100
+ if (index >= 0 && index < this.length) {
101
+ this.splice(index, 0, element);
102
+ } else {
103
+ this.push(element);
104
+ }
105
+ return element;
106
+ };
107
+ }
108
+ if (!Array.prototype.remove) {
109
+ Array.prototype.remove = function(index) {
110
+ if (index >= 0 && index < this.length) {
111
+ return this.splice(index, 1)[0];
112
+ }
113
+ return 0;
114
+ };
115
+ }
116
+ if (!Array.prototype.removeElement) {
117
+ Array.prototype.removeElement = function(element) {
118
+ const index = this.indexOf(element);
119
+ if (index >= 0) {
120
+ return this.splice(index, 1)[0];
121
+ }
122
+ return 0;
123
+ };
124
+ }
125
+ if (!Array.prototype.contains) {
126
+ Array.prototype.contains = function(element) {
127
+ return this.indexOf(element) >= 0 ? 1 : 0;
128
+ };
129
+ }
130
+ if (!Array.prototype.sortList) {
131
+ Array.prototype.sortList = function(fn) {
132
+ if (fn) {
133
+ return this.sort(fn);
134
+ }
135
+ return this.sort();
136
+ };
137
+ }
138
+ }
139
+ __name(setupArrayExtensions, "setupArrayExtensions");
140
+
141
+ // src/l8bvm.ts
142
+ function extractErrorInfo(err, fallbackFile, fallbackType, runner) {
143
+ const errorMessage = typeof err === "object" && err !== null && "error" in err && typeof err.error === "string" ? err.error : err?.message ?? String(err);
144
+ let stackTrace = err?.stackTrace;
145
+ if (!stackTrace && runner?.main_thread?.processor?.generateStackTrace) {
146
+ stackTrace = runner.main_thread.processor.generateStackTrace();
147
+ }
148
+ return {
149
+ error: errorMessage,
150
+ type: err?.type ?? fallbackType,
151
+ line: err?.line,
152
+ column: err?.column,
153
+ file: err?.file ?? fallbackFile,
154
+ stack: err?.stack,
155
+ stackTrace
156
+ };
157
+ }
158
+ __name(extractErrorInfo, "extractErrorInfo");
159
+ var L8BVM = class {
160
+ static {
161
+ __name(this, "L8BVM");
162
+ }
163
+ context;
164
+ runner;
165
+ storage_service;
166
+ error_info = null;
167
+ constructor(meta = {}, global = {}, namespace = "/l8b", preserve_ls = false) {
168
+ this.context = createVMContext(meta, global);
169
+ this.storage_service = new import_io.StorageService(namespace, preserve_ls);
170
+ this.context.global.storage = this.storage_service.getInterface();
171
+ this.runner = new import_lootiscript2.Runner(this);
172
+ this.runner.init();
173
+ setupArrayExtensions();
174
+ }
175
+ /**
176
+ * Run source code
177
+ *
178
+ * Compiles and executes a string of LootiScript code.
179
+ *
180
+ * @param {string} source - The source code to execute
181
+ * @param {number} [timeout=3000] - Execution time limit in ms
182
+ * @param {string} [filename=""] - Filename for error reporting
183
+ * @returns {any} The result of the last statement execution
184
+ * @throws {ErrorInfo} If compilation or execution fails
185
+ */
186
+ run(source, timeout = 3e3, filename = "") {
187
+ this.error_info = null;
188
+ this.context.timeout = Date.now() + timeout;
189
+ this.context.stack_size = 0;
190
+ try {
191
+ const result = this.runner.run(source, filename);
192
+ this.storage_service.check();
193
+ if (result !== null && result !== void 0) {
194
+ return this.runner.toString(result);
195
+ }
196
+ return null;
197
+ } catch (err) {
198
+ this.error_info = extractErrorInfo(err, filename, "runtime", this.runner);
199
+ throw err;
200
+ }
201
+ }
202
+ /**
203
+ * Call a global function
204
+ *
205
+ * Executes a specific function defined in the global scope.
206
+ * Useful for game loop hooks (update, draw) or event handlers.
207
+ *
208
+ * @param {string} name - Name of the function to call
209
+ * @param {any[]} [args=[]] - Arguments to pass to the function
210
+ * @param {number} [timeout=3000] - Execution time limit in ms
211
+ * @returns {any} The return value of the function
212
+ * @throws {ErrorInfo} If the function doesn't exist or execution fails
213
+ */
214
+ call(name, args = [], timeout = 3e3) {
215
+ this.error_info = null;
216
+ this.context.timeout = Date.now() + timeout;
217
+ this.context.stack_size = 0;
218
+ try {
219
+ const result = this.runner.call(name, ...args);
220
+ this.storage_service.check();
221
+ return result;
222
+ } catch (err) {
223
+ this.error_info = extractErrorInfo(err, name, "call", this.runner);
224
+ throw err;
225
+ }
226
+ }
227
+ /**
228
+ * Load a pre-compiled routine (for production builds)
229
+ *
230
+ * Loads bytecode directly into the VM, bypassing the compilation step.
231
+ * Used in production to improve startup time and obfuscate source.
232
+ *
233
+ * @param {any} routineData - Either a Routine instance or serialized JSON
234
+ * @param {string} [filename=""] - Name of the file for error reporting
235
+ * @throws {ErrorInfo} If loading fails
236
+ */
237
+ loadRoutine(routineData, filename = "") {
238
+ this.error_info = null;
239
+ try {
240
+ let routine;
241
+ if (routineData instanceof import_lootiscript2.Routine) {
242
+ routine = routineData;
243
+ } else {
244
+ routine = new import_lootiscript2.Routine(0).import(normalizeSerializedRoutine(routineData));
245
+ }
246
+ this.runner.main_thread.addCall(routine);
247
+ this.runner.tick();
248
+ } catch (err) {
249
+ this.error_info = extractErrorInfo(err, filename, "compile");
250
+ throw err;
251
+ }
252
+ }
253
+ /**
254
+ * Clear warnings
255
+ */
256
+ clearWarnings() {
257
+ this.context.warnings = {
258
+ using_undefined_variable: {},
259
+ assigning_field_to_undefined: {},
260
+ invoking_non_function: {},
261
+ assigning_api_variable: {},
262
+ assignment_as_condition: {}
263
+ };
264
+ }
265
+ /**
266
+ * Get warnings
267
+ */
268
+ getWarnings() {
269
+ return this.context.warnings || {};
270
+ }
271
+ /**
272
+ * Convert value to string (for printing)
273
+ */
274
+ toString(value) {
275
+ return this.runner.toString(value);
276
+ }
277
+ };
278
+ function normalizeSerializedRoutine(routineData) {
279
+ if (isCompiledModuleArtifact(routineData)) {
280
+ return routineData.routine;
281
+ }
282
+ return routineData;
283
+ }
284
+ __name(normalizeSerializedRoutine, "normalizeSerializedRoutine");
285
+ function isCompiledModuleArtifact(value) {
286
+ return typeof value === "object" && value !== null && "format" in value && value.format === "l8b-compiled-routine" && "routine" in value;
287
+ }
288
+ __name(isCompiledModuleArtifact, "isCompiledModuleArtifact");
289
+ // Annotate the CommonJS export names for ESM import in node:
290
+ 0 && (module.exports = {
291
+ L8BVM
292
+ });
293
+ //# sourceMappingURL=l8bvm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/l8bvm.ts","../src/context.ts","../src/extensions.ts"],"sourcesContent":["/**\n * L8BVM - Virtual Machine wrapper for lootiscript\n *\n * High-level interface for the LootiScript virtual machine.\n * Wraps the core Compiler, Processor, and Runner into a usable engine component.\n * Handles context creation, storage persistence, and error formatting.\n *\n * Responsibilities:\n * - Create and manage VM execution context\n * - Provide clean API for running code and calling functions\n * - Handle storage persistence\n * - Format and normalize runtime errors\n *\n * @module vm\n */\n\nimport type { CompiledModuleArtifact, SerializedRoutineData } from \"@al8b/framework-shared\";\nimport { StorageService } from \"@al8b/io\";\nimport { Routine, Runner } from \"@al8b/lootiscript\";\nimport { createVMContext } from \"./context\";\nimport { setupArrayExtensions } from \"./extensions\";\nimport type { ErrorInfo, GlobalAPI, MetaFunctions, VMContext } from \"./types\";\n\n/**\n * Extract normalized ErrorInfo from a caught exception.\n * Centralizes the error-parsing logic shared across run(), call(), and loadRoutine().\n */\nfunction extractErrorInfo(err: any, fallbackFile: string, fallbackType: string, runner?: Runner): ErrorInfo {\n\tconst errorMessage =\n\t\ttypeof err === \"object\" && err !== null && \"error\" in err && typeof err.error === \"string\"\n\t\t\t? err.error\n\t\t\t: err?.message ?? String(err);\n\n\tlet stackTrace = err?.stackTrace;\n\tif (!stackTrace && (runner as any)?.main_thread?.processor?.generateStackTrace) {\n\t\tstackTrace = (runner as any).main_thread.processor.generateStackTrace();\n\t}\n\n\treturn {\n\t\terror: errorMessage,\n\t\ttype: err?.type ?? fallbackType,\n\t\tline: err?.line,\n\t\tcolumn: err?.column,\n\t\tfile: err?.file ?? fallbackFile,\n\t\tstack: err?.stack,\n\t\tstackTrace,\n\t};\n}\n\nexport class L8BVM {\n\tpublic context: VMContext;\n\tpublic runner: Runner;\n\tpublic storage_service: StorageService;\n\tpublic error_info: ErrorInfo | null = null;\n\n\tconstructor(\n\t\tmeta: Partial<MetaFunctions> = {},\n\t\tglobal: Partial<GlobalAPI> = {},\n\t\tnamespace = \"/l8b\",\n\t\tpreserve_ls = false,\n\t) {\n\t\t// Initialize VM execution context with meta functions and global API\n\t\tthis.context = createVMContext(meta, global);\n\n\t\t// Initialize storage service for persistent data (localStorage/sessionStorage)\n\t\tthis.storage_service = new StorageService(namespace, preserve_ls);\n\n\t\t// Inject storage API into global scope for LootiScript access\n\t\tthis.context.global.storage = this.storage_service.getInterface();\n\n\t\t// Create Runner instance with reference to this VM for bidirectional communication\n\t\tthis.runner = new Runner(this as any);\n\n\t\t// Initialize Runner and create main execution thread\n\t\tthis.runner.init();\n\n\t\t// Add custom array methods to Array.prototype for LootiScript\n\t\tsetupArrayExtensions();\n\t}\n\n\t/**\n\t * Run source code\n\t *\n\t * Compiles and executes a string of LootiScript code.\n\t *\n\t * @param {string} source - The source code to execute\n\t * @param {number} [timeout=3000] - Execution time limit in ms\n\t * @param {string} [filename=\"\"] - Filename for error reporting\n\t * @returns {any} The result of the last statement execution\n\t * @throws {ErrorInfo} If compilation or execution fails\n\t */\n\trun(source: string, timeout = 3000, filename = \"\"): any {\n\t\tthis.error_info = null;\n\t\tthis.context.timeout = Date.now() + timeout;\n\t\tthis.context.stack_size = 0;\n\n\t\ttry {\n\t\t\tconst result = this.runner.run(source, filename);\n\t\t\tthis.storage_service.check();\n\n\t\t\tif (result !== null && result !== undefined) {\n\t\t\t\treturn this.runner.toString(result);\n\t\t\t}\n\t\t\treturn null;\n\t\t} catch (err: any) {\n\t\t\tthis.error_info = extractErrorInfo(err, filename, \"runtime\", this.runner);\n\t\t\tthrow err;\n\t\t}\n\t}\n\n\t/**\n\t * Call a global function\n\t *\n\t * Executes a specific function defined in the global scope.\n\t * Useful for game loop hooks (update, draw) or event handlers.\n\t *\n\t * @param {string} name - Name of the function to call\n\t * @param {any[]} [args=[]] - Arguments to pass to the function\n\t * @param {number} [timeout=3000] - Execution time limit in ms\n\t * @returns {any} The return value of the function\n\t * @throws {ErrorInfo} If the function doesn't exist or execution fails\n\t */\n\tcall(name: string, args: any[] = [], timeout = 3000): any {\n\t\tthis.error_info = null;\n\t\tthis.context.timeout = Date.now() + timeout;\n\t\tthis.context.stack_size = 0;\n\n\t\ttry {\n\t\t\tconst result = this.runner.call(name, ...args);\n\t\t\tthis.storage_service.check();\n\t\t\treturn result;\n\t\t} catch (err: any) {\n\t\t\tthis.error_info = extractErrorInfo(err, name, \"call\", this.runner);\n\t\t\tthrow err;\n\t\t}\n\t}\n\n\t/**\n\t * Load a pre-compiled routine (for production builds)\n\t *\n\t * Loads bytecode directly into the VM, bypassing the compilation step.\n\t * Used in production to improve startup time and obfuscate source.\n\t *\n\t * @param {any} routineData - Either a Routine instance or serialized JSON\n\t * @param {string} [filename=\"\"] - Name of the file for error reporting\n\t * @throws {ErrorInfo} If loading fails\n\t */\n\tloadRoutine(routineData: any, filename: string = \"\"): void {\n\t\tthis.error_info = null;\n\n\t\ttry {\n\t\t\tlet routine: Routine;\n\n\t\t\t// Handle both Routine instances and serialized routine data\n\t\t\t// Serialized data needs to be imported first\n\t\t\tif (routineData instanceof Routine) {\n\t\t\t\troutine = routineData;\n\t\t\t} else {\n\t\t\t\troutine = new Routine(0).import(normalizeSerializedRoutine(routineData));\n\t\t\t}\n\n\t\t\t// Add to main thread for execution\n\t\t\tthis.runner.main_thread.addCall(routine);\n\t\t\tthis.runner.tick();\n\t\t} catch (err: any) {\n\t\t\tthis.error_info = extractErrorInfo(err, filename, \"compile\");\n\t\t\tthrow err;\n\t\t}\n\t}\n\n\t/**\n\t * Clear warnings\n\t */\n\tclearWarnings(): void {\n\t\tthis.context.warnings = {\n\t\t\tusing_undefined_variable: {},\n\t\t\tassigning_field_to_undefined: {},\n\t\t\tinvoking_non_function: {},\n\t\t\tassigning_api_variable: {},\n\t\t\tassignment_as_condition: {},\n\t\t};\n\t}\n\n\t/**\n\t * Get warnings\n\t */\n\tgetWarnings(): Record<string, any> {\n\t\treturn this.context.warnings || {};\n\t}\n\n\t/**\n\t * Convert value to string (for printing)\n\t */\n\ttoString(value: any): string {\n\t\treturn this.runner.toString(value);\n\t}\n}\n\nfunction normalizeSerializedRoutine(routineData: CompiledModuleArtifact | SerializedRoutineData): SerializedRoutineData {\n\tif (isCompiledModuleArtifact(routineData)) {\n\t\treturn routineData.routine;\n\t}\n\n\treturn routineData;\n}\n\nfunction isCompiledModuleArtifact(value: unknown): value is CompiledModuleArtifact {\n\treturn (\n\t\ttypeof value === \"object\" &&\n\t\tvalue !== null &&\n\t\t\"format\" in value &&\n\t\t(value as { format?: unknown }).format === \"l8b-compiled-routine\" &&\n\t\t\"routine\" in value\n\t);\n}\n","/**\n * VM Context creation utilities\n */\n\nimport { Random } from \"@al8b/lootiscript\";\nimport type { GlobalAPI, MetaFunctions, VMContext } from \"./types\";\n\n// Shared math lambdas — allocated once, reused across all VM instances\nconst _baseMeta = {\n\tround: (x: number) => Math.round(x),\n\tfloor: (x: number) => Math.floor(x),\n\tceil: (x: number) => Math.ceil(x),\n\tabs: (x: number) => Math.abs(x),\n\tmin: (x: number, y: number) => Math.min(x, y),\n\tmax: (x: number, y: number) => Math.max(x, y),\n\tsqrt: (x: number) => Math.sqrt(x),\n\tpow: (x: number, y: number) => x ** y,\n\tsin: (x: number) => Math.sin(x),\n\tcos: (x: number) => Math.cos(x),\n\ttan: (x: number) => Math.tan(x),\n\tasin: (x: number) => Math.asin(x),\n\tacos: (x: number) => Math.acos(x),\n\tatan: (x: number) => Math.atan(x),\n\tatan2: (y: number, x: number) => Math.atan2(y, x),\n\tsind: (x: number) => Math.sin((x / 180) * Math.PI),\n\tcosd: (x: number) => Math.cos((x / 180) * Math.PI),\n\ttand: (x: number) => Math.tan((x / 180) * Math.PI),\n\tasind: (x: number) => (Math.asin(x) * 180) / Math.PI,\n\tacosd: (x: number) => (Math.acos(x) * 180) / Math.PI,\n\tatand: (x: number) => (Math.atan(x) * 180) / Math.PI,\n\tatan2d: (y: number, x: number) => (Math.atan2(y, x) * 180) / Math.PI,\n\tlog: (x: number) => Math.log(x),\n\texp: (x: number) => Math.exp(x),\n\trandom: new Random(0),\n\tPI: Math.PI,\n\ttrue: 1 as const,\n\tfalse: 0 as const,\n};\n\nconst _defaultPrint = (text: any) => console.log(text);\n\n/**\n * Create meta functions (built-in functions)\n */\nexport function createMetaFunctions(customPrint?: (text: any) => void): MetaFunctions {\n\treturn {\n\t\t..._baseMeta,\n\t\tprint: customPrint ?? _defaultPrint,\n\t};\n}\n\n/**\n * Create VM context\n */\nexport function createVMContext(meta: Partial<MetaFunctions>, global: Partial<GlobalAPI>): VMContext {\n\tconst fullMeta: MetaFunctions = {\n\t\t..._baseMeta,\n\t\tprint: meta.print ?? _defaultPrint,\n\t\t...meta,\n\t};\n\n\treturn {\n\t\tmeta: fullMeta as MetaFunctions,\n\t\tglobal: global as GlobalAPI,\n\t\tlocal: global,\n\t\tobject: global,\n\t\tbreakable: 0,\n\t\tcontinuable: 0,\n\t\treturnable: 0,\n\t\tstack_size: 0,\n\t\ttimeout: Date.now() + 3000,\n\t\twarnings: {\n\t\t\tusing_undefined_variable: {},\n\t\t\tassigning_field_to_undefined: {},\n\t\t\tinvoking_non_function: {},\n\t\t\tassigning_api_variable: {},\n\t\t\tassignment_as_condition: {},\n\t\t},\n\t};\n}\n","/**\n * Array extensions\n */\n\n/**\n * Setup array extensions\n */\nexport function setupArrayExtensions(): void {\n\t// Insert element at beginning of array (returns the inserted element)\n\tif (!Array.prototype.insert) {\n\t\tArray.prototype.insert = function (element: any) {\n\t\t\tthis.splice(0, 0, element);\n\t\t\treturn element;\n\t\t};\n\t}\n\n\t// Insert element at specific index (returns the inserted element)\n\tif (!Array.prototype.insertAt) {\n\t\tArray.prototype.insertAt = function (element: any, index: number) {\n\t\t\tif (index >= 0 && index < this.length) {\n\t\t\t\tthis.splice(index, 0, element);\n\t\t\t} else {\n\t\t\t\tthis.push(element);\n\t\t\t}\n\t\t\treturn element;\n\t\t};\n\t}\n\n\t// Remove element at index (returns removed element or 0 if out of bounds)\n\tif (!Array.prototype.remove) {\n\t\tArray.prototype.remove = function (index: number) {\n\t\t\tif (index >= 0 && index < this.length) {\n\t\t\t\treturn this.splice(index, 1)[0];\n\t\t\t}\n\t\t\treturn 0;\n\t\t};\n\t}\n\n\t// Remove first occurrence of element (returns removed element or 0 if not found)\n\tif (!Array.prototype.removeElement) {\n\t\tArray.prototype.removeElement = function (element: any) {\n\t\t\tconst index = this.indexOf(element);\n\t\t\tif (index >= 0) {\n\t\t\t\treturn this.splice(index, 1)[0];\n\t\t\t}\n\t\t\treturn 0;\n\t\t};\n\t}\n\n\t// Check if array contains element (returns 1 if found, 0 if not found)\n\tif (!Array.prototype.contains) {\n\t\tArray.prototype.contains = function (element: any) {\n\t\t\treturn this.indexOf(element) >= 0 ? 1 : 0;\n\t\t};\n\t}\n\n\t// Sort array with optional comparator function\n\tif (!Array.prototype.sortList) {\n\t\tArray.prototype.sortList = function (fn?: (a: any, b: any) => number) {\n\t\t\tif (fn) {\n\t\t\t\treturn this.sort(fn);\n\t\t\t}\n\t\t\treturn this.sort();\n\t\t};\n\t}\n}\n\n// TypeScript type declarations for Array prototype extensions\ndeclare global {\n\tinterface Array<T> {\n\t\tinsert(element: T): T;\n\t\tinsertAt(element: T, index: number): T;\n\t\tremove(index: number): T | 0;\n\t\tremoveElement(element: T): T | 0;\n\t\tcontains(element: T): 0 | 1;\n\t\tsortList(fn?: (a: T, b: T) => number): T[];\n\t}\n}\n"],"mappings":"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","names":["import_lootiscript","_baseMeta","round","x","Math","floor","ceil","abs","min","y","max","sqrt","pow","sin","cos","tan","asin","acos","atan","atan2","sind","PI","cosd","tand","asind","acosd","atand","atan2d","log","exp","random","Random","true","false","_defaultPrint","text","console","createVMContext","meta","global","fullMeta","_baseMeta","print","_defaultPrint","local","object","breakable","continuable","returnable","stack_size","timeout","Date","now","warnings","using_undefined_variable","assigning_field_to_undefined","invoking_non_function","assigning_api_variable","assignment_as_condition","setupArrayExtensions","Array","prototype","insert","element","splice","insertAt","index","length","push","remove","removeElement","indexOf","contains","sortList","fn","sort","extractErrorInfo","err","fallbackFile","fallbackType","runner","errorMessage","error","message","String","stackTrace","main_thread","processor","generateStackTrace","type","line","column","file","stack","L8BVM","context","storage_service","error_info","meta","global","namespace","preserve_ls","createVMContext","StorageService","storage","getInterface","Runner","init","setupArrayExtensions","run","source","timeout","filename","Date","now","stack_size","result","check","undefined","toString","call","name","args","loadRoutine","routineData","routine","Routine","import","normalizeSerializedRoutine","addCall","tick","clearWarnings","warnings","using_undefined_variable","assigning_field_to_undefined","invoking_non_function","assigning_api_variable","assignment_as_condition","getWarnings","value","isCompiledModuleArtifact","format"]}