@silverbulletmd/silverbullet 2.4.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 (117) hide show
  1. package/LICENSE.md +18 -0
  2. package/README.md +98 -0
  3. package/client/asset_bundle/bundle.ts +95 -0
  4. package/client/data/datastore.ts +85 -0
  5. package/client/data/kv_primitives.ts +25 -0
  6. package/client/markdown_parser/constants.ts +13 -0
  7. package/client/plugos/event.ts +36 -0
  8. package/client/plugos/eventhook.ts +8 -0
  9. package/client/plugos/hooks/code_widget.ts +59 -0
  10. package/client/plugos/hooks/command.ts +104 -0
  11. package/client/plugos/hooks/document_editor.ts +77 -0
  12. package/client/plugos/hooks/event.ts +187 -0
  13. package/client/plugos/hooks/mq.ts +154 -0
  14. package/client/plugos/hooks/plug_namespace.ts +85 -0
  15. package/client/plugos/hooks/slash_command.ts +192 -0
  16. package/client/plugos/hooks/syscall.ts +66 -0
  17. package/client/plugos/manifest_cache.ts +67 -0
  18. package/client/plugos/plug.ts +99 -0
  19. package/client/plugos/plug_compile.ts +202 -0
  20. package/client/plugos/protocol.ts +40 -0
  21. package/client/plugos/proxy_fetch.ts +53 -0
  22. package/client/plugos/sandboxes/deno_worker_sandbox.ts +6 -0
  23. package/client/plugos/sandboxes/sandbox.ts +14 -0
  24. package/client/plugos/sandboxes/web_worker_sandbox.ts +17 -0
  25. package/client/plugos/sandboxes/worker_sandbox.ts +132 -0
  26. package/client/plugos/syscalls/asset.ts +35 -0
  27. package/client/plugos/syscalls/clientStore.ts +21 -0
  28. package/client/plugos/syscalls/client_code_widget.ts +12 -0
  29. package/client/plugos/syscalls/code_widget.ts +24 -0
  30. package/client/plugos/syscalls/config.ts +46 -0
  31. package/client/plugos/syscalls/datastore.ts +89 -0
  32. package/client/plugos/syscalls/editor.ts +673 -0
  33. package/client/plugos/syscalls/event.ts +36 -0
  34. package/client/plugos/syscalls/fetch.ts +128 -0
  35. package/client/plugos/syscalls/index.ts +102 -0
  36. package/client/plugos/syscalls/jsonschema.ts +69 -0
  37. package/client/plugos/syscalls/language.ts +23 -0
  38. package/client/plugos/syscalls/lua.ts +58 -0
  39. package/client/plugos/syscalls/markdown.ts +84 -0
  40. package/client/plugos/syscalls/mq.ts +52 -0
  41. package/client/plugos/syscalls/service_registry.ts +43 -0
  42. package/client/plugos/syscalls/shell.ts +39 -0
  43. package/client/plugos/syscalls/space.ts +139 -0
  44. package/client/plugos/syscalls/sync.ts +77 -0
  45. package/client/plugos/syscalls/system.ts +150 -0
  46. package/client/plugos/system.ts +201 -0
  47. package/client/plugos/types.ts +60 -0
  48. package/client/plugos/util.ts +14 -0
  49. package/client/plugos/worker_runtime.ts +195 -0
  50. package/client/space_lua/ast.ts +328 -0
  51. package/client/space_lua/ast_narrow.ts +81 -0
  52. package/client/space_lua/eval.ts +2478 -0
  53. package/client/space_lua/labels.ts +416 -0
  54. package/client/space_lua/numeric.ts +240 -0
  55. package/client/space_lua/parse.ts +1522 -0
  56. package/client/space_lua/query_collection.ts +232 -0
  57. package/client/space_lua/rp.ts +27 -0
  58. package/client/space_lua/runtime.ts +1702 -0
  59. package/client/space_lua/stdlib/crypto.ts +10 -0
  60. package/client/space_lua/stdlib/encoding.ts +19 -0
  61. package/client/space_lua/stdlib/format.ts +770 -0
  62. package/client/space_lua/stdlib/js.ts +73 -0
  63. package/client/space_lua/stdlib/load.ts +52 -0
  64. package/client/space_lua/stdlib/math.ts +193 -0
  65. package/client/space_lua/stdlib/net.ts +113 -0
  66. package/client/space_lua/stdlib/os.ts +368 -0
  67. package/client/space_lua/stdlib/space_lua.ts +153 -0
  68. package/client/space_lua/stdlib/string.ts +286 -0
  69. package/client/space_lua/stdlib/table.ts +401 -0
  70. package/client/space_lua/stdlib.ts +489 -0
  71. package/client/space_lua/tonumber.ts +501 -0
  72. package/client/space_lua/util.ts +96 -0
  73. package/dist/plug-compile.js +1513 -0
  74. package/package.json +120 -0
  75. package/plug-api/constants.ts +42 -0
  76. package/plug-api/lib/async.ts +162 -0
  77. package/plug-api/lib/crypto.ts +202 -0
  78. package/plug-api/lib/dates.ts +13 -0
  79. package/plug-api/lib/json.ts +136 -0
  80. package/plug-api/lib/limited_map.ts +72 -0
  81. package/plug-api/lib/memory_cache.ts +21 -0
  82. package/plug-api/lib/native_fetch.ts +6 -0
  83. package/plug-api/lib/ref.ts +275 -0
  84. package/plug-api/lib/resolve.ts +90 -0
  85. package/plug-api/lib/tags.ts +15 -0
  86. package/plug-api/lib/transclusion.ts +122 -0
  87. package/plug-api/lib/tree.ts +232 -0
  88. package/plug-api/lib/yaml.ts +284 -0
  89. package/plug-api/syscall.ts +15 -0
  90. package/plug-api/syscalls/asset.ts +36 -0
  91. package/plug-api/syscalls/client_store.ts +33 -0
  92. package/plug-api/syscalls/code_widget.ts +8 -0
  93. package/plug-api/syscalls/config.ts +58 -0
  94. package/plug-api/syscalls/datastore.ts +96 -0
  95. package/plug-api/syscalls/editor.ts +517 -0
  96. package/plug-api/syscalls/event.ts +47 -0
  97. package/plug-api/syscalls/index.ts +77 -0
  98. package/plug-api/syscalls/jsonschema.ts +25 -0
  99. package/plug-api/syscalls/language.ts +23 -0
  100. package/plug-api/syscalls/lua.ts +20 -0
  101. package/plug-api/syscalls/markdown.ts +38 -0
  102. package/plug-api/syscalls/mq.ts +79 -0
  103. package/plug-api/syscalls/shell.ts +14 -0
  104. package/plug-api/syscalls/space.ts +212 -0
  105. package/plug-api/syscalls/sync.ts +28 -0
  106. package/plug-api/syscalls/system.ts +102 -0
  107. package/plug-api/syscalls/yaml.ts +28 -0
  108. package/plug-api/syscalls.ts +21 -0
  109. package/plug-api/system_mock.ts +89 -0
  110. package/plug-api/types/client.ts +116 -0
  111. package/plug-api/types/config.ts +22 -0
  112. package/plug-api/types/datastore.ts +28 -0
  113. package/plug-api/types/event.ts +27 -0
  114. package/plug-api/types/index.ts +56 -0
  115. package/plug-api/types/manifest.ts +98 -0
  116. package/plug-api/types/namespace.ts +6 -0
  117. package/plugs/builtin_plugs.ts +14 -0
@@ -0,0 +1,489 @@
1
+ import {
2
+ type ILuaFunction,
3
+ isILuaFunction,
4
+ isLuaTable,
5
+ LuaBuiltinFunction,
6
+ luaCall,
7
+ luaCloseFromMark,
8
+ luaEnsureCloseStack,
9
+ LuaEnv,
10
+ luaGet,
11
+ luaKeys,
12
+ luaLen,
13
+ LuaMultiRes,
14
+ LuaRuntimeError,
15
+ type LuaStackFrame,
16
+ type LuaTable,
17
+ luaToString,
18
+ luaTypeOf,
19
+ type LuaValue,
20
+ } from "./runtime.ts";
21
+ import { stringApi } from "./stdlib/string.ts";
22
+ import { tableApi } from "./stdlib/table.ts";
23
+ import { osApi } from "./stdlib/os.ts";
24
+ import { jsApi } from "./stdlib/js.ts";
25
+ import { spaceluaApi } from "./stdlib/space_lua.ts";
26
+ import { mathApi } from "./stdlib/math.ts";
27
+ import { parse } from "./parse.ts";
28
+ import { evalStatement } from "./eval.ts";
29
+ import { encodingApi } from "./stdlib/encoding.ts";
30
+ import { luaToNumberDetailed } from "./tonumber.ts";
31
+ import { luaLoad } from "./stdlib/load.ts";
32
+ import { cryptoApi } from "./stdlib/crypto.ts";
33
+ import { netApi } from "./stdlib/net.ts";
34
+ import { isTaggedFloat, makeLuaFloat } from "./numeric.ts";
35
+
36
+ const printFunction = new LuaBuiltinFunction(async (_sf, ...args) => {
37
+ console.log(
38
+ "[Lua]",
39
+ ...(await Promise.all(args.map((v) => luaToString(v)))),
40
+ );
41
+ });
42
+
43
+ const assertFunction = new LuaBuiltinFunction(
44
+ async (sf, value: any, message?: string) => {
45
+ if (!await value) {
46
+ throw new LuaRuntimeError(`Assertion failed: ${message}`, sf);
47
+ }
48
+ },
49
+ );
50
+
51
+ const ipairsFunction = new LuaBuiltinFunction((sf, t: LuaTable | any[]) => {
52
+ let i = 0;
53
+
54
+ return async () => {
55
+ i = i + 1;
56
+
57
+ const v = await luaGet(t, i, sf.astCtx ?? null, sf);
58
+ if (v === null || v === undefined) {
59
+ return;
60
+ }
61
+
62
+ return new LuaMultiRes([i, v]);
63
+ };
64
+ });
65
+
66
+ const pairsFunction = new LuaBuiltinFunction(
67
+ (sf, t: LuaTable | any[] | Record<string, any>) => {
68
+ // Respect `__pairs` metamethod for Lua tables
69
+ if (isLuaTable(t)) {
70
+ const mt = (t as any).metatable as LuaTable | null | undefined;
71
+ if (mt) {
72
+ const mm = mt.get("__pairs", sf);
73
+ if (mm && (typeof mm === "function" || isILuaFunction(mm))) {
74
+ // __pairs must return (iter, state, control, closing)
75
+ return luaCall(mm, [t], sf.astCtx ?? {}, sf);
76
+ }
77
+ }
78
+ }
79
+
80
+ let keys: (string | number)[];
81
+ if (Array.isArray(t)) {
82
+ keys = Array.from({ length: t.length }, (_, i) => i + 1); // For arrays, generate 1-based indices
83
+ } else if (isLuaTable(t) || t instanceof LuaEnv) {
84
+ keys = t.keys();
85
+ } else {
86
+ // For plain JavaScript objects case, note: this will also include keys from the prototype
87
+ keys = [];
88
+ for (const key in t) {
89
+ keys.push(key);
90
+ }
91
+ }
92
+
93
+ let i = 0;
94
+ const iter = async () => {
95
+ if (i >= keys.length) {
96
+ return;
97
+ }
98
+ const key = keys[i];
99
+ i++;
100
+ const value = await luaGet(t, key, sf.astCtx ?? null, sf);
101
+ return new LuaMultiRes([key, value]);
102
+ };
103
+
104
+ // Must return (iter, state, control) for generic for
105
+ return new LuaMultiRes([iter, t, null]);
106
+ },
107
+ );
108
+
109
+ export const eachFunction = new LuaBuiltinFunction(
110
+ (sf, ar: LuaTable | any[]) => {
111
+ let i = 1;
112
+ const length = (ar as any).length;
113
+ return async () => {
114
+ if (i > length) {
115
+ return;
116
+ }
117
+ const result = await luaGet(ar, i, sf.astCtx ?? null, sf);
118
+ i++;
119
+ return result;
120
+ };
121
+ },
122
+ );
123
+
124
+ const unpackFunction = new LuaBuiltinFunction(async (sf, t: LuaTable) => {
125
+ const values: LuaValue[] = [];
126
+ for (let i = 1; i <= (t as any).length; i++) {
127
+ values.push(await luaGet(t, i, sf.astCtx ?? null, sf));
128
+ }
129
+ return new LuaMultiRes(values);
130
+ });
131
+
132
+ const typeFunction = new LuaBuiltinFunction(
133
+ (_sf, value: LuaValue): string | Promise<string> => {
134
+ return luaTypeOf(value);
135
+ },
136
+ );
137
+
138
+ const tostringFunction = new LuaBuiltinFunction((_sf, value: any) => {
139
+ return luaToString(value);
140
+ });
141
+
142
+ const tonumberFunction = new LuaBuiltinFunction(
143
+ (sf, value: LuaValue, base?: number) => {
144
+ if (base !== undefined) {
145
+ if (!(typeof base === "number" && base >= 2 && base <= 36)) {
146
+ throw new LuaRuntimeError(
147
+ "bad argument #2 to 'tonumber' (base out of range)",
148
+ sf,
149
+ );
150
+ }
151
+ }
152
+
153
+ if (typeof value === "number") {
154
+ return value;
155
+ }
156
+ if (isTaggedFloat(value)) {
157
+ return value;
158
+ }
159
+
160
+ if (typeof value !== "string") {
161
+ return null;
162
+ }
163
+
164
+ const result = luaToNumberDetailed(value, base);
165
+ if (result === null) {
166
+ return null;
167
+ }
168
+
169
+ if (result.numericType === "float") {
170
+ return makeLuaFloat(result.value);
171
+ }
172
+
173
+ return result.value;
174
+ },
175
+ );
176
+
177
+ const errorFunction = new LuaBuiltinFunction((sf, message: string) => {
178
+ throw new LuaRuntimeError(message, sf);
179
+ });
180
+
181
+ async function pcallBoundary(
182
+ sf: LuaStackFrame,
183
+ fn: ILuaFunction,
184
+ args: LuaValue[],
185
+ ): Promise<
186
+ | { ok: true; values: LuaValue[] }
187
+ | { ok: false; message: string }
188
+ > {
189
+ const closeStack = luaEnsureCloseStack(sf);
190
+ const mark = closeStack.length;
191
+
192
+ const errMsgOf = (e: any): string =>
193
+ e instanceof LuaRuntimeError ? e.message : (e?.message ?? String(e));
194
+
195
+ try {
196
+ const r = await luaCall(fn, args, sf.astCtx!, sf);
197
+ await luaCloseFromMark(sf, mark, null);
198
+ const values = r instanceof LuaMultiRes ? r.flatten().values : [r];
199
+ return { ok: true, values };
200
+ } catch (e: any) {
201
+ const msg = errMsgOf(e);
202
+ try {
203
+ await luaCloseFromMark(sf, mark, msg);
204
+ return { ok: false, message: msg };
205
+ } catch (closeErr: any) {
206
+ return { ok: false, message: errMsgOf(closeErr) };
207
+ }
208
+ }
209
+ }
210
+
211
+ const pcallFunction = new LuaBuiltinFunction(
212
+ async (sf, fn: ILuaFunction, ...args) => {
213
+ // To-be-closed variables must be closed when unwinding to the
214
+ // protected call boundary. Space Lua uses a per-thread close
215
+ // stack, so we snapshot its length and close anything pushed
216
+ // after that.
217
+ //
218
+ // The protected call boundary must be established *before*
219
+ // evaluating the function and its arguments. Otherwise, any
220
+ // `<close>` locals created while evaluating `pcall`'s arguments
221
+ // will be wrongly treated as "inside" the protected call, and
222
+ // `pcall` may end up closing them (or affecting close ordering).
223
+ //
224
+ // `threadState` is read-only on the stack frame; do not reassign!
225
+ const res = await pcallBoundary(sf, fn, args);
226
+ if (res.ok) {
227
+ return new LuaMultiRes([true, ...res.values]);
228
+ }
229
+ return new LuaMultiRes([false, res.message]);
230
+ },
231
+ );
232
+
233
+ const xpcallFunction = new LuaBuiltinFunction(
234
+ async (sf, fn: ILuaFunction, errorHandler: ILuaFunction, ...args) => {
235
+ // Same semantic as `pcall` (see comments there)
236
+ const res = await pcallBoundary(sf, fn, args);
237
+ if (res.ok) {
238
+ return new LuaMultiRes([true, ...res.values]);
239
+ }
240
+ const hr = await luaCall(errorHandler, [res.message], sf.astCtx!, sf);
241
+ const outVals = hr instanceof LuaMultiRes ? hr.flatten().values : [hr];
242
+ return new LuaMultiRes([false, ...outVals]);
243
+ },
244
+ );
245
+
246
+ const setmetatableFunction = new LuaBuiltinFunction(
247
+ (sf, table: LuaTable, metatable: LuaTable) => {
248
+ if (!metatable) {
249
+ throw new LuaRuntimeError("metatable cannot be set to nil", sf);
250
+ }
251
+ table.metatable = metatable;
252
+ return table;
253
+ },
254
+ );
255
+
256
+ const rawlenFunction = new LuaBuiltinFunction(
257
+ (_sf, value: LuaValue) => {
258
+ return luaLen(value, _sf);
259
+ },
260
+ );
261
+
262
+ const rawsetFunction = new LuaBuiltinFunction(
263
+ (_sf, table: LuaTable, key: LuaValue, value: LuaValue) => {
264
+ return (table as any).rawSet(key, value);
265
+ },
266
+ );
267
+
268
+ const rawgetFunction = new LuaBuiltinFunction(
269
+ (_sf, table: any, key: LuaValue) => {
270
+ const isArray = Array.isArray(table);
271
+
272
+ const isPlainObj = typeof table === "object" &&
273
+ table !== null &&
274
+ (table as any).constructor === Object;
275
+
276
+ if (!isLuaTable(table) && !isArray && !isPlainObj) {
277
+ let typeName = "userdata";
278
+ if (table === null || table === undefined) {
279
+ typeName = "nil";
280
+ } else if (typeof table === "boolean") {
281
+ typeName = "boolean";
282
+ } else if (typeof table === "number" || isTaggedFloat(table)) {
283
+ typeName = "number";
284
+ } else if (typeof table === "string") {
285
+ typeName = "string";
286
+ } else if (
287
+ typeof table === "function" ||
288
+ (typeof table === "object" &&
289
+ table !== null &&
290
+ typeof (table as any).call === "function")
291
+ ) {
292
+ typeName = "function";
293
+ }
294
+ throw new LuaRuntimeError(
295
+ `bad argument #1 to 'rawget' (table expected, got ${typeName})`,
296
+ _sf,
297
+ );
298
+ }
299
+
300
+ if (isLuaTable(table)) {
301
+ const v = table.rawGet(key);
302
+ return v === undefined ? null : v;
303
+ }
304
+
305
+ const k = isTaggedFloat(key) ? key.value : key;
306
+
307
+ if (isArray) {
308
+ if (typeof k === "number") {
309
+ const v = (table as any[])[k - 1];
310
+ return v === undefined ? null : v;
311
+ }
312
+ const v = (table as Record<string, any>)[k];
313
+ return v === undefined ? null : v;
314
+ }
315
+
316
+ const v = (table as Record<string | number, any>)[k as any];
317
+ return v === undefined ? null : v;
318
+ },
319
+ );
320
+
321
+ const rawequalFunction = new LuaBuiltinFunction(
322
+ (_sf, a: any, b: any) => {
323
+ const av = isTaggedFloat(a) ? a.value : a;
324
+ const bv = isTaggedFloat(b) ? b.value : b;
325
+ return av === bv;
326
+ },
327
+ );
328
+
329
+ const getmetatableFunction = new LuaBuiltinFunction((_sf, table: LuaTable) => {
330
+ return (table as any).metatable;
331
+ });
332
+
333
+ const dofileFunction = new LuaBuiltinFunction(async (sf, filename: string) => {
334
+ const global = sf.threadLocal.get("_GLOBAL") as LuaEnv;
335
+ const file = await luaCall(
336
+ (global.get("space") as any).get("readFile"),
337
+ [filename],
338
+ sf.astCtx!,
339
+ sf,
340
+ ) as Uint8Array;
341
+ const code = new TextDecoder().decode(file);
342
+ try {
343
+ const parsedExpr = parse(code);
344
+ const env = new LuaEnv(global);
345
+ await evalStatement(parsedExpr, env, sf.withCtx(parsedExpr.ctx));
346
+ } catch (e: any) {
347
+ throw new LuaRuntimeError(
348
+ `Error evaluating "${filename}": ${e.message}`,
349
+ sf,
350
+ );
351
+ }
352
+ });
353
+
354
+ /**
355
+ * From the Lua docs:
356
+ *
357
+ * If index is a number, returns all arguments after argument number
358
+ * index; a negative number indexes from the end (-1 is the last
359
+ * argument). Otherwise, index must be the string "#", and select
360
+ * returns the total number of extra arguments it received.
361
+ */
362
+ const selectFunction = new LuaBuiltinFunction(
363
+ (_sf, index: number | "#", ...args: LuaValue[]) => {
364
+ if (index === "#") {
365
+ return args.length;
366
+ }
367
+ if (typeof index === "number") {
368
+ if (index >= 0) {
369
+ return new LuaMultiRes(args.slice(index - 1));
370
+ }
371
+ return new LuaMultiRes(args.slice(args.length + index));
372
+ }
373
+ },
374
+ );
375
+
376
+ /**
377
+ * From the Lua docs:
378
+ *
379
+ * Allows a program to traverse all fields of a table. Its first
380
+ * argument is a table and its second argument is an index in this
381
+ * table. A call to next returns the next index of the table and its
382
+ * associated value. When called with nil as its second argument, next
383
+ * returns an initial index and its associated value. When called with
384
+ * the last index, or with nil in an empty table, next returns nil. If
385
+ * the second argument is absent, then it is interpreted as nil. In
386
+ * particular, you can use next(t) to check whether a table is empty.
387
+ *
388
+ * The order in which the indices are enumerated is not specified, even
389
+ * for numeric indices. (To traverse a table in numerical order, use
390
+ * a numerical for.)
391
+ *
392
+ * You should not assign any value to a non-existent field in a table
393
+ * during its traversal. You may however modify existing fields. In
394
+ * particular, you may set existing fields to nil.
395
+ */
396
+ const nextFunction = new LuaBuiltinFunction(
397
+ (sf, table: LuaTable | Record<string, any>, index: number | null = null) => {
398
+ if (!table) {
399
+ // When nil value
400
+ return null;
401
+ }
402
+ const keys = luaKeys(table);
403
+
404
+ // Empty table -> null return value
405
+ if (keys.length === 0) {
406
+ return null;
407
+ }
408
+
409
+ if (index === null) {
410
+ // Return the first key, value
411
+ const key = keys[0];
412
+ return new LuaMultiRes([key, luaGet(table, key, sf.astCtx ?? null, sf)]);
413
+ }
414
+ // Find index in the key list
415
+ const idx = keys.indexOf(index);
416
+ if (idx === -1) { // Not found
417
+ throw new LuaRuntimeError("invalid key to 'next': key not found", sf);
418
+ }
419
+ const key = keys[idx + 1];
420
+ if (key === undefined) {
421
+ // When called with the last key, should return nil
422
+ return null;
423
+ }
424
+ return new LuaMultiRes([key, luaGet(table, key, sf.astCtx ?? null, sf)]);
425
+ },
426
+ );
427
+
428
+ // Non-standard, but useful
429
+ const someFunction = new LuaBuiltinFunction(async (_sf, value: any) => {
430
+ switch (await luaTypeOf(value)) {
431
+ case "number":
432
+ if (!isFinite(value)) return null;
433
+ break;
434
+ case "string":
435
+ if (value.trim() === "") return null;
436
+ break;
437
+ case "table":
438
+ if (luaKeys(value).length === 0) return null;
439
+ }
440
+ return value;
441
+ });
442
+
443
+ const loadFunction = new LuaBuiltinFunction((sf, s) => luaLoad(s, sf));
444
+
445
+ export function luaBuildStandardEnv() {
446
+ const env = new LuaEnv();
447
+ // _G global
448
+ env.set("_G", env);
449
+ // Top-level builtins
450
+ env.set("print", printFunction);
451
+ env.set("assert", assertFunction);
452
+ env.set("type", typeFunction);
453
+ env.set("tostring", tostringFunction);
454
+ env.set("tonumber", tonumberFunction);
455
+ env.set("unpack", unpackFunction);
456
+ env.set("select", selectFunction);
457
+ env.set("next", nextFunction);
458
+ // Iterators
459
+ env.set("pairs", pairsFunction);
460
+ env.set("ipairs", ipairsFunction);
461
+ // meta table stuff
462
+ env.set("setmetatable", setmetatableFunction);
463
+ env.set("getmetatable", getmetatableFunction);
464
+ env.set("rawlen", rawlenFunction);
465
+ env.set("rawset", rawsetFunction);
466
+ env.set("rawget", rawgetFunction);
467
+ env.set("rawequal", rawequalFunction);
468
+ env.set("dofile", dofileFunction);
469
+ // Error handling
470
+ env.set("error", errorFunction);
471
+ env.set("pcall", pcallFunction);
472
+ env.set("xpcall", xpcallFunction);
473
+ // Evaluation
474
+ env.set("load", loadFunction);
475
+ // APIs
476
+ env.set("string", stringApi);
477
+ env.set("table", tableApi);
478
+ env.set("os", osApi);
479
+ env.set("js", jsApi);
480
+ env.set("math", mathApi);
481
+ // Non-standard
482
+ env.set("each", eachFunction);
483
+ env.set("spacelua", spaceluaApi);
484
+ env.set("encoding", encodingApi);
485
+ env.set("crypto", cryptoApi);
486
+ env.set("net", netApi);
487
+ env.set("some", someFunction);
488
+ return env;
489
+ }