@silverbulletmd/silverbullet 2.5.3 → 2.6.1

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 (90) hide show
  1. package/README.md +4 -5
  2. package/client/asset_bundle/bundle.ts +3 -9
  3. package/client/data/datastore.ts +4 -5
  4. package/client/markdown_parser/constants.ts +3 -2
  5. package/client/plugos/hooks/code_widget.ts +3 -5
  6. package/client/plugos/hooks/command.ts +8 -8
  7. package/client/plugos/hooks/document_editor.ts +10 -12
  8. package/client/plugos/hooks/event.ts +33 -36
  9. package/client/plugos/hooks/mq.ts +17 -17
  10. package/client/plugos/hooks/plug_namespace.ts +3 -5
  11. package/client/plugos/hooks/slash_command.ts +12 -27
  12. package/client/plugos/hooks/syscall.ts +3 -3
  13. package/client/plugos/manifest_cache.ts +22 -15
  14. package/client/plugos/plug.ts +2 -5
  15. package/client/plugos/plug_compile.ts +67 -65
  16. package/client/plugos/protocol.ts +28 -28
  17. package/client/plugos/proxy_fetch.ts +7 -6
  18. package/client/plugos/sandboxes/worker_sandbox.ts +16 -15
  19. package/client/plugos/syscalls/asset.ts +1 -3
  20. package/client/plugos/syscalls/code_widget.ts +1 -3
  21. package/client/plugos/syscalls/config.ts +1 -5
  22. package/client/plugos/syscalls/datastore.ts +1 -1
  23. package/client/plugos/syscalls/editor.ts +63 -60
  24. package/client/plugos/syscalls/event.ts +9 -12
  25. package/client/plugos/syscalls/fetch.ts +30 -22
  26. package/client/plugos/syscalls/index.ts +10 -1
  27. package/client/plugos/syscalls/jsonschema.ts +72 -32
  28. package/client/plugos/syscalls/language.ts +9 -5
  29. package/client/plugos/syscalls/markdown.ts +29 -7
  30. package/client/plugos/syscalls/mq.ts +3 -11
  31. package/client/plugos/syscalls/service_registry.ts +1 -4
  32. package/client/plugos/syscalls/shell.ts +2 -5
  33. package/client/plugos/syscalls/sync.ts +69 -60
  34. package/client/plugos/syscalls/system.ts +2 -3
  35. package/client/plugos/system.ts +4 -10
  36. package/client/plugos/worker_runtime.ts +4 -3
  37. package/client/space_lua/aggregates.ts +632 -59
  38. package/client/space_lua/ast.ts +21 -9
  39. package/client/space_lua/ast_narrow.ts +4 -2
  40. package/client/space_lua/eval.ts +842 -536
  41. package/client/space_lua/labels.ts +6 -11
  42. package/client/space_lua/liq_null.ts +6 -0
  43. package/client/space_lua/numeric.ts +5 -8
  44. package/client/space_lua/parse.ts +290 -169
  45. package/client/space_lua/query_collection.ts +213 -149
  46. package/client/space_lua/render_lua_markdown.ts +369 -0
  47. package/client/space_lua/rp.ts +5 -4
  48. package/client/space_lua/runtime.ts +245 -142
  49. package/client/space_lua/stdlib/format.ts +34 -20
  50. package/client/space_lua/stdlib/js.ts +3 -7
  51. package/client/space_lua/stdlib/load.ts +1 -3
  52. package/client/space_lua/stdlib/math.ts +15 -14
  53. package/client/space_lua/stdlib/net.ts +25 -15
  54. package/client/space_lua/stdlib/os.ts +76 -85
  55. package/client/space_lua/stdlib/pattern.ts +28 -35
  56. package/client/space_lua/stdlib/prng.ts +15 -12
  57. package/client/space_lua/stdlib/space_lua.ts +16 -17
  58. package/client/space_lua/stdlib/string.ts +7 -17
  59. package/client/space_lua/stdlib/string_pack.ts +23 -19
  60. package/client/space_lua/stdlib/table.ts +5 -9
  61. package/client/space_lua/stdlib.ts +20 -30
  62. package/client/space_lua/tonumber.ts +79 -40
  63. package/client/space_lua/util.ts +14 -10
  64. package/dist/plug-compile.js +44 -41
  65. package/package.json +24 -22
  66. package/plug-api/lib/async.ts +19 -6
  67. package/plug-api/lib/crypto.ts +5 -6
  68. package/plug-api/lib/dates.ts +15 -7
  69. package/plug-api/lib/json.ts +10 -4
  70. package/plug-api/lib/ref.ts +18 -18
  71. package/plug-api/lib/resolve.ts +7 -11
  72. package/plug-api/lib/tags.ts +13 -4
  73. package/plug-api/lib/transclusion.ts +6 -17
  74. package/plug-api/lib/tree.ts +115 -43
  75. package/plug-api/lib/yaml.ts +25 -15
  76. package/plug-api/syscalls/asset.ts +1 -1
  77. package/plug-api/syscalls/config.ts +1 -4
  78. package/plug-api/syscalls/editor.ts +14 -14
  79. package/plug-api/syscalls/jsonschema.ts +1 -3
  80. package/plug-api/syscalls/lua.ts +3 -9
  81. package/plug-api/syscalls/mq.ts +1 -4
  82. package/plug-api/syscalls/shell.ts +4 -1
  83. package/plug-api/syscalls/space.ts +3 -10
  84. package/plug-api/syscalls/system.ts +1 -4
  85. package/plug-api/syscalls/yaml.ts +2 -6
  86. package/plug-api/types/client.ts +16 -1
  87. package/plug-api/types/event.ts +6 -4
  88. package/plug-api/types/manifest.ts +8 -9
  89. package/plugs/builtin_plugs.ts +2 -2
  90. package/dist/worker_runtime_bundle.js +0 -233
@@ -54,7 +54,7 @@ function toBytes(s: string): Uint8Array {
54
54
  const len = s.length;
55
55
  const arr = new Uint8Array(len);
56
56
  for (let i = 0; i < len; i++) {
57
- arr[i] = s.charCodeAt(i) & 0xFF;
57
+ arr[i] = s.charCodeAt(i) & 0xff;
58
58
  }
59
59
  return arr;
60
60
  }
@@ -79,8 +79,11 @@ function matchClass(c: number, cl: number): boolean {
79
79
  res = c >= 97 && c <= 122;
80
80
  break;
81
81
  case 112: // 'p'
82
- res = (c >= 33 && c <= 47) || (c >= 58 && c <= 64) ||
83
- (c >= 91 && c <= 96) || (c >= 123 && c <= 126);
82
+ res =
83
+ (c >= 33 && c <= 47) ||
84
+ (c >= 58 && c <= 64) ||
85
+ (c >= 91 && c <= 96) ||
86
+ (c >= 123 && c <= 126);
84
87
  break;
85
88
  case 115: // 's'
86
89
  res = c === 32 || (c >= 9 && c <= 13);
@@ -89,12 +92,12 @@ function matchClass(c: number, cl: number): boolean {
89
92
  res = c >= 65 && c <= 90;
90
93
  break;
91
94
  case 119: // 'w'
92
- res = (c >= 65 && c <= 90) || (c >= 97 && c <= 122) ||
93
- (c >= 48 && c <= 57);
95
+ res =
96
+ (c >= 65 && c <= 90) || (c >= 97 && c <= 122) || (c >= 48 && c <= 57);
94
97
  break;
95
98
  case 120: // 'x'
96
- res = (c >= 48 && c <= 57) || (c >= 65 && c <= 70) ||
97
- (c >= 97 && c <= 102);
99
+ res =
100
+ (c >= 48 && c <= 57) || (c >= 65 && c <= 70) || (c >= 97 && c <= 102);
98
101
  break;
99
102
  case 122: // 'z'
100
103
  res = c === 0;
@@ -102,7 +105,7 @@ function matchClass(c: number, cl: number): boolean {
102
105
  default:
103
106
  return cl === c;
104
107
  }
105
- return (cl >= 97 && cl <= 122) ? res : !res;
108
+ return cl >= 97 && cl <= 122 ? res : !res;
106
109
  }
107
110
 
108
111
  function classEnd(p: Uint8Array, plen: number, pi: number): number {
@@ -150,9 +153,7 @@ function matchBracketClass(
150
153
  if (pch === CH_ESC) {
151
154
  pi++;
152
155
  if (matchClass(c, p[pi])) return sig;
153
- } else if (
154
- pi + 2 < ec && p[pi + 1] === CH_DASH
155
- ) {
156
+ } else if (pi + 2 < ec && p[pi + 1] === CH_DASH) {
156
157
  pi += 2;
157
158
  if (pch <= c && c <= p[pi]) return sig;
158
159
  } else if (pch === c) {
@@ -182,11 +183,7 @@ function singleMatch(
182
183
  return pch === c;
183
184
  }
184
185
 
185
- function matchBalance(
186
- ms: MatchState,
187
- si: number,
188
- pi: number,
189
- ): number {
186
+ function matchBalance(ms: MatchState, si: number, pi: number): number {
190
187
  if (pi >= ms.plen - 1) {
191
188
  throw new Error("malformed pattern (missing arguments to '%b')");
192
189
  }
@@ -209,12 +206,7 @@ function matchBalance(
209
206
  return -1;
210
207
  }
211
208
 
212
- function maxExpand(
213
- ms: MatchState,
214
- si: number,
215
- pi: number,
216
- ep: number,
217
- ): number {
209
+ function maxExpand(ms: MatchState, si: number, pi: number, ep: number): number {
218
210
  let i = 0;
219
211
  while (singleMatch(ms, si + i, pi, ep)) i++;
220
212
  while (i >= 0) {
@@ -225,12 +217,7 @@ function maxExpand(
225
217
  return -1;
226
218
  }
227
219
 
228
- function minExpand(
229
- ms: MatchState,
230
- si: number,
231
- pi: number,
232
- ep: number,
233
- ): number {
220
+ function minExpand(ms: MatchState, si: number, pi: number, ep: number): number {
234
221
  for (;;) {
235
222
  const res = match(ms, si, ep + 1);
236
223
  if (res >= 0) return res;
@@ -326,7 +313,8 @@ function match(ms: MatchState, si: number, pi: number): number {
326
313
  }
327
314
  if (pch === CH_ESC && pi + 1 < ms.plen) {
328
315
  const next = ms.p[pi + 1];
329
- if (next === 98) { // 'b'
316
+ if (next === 98) {
317
+ // 'b'
330
318
  si = matchBalance(ms, si, pi + 2);
331
319
  if (si >= 0) {
332
320
  pi += 4;
@@ -335,7 +323,8 @@ function match(ms: MatchState, si: number, pi: number): number {
335
323
  ms.matchdepth++;
336
324
  return -1;
337
325
  }
338
- if (next === 102) { // 'f'
326
+ if (next === 102) {
327
+ // 'f'
339
328
  pi += 2;
340
329
  if (pi >= ms.plen || ms.p[pi] !== CH_LBRACKET) {
341
330
  throw new Error("missing '[' after '%f' in pattern");
@@ -370,7 +359,9 @@ function match(ms: MatchState, si: number, pi: number): number {
370
359
  if (ep < ms.plen) {
371
360
  const suffix = ms.p[ep];
372
361
  if (
373
- suffix === CH_STAR || suffix === CH_QUESTION || suffix === CH_DASH
362
+ suffix === CH_STAR ||
363
+ suffix === CH_QUESTION ||
364
+ suffix === CH_DASH
374
365
  ) {
375
366
  pi = ep + 1;
376
367
  continue;
@@ -614,10 +605,12 @@ function expandReplacementString(
614
605
  } else if (rc === CH_0) {
615
606
  parts.push(ms.src.substring(matchStart, matchEnd));
616
607
  } else if (rc >= 49 && rc <= CH_9) {
617
- parts.push(getRawCaptureString(
618
- ms,
619
- getOneRawCapture(ms, rc - 49, matchStart, matchEnd),
620
- ));
608
+ parts.push(
609
+ getRawCaptureString(
610
+ ms,
611
+ getOneRawCapture(ms, rc - 49, matchStart, matchEnd),
612
+ ),
613
+ );
621
614
  } else {
622
615
  throw new Error("invalid use of '%' in replacement string");
623
616
  }
@@ -10,7 +10,7 @@ export class LuaPRNG {
10
10
 
11
11
  private rotl(x: bigint, k: number): bigint {
12
12
  k = k & 63;
13
- return ((x << BigInt(k)) | (x >> BigInt(64 - k))) & 0xFFFFFFFFFFFFFFFFn;
13
+ return ((x << BigInt(k)) | (x >> BigInt(64 - k))) & 0xffffffffffffffffn;
14
14
  }
15
15
 
16
16
  private nextrand(): bigint {
@@ -20,10 +20,11 @@ export class LuaPRNG {
20
20
  const s2 = s[2];
21
21
  const s3 = s[3];
22
22
 
23
- const res = this.rotl((s1 * 5n) & 0xFFFFFFFFFFFFFFFFn, 7) * 9n &
24
- 0xFFFFFFFFFFFFFFFFn;
23
+ const res =
24
+ (this.rotl((s1 * 5n) & 0xffffffffffffffffn, 7) * 9n) &
25
+ 0xffffffffffffffffn;
25
26
 
26
- const t = (s1 << 17n) & 0xFFFFFFFFFFFFFFFFn;
27
+ const t = (s1 << 17n) & 0xffffffffffffffffn;
27
28
  s[2] = s2 ^ s0;
28
29
  s[3] = s3 ^ s1;
29
30
  s[1] = s1 ^ s[2];
@@ -35,17 +36,17 @@ export class LuaPRNG {
35
36
  }
36
37
 
37
38
  public setSeed(seed1: bigint, seed2: bigint = 0n): [bigint, bigint] {
38
- const MASK = 0xFFFFFFFFFFFFFFFFn;
39
+ const MASK = 0xffffffffffffffffn;
39
40
  const s = this.state;
40
41
 
41
42
  const sm64 = (x: bigint): bigint => {
42
- x = (x ^ (x >> 30n)) * 0xBF58476D1CE4E5B9n & MASK;
43
- x = (x ^ (x >> 27n)) * 0x94D049BB133111EBn & MASK;
43
+ x = ((x ^ (x >> 30n)) * 0xbf58476d1ce4e5b9n) & MASK;
44
+ x = ((x ^ (x >> 27n)) * 0x94d049bb133111ebn) & MASK;
44
45
  return (x ^ (x >> 31n)) & MASK;
45
46
  };
46
47
 
47
48
  s[0] = sm64(seed1 & MASK);
48
- s[1] = sm64((seed1 & MASK) | 0xFFn);
49
+ s[1] = sm64((seed1 & MASK) | 0xffn);
49
50
  s[2] = sm64(seed2 & MASK);
50
51
  s[3] = sm64(0n);
51
52
 
@@ -101,9 +102,8 @@ export class LuaPRNG {
101
102
  if (arg2 === undefined) {
102
103
  if (arg1 === 0) {
103
104
  // Raw 64-bit as signed bigint
104
- const signed = rv > 0x7FFFFFFFFFFFFFFFn
105
- ? rv - 0x10000000000000000n
106
- : rv;
105
+ const signed =
106
+ rv > 0x7fffffffffffffffn ? rv - 0x10000000000000000n : rv;
107
107
  return signed;
108
108
  }
109
109
  if (arg1 < 1) {
@@ -133,7 +133,10 @@ export class LuaPRNG {
133
133
  "bad argument #1 to 'randomseed' (number has no integer representation)",
134
134
  );
135
135
  }
136
- if (arg2 !== undefined && (!Number.isFinite(arg2) || !Number.isInteger(arg2))) {
136
+ if (
137
+ arg2 !== undefined &&
138
+ (!Number.isFinite(arg2) || !Number.isInteger(arg2))
139
+ ) {
137
140
  throw new Error(
138
141
  "bad argument #2 to 'randomseed' (number has no integer representation)",
139
142
  );
@@ -2,6 +2,7 @@ import { parseExpressionString } from "../parse.ts";
2
2
  import type { LuaExpression } from "../ast.ts";
3
3
  import { evalExpression } from "../eval.ts";
4
4
  import {
5
+ jsToLuaValue,
5
6
  LuaBuiltinFunction,
6
7
  LuaEnv,
7
8
  LuaRuntimeError,
@@ -11,6 +12,7 @@ import {
11
12
  luaValueToJS,
12
13
  singleResult,
13
14
  } from "../runtime.ts";
15
+ import { isSqlNull } from "../liq_null.ts";
14
16
 
15
17
  /**
16
18
  * These are Space Lua specific functions that are available to all scripts, but are not part of the standard Lua language.
@@ -31,7 +33,8 @@ function createAugmentedEnv(
31
33
  if (envAugmentation) {
32
34
  env.setLocal("_", envAugmentation);
33
35
  for (const key of envAugmentation.keys()) {
34
- env.setLocal(key, envAugmentation.rawGet(key));
36
+ const v = envAugmentation.rawGet(key);
37
+ env.setLocal(key, isSqlNull(v) ? null : v);
35
38
  }
36
39
  }
37
40
  return env;
@@ -89,10 +92,7 @@ export async function interpolateLuaString(
89
92
  const luaResult = singleResult(await evalExpression(parsedExpr, env, sf));
90
93
  result += await luaToString(luaResult);
91
94
  } catch (e: any) {
92
- throw new LuaRuntimeError(
93
- `Error evaluating "${expr}": ${e.message}`,
94
- sf,
95
- );
95
+ throw new LuaRuntimeError(`Error evaluating "${expr}": ${e.message}`, sf);
96
96
  }
97
97
 
98
98
  currentIndex = endIndex + 1;
@@ -109,11 +109,9 @@ export const spaceluaApi = new LuaTable({
109
109
  * @param luaExpression - The lua expression to parse.
110
110
  * @returns The parsed expression.
111
111
  */
112
- parseExpression: new LuaBuiltinFunction(
113
- (_sf, luaExpression: string) => {
114
- return parseExpressionString(luaExpression);
115
- },
116
- ),
112
+ parseExpression: new LuaBuiltinFunction((_sf, luaExpression: string) => {
113
+ return parseExpressionString(luaExpression);
114
+ }),
117
115
  /**
118
116
  * Evaluates a parsed lua expression and returns the result.
119
117
  *
@@ -132,17 +130,18 @@ export const spaceluaApi = new LuaTable({
132
130
  * Interpolates a string with lua expressions and returns the result.
133
131
  */
134
132
  interpolate: new LuaBuiltinFunction(
135
- (sf, template: string, envAugmentation?: LuaTable) => {
133
+ (sf, template: string, envAugmentation?: LuaTable | any) => {
134
+ if (envAugmentation && !(envAugmentation instanceof LuaTable)) {
135
+ envAugmentation = jsToLuaValue(envAugmentation);
136
+ }
136
137
  return interpolateLuaString(sf, template, envAugmentation);
137
138
  },
138
139
  ),
139
140
  /**
140
141
  * Returns your SilverBullet instance's base URL
141
142
  */
142
- baseUrl: new LuaBuiltinFunction(
143
- () => {
144
- //NOTE: Removing trailing slash to stay compatible with original code: `location.protocol + "//" + location.host;`
145
- return document.baseURI.replace(/\/*$/, "");
146
- },
147
- ),
143
+ baseUrl: new LuaBuiltinFunction(() => {
144
+ //NOTE: Removing trailing slash to stay compatible with original code: `location.protocol + "//" + location.host;`
145
+ return document.baseURI.replace(/\/*$/, "");
146
+ }),
148
147
  });
@@ -24,9 +24,7 @@ function capturesToLua(caps: CaptureResult[]): any {
24
24
  const c = caps[0];
25
25
  return "s" in c ? c.s : c.position;
26
26
  }
27
- return new LuaMultiRes(
28
- caps.map((c) => ("s" in c ? c.s : c.position)),
29
- );
27
+ return new LuaMultiRes(caps.map((c) => ("s" in c ? c.s : c.position)));
30
28
  }
31
29
 
32
30
  export const stringApi = new LuaTable({
@@ -72,13 +70,7 @@ export const stringApi = new LuaTable({
72
70
  },
73
71
  ),
74
72
  gsub: new LuaBuiltinFunction(
75
- async (
76
- sf,
77
- s: string,
78
- pattern: string,
79
- repl: any,
80
- n?: number,
81
- ) => {
73
+ async (sf, s: string, pattern: string, repl: any, n?: number) => {
82
74
  const callbacks: GsubCallbacks = {};
83
75
  if (typeof repl === "string") {
84
76
  callbacks.replString = repl;
@@ -121,13 +113,11 @@ export const stringApi = new LuaTable({
121
113
  upper: new LuaBuiltinFunction((_sf, s: string) => {
122
114
  return luaToString(s.toUpperCase());
123
115
  }),
124
- match: new LuaBuiltinFunction(
125
- (_sf, s: string, pattern: string, init = 1) => {
126
- const caps = patternMatch(s, pattern, init);
127
- if (!caps) return null;
128
- return capturesToLua(caps);
129
- },
130
- ),
116
+ match: new LuaBuiltinFunction((_sf, s: string, pattern: string, init = 1) => {
117
+ const caps = patternMatch(s, pattern, init);
118
+ if (!caps) return null;
119
+ return capturesToLua(caps);
120
+ }),
131
121
  rep: new LuaBuiltinFunction((_sf, s: string, n: number, sep?: string) => {
132
122
  if (n <= 0) return "";
133
123
  sep = sep ?? "";
@@ -73,7 +73,8 @@ function getOption(
73
73
  fmt: string,
74
74
  pos: number,
75
75
  h: Header,
76
- ): [KOption, number, number] { // [opt, size, newPos]
76
+ ): [KOption, number, number] {
77
+ // [opt, size, newPos]
77
78
  const c = fmt[pos++];
78
79
  switch (c) {
79
80
  case "b":
@@ -171,7 +172,10 @@ function getDetails(
171
172
 
172
173
  let ntoalign = 0;
173
174
  if (
174
- opt !== "char" && opt !== "nop" && opt !== "padding" && opt !== "paddalign"
175
+ opt !== "char" &&
176
+ opt !== "nop" &&
177
+ opt !== "padding" &&
178
+ opt !== "paddalign"
175
179
  ) {
176
180
  const realign = Math.min(align, h.maxalign);
177
181
  if (realign > 0) {
@@ -381,7 +385,9 @@ export const strUnpackFn = new LuaBuiltinFunction(
381
385
 
382
386
  if (opt.ntoalign + opt.size > buf.length - pos) {
383
387
  if (
384
- opt.opt !== "nop" && opt.opt !== "paddalign" && opt.opt !== "padding"
388
+ opt.opt !== "nop" &&
389
+ opt.opt !== "paddalign" &&
390
+ opt.opt !== "padding"
385
391
  ) {
386
392
  throw new LuaRuntimeError("data string too short", sf);
387
393
  }
@@ -464,23 +470,21 @@ export const strUnpackFn = new LuaBuiltinFunction(
464
470
  },
465
471
  );
466
472
 
467
- export const strPackSizeFn = new LuaBuiltinFunction(
468
- (_sf, fmt: string) => {
469
- const h = makeHeader();
470
- let totalsize = 0;
471
- let pos = 0;
472
-
473
- while (pos < fmt.length) {
474
- let opt: ParsedOption;
475
- [opt, pos] = getDetails(fmt, pos, h, totalsize);
473
+ export const strPackSizeFn = new LuaBuiltinFunction((_sf, fmt: string) => {
474
+ const h = makeHeader();
475
+ let totalsize = 0;
476
+ let pos = 0;
476
477
 
477
- if (opt.opt === "string" || opt.opt === "zstr") {
478
- throw new LuaRuntimeError("variable-length format", _sf);
479
- }
478
+ while (pos < fmt.length) {
479
+ let opt: ParsedOption;
480
+ [opt, pos] = getDetails(fmt, pos, h, totalsize);
480
481
 
481
- totalsize += opt.ntoalign + opt.size;
482
+ if (opt.opt === "string" || opt.opt === "zstr") {
483
+ throw new LuaRuntimeError("variable-length format", _sf);
482
484
  }
483
485
 
484
- return totalsize;
485
- },
486
- );
486
+ totalsize += opt.ntoalign + opt.size;
487
+ }
488
+
489
+ return totalsize;
490
+ });
@@ -84,9 +84,8 @@ export const tableApi = new LuaTable({
84
84
  return luaFormatNumber(v.value, "float");
85
85
  }
86
86
 
87
- const ty = typeof v === "object" && v instanceof LuaTable
88
- ? "table"
89
- : typeof v;
87
+ const ty =
88
+ typeof v === "object" && v instanceof LuaTable ? "table" : typeof v;
90
89
  throw new LuaRuntimeError(
91
90
  `invalid value (${ty}) at index ${idx} in table for 'concat'`,
92
91
  sf,
@@ -301,10 +300,7 @@ export const tableApi = new LuaTable({
301
300
 
302
301
  const ta = typeof av;
303
302
  const tb = typeof bv;
304
- throw new LuaRuntimeError(
305
- `attempt to compare ${ta} with ${tb}`,
306
- sf,
307
- );
303
+ throw new LuaRuntimeError(`attempt to compare ${ta} with ${tb}`, sf);
308
304
  };
309
305
 
310
306
  const sorted = await asyncQuickSort(values, cmp);
@@ -399,7 +395,7 @@ export const tableApi = new LuaTable({
399
395
  for (let i = 0; i < n; i++) {
400
396
  await luaSet(tbl, i + 1, args[i], sf);
401
397
  }
402
- tbl.rawSet("n", n);
398
+ void tbl.rawSet("n", n);
403
399
  return tbl;
404
400
  }),
405
401
 
@@ -410,7 +406,7 @@ export const tableApi = new LuaTable({
410
406
  */
411
407
  unpack: new LuaBuiltinFunction(
412
408
  async (sf, tbl: LuaTable | any[], i?: number, j?: number) => {
413
- i = (i === undefined || i === null) ? 1 : i;
409
+ i = i === undefined || i === null ? 1 : i;
414
410
  if (j === undefined || j === null) {
415
411
  j = Array.isArray(tbl)
416
412
  ? tbl.length
@@ -35,17 +35,15 @@ import { cryptoApi } from "./stdlib/crypto.ts";
35
35
  import { netApi } from "./stdlib/net.ts";
36
36
  import { isTaggedFloat, makeLuaFloat } from "./numeric.ts";
37
37
  import { isPromise } from "./rp.ts";
38
+ import { isSqlNull } from "./liq_null.ts";
38
39
 
39
40
  const printFunction = new LuaBuiltinFunction(async (_sf, ...args) => {
40
- console.log(
41
- "[Lua]",
42
- ...(await Promise.all(args.map((v) => luaToString(v)))),
43
- );
41
+ console.log("[Lua]", ...(await Promise.all(args.map((v) => luaToString(v)))));
44
42
  });
45
43
 
46
44
  const assertFunction = new LuaBuiltinFunction(
47
45
  async (sf, value: any, message?: string) => {
48
- if (!await value) {
46
+ if (!(await value)) {
49
47
  throw new LuaRuntimeError(`Assertion failed: ${message}`, sf);
50
48
  }
51
49
  },
@@ -143,10 +141,7 @@ const tostringFunction = new LuaBuiltinFunction(
143
141
  const unwrap = (v: any): string => {
144
142
  const s = singleResult(v);
145
143
  if (typeof s !== "string") {
146
- throw new LuaRuntimeError(
147
- "'__tostring' must return a string",
148
- sf,
149
- );
144
+ throw new LuaRuntimeError("'__tostring' must return a string", sf);
150
145
  }
151
146
  return s;
152
147
  };
@@ -203,10 +198,7 @@ async function pcallBoundary(
203
198
  sf: LuaStackFrame,
204
199
  fn: ILuaFunction,
205
200
  args: LuaValue[],
206
- ): Promise<
207
- | { ok: true; values: LuaValue[] }
208
- | { ok: false; message: string }
209
- > {
201
+ ): Promise<{ ok: true; values: LuaValue[] } | { ok: false; message: string }> {
210
202
  const closeStack = luaEnsureCloseStack(sf);
211
203
  const mark = closeStack.length;
212
204
 
@@ -274,11 +266,9 @@ const setmetatableFunction = new LuaBuiltinFunction(
274
266
  },
275
267
  );
276
268
 
277
- const rawlenFunction = new LuaBuiltinFunction(
278
- (_sf, value: LuaValue) => {
279
- return luaLen(value, _sf, true);
280
- },
281
- );
269
+ const rawlenFunction = new LuaBuiltinFunction((_sf, value: LuaValue) => {
270
+ return luaLen(value, _sf, true);
271
+ });
282
272
 
283
273
  const rawsetFunction = new LuaBuiltinFunction(
284
274
  (_sf, table: LuaTable, key: LuaValue, value: LuaValue) => {
@@ -290,7 +280,8 @@ const rawgetFunction = new LuaBuiltinFunction(
290
280
  (_sf, table: any, key: LuaValue) => {
291
281
  const isArray = Array.isArray(table);
292
282
 
293
- const isPlainObj = typeof table === "object" &&
283
+ const isPlainObj =
284
+ typeof table === "object" &&
294
285
  table !== null &&
295
286
  (table as any).constructor === Object;
296
287
 
@@ -320,7 +311,7 @@ const rawgetFunction = new LuaBuiltinFunction(
320
311
 
321
312
  if (isLuaTable(table)) {
322
313
  const v = table.rawGet(key);
323
- return v === undefined ? null : v;
314
+ return v === undefined || isSqlNull(v) ? null : v;
324
315
  }
325
316
 
326
317
  const k = isTaggedFloat(key) ? key.value : key;
@@ -339,13 +330,11 @@ const rawgetFunction = new LuaBuiltinFunction(
339
330
  },
340
331
  );
341
332
 
342
- const rawequalFunction = new LuaBuiltinFunction(
343
- (_sf, a: any, b: any) => {
344
- const av = isTaggedFloat(a) ? a.value : a;
345
- const bv = isTaggedFloat(b) ? b.value : b;
346
- return av === bv;
347
- },
348
- );
333
+ const rawequalFunction = new LuaBuiltinFunction((_sf, a: any, b: any) => {
334
+ const av = isTaggedFloat(a) ? a.value : a;
335
+ const bv = isTaggedFloat(b) ? b.value : b;
336
+ return av === bv;
337
+ });
349
338
 
350
339
  const getmetatableFunction = new LuaBuiltinFunction((_sf, table: LuaTable) => {
351
340
  return (table as any).metatable;
@@ -353,12 +342,12 @@ const getmetatableFunction = new LuaBuiltinFunction((_sf, table: LuaTable) => {
353
342
 
354
343
  const dofileFunction = new LuaBuiltinFunction(async (sf, filename: string) => {
355
344
  const global = sf.threadLocal.get("_GLOBAL") as LuaEnv;
356
- const file = await luaCall(
345
+ const file = (await luaCall(
357
346
  (global.get("space") as any).get("readFile"),
358
347
  [filename],
359
348
  sf.astCtx!,
360
349
  sf,
361
- ) as Uint8Array;
350
+ )) as Uint8Array;
362
351
  const code = new TextDecoder().decode(file);
363
352
  try {
364
353
  const parsedExpr = parse(code);
@@ -434,7 +423,8 @@ const nextFunction = new LuaBuiltinFunction(
434
423
  }
435
424
  // Find index in the key list
436
425
  const idx = keys.indexOf(index);
437
- if (idx === -1) { // Not found
426
+ if (idx === -1) {
427
+ // Not found
438
428
  throw new LuaRuntimeError("invalid key to 'next': key not found", sf);
439
429
  }
440
430
  const key = keys[idx + 1];