@silverbulletmd/silverbullet 2.8.1 → 2.10.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.
Files changed (65) hide show
  1. package/README.md +42 -25
  2. package/client/plugos/hooks/syscall.ts +24 -10
  3. package/client/plugos/syscalls/asset.ts +61 -23
  4. package/client/plugos/syscalls/clientStore.ts +32 -6
  5. package/client/plugos/syscalls/client_code_widget.ts +9 -4
  6. package/client/plugos/syscalls/code_widget.ts +26 -11
  7. package/client/plugos/syscalls/config.ts +146 -30
  8. package/client/plugos/syscalls/datastore.ts +146 -40
  9. package/client/plugos/syscalls/editor.ts +1432 -700
  10. package/client/plugos/syscalls/event.ts +46 -13
  11. package/client/plugos/syscalls/fetch.ts +123 -82
  12. package/client/plugos/syscalls/index.ts +243 -114
  13. package/client/plugos/syscalls/jsonschema.ts +107 -8
  14. package/client/plugos/syscalls/language.ts +38 -12
  15. package/client/plugos/syscalls/markdown.ts +166 -50
  16. package/client/plugos/syscalls/mq.ts +93 -20
  17. package/client/plugos/syscalls/schema_introspection.ts +33 -0
  18. package/client/plugos/syscalls/service_registry.ts +74 -20
  19. package/client/plugos/syscalls/shell.ts +51 -20
  20. package/client/plugos/syscalls/space.ts +169 -113
  21. package/client/plugos/syscalls/sync.ts +50 -19
  22. package/client/plugos/syscalls/system.ts +236 -139
  23. package/client/plugos/system.ts +21 -5
  24. package/client/space_lua/api_documentation.ts +107 -0
  25. package/client/space_lua/ast.ts +13 -0
  26. package/client/space_lua/eval.ts +12 -4
  27. package/client/space_lua/parse.ts +254 -119
  28. package/client/space_lua/pretty_print.ts +465 -0
  29. package/client/space_lua/query_collection.ts +3 -3
  30. package/client/space_lua/render_widget.ts +156 -0
  31. package/client/space_lua/runtime.ts +83 -22
  32. package/client/space_lua/stdlib/crypto.ts +8 -3
  33. package/client/space_lua/stdlib/encoding.ts +27 -9
  34. package/client/space_lua/stdlib/js.ts +137 -22
  35. package/client/space_lua/stdlib/load.ts +26 -17
  36. package/client/space_lua/stdlib/math.ts +323 -118
  37. package/client/space_lua/stdlib/net.ts +57 -9
  38. package/client/space_lua/stdlib/os.ts +111 -44
  39. package/client/space_lua/stdlib/space_lua.ts +397 -13
  40. package/client/space_lua/stdlib/string.ts +282 -104
  41. package/client/space_lua/stdlib/string_pack.ts +58 -19
  42. package/client/space_lua/stdlib/table.ts +195 -40
  43. package/client/space_lua/stdlib.ts +336 -94
  44. package/client/space_lua/syscalls.ts +270 -0
  45. package/dist/plug-compile.js +1 -1
  46. package/package.json +12 -4
  47. package/plug-api/lib/ref.ts +96 -0
  48. package/plug-api/lib/shortcut.ts +2 -1
  49. package/plug-api/syscalls/config.ts +5 -3
  50. package/plug-api/syscalls/editor.ts +23 -2
  51. package/plug-api/syscalls/index.ts +24 -1
  52. package/plug-api/syscalls/jsonschema.ts +9 -0
  53. package/plug-api/syscalls/lua.ts +28 -1
  54. package/plug-api/syscalls/shell.ts +0 -1
  55. package/plug-api/syscalls/system.ts +7 -0
  56. package/plug-api/system_mock.ts +2 -2
  57. package/plug-api/types/config.ts +1 -1
  58. package/plug-api/types/index.ts +52 -1
  59. package/plug-api/types/manifest.ts +22 -4
  60. package/plug-api/ui/cx.ts +4 -0
  61. package/plug-api/ui/index.ts +22 -0
  62. package/plug-api/ui/panel_styles.ts +33 -0
  63. package/plug-api/ui/slugify.ts +44 -0
  64. package/plugs/builtin_plugs.ts +1 -0
  65. package/client/plugos/syscalls/lua.ts +0 -58
@@ -5,6 +5,10 @@ import { isPromise, rpAll } from "./rp.ts";
5
5
  import { isNegativeZero, isTaggedFloat } from "./numeric.ts";
6
6
  import { isSqlNull } from "./sliq_null.ts";
7
7
  import { luaFormat } from "./stdlib/format.ts";
8
+ import type {
9
+ LuaFunctionDocumentation,
10
+ LuaFunctionInfo,
11
+ } from "../../plug-api/types/index.ts";
8
12
 
9
13
  export type LuaType =
10
14
  | "nil"
@@ -20,10 +24,19 @@ export type LuaType =
20
24
  export type LuaValue = any;
21
25
  export type JSValue = any;
22
26
 
27
+ type LuaFunctionDefinitionMetadata = LuaFunctionDocumentation &
28
+ Partial<Pick<LuaFunctionInfo, "kind" | "name" | "source">>;
29
+
30
+ export type LuaFunctionDefinition<Callback> = {
31
+ callback: Callback;
32
+ } & LuaFunctionDefinitionMetadata;
33
+
23
34
  export interface ILuaFunction {
24
35
  call(sf: LuaStackFrame, ...args: LuaValue[]): Promise<LuaValue> | LuaValue;
25
36
 
26
37
  asString(): string;
38
+
39
+ info?: LuaFunctionInfo;
27
40
  }
28
41
 
29
42
  export interface ILuaSettable {
@@ -453,12 +466,25 @@ export function singleResult(value: any): any {
453
466
  export class LuaFunction implements ILuaFunction {
454
467
  private capturedEnv: LuaEnv;
455
468
  funcHasGotos?: boolean;
469
+ info: LuaFunctionInfo;
456
470
 
457
471
  constructor(
458
472
  readonly body: LuaFunctionBody,
459
473
  closure: LuaEnv,
474
+ info: Partial<LuaFunctionInfo> = {},
460
475
  ) {
461
476
  this.capturedEnv = closure;
477
+ const documentation = body.documentation ?? {};
478
+ this.info = {
479
+ kind: "lua",
480
+ source: { ...body.ctx },
481
+ ...documentation,
482
+ ...info,
483
+ parameters:
484
+ info.parameters ??
485
+ documentation.parameters ??
486
+ body.parameters.map((name) => ({ name })),
487
+ };
462
488
  }
463
489
 
464
490
  call(sf: LuaStackFrame, ...args: LuaValue[]): Promise<LuaValue> | LuaValue {
@@ -482,10 +508,7 @@ export class LuaFunction implements ILuaFunction {
482
508
  for (let i = 0; i < varargStart; i++) {
483
509
  env.setLocal(params[i], resolvedArgs[i] ?? null);
484
510
  }
485
- env.setLocal(
486
- "...",
487
- new LuaMultiRes(resolvedArgs.slice(varargStart)),
488
- );
511
+ env.setLocal("...", new LuaMultiRes(resolvedArgs.slice(varargStart)));
489
512
  } else {
490
513
  // Non-variadic: bind all named params directly
491
514
  for (let i = 0; i < params.length; i++) {
@@ -565,7 +588,26 @@ function mapFunctionReturnValue(values: any[]): any {
565
588
  }
566
589
 
567
590
  export class LuaNativeJSFunction implements ILuaFunction {
568
- constructor(readonly fn: (...args: JSValue[]) => JSValue) {}
591
+ readonly fn: (...args: JSValue[]) => JSValue;
592
+ public info: LuaFunctionInfo;
593
+
594
+ constructor(
595
+ definition:
596
+ | ((...args: JSValue[]) => JSValue)
597
+ | LuaFunctionDefinition<(...args: JSValue[]) => JSValue>,
598
+ ) {
599
+ if (typeof definition === "function") {
600
+ this.fn = definition;
601
+ this.info = { kind: "builtin" };
602
+ } else {
603
+ const { callback, ...info } = definition;
604
+ this.fn = callback;
605
+ this.info = {
606
+ kind: "builtin",
607
+ ...info,
608
+ };
609
+ }
610
+ }
569
611
 
570
612
  // Performs automatic conversion between Lua and JS values for arguments, but not for return values
571
613
  call(sf: LuaStackFrame, ...args: LuaValue[]): Promise<LuaValue> | LuaValue {
@@ -595,9 +637,28 @@ export class LuaNativeJSFunction implements ILuaFunction {
595
637
  }
596
638
 
597
639
  export class LuaBuiltinFunction implements ILuaFunction {
640
+ readonly fn: (sf: LuaStackFrame, ...args: LuaValue[]) => LuaValue;
641
+ public info: LuaFunctionInfo;
642
+
598
643
  constructor(
599
- readonly fn: (sf: LuaStackFrame, ...args: LuaValue[]) => LuaValue,
600
- ) {}
644
+ definition:
645
+ | ((sf: LuaStackFrame, ...args: LuaValue[]) => LuaValue)
646
+ | LuaFunctionDefinition<
647
+ (sf: LuaStackFrame, ...args: LuaValue[]) => LuaValue
648
+ >,
649
+ ) {
650
+ if (typeof definition === "function") {
651
+ this.fn = definition;
652
+ this.info = { kind: "builtin" };
653
+ } else {
654
+ const { callback, ...info } = definition;
655
+ this.fn = callback;
656
+ this.info = {
657
+ kind: "builtin",
658
+ ...info,
659
+ };
660
+ }
661
+ }
601
662
 
602
663
  call(sf: LuaStackFrame, ...args: LuaValue[]): Promise<LuaValue> | LuaValue {
603
664
  // _CTX is already available via the stack frame
@@ -1313,11 +1374,9 @@ export function luaSet(
1313
1374
  const k = toNumKey(normKey);
1314
1375
  const jsVal = luaValueToJS(value, sf);
1315
1376
  if (isPromise(jsVal)) {
1316
- return (jsVal as Promise<any>).then(
1317
- (v) => {
1318
- (obj as Record<string | number, any>)[k] = v;
1319
- },
1320
- );
1377
+ return (jsVal as Promise<any>).then((v) => {
1378
+ (obj as Record<string | number, any>)[k] = v;
1379
+ });
1321
1380
  }
1322
1381
  (obj as Record<string | number, any>)[k] = jsVal;
1323
1382
  }
@@ -1492,16 +1551,18 @@ export function luaCall(
1492
1551
 
1493
1552
  export function luaEquals(a: any, b: any): boolean {
1494
1553
  // Normalize nil variants (null, undefined, SQL NULL) to null
1495
- const an = (a === null || a === undefined || isSqlNull(a))
1496
- ? null
1497
- : isTaggedFloat(a)
1498
- ? a.value
1499
- : a;
1500
- const bn = (b === null || b === undefined || isSqlNull(b))
1501
- ? null
1502
- : isTaggedFloat(b)
1503
- ? b.value
1504
- : b;
1554
+ const an =
1555
+ a === null || a === undefined || isSqlNull(a)
1556
+ ? null
1557
+ : isTaggedFloat(a)
1558
+ ? a.value
1559
+ : a;
1560
+ const bn =
1561
+ b === null || b === undefined || isSqlNull(b)
1562
+ ? null
1563
+ : isTaggedFloat(b)
1564
+ ? b.value
1565
+ : b;
1505
1566
  return an === bn;
1506
1567
  }
1507
1568
 
@@ -2,9 +2,14 @@ import { LuaBuiltinFunction, LuaTable } from "../runtime.ts";
2
2
  import { hashSHA256 } from "../../../plug-api/lib/crypto.ts";
3
3
 
4
4
  export const cryptoApi = new LuaTable({
5
- sha256: new LuaBuiltinFunction(
6
- (_sf, s: string | Uint8Array): Promise<string> => {
5
+ sha256: new LuaBuiltinFunction({
6
+ callback: (_sf, s: string | Uint8Array): Promise<string> => {
7
7
  return hashSHA256(s);
8
8
  },
9
- ),
9
+ description: "Computes the SHA-256 digest of a string or byte buffer.",
10
+ parameters: [
11
+ { name: "data", type: "string|bytes", description: "Data to hash." },
12
+ ],
13
+ returns: [{ type: "string", description: "Hexadecimal SHA-256 digest." }],
14
+ }),
10
15
  });
@@ -2,18 +2,36 @@ import { LuaBuiltinFunction, LuaTable } from "../runtime.ts";
2
2
  import { base64Decode, base64Encode } from "../../../plug-api/lib/crypto.ts";
3
3
 
4
4
  export const encodingApi = new LuaTable({
5
- base64Encode: new LuaBuiltinFunction(
6
- (_sf, s: string | Uint8Array): string => {
5
+ base64Encode: new LuaBuiltinFunction({
6
+ callback: (_sf, s: string | Uint8Array): string => {
7
7
  return base64Encode(s);
8
8
  },
9
- ),
10
- base64Decode: new LuaBuiltinFunction((_sf, s: string): Uint8Array => {
11
- return base64Decode(s);
9
+ description: "Encodes a string or byte buffer as Base64.",
10
+ parameters: [{ name: "data", type: "string|bytes" }],
11
+ returns: [{ type: "string", description: "Base64-encoded data." }],
12
12
  }),
13
- utf8Encode: new LuaBuiltinFunction((_sf, s: string): Uint8Array => {
14
- return new TextEncoder().encode(s);
13
+ base64Decode: new LuaBuiltinFunction({
14
+ callback: (_sf, s: string): Uint8Array => {
15
+ return base64Decode(s);
16
+ },
17
+ description: "Decodes a Base64 string into a byte buffer.",
18
+ parameters: [{ name: "encoded", type: "string" }],
19
+ returns: [{ type: "bytes", description: "Decoded bytes." }],
20
+ }),
21
+ utf8Encode: new LuaBuiltinFunction({
22
+ callback: (_sf, s: string): Uint8Array => {
23
+ return new TextEncoder().encode(s);
24
+ },
25
+ description: "Encodes a UTF-8 string into a byte buffer.",
26
+ parameters: [{ name: "value", type: "string" }],
27
+ returns: [{ type: "bytes", description: "UTF-8 encoded bytes." }],
15
28
  }),
16
- utf8Decode: new LuaBuiltinFunction((_sf, data: Uint8Array): string => {
17
- return new TextDecoder().decode(data);
29
+ utf8Decode: new LuaBuiltinFunction({
30
+ callback: (_sf, data: Uint8Array): string => {
31
+ return new TextDecoder().decode(data);
32
+ },
33
+ description: "Decodes a UTF-8 byte buffer into a string.",
34
+ parameters: [{ name: "data", type: "bytes" }],
35
+ returns: [{ type: "string", description: "Decoded text." }],
18
36
  }),
19
37
  });
@@ -4,6 +4,7 @@ import {
4
4
  LuaTable,
5
5
  luaValueToJS,
6
6
  } from "../runtime.ts";
7
+ import { fsEndpoint } from "../../spaces/constants.ts";
7
8
 
8
9
  export const jsApi = new LuaTable({
9
10
  /**
@@ -12,57 +13,171 @@ export const jsApi = new LuaTable({
12
13
  * @param args - The arguments to pass to the constructor.
13
14
  * @returns The new instance.
14
15
  */
15
- new: new LuaBuiltinFunction((sf, constructorFn: any, ...args) => {
16
- return new constructorFn(...args.map((v) => luaValueToJS(v, sf)));
16
+ new: new LuaBuiltinFunction({
17
+ callback: (sf, constructorFn: any, ...args) => {
18
+ return new constructorFn(...args.map((v) => luaValueToJS(v, sf)));
19
+ },
20
+ description: "Creates an instance of a JavaScript class.",
21
+ signatures: ["js.new(constructor, ...): userdata"],
22
+ parameters: [
23
+ {
24
+ name: "constructor",
25
+ type: "userdata",
26
+ description: "JavaScript constructor function.",
27
+ },
28
+ {
29
+ name: "...",
30
+ description: "Constructor arguments converted to JavaScript values.",
31
+ },
32
+ ],
33
+ returns: [{ type: "userdata", description: "New JavaScript instance." }],
34
+ examples: [{ code: 'local value = js.new(js.window.Date, "2024-03-14")' }],
17
35
  }),
18
36
  /**
19
37
  * Imports a JavaScript module.
20
38
  * @param url - The URL of the module to import.
21
39
  * @returns The imported module.
22
40
  */
23
- import: new LuaBuiltinFunction(async (_sf, url) => {
24
- let m = await import(url);
25
- // Unwrap default if it exists
26
- if (Object.keys(m).length === 1 && m.default) {
27
- m = m.default;
28
- }
29
- return m;
41
+ import: new LuaBuiltinFunction({
42
+ callback: async (_sf, url) => {
43
+ let m = await import(url);
44
+ // Unwrap default if it exists
45
+ if (Object.keys(m).length === 1 && m.default) {
46
+ m = m.default;
47
+ }
48
+ return m;
49
+ },
50
+ description: "Dynamically imports a JavaScript module from a URL.",
51
+ parameters: [{ name: "url", type: "string", description: "Module URL." }],
52
+ returns: [
53
+ {
54
+ type: "userdata",
55
+ description: "Imported module, with a sole default export unwrapped.",
56
+ },
57
+ ],
58
+ examples: [
59
+ { code: 'local lib = js.import("https://esm.sh/lodash@4.17.21")' },
60
+ ],
30
61
  }),
31
- eachIterable: new LuaBuiltinFunction((_sf, val) => {
32
- const iterator = val[Symbol.asyncIterator]();
33
- return async () => {
34
- const result = await iterator.next();
35
- if (result.done) {
36
- return;
62
+ /**
63
+ * Like `js.import`, but takes a path to a file in the current space (e.g.
64
+ * "Library/foo/bar.js") and resolves it to its full same-origin `/.fs` URL
65
+ * before importing.
66
+ * @param path - Space-relative path to the JS module (leading "/" optional).
67
+ * @returns The imported module (with a sole `default` export unwrapped).
68
+ */
69
+ importFromSpace: new LuaBuiltinFunction({
70
+ callback: async (_sf, path: string) => {
71
+ const base = document.baseURI.replace(/\/*$/, "/");
72
+ const rel = String(path).replace(/^\/+/, "");
73
+ let m = await import(`${base}${fsEndpoint.slice(1)}/${rel}`);
74
+ // Unwrap default if it exists (same contract as `js.import`).
75
+ if (Object.keys(m).length === 1 && m.default) {
76
+ m = m.default;
37
77
  }
38
- return result.value;
39
- };
78
+ return m;
79
+ },
80
+ description:
81
+ "Imports a JavaScript module from a file in the current space.",
82
+ parameters: [
83
+ {
84
+ name: "path",
85
+ type: "string",
86
+ description:
87
+ "Space-relative module path, with an optional leading slash.",
88
+ },
89
+ ],
90
+ returns: [
91
+ {
92
+ type: "userdata",
93
+ description: "Imported module, with a sole default export unwrapped.",
94
+ },
95
+ ],
96
+ examples: [
97
+ { code: 'local acme = js.importFromSpace("Library/acme/acme.js")' },
98
+ ],
99
+ }),
100
+ eachIterable: new LuaBuiltinFunction({
101
+ callback: (_sf, val) => {
102
+ const iterator = val[Symbol.asyncIterator]();
103
+ return async () => {
104
+ const result = await iterator.next();
105
+ if (result.done) {
106
+ return;
107
+ }
108
+ return result.value;
109
+ };
110
+ },
111
+ description: "Creates a Lua iterator over a JavaScript async iterable.",
112
+ parameters: [
113
+ {
114
+ name: "iterable",
115
+ type: "userdata",
116
+ description: "JavaScript async iterable.",
117
+ },
118
+ ],
119
+ returns: [
120
+ {
121
+ type: "function",
122
+ description: "Iterator yielding successive JavaScript values.",
123
+ },
124
+ ],
125
+ examples: [
126
+ {
127
+ code: "for value in js.eachIterable(someJsAsyncIterable) do\n print(value)\nend",
128
+ },
129
+ ],
40
130
  }),
41
131
  /**
42
132
  * Converts a JavaScript value to a Lua value.
43
133
  * @param val - The JavaScript value to convert.
44
134
  * @returns The Lua value.
45
135
  */
46
- tolua: new LuaBuiltinFunction((_sf, val) => jsToLuaValue(val)),
136
+ tolua: new LuaBuiltinFunction({
137
+ callback: (_sf, val) => jsToLuaValue(val),
138
+ description: "Converts a JavaScript value to its Lua representation.",
139
+ parameters: [
140
+ { name: "value", description: "JavaScript value to convert." },
141
+ ],
142
+ returns: [{ description: "Converted Lua value." }],
143
+ examples: [{ code: "local luaTable = js.tolua(jsArray)" }],
144
+ }),
47
145
  /**
48
146
  * Converts a Lua value to a JavaScript value.
49
147
  * @param val - The Lua value to convert.
50
148
  * @returns The JavaScript value.
51
149
  */
52
- tojs: new LuaBuiltinFunction((sf, val) => luaValueToJS(val, sf)),
150
+ tojs: new LuaBuiltinFunction({
151
+ callback: (sf, val) => luaValueToJS(val, sf),
152
+ description: "Converts a Lua value to its JavaScript representation.",
153
+ parameters: [{ name: "value", description: "Lua value to convert." }],
154
+ returns: [{ description: "Converted JavaScript value." }],
155
+ examples: [{ code: "local jsArray = js.tojs({1, 2, 3})" }],
156
+ }),
53
157
  /**
54
158
  * Logs a message to the console.
55
159
  * @param args - The arguments to log.
56
160
  */
57
- log: new LuaBuiltinFunction((_sf, ...args) => {
58
- console.log(...args);
161
+ log: new LuaBuiltinFunction({
162
+ callback: (_sf, ...args) => {
163
+ console.log(...args);
164
+ },
165
+ description: "Logs values to the JavaScript console.",
166
+ parameters: [{ name: "...", description: "Values to log." }],
167
+ examples: [{ code: 'js.log("User data:", {name = "Ada"})' }],
59
168
  }),
60
169
  /**
61
170
  * Converts a Lua value to a JSON string.
62
171
  * @param val - The Lua value to convert.
63
172
  * @returns The JSON string.
64
173
  */
65
- stringify: new LuaBuiltinFunction((_sf, val) => JSON.stringify(val)),
174
+ stringify: new LuaBuiltinFunction({
175
+ callback: (_sf, val) => JSON.stringify(val),
176
+ description: "Serializes a value as JSON using JavaScript semantics.",
177
+ parameters: [{ name: "value", description: "Value to serialize." }],
178
+ returns: [{ type: "string", description: "JSON representation." }],
179
+ examples: [{ code: "print(js.stringify({1, 2, 3})) -- [1,2,3]" }],
180
+ }),
66
181
 
67
182
  // Expose the global window object
68
183
  window: globalThis,
@@ -5,7 +5,7 @@ import {
5
5
  type LuaStackFrame,
6
6
  type LuaValue,
7
7
  } from "../runtime.ts";
8
- import { parse } from "../parse.ts";
8
+ import { parseBlock } from "../parse.ts";
9
9
  import { evalStatement } from "../eval.ts";
10
10
 
11
11
  // Returns a function (callable chunk) or (nil, "error message") pair.
@@ -13,7 +13,7 @@ export function luaLoad(code: LuaValue, sf: LuaStackFrame): LuaValue {
13
13
  const s = typeof code === "string" ? code : String(code);
14
14
 
15
15
  try {
16
- const block = parse(s, sf.astCtx || {});
16
+ const block = parseBlock(s, sf.astCtx || {});
17
17
  const globalEnvMaybe = sf.threadLocal.get("_GLOBAL");
18
18
 
19
19
  // Be vocal when no _GLOBAL is set
@@ -24,22 +24,31 @@ export function luaLoad(code: LuaValue, sf: LuaStackFrame): LuaValue {
24
24
 
25
25
  const globalEnv: LuaEnv = globalEnvMaybe as LuaEnv;
26
26
 
27
- const runner = new LuaBuiltinFunction(async (innerSf: LuaStackFrame) => {
28
- const res = await evalStatement(block, globalEnv, innerSf, true);
29
- if (res === undefined) {
30
- return null;
31
- } else {
32
- if (res && typeof res === "object" && (res as any).ctrl === "return") {
33
- return new LuaMultiRes((res as any).values);
27
+ const runner = new LuaBuiltinFunction({
28
+ callback: async (innerSf: LuaStackFrame) => {
29
+ const res = await evalStatement(block, globalEnv, innerSf, true);
30
+ if (res === undefined) {
31
+ return null;
32
+ } else {
33
+ if (
34
+ res &&
35
+ typeof res === "object" &&
36
+ (res as any).ctrl === "return"
37
+ ) {
38
+ return new LuaMultiRes((res as any).values);
39
+ }
40
+ if (res && typeof res === "object" && (res as any).ctrl === "break") {
41
+ throw new Error("break outside loop");
42
+ }
43
+ if (res && typeof res === "object" && (res as any).ctrl === "goto") {
44
+ throw new Error("unexpected goto signal");
45
+ }
46
+ return null;
34
47
  }
35
- if (res && typeof res === "object" && (res as any).ctrl === "break") {
36
- throw new Error("break outside loop");
37
- }
38
- if (res && typeof res === "object" && (res as any).ctrl === "goto") {
39
- throw new Error("unexpected goto signal");
40
- }
41
- return null;
42
- }
48
+ },
49
+ description: "Executes the Lua chunk compiled by `load`.",
50
+ signatures: ["function(...)"],
51
+ returns: [{ description: "Values returned by the compiled chunk." }],
43
52
  });
44
53
 
45
54
  return runner;