lilac-wasm-bin 0.2.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.
- checksums.yaml +7 -0
- data/README.md +46 -0
- data/data/lilac-compiled.wasm +0 -0
- data/data/lilac-full.wasm +0 -0
- data/data/mrbc-host.wasm +0 -0
- data/data/mruby-wasm-js/_memory.js +35 -0
- data/data/mruby-wasm-js/_smoke.ts +117 -0
- data/data/mruby-wasm-js/debug.js +8 -0
- data/data/mruby-wasm-js/index.d.ts +177 -0
- data/data/mruby-wasm-js/index.js +461 -0
- data/data/mruby-wasm-js/wasi-preview1.js +705 -0
- data/lib/lilac/wasm/bin/version.rb +9 -0
- data/lib/lilac/wasm/bin.rb +101 -0
- metadata +67 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 0643e7b710fc139e195c98efefa72f55b51d11f0b83fc45f0bf1204e9b1f96cb
|
|
4
|
+
data.tar.gz: 4ff9a88520b3d9042b204514e2cd3d6bf3832b90cc64b35f1031195ab85743a1
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 7e5d5d6fa6e64f64710b865881f67ecbaad828beadc7425c9a976af4339542d52efbe6e9f20b9f1bcaa972b1d686116fdb61f036112858231639aa995a84564a
|
|
7
|
+
data.tar.gz: c3ac8131575d118658ce66803da657bdc5e48445cb62926255697ddb19a40f2414b79e546e170d2b498627064ff59b43758c80db16af6d0e6fca5a458e6d356a
|
data/README.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# lilac-wasm-bin
|
|
2
|
+
|
|
3
|
+
Bundles the Lilac wasm runtimes (`lilac-full.wasm`, `lilac-compiled.wasm`)
|
|
4
|
+
and the `mruby-wasm-js` JS bridge as a single Ruby gem so that
|
|
5
|
+
|
|
6
|
+
```
|
|
7
|
+
gem install lilac-cli
|
|
8
|
+
lilac new my-app && cd my-app
|
|
9
|
+
bundle install
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
is enough to make both `lilac dev` and `lilac build` work — no `npm
|
|
13
|
+
install`, no manual `cp` of wasm files into `public/vendor/...`.
|
|
14
|
+
|
|
15
|
+
The scaffolded `Gemfile` declares `gem "lilac-wasm-bin"`, so the gem is
|
|
16
|
+
pulled transparently during `bundle install`. The `lilac-cli` gem
|
|
17
|
+
itself does **not** depend on this gem — projects that don't need the
|
|
18
|
+
bundled wasm (e.g. CI for an external runtime) can skip it without
|
|
19
|
+
penalty.
|
|
20
|
+
|
|
21
|
+
## Resolution
|
|
22
|
+
|
|
23
|
+
`lilac-cli`'s `CompiledRuntimeResolver` soft-requires `lilac/wasm/bin`
|
|
24
|
+
and consults `Lilac::Wasm::Bin.lilac_compiled_wasm` (and friends) when
|
|
25
|
+
discovering wasm. If the gem is absent the resolver falls back to the
|
|
26
|
+
existing env / config / monorepo / node_modules discovery chain.
|
|
27
|
+
|
|
28
|
+
## Layout
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
lilac-wasm-bin-X.Y.Z/
|
|
32
|
+
├── lib/lilac/wasm/bin.rb # path constants + resolution helpers
|
|
33
|
+
└── data/ # populated by `rake build:assets`
|
|
34
|
+
├── lilac-full.wasm
|
|
35
|
+
├── lilac-compiled.wasm
|
|
36
|
+
└── mruby-wasm-js/ # JS bridge source
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
`data/` is gitignored and populated by `rake build:assets` immediately
|
|
40
|
+
before `gem build`. The gem build pipeline expects monorepo build
|
|
41
|
+
artifacts under `<monorepo>/build/` and `<monorepo>/mrbgem/mruby-wasm-js/`.
|
|
42
|
+
|
|
43
|
+
For monorepo development (when the gem is referenced as `gem
|
|
44
|
+
"lilac-wasm-bin", path: "../wasm-bin"`), the resolution helpers also
|
|
45
|
+
walk up to the monorepo `build/` directory as a fallback, so contributors
|
|
46
|
+
don't have to re-run `rake build:assets` after every wasm rebuild.
|
|
Binary file
|
|
Binary file
|
data/data/mrbc-host.wasm
ADDED
|
Binary file
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// Shared memory helpers for index.js and wasi-preview1.js.
|
|
2
|
+
//
|
|
3
|
+
// Both modules need to encode/decode UTF-8 from wasm linear memory and
|
|
4
|
+
// read i32 arrays of handles. Keeping a single TextDecoder/Encoder pair
|
|
5
|
+
// avoids re-allocating per call, and the `createMemoryHelpers` factory
|
|
6
|
+
// binds them to a particular VM's instance via the `getInstance`
|
|
7
|
+
// callback (read on every helper call so callers can wire it before
|
|
8
|
+
// they actually have an instance handle — e.g. when building the
|
|
9
|
+
// imports object that's fed to instantiateStreaming).
|
|
10
|
+
|
|
11
|
+
export const decoder = new TextDecoder("utf-8");
|
|
12
|
+
export const encoder = new TextEncoder();
|
|
13
|
+
|
|
14
|
+
export function createMemoryHelpers(getInstance) {
|
|
15
|
+
function readUtf8(ptr, len) {
|
|
16
|
+
const memory = getInstance().exports.memory;
|
|
17
|
+
return decoder.decode(new Uint8Array(memory.buffer, ptr, len));
|
|
18
|
+
}
|
|
19
|
+
function writeUtf8(s, ptr, maxLen) {
|
|
20
|
+
const memory = getInstance().exports.memory;
|
|
21
|
+
const view = new Uint8Array(memory.buffer, ptr, maxLen);
|
|
22
|
+
const encoded = encoder.encode(s);
|
|
23
|
+
const n = Math.min(encoded.length, maxLen);
|
|
24
|
+
view.set(encoded.subarray(0, n));
|
|
25
|
+
return n;
|
|
26
|
+
}
|
|
27
|
+
function readHandleArray(ptr, count) {
|
|
28
|
+
if (count <= 0) return [];
|
|
29
|
+
const view = new DataView(getInstance().exports.memory.buffer);
|
|
30
|
+
const out = new Array(count);
|
|
31
|
+
for (let i = 0; i < count; i++) out[i] = view.getInt32(ptr + i * 4, true);
|
|
32
|
+
return out;
|
|
33
|
+
}
|
|
34
|
+
return { readUtf8, writeUtf8, readHandleArray };
|
|
35
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
// Type smoke test for index.d.ts. Run with:
|
|
2
|
+
// npx -p typescript@5 tsc --noEmit --module nodenext --moduleResolution nodenext --target es2022 --strict _smoke.ts
|
|
3
|
+
//
|
|
4
|
+
// Not shipped — exercises every exported shape so a future drift in
|
|
5
|
+
// index.d.ts surfaces as a tsc error.
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
createVM,
|
|
9
|
+
Directory,
|
|
10
|
+
File,
|
|
11
|
+
createFsFacade,
|
|
12
|
+
debug,
|
|
13
|
+
RubyError,
|
|
14
|
+
type FsFacade,
|
|
15
|
+
type VMCore,
|
|
16
|
+
type VMWithBundledWasi,
|
|
17
|
+
type CreateVMOptions,
|
|
18
|
+
type EvalOptions,
|
|
19
|
+
type LoadBytecodeOptions,
|
|
20
|
+
} from "./index.js";
|
|
21
|
+
|
|
22
|
+
// --- Directory / File ---------------------------------------------------
|
|
23
|
+
const f: File = new File(new Uint8Array([1, 2, 3]));
|
|
24
|
+
const bytes: Uint8Array = f.data;
|
|
25
|
+
void bytes;
|
|
26
|
+
|
|
27
|
+
const root: Directory = new Directory({
|
|
28
|
+
"hello.txt": new File(new TextEncoder().encode("hi")),
|
|
29
|
+
nested: new Directory({ "a.txt": new File() }),
|
|
30
|
+
});
|
|
31
|
+
const childEntries: Record<string, File | Directory> = root.entries;
|
|
32
|
+
void childEntries;
|
|
33
|
+
|
|
34
|
+
// --- createFsFacade -----------------------------------------------------
|
|
35
|
+
const fs: FsFacade = createFsFacade(root);
|
|
36
|
+
fs.set("/x.txt", new Uint8Array(0)).set("/y.txt", new Uint8Array(0));
|
|
37
|
+
const got: Uint8Array | undefined = fs.get("/x.txt");
|
|
38
|
+
const present: boolean = fs.has("/x.txt");
|
|
39
|
+
const sz: number = fs.size;
|
|
40
|
+
void got; void present; void sz;
|
|
41
|
+
for (const [path, data] of fs) {
|
|
42
|
+
const p: string = path;
|
|
43
|
+
const d: Uint8Array = data;
|
|
44
|
+
void p; void d;
|
|
45
|
+
}
|
|
46
|
+
const k: IterableIterator<string> = fs.keys();
|
|
47
|
+
void k.next();
|
|
48
|
+
|
|
49
|
+
// --- debug --------------------------------------------------------------
|
|
50
|
+
debug.trace = true;
|
|
51
|
+
|
|
52
|
+
// --- createVM with bundled WASI -----------------------------------------
|
|
53
|
+
const vmBundled: VMWithBundledWasi = await createVM({
|
|
54
|
+
wasm: "/path/to/mruby-js.wasm",
|
|
55
|
+
env: { LANG: "C.UTF-8" },
|
|
56
|
+
args: ["mruby-wasm-js", "demo"],
|
|
57
|
+
stdin: "hello\n",
|
|
58
|
+
fs: root,
|
|
59
|
+
});
|
|
60
|
+
const rc: number = vmBundled.eval('puts "hi"');
|
|
61
|
+
void rc;
|
|
62
|
+
vmBundled.loadBytecode(new Uint8Array(0));
|
|
63
|
+
vmBundled.loadBytecode(new ArrayBuffer(0));
|
|
64
|
+
vmBundled.fs.set("/runtime-added.txt", new Uint8Array(0));
|
|
65
|
+
vmBundled.env.NEW_VAR = "1";
|
|
66
|
+
vmBundled.args.push("more");
|
|
67
|
+
vmBundled.stdin.pushText("more\n");
|
|
68
|
+
|
|
69
|
+
// --- createVM with custom WASI ------------------------------------------
|
|
70
|
+
const wasi: WebAssembly.ModuleImports = {
|
|
71
|
+
fd_write: (() => 0) as unknown as Function,
|
|
72
|
+
};
|
|
73
|
+
const vmCustom: VMCore = await createVM({
|
|
74
|
+
wasm: "/path/to/mruby-js.wasm",
|
|
75
|
+
wasi,
|
|
76
|
+
onStart: (inst) => {
|
|
77
|
+
const start = inst.exports._start as () => void;
|
|
78
|
+
start();
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// @ts-expect-error -- VMCore must NOT carry `fs` (that's bundled-only)
|
|
83
|
+
vmCustom.fs;
|
|
84
|
+
|
|
85
|
+
// --- CreateVMOptions union exposed for callers --------------------------
|
|
86
|
+
const opts: CreateVMOptions = { wasm: "x" };
|
|
87
|
+
void opts;
|
|
88
|
+
|
|
89
|
+
// --- VMCore handle table -----------------------------------------------
|
|
90
|
+
const h: number = vmCustom.alloc({ any: "value" });
|
|
91
|
+
const back: unknown = vmCustom.get(h);
|
|
92
|
+
vmCustom.release(h);
|
|
93
|
+
const live: number = vmCustom.handleCount();
|
|
94
|
+
void back; void live;
|
|
95
|
+
|
|
96
|
+
// --- evalScript ---------------------------------------------------------
|
|
97
|
+
vmBundled.evalScript("#ruby");
|
|
98
|
+
vmBundled.evalScript("#ruby", { filename: "embedded.rb", lineOffset: 5 });
|
|
99
|
+
|
|
100
|
+
// --- RubyError + eval options -------------------------------------------
|
|
101
|
+
const evalOpts: EvalOptions = { filename: "app.rb", lineOffset: 1, throw: false };
|
|
102
|
+
const loadOpts: LoadBytecodeOptions = { throw: false };
|
|
103
|
+
const noThrowRc: number = vmBundled.eval("nope", evalOpts);
|
|
104
|
+
const noThrowLoad: number = vmBundled.loadBytecode(new Uint8Array(0), loadOpts);
|
|
105
|
+
void noThrowRc; void noThrowLoad;
|
|
106
|
+
|
|
107
|
+
try {
|
|
108
|
+
vmBundled.eval("def foo", { filename: "x.rb" });
|
|
109
|
+
} catch (e) {
|
|
110
|
+
if (e instanceof RubyError) {
|
|
111
|
+
const cls: string = e.rubyClass;
|
|
112
|
+
const bt: string[] = e.backtrace;
|
|
113
|
+
void cls; void bt;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
const re: RubyError = new RubyError({ class: "Boom", message: "x", backtrace: [] });
|
|
117
|
+
void re;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// Shared debug toggle. Lives in its own module so index.js (gem core)
|
|
2
|
+
// and wasi-preview1.js (one of N possible WASI impls) can both import it
|
|
3
|
+
// without forming a cycle.
|
|
4
|
+
//
|
|
5
|
+
// Set `debug.trace = true` at runtime to log handle release / callback
|
|
6
|
+
// dispatch / WASI fd_read / WASI path_open. Off by default — production
|
|
7
|
+
// noise.
|
|
8
|
+
export const debug = { trace: false };
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
// Type definitions for @takahashim/mruby-wasm-js
|
|
2
|
+
// mruby ↔ JavaScript bridge for WebAssembly.
|
|
3
|
+
|
|
4
|
+
/** A regular-file node in the virtual filesystem. */
|
|
5
|
+
export class File {
|
|
6
|
+
constructor(data?: Uint8Array);
|
|
7
|
+
data: Uint8Array;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/** A directory node in the virtual filesystem. */
|
|
11
|
+
export class Directory {
|
|
12
|
+
constructor(entries?: Record<string, File | Directory>);
|
|
13
|
+
entries: Record<string, File | Directory>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Map-style facade over a {@link Directory} tree. Iteration walks the
|
|
18
|
+
* tree depth-first and yields only File leaves, keyed by absolute path.
|
|
19
|
+
*/
|
|
20
|
+
export interface FsFacade {
|
|
21
|
+
set(path: string, bytes: Uint8Array): this;
|
|
22
|
+
get(path: string): Uint8Array | undefined;
|
|
23
|
+
has(path: string): boolean;
|
|
24
|
+
delete(path: string): boolean;
|
|
25
|
+
entries(): IterableIterator<[string, Uint8Array]>;
|
|
26
|
+
keys(): IterableIterator<string>;
|
|
27
|
+
values(): IterableIterator<Uint8Array>;
|
|
28
|
+
[Symbol.iterator](): IterableIterator<[string, Uint8Array]>;
|
|
29
|
+
readonly size: number;
|
|
30
|
+
clear(): void;
|
|
31
|
+
/** Replace root contents with another Directory's entries. */
|
|
32
|
+
populate(dir: Directory): void;
|
|
33
|
+
readonly root: Directory;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Wrap a {@link Directory} root as a Map-compatible facade. */
|
|
37
|
+
export function createFsFacade(root: Directory): FsFacade;
|
|
38
|
+
|
|
39
|
+
/** Mutable bundled-stdin handle exposed on the VM. */
|
|
40
|
+
export interface VMStdin {
|
|
41
|
+
bytes: Uint8Array;
|
|
42
|
+
pushText(s: string): void;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Thrown by {@link VMCore.eval} / {@link VMCore.loadBytecode} when
|
|
47
|
+
* mruby raises an unhandled exception. `rubyClass` mirrors
|
|
48
|
+
* `exception.class.name`; `backtrace` mirrors `exception.backtrace`.
|
|
49
|
+
*/
|
|
50
|
+
export class RubyError extends Error {
|
|
51
|
+
constructor(info?: { class?: string; message?: string; backtrace?: string[] });
|
|
52
|
+
rubyClass: string;
|
|
53
|
+
backtrace: string[];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** Optional knobs for {@link VMCore.eval}. */
|
|
57
|
+
export interface EvalOptions {
|
|
58
|
+
/** Filename surfaced in error backtraces (e.g., `"app.rb"`). */
|
|
59
|
+
filename?: string;
|
|
60
|
+
/**
|
|
61
|
+
* 1-based line number that source line 1 reports as. Useful when the
|
|
62
|
+
* Ruby was extracted from a wrapping context (e.g., `<script>` block
|
|
63
|
+
* embedded at line 17 of an HTML file).
|
|
64
|
+
*/
|
|
65
|
+
lineOffset?: number;
|
|
66
|
+
/**
|
|
67
|
+
* When `true` (default), mruby exceptions surface as a thrown
|
|
68
|
+
* {@link RubyError}. Pass `false` to retain the legacy contract where
|
|
69
|
+
* `eval` returns `1` on failure and the caller inspects rc.
|
|
70
|
+
*/
|
|
71
|
+
throw?: boolean;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Optional knobs for {@link VMCore.loadBytecode}. */
|
|
75
|
+
export interface LoadBytecodeOptions {
|
|
76
|
+
/** Same semantics as {@link EvalOptions.throw}. */
|
|
77
|
+
throw?: boolean;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Methods common to every VM returned by {@link createVM}. */
|
|
81
|
+
export interface VMCore {
|
|
82
|
+
instance: WebAssembly.Instance;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Parse + run Ruby source on the live VM. By default throws
|
|
86
|
+
* {@link RubyError} on parse/runtime error. Returns 0 on success.
|
|
87
|
+
* Throws `NotImplementedError` in compiler-less builds (use
|
|
88
|
+
* {@link loadBytecode} instead). With `options.throw === false`,
|
|
89
|
+
* returns 1 on error instead of throwing.
|
|
90
|
+
*/
|
|
91
|
+
eval(source: string, options?: EvalOptions): number;
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Load pre-compiled mruby bytecode (mrbc output). By default throws
|
|
95
|
+
* {@link RubyError} on runtime error. Returns 0 on success. Accepts
|
|
96
|
+
* `Uint8Array` or `ArrayBuffer`. Available in every build variant.
|
|
97
|
+
* With `options.throw === false`, returns 1 on error instead of throwing.
|
|
98
|
+
*/
|
|
99
|
+
loadBytecode(bytes: Uint8Array | ArrayBuffer, options?: LoadBytecodeOptions): number;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Eval the textContent of a DOM element matched by `selector`. Pairs
|
|
103
|
+
* with `<script type="text/ruby">` blocks. Browser-only — throws if
|
|
104
|
+
* `document` is undefined.
|
|
105
|
+
*/
|
|
106
|
+
evalScript(selector: string, options?: EvalOptions): number;
|
|
107
|
+
|
|
108
|
+
/** Power-user handle table — allocate a slot for a JS value. */
|
|
109
|
+
alloc(value: unknown): number;
|
|
110
|
+
/** Look up the JS value behind a handle. */
|
|
111
|
+
get(handle: number): unknown;
|
|
112
|
+
/** Release a handle slot. */
|
|
113
|
+
release(handle: number): void;
|
|
114
|
+
/** Live handle count (useful for leak detection in tests). */
|
|
115
|
+
handleCount(): number;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* VM returned when `createVM` is invoked without `options.wasi`.
|
|
120
|
+
* The bundled WASI preview1 impl owns fs / env / args / stdin and
|
|
121
|
+
* exposes them here.
|
|
122
|
+
*/
|
|
123
|
+
export interface VMWithBundledWasi extends VMCore {
|
|
124
|
+
fs: FsFacade;
|
|
125
|
+
env: Record<string, string>;
|
|
126
|
+
args: string[];
|
|
127
|
+
stdin: VMStdin;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/** Options shared by every {@link createVM} call. */
|
|
131
|
+
interface CreateVMOptionsBase {
|
|
132
|
+
/** URL to mruby-js.wasm. Required. */
|
|
133
|
+
wasm: string;
|
|
134
|
+
/**
|
|
135
|
+
* Post-instantiate callback. Defaults to calling
|
|
136
|
+
* `instance.exports._initialize()` for reactor modules, falling back
|
|
137
|
+
* to `_start()` for command modules.
|
|
138
|
+
*/
|
|
139
|
+
onStart?: (instance: WebAssembly.Instance) => void;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Options when using the bundled in-memory WASI preview1 impl
|
|
144
|
+
* (default — when `wasi` is omitted).
|
|
145
|
+
*/
|
|
146
|
+
export interface CreateVMOptionsBundled extends CreateVMOptionsBase {
|
|
147
|
+
wasi?: undefined;
|
|
148
|
+
/** Initial ENV available to Ruby via `ENV[]`. */
|
|
149
|
+
env?: Record<string, string>;
|
|
150
|
+
/** Initial ARGV. `args[1..]` lands in Ruby's `ARGV`. */
|
|
151
|
+
args?: string[];
|
|
152
|
+
/** Initial stdin payload for `STDIN.read` / `gets`. */
|
|
153
|
+
stdin?: string | Uint8Array;
|
|
154
|
+
/** Initial root directory for the virtual filesystem. */
|
|
155
|
+
fs?: Directory;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Options when supplying a replacement `wasi_snapshot_preview1` import
|
|
160
|
+
* object (e.g. `@bjorn3/browser_wasi_shim`). The returned VM does NOT
|
|
161
|
+
* include fs / env / args / stdin — the caller's WASI owns that state.
|
|
162
|
+
*/
|
|
163
|
+
export interface CreateVMOptionsCustomWasi extends CreateVMOptionsBase {
|
|
164
|
+
wasi: WebAssembly.ModuleImports;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export type CreateVMOptions = CreateVMOptionsBundled | CreateVMOptionsCustomWasi;
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Instantiate a fresh mruby VM. Each call gets an independent handle
|
|
171
|
+
* table + WASI state — multiple VMs can coexist in one process.
|
|
172
|
+
*/
|
|
173
|
+
export function createVM(options: CreateVMOptionsCustomWasi): Promise<VMCore>;
|
|
174
|
+
export function createVM(options: CreateVMOptionsBundled): Promise<VMWithBundledWasi>;
|
|
175
|
+
|
|
176
|
+
/** Global debug toggle (`{ trace: false }` by default). */
|
|
177
|
+
export const debug: { trace: boolean };
|