@loom-dev/luau 0.0.0-stage → 0.14.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.
- package/LICENSE +21 -0
- package/dist/entry.d.ts +1 -0
- package/dist/entry.js +14 -0
- package/dist/entry.js.map +1 -0
- package/dist/index.d.ts +352 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +65 -0
- package/dist/index.js.map +1 -0
- package/dist/mount-2LXSpSYv.js +1444 -0
- package/dist/mount-2LXSpSYv.js.map +1 -0
- package/package.json +62 -3
- package/wasm/luau-vm.d.mts +85 -0
- package/wasm/luau-vm.mjs +2 -0
- package/wasm/luau-vm.wasm +0 -0
- package/README.md +0 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 astra-void
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/entry.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
package/dist/entry.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { r as runLuauProject } from "./mount-2LXSpSYv.js";
|
|
2
|
+
import { project } from "virtual:loom-luau-project";
|
|
3
|
+
//#region src/entry.ts
|
|
4
|
+
/**
|
|
5
|
+
* `@loom-dev/luau/entry` — the client entry `@loom-dev/preview` gives a Luau
|
|
6
|
+
* project's page: build the Rojo project the preview plugin serves, and start
|
|
7
|
+
* the client. A real module rather than a generated one, so Vite's dependency
|
|
8
|
+
* scan can follow it like any app entry.
|
|
9
|
+
*/
|
|
10
|
+
runLuauProject(project);
|
|
11
|
+
//#endregion
|
|
12
|
+
export {};
|
|
13
|
+
|
|
14
|
+
//# sourceMappingURL=entry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entry.js","names":[],"sources":["../src/entry.ts"],"sourcesContent":["/**\n * `@loom-dev/luau/entry` — the client entry `@loom-dev/preview` gives a Luau\n * project's page: build the Rojo project the preview plugin serves, and start\n * the client. A real module rather than a generated one, so Vite's dependency\n * scan can follow it like any app entry.\n */\nimport { project } from \"virtual:loom-luau-project\";\nimport { runLuauProject } from \"./mount.ts\";\n\nvoid runLuauProject(project);\n"],"mappings":";;;;;;;;;AASK,eAAe,OAAO"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
import { LoomInstance } from "@loom-dev/runtime";
|
|
2
|
+
import { World, WorldOptions } from "@loom-dev/react";
|
|
3
|
+
import { FunctionComponent } from "react";
|
|
4
|
+
//#region src/vm.d.ts
|
|
5
|
+
/** An error raised in Luau, or by a host function on Luau's behalf. */
|
|
6
|
+
declare class LuauError extends Error {
|
|
7
|
+
/** The raised value itself (`error({ code = 1 })` keeps its table). */
|
|
8
|
+
readonly value: unknown;
|
|
9
|
+
/** The Luau stack at the point of the error, when known. */
|
|
10
|
+
readonly traceback?: string | undefined;
|
|
11
|
+
readonly name = "LuauError";
|
|
12
|
+
constructor(message: string,
|
|
13
|
+
/** The raised value itself (`error({ code = 1 })` keeps its table). */
|
|
14
|
+
value?: unknown,
|
|
15
|
+
/** The Luau stack at the point of the error, when known. */
|
|
16
|
+
traceback?: string | undefined);
|
|
17
|
+
}
|
|
18
|
+
/** Several return values from a host function. */
|
|
19
|
+
declare class Tuple {
|
|
20
|
+
readonly values: readonly unknown[];
|
|
21
|
+
constructor(values: readonly unknown[]);
|
|
22
|
+
}
|
|
23
|
+
/** Return several values from a host function. */
|
|
24
|
+
declare function tuple(...values: unknown[]): Tuple;
|
|
25
|
+
/**
|
|
26
|
+
* Returned by a host function to yield the thread that called it. `wait` runs
|
|
27
|
+
* once the thread has actually suspended and receives the function that
|
|
28
|
+
* resumes it with the host function's results.
|
|
29
|
+
*/
|
|
30
|
+
declare class Suspend {
|
|
31
|
+
readonly wait: (resume: (...values: unknown[]) => void) => void;
|
|
32
|
+
constructor(wait: (resume: (...values: unknown[]) => void) => void);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* How Luau sees one kind of host object. Every hook is optional: a missing
|
|
36
|
+
* `index` makes every field read an error, a missing `namecall` every method
|
|
37
|
+
* call. Arithmetic hooks receive both operands, either of which may be the
|
|
38
|
+
* host object.
|
|
39
|
+
*/
|
|
40
|
+
interface HostClass<T extends object = object> {
|
|
41
|
+
/** What `typeof` returns. */
|
|
42
|
+
readonly name: string;
|
|
43
|
+
index?(self: T, key: unknown): unknown;
|
|
44
|
+
newindex?(self: T, key: unknown, value: unknown): void;
|
|
45
|
+
namecall?(self: T, method: string, args: unknown[]): unknown;
|
|
46
|
+
call?(self: T, args: unknown[]): unknown;
|
|
47
|
+
tostring?(self: T): string;
|
|
48
|
+
eq?(a: T, b: unknown): boolean;
|
|
49
|
+
lt?(a: unknown, b: unknown): boolean;
|
|
50
|
+
le?(a: unknown, b: unknown): boolean;
|
|
51
|
+
len?(self: T): number;
|
|
52
|
+
unm?(self: T): unknown;
|
|
53
|
+
add?(a: unknown, b: unknown): unknown;
|
|
54
|
+
sub?(a: unknown, b: unknown): unknown;
|
|
55
|
+
mul?(a: unknown, b: unknown): unknown;
|
|
56
|
+
div?(a: unknown, b: unknown): unknown;
|
|
57
|
+
idiv?(a: unknown, b: unknown): unknown;
|
|
58
|
+
mod?(a: unknown, b: unknown): unknown;
|
|
59
|
+
pow?(a: unknown, b: unknown): unknown;
|
|
60
|
+
}
|
|
61
|
+
/** Picks the `HostClass` for a JS object, or `undefined` to copy it as a table. */
|
|
62
|
+
type Classifier = (value: object) => HostClass | undefined;
|
|
63
|
+
interface LuauVMOptions {
|
|
64
|
+
/** Decides which JS objects cross as host userdata. */
|
|
65
|
+
classify?: Classifier;
|
|
66
|
+
/** Where an error that escapes a thread goes. Defaults to `console.error`. */
|
|
67
|
+
onError?: (error: LuauError) => void;
|
|
68
|
+
/** Wall-clock milliseconds one entry into Luau may run. 0 disables. */
|
|
69
|
+
budgetMs?: number;
|
|
70
|
+
/** Passed to emscripten — for loading the `.wasm` from somewhere unusual. */
|
|
71
|
+
locateFile?: (path: string, prefix: string) => string;
|
|
72
|
+
/** The `.wasm` bytes themselves, skipping the fetch (tests, Node). */
|
|
73
|
+
wasmBinary?: ArrayBuffer | Uint8Array;
|
|
74
|
+
/**
|
|
75
|
+
* Globals that stay writable tables after the freeze, one table each that
|
|
76
|
+
* every script shares — Roblox's `_G` and `shared`. The sandbox freezes
|
|
77
|
+
* every table it finds, so these are made fresh once it has run.
|
|
78
|
+
*/
|
|
79
|
+
sharedTables?: readonly string[];
|
|
80
|
+
}
|
|
81
|
+
/** How a resumed thread came back. */
|
|
82
|
+
type ThreadResult = {
|
|
83
|
+
readonly status: "done";
|
|
84
|
+
readonly values: unknown[];
|
|
85
|
+
} | {
|
|
86
|
+
readonly status: "yielded";
|
|
87
|
+
} | {
|
|
88
|
+
readonly status: "error";
|
|
89
|
+
readonly error: LuauError;
|
|
90
|
+
};
|
|
91
|
+
/** A reference that keeps a Luau value alive until the JS side is collected. */
|
|
92
|
+
declare abstract class LuauRef {
|
|
93
|
+
/** @internal */ readonly vm: LuauVM;
|
|
94
|
+
/** @internal */ readonly ref: number;
|
|
95
|
+
constructor( /** @internal */ vm: LuauVM, /** @internal */ ref: number);
|
|
96
|
+
}
|
|
97
|
+
/** A Luau function. `call` runs it to completion; `spawn` gives it a thread. */
|
|
98
|
+
declare class LuauFunction extends LuauRef {
|
|
99
|
+
call(...args: unknown[]): unknown[];
|
|
100
|
+
spawn(...args: unknown[]): ThreadResult;
|
|
101
|
+
}
|
|
102
|
+
/** A Luau table, read and written raw (no metamethods). */
|
|
103
|
+
declare class LuauTable extends LuauRef {
|
|
104
|
+
get(key: unknown): unknown;
|
|
105
|
+
set(key: unknown, value: unknown): void;
|
|
106
|
+
/** `#t`. */
|
|
107
|
+
get length(): number;
|
|
108
|
+
/** Every key/value pair, in `next` order. */
|
|
109
|
+
entries(): [unknown, unknown][];
|
|
110
|
+
/** `t[1]` … `t[#t]`. */
|
|
111
|
+
array(): unknown[];
|
|
112
|
+
}
|
|
113
|
+
/** A Luau coroutine. */
|
|
114
|
+
declare class LuauThread extends LuauRef {}
|
|
115
|
+
/** A Luau value JS has no use for beyond handing it back (vector, buffer, …). */
|
|
116
|
+
declare class LuauOpaque extends LuauRef {
|
|
117
|
+
readonly typeName: string;
|
|
118
|
+
constructor(vm: LuauVM, ref: number, typeName: string);
|
|
119
|
+
}
|
|
120
|
+
declare class LuauVM {
|
|
121
|
+
/** Instantiate the WASM module and open a fresh Luau state. */
|
|
122
|
+
static create(options?: LuauVMOptions): Promise<LuauVM>;
|
|
123
|
+
private readonly M;
|
|
124
|
+
private readonly L;
|
|
125
|
+
private readonly classify;
|
|
126
|
+
private readonly onError;
|
|
127
|
+
private readonly budgetMs;
|
|
128
|
+
private readonly sharedTables;
|
|
129
|
+
private readonly entries;
|
|
130
|
+
private readonly functionIds;
|
|
131
|
+
private readonly debugNames;
|
|
132
|
+
private readonly handles;
|
|
133
|
+
private readonly handleOf;
|
|
134
|
+
private nextHandle;
|
|
135
|
+
private readonly metatables;
|
|
136
|
+
private readonly metamethodIds;
|
|
137
|
+
private readonly refs;
|
|
138
|
+
private scratch;
|
|
139
|
+
private scratchSize;
|
|
140
|
+
private readonly lenPtr;
|
|
141
|
+
private depth;
|
|
142
|
+
private frozen;
|
|
143
|
+
private closed;
|
|
144
|
+
/** `run`'s `onFinish` for each thread still on its way to the end. */
|
|
145
|
+
private readonly finishers;
|
|
146
|
+
private constructor();
|
|
147
|
+
/** Define a global. Only before the first script runs (globals freeze then). */
|
|
148
|
+
setGlobal(name: string, value: unknown): void;
|
|
149
|
+
getGlobal(name: string): unknown;
|
|
150
|
+
/**
|
|
151
|
+
* Freeze the globals and the standard libraries, Roblox style. Runs on its
|
|
152
|
+
* own before the first script; scripts then see the frozen set through
|
|
153
|
+
* their own writable environment.
|
|
154
|
+
*/
|
|
155
|
+
freeze(): void;
|
|
156
|
+
/** Compile `source` into a function, or throw the syntax error. */
|
|
157
|
+
load(source: string, chunkname?: string): LuauFunction;
|
|
158
|
+
/**
|
|
159
|
+
* Run `source` as a script: its own thread with its own global environment
|
|
160
|
+
* (the frozen globals plus `globals`), the way Roblox runs a Script or
|
|
161
|
+
* LocalScript. Returns how the thread first came back; `onFinish` hears how
|
|
162
|
+
* it ended, after however many yields (`require` of a module that yields).
|
|
163
|
+
*/
|
|
164
|
+
run(source: string, options?: {
|
|
165
|
+
chunkname?: string;
|
|
166
|
+
globals?: Record<string, unknown>;
|
|
167
|
+
onFinish?: (result: ThreadResult) => void;
|
|
168
|
+
}): ThreadResult;
|
|
169
|
+
/**
|
|
170
|
+
* Call a Luau function to completion and return its results. A function
|
|
171
|
+
* that yields throws here — give it a thread with `spawn` instead.
|
|
172
|
+
*/
|
|
173
|
+
call(fn: LuauFunction, args?: readonly unknown[]): unknown[];
|
|
174
|
+
/** Run a Luau function in a new thread (`task.spawn`). */
|
|
175
|
+
spawn(fn: LuauFunction, args?: readonly unknown[]): ThreadResult;
|
|
176
|
+
/**
|
|
177
|
+
* Resume a Luau thread (`task.defer`'s and `task.delay`'s, made with
|
|
178
|
+
* `coroutine.create`). A thread that cannot be resumed — finished, running,
|
|
179
|
+
* or closed by `task.cancel` — is left alone and gives `undefined`.
|
|
180
|
+
*/
|
|
181
|
+
resumeThread(thread: LuauThread, args?: readonly unknown[]): ThreadResult | undefined;
|
|
182
|
+
/** Hand an error to `onError`, as if it had escaped a thread. */
|
|
183
|
+
report(error: LuauError): void;
|
|
184
|
+
/** Collect garbage now (tests use it to observe userdata release). */
|
|
185
|
+
collect(): void;
|
|
186
|
+
/** Close the state. Every reference into it is dead afterwards. */
|
|
187
|
+
close(): void;
|
|
188
|
+
/** Whether `close` has run: every entry into Luau throws afterwards. */
|
|
189
|
+
get isClosed(): boolean;
|
|
190
|
+
/** How many JS objects Luau currently holds as userdata. */
|
|
191
|
+
get liveHostObjects(): number;
|
|
192
|
+
/** @internal */
|
|
193
|
+
track(owner: LuauRef, ref: number): void;
|
|
194
|
+
/** @internal */
|
|
195
|
+
tableGet(table: LuauTable, key: unknown): unknown;
|
|
196
|
+
/** @internal */
|
|
197
|
+
tableSet(table: LuauTable, key: unknown, value: unknown): void;
|
|
198
|
+
/** @internal */
|
|
199
|
+
tableLength(table: LuauTable): number;
|
|
200
|
+
/** @internal */
|
|
201
|
+
tableEntries(table: LuauTable): [unknown, unknown][];
|
|
202
|
+
/** Resume `co` with the top `nargs` values of its stack. */
|
|
203
|
+
private resume;
|
|
204
|
+
private resumeOnce;
|
|
205
|
+
/**
|
|
206
|
+
* A host function returned `suspend` on thread `co`. Keep the thread alive
|
|
207
|
+
* and hand `wait` its resume function once Luau has unwound — only then is
|
|
208
|
+
* the thread really suspended, whoever resumed it.
|
|
209
|
+
*/
|
|
210
|
+
/** The `lua_State*` behind a thread reference. */
|
|
211
|
+
private threadOf;
|
|
212
|
+
private suspend;
|
|
213
|
+
/** Run `fn` as one entry into Luau, under the run-time budget. */
|
|
214
|
+
private enter;
|
|
215
|
+
private register;
|
|
216
|
+
private hostCall;
|
|
217
|
+
private pushResults;
|
|
218
|
+
private hostRelease;
|
|
219
|
+
/** The host function behind metamethod `name`, shared by every class. */
|
|
220
|
+
private metamethod;
|
|
221
|
+
private classOf;
|
|
222
|
+
private metatableFor;
|
|
223
|
+
private read;
|
|
224
|
+
private readRange;
|
|
225
|
+
private push;
|
|
226
|
+
private pushHost;
|
|
227
|
+
private functionId;
|
|
228
|
+
private ensureStack;
|
|
229
|
+
private loadOnto;
|
|
230
|
+
private pushString;
|
|
231
|
+
/** A NUL-terminated copy of `value` in the scratch buffer (overwritten by the next use). */
|
|
232
|
+
private cstr;
|
|
233
|
+
/** A permanent NUL-terminated string: Luau keeps C function debug names by pointer. */
|
|
234
|
+
private debugName;
|
|
235
|
+
private reserve;
|
|
236
|
+
}
|
|
237
|
+
//#endregion
|
|
238
|
+
//#region src/bindings.d.ts
|
|
239
|
+
/**
|
|
240
|
+
* The Roblox class surface, bound to one VM. `classify` is what the VM is
|
|
241
|
+
* created with; `install` defines the globals once the VM exists.
|
|
242
|
+
*/
|
|
243
|
+
interface RobloxBindings {
|
|
244
|
+
readonly classify: Classifier;
|
|
245
|
+
install(vm: LuauVM): void;
|
|
246
|
+
}
|
|
247
|
+
declare function createRobloxBindings(): RobloxBindings;
|
|
248
|
+
//#endregion
|
|
249
|
+
//#region src/project.d.ts
|
|
250
|
+
/** One instance of a project tree, as the preview plugin emits it. */
|
|
251
|
+
interface LuauProjectNode {
|
|
252
|
+
readonly name: string;
|
|
253
|
+
readonly className: string;
|
|
254
|
+
/** A script's source. */
|
|
255
|
+
readonly source?: string;
|
|
256
|
+
readonly children?: readonly LuauProjectNode[];
|
|
257
|
+
}
|
|
258
|
+
interface LuauProject {
|
|
259
|
+
/** The `DataModel` root; its children are services. */
|
|
260
|
+
readonly tree: LuauProjectNode;
|
|
261
|
+
}
|
|
262
|
+
/** Attach `source` to a script instance (what `require` and `startClient` run). */
|
|
263
|
+
declare function setScriptSource(script: LoomInstance, source: string): void;
|
|
264
|
+
/** The source behind a script instance, if loom has one for it. */
|
|
265
|
+
declare function getScriptSource(script: LoomInstance): string | undefined;
|
|
266
|
+
/**
|
|
267
|
+
* `Clone`, keeping every script's source. The runtime copies instances but
|
|
268
|
+
* knows nothing about loom's source registry, so the two trees are walked side
|
|
269
|
+
* by side — `Clone` keeps child order and drops the non-Archivable ones.
|
|
270
|
+
*/
|
|
271
|
+
declare function cloneWithSources(original: LoomInstance): LoomInstance | undefined;
|
|
272
|
+
/**
|
|
273
|
+
* Build `project` into the runtime's `game`, once per project object. A node
|
|
274
|
+
* whose name and class match an instance that already exists (a service,
|
|
275
|
+
* `StarterPlayerScripts`) is merged into it rather than duplicated.
|
|
276
|
+
*/
|
|
277
|
+
declare function instantiateProject(project: LuauProject): void;
|
|
278
|
+
//#endregion
|
|
279
|
+
//#region src/mount.d.ts
|
|
280
|
+
/** How a Roblox-flavoured Luau VM is made: shared by every entry point. */
|
|
281
|
+
interface LuauVMSetup {
|
|
282
|
+
/** Where an error that escapes a script thread goes. Defaults to `console.error`. */
|
|
283
|
+
onError?: (error: LuauError) => void;
|
|
284
|
+
/** Wall-clock milliseconds one entry into Luau may run. Defaults to 5000. */
|
|
285
|
+
budgetMs?: number;
|
|
286
|
+
/** The Luau VM's `.wasm` bytes, skipping the fetch (tests). */
|
|
287
|
+
wasmBinary?: ArrayBuffer | Uint8Array;
|
|
288
|
+
}
|
|
289
|
+
interface MountLuauOptions extends LuauVMSetup, WorldOptions {
|
|
290
|
+
/** The element to paint into; defaults to a fresh container under `#loom-root`. */
|
|
291
|
+
target?: HTMLElement;
|
|
292
|
+
/** The script's `Name`, which is also its chunk name in errors. */
|
|
293
|
+
name?: string;
|
|
294
|
+
}
|
|
295
|
+
/** A fresh VM with Roblox's globals installed, ready to run scripts. */
|
|
296
|
+
declare function createLuauVM(setup?: LuauVMSetup): Promise<LuauVM>;
|
|
297
|
+
interface LuauMount {
|
|
298
|
+
readonly vm: LuauVM;
|
|
299
|
+
readonly world: World;
|
|
300
|
+
/** The `LocalScript` the source runs as (`script` inside it). */
|
|
301
|
+
readonly script: LoomInstance;
|
|
302
|
+
/** How the script's thread first came back. */
|
|
303
|
+
readonly result: ThreadResult;
|
|
304
|
+
unmount(): void;
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Run `source` as a LocalScript in a fresh VM and paint what it builds. The
|
|
308
|
+
* script sits inside the world's default ScreenGui, so the common
|
|
309
|
+
* `script.Parent` idiom lands its UI on screen, and anything it parents to
|
|
310
|
+
* `Players.LocalPlayer.PlayerGui` renders as its own layer.
|
|
311
|
+
*/
|
|
312
|
+
declare function mountLuau(source: string, options?: MountLuauOptions): Promise<LuauMount>;
|
|
313
|
+
interface RunLuauProjectOptions extends LuauVMSetup, WorldOptions {
|
|
314
|
+
/** The element to paint into; defaults to a fresh container under `#loom-root`. */
|
|
315
|
+
target?: HTMLElement;
|
|
316
|
+
}
|
|
317
|
+
interface LuauProjectMount {
|
|
318
|
+
readonly vm: LuauVM;
|
|
319
|
+
readonly world: World;
|
|
320
|
+
/** Every LocalScript the client started, with how its thread first came back. */
|
|
321
|
+
readonly scripts: ReadonlyArray<{
|
|
322
|
+
readonly script: LoomInstance;
|
|
323
|
+
readonly result: ThreadResult;
|
|
324
|
+
}>;
|
|
325
|
+
unmount(): void;
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Start a Rojo project the way a client joins a place: build the tree into
|
|
329
|
+
* `game`, then run every LocalScript a client runs (ReplicatedFirst, the
|
|
330
|
+
* StarterGui copy in PlayerGui, the StarterPlayerScripts copy in
|
|
331
|
+
* PlayerScripts) in one VM, so `require` shares each module between them.
|
|
332
|
+
*/
|
|
333
|
+
declare function runLuauProject(project: LuauProject, options?: RunLuauProjectOptions): Promise<LuauProjectMount>;
|
|
334
|
+
//#endregion
|
|
335
|
+
//#region src/preview.d.ts
|
|
336
|
+
interface LuauPreviewOptions extends LuauVMSetup {
|
|
337
|
+
/** The script's `Name`, and its chunk name in errors. */
|
|
338
|
+
readonly name: string;
|
|
339
|
+
/** The gallery sidebar label; the file name when omitted. */
|
|
340
|
+
readonly title?: string;
|
|
341
|
+
/** The project around the target, so its `require`s find their modules. */
|
|
342
|
+
readonly project?: LuauProject;
|
|
343
|
+
}
|
|
344
|
+
interface LuauPreview {
|
|
345
|
+
readonly title: string;
|
|
346
|
+
readonly render: FunctionComponent;
|
|
347
|
+
}
|
|
348
|
+
/** The `preview` export a `*.loom.luau` file compiles to. */
|
|
349
|
+
declare function luauPreview(source: string, options: LuauPreviewOptions): LuauPreview;
|
|
350
|
+
//#endregion
|
|
351
|
+
export { type Classifier, type HostClass, LuauError, LuauFunction, type LuauMount, LuauOpaque, type LuauPreview, type LuauPreviewOptions, type LuauProject, type LuauProjectMount, type LuauProjectNode, LuauTable, LuauThread, LuauVM, type LuauVMOptions, type LuauVMSetup, type MountLuauOptions, type RobloxBindings, type RunLuauProjectOptions, Suspend, type ThreadResult, Tuple, cloneWithSources, createLuauVM, createRobloxBindings, getScriptSource, instantiateProject, luauPreview, mountLuau, runLuauProject, setScriptSource, tuple };
|
|
352
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/vm.ts","../src/bindings.ts","../src/project.ts","../src/mount.ts","../src/preview.ts"],"mappings":"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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { _ as setScriptSource, a as LuauError, c as LuauTable, d as Suspend, f as Tuple, g as instantiateProject, h as getScriptSource, i as createRobloxBindings, l as LuauThread, m as cloneWithSources, n as mountLuau, o as LuauFunction, p as tuple, r as runLuauProject, s as LuauOpaque, t as createLuauVM, u as LuauVM } from "./mount-2LXSpSYv.js";
|
|
2
|
+
import { createInstance, game } from "@loom-dev/runtime";
|
|
3
|
+
import { createElement, useEffect, useState } from "react";
|
|
4
|
+
//#region src/preview.ts
|
|
5
|
+
/**
|
|
6
|
+
* `preview.ts` — a `*.loom.luau` file as a gallery target.
|
|
7
|
+
*
|
|
8
|
+
* The gallery shell mounts `preview.render` as a React component, so a Luau
|
|
9
|
+
* target is one: it renders a ScreenGui and, once React has made it, runs the
|
|
10
|
+
* target's source as a LocalScript inside it. The script shares the shell's
|
|
11
|
+
* world — what it parents under `script.Parent` paints beside React's own
|
|
12
|
+
* instances — and an error that stops its first run reaches the shell's error
|
|
13
|
+
* boundary the way a throwing component's would.
|
|
14
|
+
*/
|
|
15
|
+
function playerGui() {
|
|
16
|
+
return game.GetService("Players").LocalPlayer.WaitForChild("PlayerGui");
|
|
17
|
+
}
|
|
18
|
+
/** The `preview` export a `*.loom.luau` file compiles to. */
|
|
19
|
+
function luauPreview(source, options) {
|
|
20
|
+
function LuauTarget() {
|
|
21
|
+
const [gui, setGui] = useState(null);
|
|
22
|
+
const [failure, setFailure] = useState();
|
|
23
|
+
if (failure) throw failure;
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
if (gui === null) return;
|
|
26
|
+
let vm;
|
|
27
|
+
let cancelled = false;
|
|
28
|
+
const before = new Set(playerGui().GetChildren());
|
|
29
|
+
createLuauVM(options).then((created) => {
|
|
30
|
+
if (cancelled) {
|
|
31
|
+
created.close();
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
vm = created;
|
|
35
|
+
if (options.project) instantiateProject(options.project);
|
|
36
|
+
const script = createInstance("LocalScript", options.name);
|
|
37
|
+
script.Parent = gui;
|
|
38
|
+
const result = created.run(source, {
|
|
39
|
+
chunkname: `=${options.name}`,
|
|
40
|
+
globals: { script }
|
|
41
|
+
});
|
|
42
|
+
if (result.status === "error") setFailure(result.error);
|
|
43
|
+
}, setFailure);
|
|
44
|
+
return () => {
|
|
45
|
+
cancelled = true;
|
|
46
|
+
vm?.close();
|
|
47
|
+
for (const child of playerGui().GetChildren()) if (!before.has(child)) child.Destroy();
|
|
48
|
+
};
|
|
49
|
+
}, [gui]);
|
|
50
|
+
return createElement("screengui", {
|
|
51
|
+
ref: setGui,
|
|
52
|
+
Name: options.name,
|
|
53
|
+
ResetOnSpawn: false
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
LuauTarget.displayName = `LuauTarget(${options.name})`;
|
|
57
|
+
return {
|
|
58
|
+
title: options.title ?? options.name,
|
|
59
|
+
render: LuauTarget
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
//#endregion
|
|
63
|
+
export { LuauError, LuauFunction, LuauOpaque, LuauTable, LuauThread, LuauVM, Suspend, Tuple, cloneWithSources, createLuauVM, createRobloxBindings, getScriptSource, instantiateProject, luauPreview, mountLuau, runLuauProject, setScriptSource, tuple };
|
|
64
|
+
|
|
65
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/preview.ts"],"sourcesContent":["/**\n * `preview.ts` — a `*.loom.luau` file as a gallery target.\n *\n * The gallery shell mounts `preview.render` as a React component, so a Luau\n * target is one: it renders a ScreenGui and, once React has made it, runs the\n * target's source as a LocalScript inside it. The script shares the shell's\n * world — what it parents under `script.Parent` paints beside React's own\n * instances — and an error that stops its first run reaches the shell's error\n * boundary the way a throwing component's would.\n */\nimport { createInstance, game, type LoomInstance } from \"@loom-dev/runtime\";\nimport {\n\tcreateElement,\n\ttype FunctionComponent,\n\tuseEffect,\n\tuseState,\n} from \"react\";\nimport { createLuauVM, type LuauVMSetup } from \"./mount.ts\";\nimport { instantiateProject, type LuauProject } from \"./project.ts\";\nimport type { LuauError, LuauVM } from \"./vm.ts\";\n\nexport interface LuauPreviewOptions extends LuauVMSetup {\n\t/** The script's `Name`, and its chunk name in errors. */\n\treadonly name: string;\n\t/** The gallery sidebar label; the file name when omitted. */\n\treadonly title?: string;\n\t/** The project around the target, so its `require`s find their modules. */\n\treadonly project?: LuauProject;\n}\n\nexport interface LuauPreview {\n\treadonly title: string;\n\treadonly render: FunctionComponent;\n}\n\nfunction playerGui(): LoomInstance {\n\tconst player = game.GetService(\"Players\").LocalPlayer as LoomInstance;\n\treturn player.WaitForChild(\"PlayerGui\") as LoomInstance;\n}\n\n/** The `preview` export a `*.loom.luau` file compiles to. */\nexport function luauPreview(\n\tsource: string,\n\toptions: LuauPreviewOptions,\n): LuauPreview {\n\tfunction LuauTarget() {\n\t\tconst [gui, setGui] = useState<LoomInstance | null>(null);\n\t\tconst [failure, setFailure] = useState<LuauError>();\n\t\tif (failure) throw failure;\n\n\t\tuseEffect(() => {\n\t\t\tif (gui === null) return;\n\t\t\tlet vm: LuauVM | undefined;\n\t\t\tlet cancelled = false;\n\t\t\t// A target may parent a ScreenGui straight to PlayerGui; that one is\n\t\t\t// not under React, so unmounting has to take it away by hand.\n\t\t\tconst before = new Set(playerGui().GetChildren());\n\t\t\tvoid createLuauVM(options).then((created) => {\n\t\t\t\tif (cancelled) {\n\t\t\t\t\tcreated.close();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tvm = created;\n\t\t\t\tif (options.project) instantiateProject(options.project);\n\t\t\t\tconst script = createInstance(\"LocalScript\", options.name);\n\t\t\t\tscript.Parent = gui;\n\t\t\t\tconst result = created.run(source, {\n\t\t\t\t\tchunkname: `=${options.name}`,\n\t\t\t\t\tglobals: { script },\n\t\t\t\t});\n\t\t\t\tif (result.status === \"error\") setFailure(result.error);\n\t\t\t}, setFailure);\n\t\t\treturn () => {\n\t\t\t\tcancelled = true;\n\t\t\t\tvm?.close();\n\t\t\t\tfor (const child of playerGui().GetChildren()) {\n\t\t\t\t\tif (!before.has(child)) child.Destroy();\n\t\t\t\t}\n\t\t\t};\n\t\t}, [gui]);\n\n\t\treturn createElement(\"screengui\", {\n\t\t\tref: setGui,\n\t\t\tName: options.name,\n\t\t\tResetOnSpawn: false,\n\t\t});\n\t}\n\tLuauTarget.displayName = `LuauTarget(${options.name})`;\n\treturn { title: options.title ?? options.name, render: LuauTarget };\n}\n"],"mappings":";;;;;;;;;;;;;;AAmCA,SAAS,YAA0B;CAElC,OADe,KAAK,WAAW,SAAS,CAAC,CAAC,YAC5B,aAAa,WAAW;AACvC;;AAGA,SAAgB,YACf,QACA,SACc;CACd,SAAS,aAAa;EACrB,MAAM,CAAC,KAAK,UAAU,SAA8B,IAAI;EACxD,MAAM,CAAC,SAAS,cAAc,SAAoB;EAClD,IAAI,SAAS,MAAM;EAEnB,gBAAgB;GACf,IAAI,QAAQ,MAAM;GAClB,IAAI;GACJ,IAAI,YAAY;GAGhB,MAAM,SAAS,IAAI,IAAI,UAAU,CAAC,CAAC,YAAY,CAAC;GAChD,aAAkB,OAAO,CAAC,CAAC,MAAM,YAAY;IAC5C,IAAI,WAAW;KACd,QAAQ,MAAM;KACd;IACD;IACA,KAAK;IACL,IAAI,QAAQ,SAAS,mBAAmB,QAAQ,OAAO;IACvD,MAAM,SAAS,eAAe,eAAe,QAAQ,IAAI;IACzD,OAAO,SAAS;IAChB,MAAM,SAAS,QAAQ,IAAI,QAAQ;KAClC,WAAW,IAAI,QAAQ;KACvB,SAAS,EAAE,OAAO;IACnB,CAAC;IACD,IAAI,OAAO,WAAW,SAAS,WAAW,OAAO,KAAK;GACvD,GAAG,UAAU;GACb,aAAa;IACZ,YAAY;IACZ,IAAI,MAAM;IACV,KAAK,MAAM,SAAS,UAAU,CAAC,CAAC,YAAY,GAC3C,IAAI,CAAC,OAAO,IAAI,KAAK,GAAG,MAAM,QAAQ;GAExC;EACD,GAAG,CAAC,GAAG,CAAC;EAER,OAAO,cAAc,aAAa;GACjC,KAAK;GACL,MAAM,QAAQ;GACd,cAAc;EACf,CAAC;CACF;CACA,WAAW,cAAc,cAAc,QAAQ,KAAK;CACpD,OAAO;EAAE,OAAO,QAAQ,SAAS,QAAQ;EAAM,QAAQ;CAAW;AACnE"}
|