@onda-lang/wasm-compiler 0.5.4 → 0.7.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.
- package/README.md +63 -7
- package/bin/onda-wasm.js +1 -1
- package/dist/backend/artifact.d.ts +2 -0
- package/dist/backend/constants.js +1 -1
- package/dist/backend/index.d.ts +2 -0
- package/dist/backend/index.js +2639 -317
- package/dist/build.json +3 -3
- package/dist/frontend/README.md +20 -7
- package/dist/frontend/onda_compiler_web.d.ts +120 -9
- package/dist/frontend/onda_compiler_web.js +556 -42
- package/dist/frontend/onda_compiler_web_bg.wasm +0 -0
- package/dist/frontend/onda_compiler_web_bg.wasm.d.ts +42 -5
- package/dist/frontend/package.json +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -2
- package/src/index.d.ts +119 -5
- package/src/index.js +455 -26
- package/src/worker.js +63 -6
package/src/index.js
CHANGED
|
@@ -3,6 +3,8 @@ import {
|
|
|
3
3
|
PROCESSOR_ABI_VERSION,
|
|
4
4
|
PROCESSOR_ARTIFACT_FORMAT,
|
|
5
5
|
PROCESSOR_ARTIFACT_FORMAT_VERSION,
|
|
6
|
+
PROCESSOR_EXECUTION_OK,
|
|
7
|
+
PROCESSOR_EXECUTION_RUNTIME_SAFETY_FAILURE,
|
|
6
8
|
PROCESSOR_SNAPSHOT_FORMAT_VERSION,
|
|
7
9
|
createProcessorArtifactFiles,
|
|
8
10
|
loadProcessorArtifactFiles,
|
|
@@ -27,6 +29,8 @@ export {
|
|
|
27
29
|
PROCESSOR_ABI_VERSION,
|
|
28
30
|
PROCESSOR_ARTIFACT_FORMAT,
|
|
29
31
|
PROCESSOR_ARTIFACT_FORMAT_VERSION,
|
|
32
|
+
PROCESSOR_EXECUTION_OK,
|
|
33
|
+
PROCESSOR_EXECUTION_RUNTIME_SAFETY_FAILURE,
|
|
30
34
|
PROCESSOR_SNAPSHOT_FORMAT_VERSION,
|
|
31
35
|
createProcessorArtifactFiles,
|
|
32
36
|
loadProcessorArtifactFiles,
|
|
@@ -46,7 +50,10 @@ export class OndaCompilerError extends Error {
|
|
|
46
50
|
}
|
|
47
51
|
|
|
48
52
|
export class OndaCompileError extends OndaCompilerError {
|
|
49
|
-
constructor(
|
|
53
|
+
constructor(
|
|
54
|
+
diagnostics,
|
|
55
|
+
{ cause, sourceFiles = [], unresolvedSourceFiles = [] } = {},
|
|
56
|
+
) {
|
|
50
57
|
const normalized = normalizeDiagnostics(diagnostics);
|
|
51
58
|
const first = normalized[0];
|
|
52
59
|
const message = first
|
|
@@ -55,6 +62,8 @@ export class OndaCompileError extends OndaCompilerError {
|
|
|
55
62
|
super(message, { cause });
|
|
56
63
|
this.name = "OndaCompileError";
|
|
57
64
|
this.diagnostics = normalized;
|
|
65
|
+
this.sourceFiles = normalizeSourceFiles(sourceFiles);
|
|
66
|
+
this.unresolvedSourceFiles = normalizeSourceFiles(unresolvedSourceFiles);
|
|
58
67
|
}
|
|
59
68
|
}
|
|
60
69
|
|
|
@@ -72,9 +81,9 @@ class OndaCompiler {
|
|
|
72
81
|
throw configurationError("source must be a string");
|
|
73
82
|
}
|
|
74
83
|
const compile = normalizeCompileOptions(options);
|
|
75
|
-
let
|
|
84
|
+
let frontendCompilation;
|
|
76
85
|
try {
|
|
77
|
-
|
|
86
|
+
frontendCompilation = this.frontend.compile_to_mir_messagepack(
|
|
78
87
|
source,
|
|
79
88
|
compile.sampleRate,
|
|
80
89
|
compile.blockSize,
|
|
@@ -82,38 +91,204 @@ class OndaCompiler {
|
|
|
82
91
|
} catch (error) {
|
|
83
92
|
throw diagnosticsFromFrontend(error);
|
|
84
93
|
}
|
|
85
|
-
|
|
94
|
+
const { mir, sourceFiles, sourceGraph } = consumeFrontendCompilation(frontendCompilation);
|
|
95
|
+
const artifact = compileMirTransport(
|
|
96
|
+
mir,
|
|
97
|
+
compile.codegen,
|
|
98
|
+
this.compileTrustedMir,
|
|
99
|
+
sourceFiles,
|
|
100
|
+
);
|
|
101
|
+
return { artifact, sourceFiles, sourceGraph };
|
|
86
102
|
}
|
|
87
103
|
|
|
88
|
-
async
|
|
89
|
-
if (!
|
|
90
|
-
throw configurationError("
|
|
104
|
+
async compileWorkspace(workspace, options = {}) {
|
|
105
|
+
if (!workspace || typeof workspace !== "object" || Array.isArray(workspace)) {
|
|
106
|
+
throw configurationError("workspace must contain an entry and source map");
|
|
91
107
|
}
|
|
92
|
-
if (typeof
|
|
93
|
-
throw configurationError("
|
|
108
|
+
if (typeof workspace.entry !== "string" || workspace.entry.length === 0) {
|
|
109
|
+
throw configurationError("workspace.entry must be a non-empty string");
|
|
94
110
|
}
|
|
95
|
-
if (!
|
|
96
|
-
throw configurationError("
|
|
111
|
+
if (!workspace.sources || typeof workspace.sources !== "object" || Array.isArray(workspace.sources)) {
|
|
112
|
+
throw configurationError("workspace.sources must be an object of paths to source strings");
|
|
97
113
|
}
|
|
98
|
-
for (const [path, source] of Object.entries(
|
|
114
|
+
for (const [path, source] of Object.entries(workspace.sources)) {
|
|
99
115
|
if (typeof source !== "string") {
|
|
100
|
-
throw configurationError(`
|
|
116
|
+
throw configurationError(`workspace source '${path}' must be a string`);
|
|
101
117
|
}
|
|
102
118
|
}
|
|
103
119
|
|
|
104
120
|
const compile = normalizeCompileOptions(options);
|
|
105
|
-
let
|
|
121
|
+
let frontendCompilation;
|
|
122
|
+
try {
|
|
123
|
+
frontendCompilation = this.frontend.compile_source_workspace_to_mir_messagepack(
|
|
124
|
+
workspace.entry,
|
|
125
|
+
JSON.stringify(workspace.sources),
|
|
126
|
+
compile.sampleRate,
|
|
127
|
+
compile.blockSize,
|
|
128
|
+
);
|
|
129
|
+
} catch (error) {
|
|
130
|
+
throw diagnosticsFromFrontend(error);
|
|
131
|
+
}
|
|
132
|
+
const { mir, sourceFiles, sourceGraph } = consumeFrontendCompilation(frontendCompilation);
|
|
133
|
+
const artifact = compileMirTransport(
|
|
134
|
+
mir,
|
|
135
|
+
compile.codegen,
|
|
136
|
+
this.compileTrustedMir,
|
|
137
|
+
sourceFiles,
|
|
138
|
+
);
|
|
139
|
+
return { artifact, sourceFiles, sourceGraph };
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
async compileProjectImage(imageBytes, options = {}) {
|
|
143
|
+
const bytes = normalizeBytes(imageBytes, "project image");
|
|
144
|
+
const compile = normalizeCompileOptions(options);
|
|
145
|
+
let frontendCompilation;
|
|
106
146
|
try {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
JSON.stringify(project.sources),
|
|
147
|
+
frontendCompilation = this.frontend.compile_project_image_to_mir_messagepack(
|
|
148
|
+
bytes,
|
|
110
149
|
compile.sampleRate,
|
|
111
150
|
compile.blockSize,
|
|
112
151
|
);
|
|
113
152
|
} catch (error) {
|
|
114
153
|
throw diagnosticsFromFrontend(error);
|
|
115
154
|
}
|
|
116
|
-
|
|
155
|
+
const { mir, sourceFiles, sourceGraph } = consumeFrontendCompilation(frontendCompilation);
|
|
156
|
+
const artifact = compileMirTransport(
|
|
157
|
+
mir,
|
|
158
|
+
compile.codegen,
|
|
159
|
+
this.compileTrustedMir,
|
|
160
|
+
sourceFiles,
|
|
161
|
+
);
|
|
162
|
+
return { artifact, sourceFiles, sourceGraph };
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
async createProjectImage(sourceGraph, buffers = new Map()) {
|
|
166
|
+
const graph = normalizeSourceGraph(sourceGraph);
|
|
167
|
+
const builder = new this.frontend.WebProjectImageBuilder(JSON.stringify(graph));
|
|
168
|
+
try {
|
|
169
|
+
for (const [name, bytes] of normalizeBufferAssetEntries(buffers)) {
|
|
170
|
+
builder.add_buffer(name, bytes);
|
|
171
|
+
}
|
|
172
|
+
const bytes = builder.serialize();
|
|
173
|
+
return {
|
|
174
|
+
bytes,
|
|
175
|
+
...normalizeProjectImageInfo(JSON.parse(this.frontend.inspect_project_image(bytes))),
|
|
176
|
+
};
|
|
177
|
+
} catch (cause) {
|
|
178
|
+
throw new OndaCompilerError("failed to create Onda project image", { cause });
|
|
179
|
+
} finally {
|
|
180
|
+
builder.free();
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
async inspectProjectImage(imageBytes) {
|
|
185
|
+
try {
|
|
186
|
+
return normalizeProjectImageInfo(JSON.parse(this.frontend.inspect_project_image(
|
|
187
|
+
normalizeBytes(imageBytes, "project image"),
|
|
188
|
+
)));
|
|
189
|
+
} catch (cause) {
|
|
190
|
+
throw new OndaCompilerError("failed to inspect Onda project image", { cause });
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
async loadProjectFiles(files, projectFilePath = null) {
|
|
195
|
+
const builder = new this.frontend.WebMaterializedProjectBuilder();
|
|
196
|
+
try {
|
|
197
|
+
if (projectFilePath !== null) {
|
|
198
|
+
builder.select_project(normalizeProjectFilePath(projectFilePath));
|
|
199
|
+
}
|
|
200
|
+
for (const [path, bytes] of normalizeProjectFileEntries(files)) {
|
|
201
|
+
builder.add_file(path, bytes);
|
|
202
|
+
}
|
|
203
|
+
const bytes = builder.serialize();
|
|
204
|
+
return {
|
|
205
|
+
bytes,
|
|
206
|
+
...normalizeProjectImageInfo(JSON.parse(this.frontend.inspect_project_image(bytes))),
|
|
207
|
+
};
|
|
208
|
+
} catch (cause) {
|
|
209
|
+
throw new OndaCompilerError("failed to load Onda project files", { cause });
|
|
210
|
+
} finally {
|
|
211
|
+
builder.free();
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
async materializeProjectImage(imageBytes, assetFileNames = new Map()) {
|
|
216
|
+
let plan;
|
|
217
|
+
try {
|
|
218
|
+
plan = this.frontend.materialize_project_image(
|
|
219
|
+
normalizeBytes(imageBytes, "project image"),
|
|
220
|
+
JSON.stringify(Object.fromEntries(normalizeAssetFileNameEntries(assetFileNames))),
|
|
221
|
+
);
|
|
222
|
+
const files = [];
|
|
223
|
+
for (let index = 0; index < plan.file_count(); index += 1) {
|
|
224
|
+
files.push({ path: plan.file_path(index), bytes: plan.file_bytes(index) });
|
|
225
|
+
}
|
|
226
|
+
return { directories: JSON.parse(plan.directories_json()), files };
|
|
227
|
+
} catch (cause) {
|
|
228
|
+
throw new OndaCompilerError("failed to materialize Onda project image", { cause });
|
|
229
|
+
} finally {
|
|
230
|
+
plan?.free();
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
async encodeBufferAsset(binding) {
|
|
235
|
+
const normalized = normalizeBufferBinding(binding);
|
|
236
|
+
try {
|
|
237
|
+
return this.frontend.encode_buffer_asset(
|
|
238
|
+
normalized.element,
|
|
239
|
+
normalized.frames,
|
|
240
|
+
normalized.channels,
|
|
241
|
+
normalized.sampleRate,
|
|
242
|
+
encodeCanonicalPayload(normalized.element, normalized.data),
|
|
243
|
+
);
|
|
244
|
+
} catch (cause) {
|
|
245
|
+
throw new OndaCompilerError("failed to encode Onda buffer asset", { cause });
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
async decodeBufferAsset(bytes) {
|
|
250
|
+
return this.#decodeBuffer(
|
|
251
|
+
() => this.frontend.decode_buffer_asset(normalizeBytes(bytes, "buffer asset")),
|
|
252
|
+
"failed to decode Onda buffer asset",
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
async decodeBufferFile(bytes, path = "buffer") {
|
|
257
|
+
return this.#decodeBuffer(
|
|
258
|
+
() => this.frontend.decode_buffer_file(
|
|
259
|
+
normalizeBytes(bytes, "buffer file"),
|
|
260
|
+
String(path),
|
|
261
|
+
),
|
|
262
|
+
"failed to decode buffer file",
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
async #decodeBuffer(decode, message) {
|
|
267
|
+
let decoded;
|
|
268
|
+
try {
|
|
269
|
+
decoded = decode();
|
|
270
|
+
const element = decoded.element();
|
|
271
|
+
const payload = decoded.canonical_payload();
|
|
272
|
+
return {
|
|
273
|
+
element,
|
|
274
|
+
frames: decoded.frames(),
|
|
275
|
+
channels: decoded.channels(),
|
|
276
|
+
sampleRate: decoded.sample_rate(),
|
|
277
|
+
data: decodeCanonicalPayload(element, payload),
|
|
278
|
+
};
|
|
279
|
+
} catch (cause) {
|
|
280
|
+
throw new OndaCompilerError(message, { cause });
|
|
281
|
+
} finally {
|
|
282
|
+
decoded?.free();
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
async projectCapabilities() {
|
|
287
|
+
return {
|
|
288
|
+
imageFormatVersion: this.frontend.project_image_format_version(),
|
|
289
|
+
bufferAssetFormatVersion: this.frontend.buffer_asset_format_version(),
|
|
290
|
+
stdlibDigest: this.frontend.current_stdlib_digest(),
|
|
291
|
+
};
|
|
117
292
|
}
|
|
118
293
|
|
|
119
294
|
async sendLspMessage(message) {
|
|
@@ -167,8 +342,44 @@ class WorkerOndaCompiler {
|
|
|
167
342
|
return this.request("compileSource", { source, options });
|
|
168
343
|
}
|
|
169
344
|
|
|
170
|
-
|
|
171
|
-
return this.request("
|
|
345
|
+
compileWorkspace(workspace, options = {}) {
|
|
346
|
+
return this.request("compileWorkspace", { workspace, options });
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
compileProjectImage(imageBytes, options = {}) {
|
|
350
|
+
return this.request("compileProjectImage", { imageBytes, options });
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
createProjectImage(sourceGraph, buffers = new Map()) {
|
|
354
|
+
return this.request("createProjectImage", { sourceGraph, buffers });
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
inspectProjectImage(imageBytes) {
|
|
358
|
+
return this.request("inspectProjectImage", { imageBytes });
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
loadProjectFiles(files, projectFilePath = null) {
|
|
362
|
+
return this.request("loadProjectFiles", { files, projectFilePath });
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
materializeProjectImage(imageBytes, assetFileNames = new Map()) {
|
|
366
|
+
return this.request("materializeProjectImage", { imageBytes, assetFileNames });
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
encodeBufferAsset(binding) {
|
|
370
|
+
return this.request("encodeBufferAsset", { binding });
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
decodeBufferAsset(bytes) {
|
|
374
|
+
return this.request("decodeBufferAsset", { bytes });
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
decodeBufferFile(bytes, path = "buffer") {
|
|
378
|
+
return this.request("decodeBufferFile", { bytes, path });
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
projectCapabilities() {
|
|
382
|
+
return this.request("projectCapabilities");
|
|
172
383
|
}
|
|
173
384
|
|
|
174
385
|
sendLspMessage(message) {
|
|
@@ -212,7 +423,10 @@ class WorkerOndaCompiler {
|
|
|
212
423
|
return;
|
|
213
424
|
}
|
|
214
425
|
const error = message.error?.diagnostics
|
|
215
|
-
? new OndaCompileError(message.error.diagnostics
|
|
426
|
+
? new OndaCompileError(message.error.diagnostics, {
|
|
427
|
+
sourceFiles: message.error.sourceFiles,
|
|
428
|
+
unresolvedSourceFiles: message.error.unresolvedSourceFiles,
|
|
429
|
+
})
|
|
216
430
|
: new OndaCompilerError(message.error?.message ?? "compiler worker failed");
|
|
217
431
|
if (message.error?.name) error.name = message.error.name;
|
|
218
432
|
if (message.error?.stack) error.stack = message.error.stack;
|
|
@@ -310,7 +524,20 @@ function normalizeCompileOptions(options) {
|
|
|
310
524
|
return { sampleRate, blockSize, codegen: options.codegen ?? {} };
|
|
311
525
|
}
|
|
312
526
|
|
|
313
|
-
function
|
|
527
|
+
function consumeFrontendCompilation(compilation) {
|
|
528
|
+
try {
|
|
529
|
+
const mir = compilation.take_mir();
|
|
530
|
+
const sourceFiles = normalizeSourceFiles(JSON.parse(compilation.source_files_json()));
|
|
531
|
+
const sourceGraph = normalizeReturnedSourceGraph(
|
|
532
|
+
JSON.parse(compilation.source_image_json()),
|
|
533
|
+
);
|
|
534
|
+
return { mir, sourceFiles, sourceGraph };
|
|
535
|
+
} finally {
|
|
536
|
+
compilation.free();
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
function compileMirTransport(mir, codegen, compileTrustedMir, sourceFiles) {
|
|
314
541
|
try {
|
|
315
542
|
return compileTrustedMir(mir, codegen);
|
|
316
543
|
} catch (cause) {
|
|
@@ -325,7 +552,7 @@ function compileMirTransport(mir, codegen, compileTrustedMir) {
|
|
|
325
552
|
end_line: 0,
|
|
326
553
|
end_column: 0,
|
|
327
554
|
trace: [],
|
|
328
|
-
}], { cause });
|
|
555
|
+
}], { cause, sourceFiles });
|
|
329
556
|
}
|
|
330
557
|
}
|
|
331
558
|
|
|
@@ -333,9 +560,16 @@ function diagnosticsFromFrontend(error) {
|
|
|
333
560
|
const encoded = typeof error === "string" ? error : error?.message;
|
|
334
561
|
if (typeof encoded === "string") {
|
|
335
562
|
try {
|
|
336
|
-
const
|
|
337
|
-
if (Array.isArray(
|
|
338
|
-
return new OndaCompileError(
|
|
563
|
+
const failure = JSON.parse(encoded);
|
|
564
|
+
if (Array.isArray(failure)) {
|
|
565
|
+
return new OndaCompileError(failure, { cause: error });
|
|
566
|
+
}
|
|
567
|
+
if (failure && Array.isArray(failure.diagnostics)) {
|
|
568
|
+
return new OndaCompileError(failure.diagnostics, {
|
|
569
|
+
cause: error,
|
|
570
|
+
sourceFiles: failure.source_files,
|
|
571
|
+
unresolvedSourceFiles: failure.unresolved_source_files,
|
|
572
|
+
});
|
|
339
573
|
}
|
|
340
574
|
} catch {}
|
|
341
575
|
}
|
|
@@ -382,3 +616,198 @@ function normalizeDiagnostics(diagnostics) {
|
|
|
382
616
|
: [],
|
|
383
617
|
}));
|
|
384
618
|
}
|
|
619
|
+
|
|
620
|
+
function normalizeSourceFiles(sourceFiles) {
|
|
621
|
+
if (!Array.isArray(sourceFiles)) return [];
|
|
622
|
+
return sourceFiles.map((path) => String(path));
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
function normalizeBytes(value, context) {
|
|
626
|
+
if (value instanceof Uint8Array) return value;
|
|
627
|
+
if (value instanceof ArrayBuffer) return new Uint8Array(value);
|
|
628
|
+
if (ArrayBuffer.isView(value)) {
|
|
629
|
+
return new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
|
|
630
|
+
}
|
|
631
|
+
throw new OndaCompilerError(`${context} must be an ArrayBuffer or typed-array view`);
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
function normalizeSourceGraph(graph) {
|
|
635
|
+
if (!graph || typeof graph !== "object" || Array.isArray(graph)) {
|
|
636
|
+
throw new OndaCompilerError("source graph must be an object");
|
|
637
|
+
}
|
|
638
|
+
const entry = String(graph.entry ?? "");
|
|
639
|
+
const stdlibDigest = String(graph.stdlibDigest ?? graph.stdlib_digest ?? "");
|
|
640
|
+
if (!entry || !stdlibDigest) {
|
|
641
|
+
throw new OndaCompilerError("source graph requires entry and stdlibDigest");
|
|
642
|
+
}
|
|
643
|
+
const documents = Array.isArray(graph.documents) ? graph.documents.map((document) => ({
|
|
644
|
+
path: String(document?.path ?? ""),
|
|
645
|
+
contents: String(document?.contents ?? ""),
|
|
646
|
+
})) : [];
|
|
647
|
+
const resolutions = Array.isArray(graph.resolutions) ? graph.resolutions.map((resolution) => ({
|
|
648
|
+
source: String(resolution?.source ?? ""),
|
|
649
|
+
kind: String(resolution?.kind ?? ""),
|
|
650
|
+
specifier: String(resolution?.specifier ?? ""),
|
|
651
|
+
target: String(resolution?.target ?? ""),
|
|
652
|
+
})) : [];
|
|
653
|
+
return {
|
|
654
|
+
entry,
|
|
655
|
+
stdlib_digest: stdlibDigest,
|
|
656
|
+
documents,
|
|
657
|
+
resolutions,
|
|
658
|
+
};
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
function normalizeReturnedSourceGraph(graph) {
|
|
662
|
+
if (!graph) return null;
|
|
663
|
+
return {
|
|
664
|
+
entry: String(graph.entry),
|
|
665
|
+
stdlibDigest: String(graph.stdlib_digest),
|
|
666
|
+
documents: graph.documents.map((document) => ({
|
|
667
|
+
path: String(document.path),
|
|
668
|
+
contents: String(document.contents),
|
|
669
|
+
})),
|
|
670
|
+
resolutions: graph.resolutions.map((resolution) => ({
|
|
671
|
+
source: String(resolution.source),
|
|
672
|
+
kind: String(resolution.kind),
|
|
673
|
+
specifier: String(resolution.specifier),
|
|
674
|
+
target: String(resolution.target),
|
|
675
|
+
})),
|
|
676
|
+
};
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
function normalizeProjectImageInfo(info) {
|
|
680
|
+
return {
|
|
681
|
+
formatVersion: Number(info.format_version),
|
|
682
|
+
contentDigest: String(info.content_digest),
|
|
683
|
+
sourceGraph: normalizeReturnedSourceGraph(info.sources),
|
|
684
|
+
buffers: info.buffers.map((buffer) => ({
|
|
685
|
+
name: String(buffer.name),
|
|
686
|
+
assetId: String(buffer.asset_id),
|
|
687
|
+
element: String(buffer.element),
|
|
688
|
+
frames: Number(buffer.frames),
|
|
689
|
+
channels: Number(buffer.channels),
|
|
690
|
+
sampleRate: Number(buffer.sample_rate),
|
|
691
|
+
})),
|
|
692
|
+
};
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
function normalizeBufferAssetEntries(buffers) {
|
|
696
|
+
const entries = buffers instanceof Map
|
|
697
|
+
? [...buffers]
|
|
698
|
+
: buffers && typeof buffers === "object" && !Array.isArray(buffers)
|
|
699
|
+
? Object.entries(buffers)
|
|
700
|
+
: null;
|
|
701
|
+
if (!entries) throw new OndaCompilerError("project buffers must be a Map or object");
|
|
702
|
+
return entries.map(([name, bytes]) => {
|
|
703
|
+
if (typeof name !== "string" || !name) {
|
|
704
|
+
throw new OndaCompilerError("project buffer names must be non-empty strings");
|
|
705
|
+
}
|
|
706
|
+
return [name, normalizeBytes(bytes, `project buffer '${name}'`)];
|
|
707
|
+
});
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
function normalizeAssetFileNameEntries(fileNames) {
|
|
711
|
+
const entries = fileNames instanceof Map
|
|
712
|
+
? [...fileNames]
|
|
713
|
+
: fileNames && typeof fileNames === "object" && !Array.isArray(fileNames)
|
|
714
|
+
? Object.entries(fileNames)
|
|
715
|
+
: null;
|
|
716
|
+
if (!entries) throw new OndaCompilerError("asset filenames must be a Map or object");
|
|
717
|
+
return entries.map(([name, fileName]) => {
|
|
718
|
+
if (typeof name !== "string" || !name || typeof fileName !== "string" || !fileName) {
|
|
719
|
+
throw new OndaCompilerError("asset filenames require non-empty buffer names and filenames");
|
|
720
|
+
}
|
|
721
|
+
return [name, fileName];
|
|
722
|
+
});
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
function normalizeProjectFilePath(path) {
|
|
726
|
+
if (typeof path !== "string" || !path) {
|
|
727
|
+
throw new OndaCompilerError("selected project manifest must be a non-empty string");
|
|
728
|
+
}
|
|
729
|
+
return path;
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
function normalizeProjectFileEntries(files) {
|
|
733
|
+
const entries = files instanceof Map
|
|
734
|
+
? [...files]
|
|
735
|
+
: files && typeof files === "object" && !Array.isArray(files)
|
|
736
|
+
? Object.entries(files)
|
|
737
|
+
: null;
|
|
738
|
+
if (!entries) throw new OndaCompilerError("project files must be a Map or object");
|
|
739
|
+
return entries.map(([path, bytes]) => {
|
|
740
|
+
if (typeof path !== "string" || !path) {
|
|
741
|
+
throw new OndaCompilerError("project file paths must be non-empty strings");
|
|
742
|
+
}
|
|
743
|
+
return [path, normalizeBytes(bytes, `project file '${path}'`)];
|
|
744
|
+
});
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
function normalizeBufferBinding(binding) {
|
|
748
|
+
if (!binding || typeof binding !== "object" || Array.isArray(binding)) {
|
|
749
|
+
throw new OndaCompilerError("buffer binding must be an object");
|
|
750
|
+
}
|
|
751
|
+
const element = String(binding.element ?? binding.scalar ?? "");
|
|
752
|
+
const frames = Number(binding.frames);
|
|
753
|
+
const channels = Number(binding.channels);
|
|
754
|
+
const sampleRate = Number(binding.sampleRate);
|
|
755
|
+
const data = binding.data;
|
|
756
|
+
const expectedConstructor = {
|
|
757
|
+
bool: Uint8Array,
|
|
758
|
+
i32: Int32Array,
|
|
759
|
+
i64: BigInt64Array,
|
|
760
|
+
f32: Float32Array,
|
|
761
|
+
f64: Float64Array,
|
|
762
|
+
}[element];
|
|
763
|
+
if (!expectedConstructor || !(data instanceof expectedConstructor)) {
|
|
764
|
+
throw new OndaCompilerError(`buffer element '${element}' requires ${expectedConstructor?.name ?? "a supported typed array"}`);
|
|
765
|
+
}
|
|
766
|
+
if (
|
|
767
|
+
!Number.isInteger(frames) || frames <= 0
|
|
768
|
+
|| !Number.isInteger(channels) || channels <= 0
|
|
769
|
+
|| !Number.isFinite(sampleRate) || sampleRate <= 0
|
|
770
|
+
|| data.length !== frames * channels
|
|
771
|
+
) {
|
|
772
|
+
throw new OndaCompilerError("buffer binding has an invalid shape or sample rate");
|
|
773
|
+
}
|
|
774
|
+
return { element, frames, channels, sampleRate, data };
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
function encodeCanonicalPayload(element, data) {
|
|
778
|
+
if (element === "bool") {
|
|
779
|
+
if (data.some((value) => value > 1)) {
|
|
780
|
+
throw new OndaCompilerError("bool buffer values must be 0 or 1");
|
|
781
|
+
}
|
|
782
|
+
return data.slice();
|
|
783
|
+
}
|
|
784
|
+
const bytes = new Uint8Array(data.length * data.BYTES_PER_ELEMENT);
|
|
785
|
+
const view = new DataView(bytes.buffer);
|
|
786
|
+
for (let index = 0; index < data.length; index += 1) {
|
|
787
|
+
const offset = index * data.BYTES_PER_ELEMENT;
|
|
788
|
+
if (element === "i32") view.setInt32(offset, data[index], true);
|
|
789
|
+
else if (element === "i64") view.setBigInt64(offset, data[index], true);
|
|
790
|
+
else if (element === "f32") view.setFloat32(offset, data[index], true);
|
|
791
|
+
else view.setFloat64(offset, data[index], true);
|
|
792
|
+
}
|
|
793
|
+
return bytes;
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
function decodeCanonicalPayload(element, payload) {
|
|
797
|
+
if (element === "bool") return payload.slice();
|
|
798
|
+
const elementBytes = element === "i32" || element === "f32" ? 4 : 8;
|
|
799
|
+
const length = payload.byteLength / elementBytes;
|
|
800
|
+
const output = element === "i32" ? new Int32Array(length)
|
|
801
|
+
: element === "i64" ? new BigInt64Array(length)
|
|
802
|
+
: element === "f32" ? new Float32Array(length)
|
|
803
|
+
: new Float64Array(length);
|
|
804
|
+
const view = new DataView(payload.buffer, payload.byteOffset, payload.byteLength);
|
|
805
|
+
for (let index = 0; index < length; index += 1) {
|
|
806
|
+
const offset = index * elementBytes;
|
|
807
|
+
output[index] = element === "i32" ? view.getInt32(offset, true)
|
|
808
|
+
: element === "i64" ? view.getBigInt64(offset, true)
|
|
809
|
+
: element === "f32" ? view.getFloat32(offset, true)
|
|
810
|
+
: view.getFloat64(offset, true);
|
|
811
|
+
}
|
|
812
|
+
return output;
|
|
813
|
+
}
|
package/src/worker.js
CHANGED
|
@@ -12,19 +12,74 @@ globalThis.addEventListener("message", async (event) => {
|
|
|
12
12
|
return;
|
|
13
13
|
}
|
|
14
14
|
if (message.type === "compileSource") {
|
|
15
|
-
const
|
|
15
|
+
const result = await (await compiler()).compileSource(
|
|
16
16
|
message.source,
|
|
17
17
|
message.options,
|
|
18
18
|
);
|
|
19
|
-
respond(requestId,
|
|
19
|
+
respond(requestId, result, [result.artifact.wasm.buffer]);
|
|
20
20
|
return;
|
|
21
21
|
}
|
|
22
|
-
if (message.type === "
|
|
23
|
-
const
|
|
24
|
-
message.
|
|
22
|
+
if (message.type === "compileWorkspace") {
|
|
23
|
+
const result = await (await compiler()).compileWorkspace(
|
|
24
|
+
message.workspace,
|
|
25
25
|
message.options,
|
|
26
26
|
);
|
|
27
|
-
respond(requestId,
|
|
27
|
+
respond(requestId, result, [result.artifact.wasm.buffer]);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
if (message.type === "compileProjectImage") {
|
|
31
|
+
const result = await (await compiler()).compileProjectImage(
|
|
32
|
+
message.imageBytes,
|
|
33
|
+
message.options,
|
|
34
|
+
);
|
|
35
|
+
respond(requestId, result, [result.artifact.wasm.buffer]);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (message.type === "createProjectImage") {
|
|
39
|
+
const result = await (await compiler()).createProjectImage(
|
|
40
|
+
message.sourceGraph,
|
|
41
|
+
message.buffers,
|
|
42
|
+
);
|
|
43
|
+
respond(requestId, result, [result.bytes.buffer]);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (message.type === "inspectProjectImage") {
|
|
47
|
+
respond(requestId, await (await compiler()).inspectProjectImage(message.imageBytes));
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (message.type === "loadProjectFiles") {
|
|
51
|
+
const result = await (await compiler()).loadProjectFiles(
|
|
52
|
+
message.files,
|
|
53
|
+
message.projectFilePath,
|
|
54
|
+
);
|
|
55
|
+
respond(requestId, result, [result.bytes.buffer]);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (message.type === "materializeProjectImage") {
|
|
59
|
+
const result = await (await compiler()).materializeProjectImage(
|
|
60
|
+
message.imageBytes,
|
|
61
|
+
message.assetFileNames,
|
|
62
|
+
);
|
|
63
|
+
respond(requestId, result, result.files.map((file) => file.bytes.buffer));
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (message.type === "encodeBufferAsset") {
|
|
67
|
+
const result = await (await compiler()).encodeBufferAsset(message.binding);
|
|
68
|
+
respond(requestId, result, [result.buffer]);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (message.type === "decodeBufferAsset") {
|
|
72
|
+
const result = await (await compiler()).decodeBufferAsset(message.bytes);
|
|
73
|
+
respond(requestId, result, [result.data.buffer]);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
if (message.type === "decodeBufferFile") {
|
|
77
|
+
const result = await (await compiler()).decodeBufferFile(message.bytes, message.path);
|
|
78
|
+
respond(requestId, result, [result.data.buffer]);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (message.type === "projectCapabilities") {
|
|
82
|
+
respond(requestId, await (await compiler()).projectCapabilities());
|
|
28
83
|
return;
|
|
29
84
|
}
|
|
30
85
|
if (message.type === "lspMessage") {
|
|
@@ -53,6 +108,8 @@ globalThis.addEventListener("message", async (event) => {
|
|
|
53
108
|
message: error?.message ?? String(error),
|
|
54
109
|
stack: error?.stack,
|
|
55
110
|
diagnostics: error?.diagnostics,
|
|
111
|
+
sourceFiles: error?.sourceFiles,
|
|
112
|
+
unresolvedSourceFiles: error?.unresolvedSourceFiles,
|
|
56
113
|
},
|
|
57
114
|
});
|
|
58
115
|
}
|