@earthyscience/netcdf4-wasm 0.1.0 → 0.1.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/dist/netcdf4.js CHANGED
@@ -1,7 +1,8 @@
1
1
  // Main NetCDF4 class implementation
2
2
  import { Group } from './group.js';
3
3
  import { WasmModuleLoader } from './wasm-module.js';
4
- import { NC_CONSTANTS, DATA_TYPE_SIZE, CONSTANT_DTYPE_MAP } from './constants.js';
4
+ import { NC_CONSTANTS } from './constants.js';
5
+ import * as NCGet from './netcdf-getters.js';
5
6
  export class NetCDF4 extends Group {
6
7
  filename;
7
8
  mode;
@@ -11,6 +12,9 @@ export class NetCDF4 extends Group {
11
12
  ncid = -1;
12
13
  _isOpen = false;
13
14
  memorySource;
15
+ workerSource;
16
+ worker;
17
+ workerReady;
14
18
  constructor(filename, mode = 'r', options = {}) {
15
19
  super(null, '', -1);
16
20
  this.filename = filename;
@@ -20,30 +24,32 @@ export class NetCDF4 extends Group {
20
24
  this.netcdf = this;
21
25
  }
22
26
  async initialize() {
23
- if (this.initialized) {
27
+ if (this.initialized)
24
28
  return;
25
- }
26
29
  try {
27
- this.module = await WasmModuleLoader.loadModule(this.options);
28
- this.initialized = true;
29
- // Mount memory data in virtual file system if provided
30
- if (this.memorySource) {
31
- await this.mountMemoryData();
30
+ if (this.workerSource) {
31
+ // This now handles the WORKERFS mounting
32
+ await this.setupWorker();
33
+ this.initialized = true;
34
+ }
35
+ else {
36
+ this.module = await WasmModuleLoader.loadModule(this.options);
37
+ if (this.memorySource) {
38
+ await this.mountMemoryData();
39
+ }
32
40
  }
33
- // Auto-open file if filename provided (including empty strings which should error)
34
- if (this.filename !== undefined && this.filename !== null) {
41
+ this.initialized = true;
42
+ // Automatically open the file if a filename was provided
43
+ if (this.filename && !this.workerSource) {
35
44
  await this.open();
36
45
  }
37
46
  }
38
47
  catch (error) {
39
- // Check if this is a test environment and we should use mock mode
40
48
  if (typeof process !== 'undefined' && process.env.NODE_ENV === 'test') {
41
- // Mock the module for testing
42
49
  this.module = this.createMockModule();
43
50
  this.initialized = true;
44
- if (this.filename !== undefined && this.filename !== null) {
51
+ if (this.filename)
45
52
  await this.open();
46
- }
47
53
  }
48
54
  else {
49
55
  throw error;
@@ -84,9 +90,27 @@ export class NetCDF4 extends Group {
84
90
  await dataset.initialize();
85
91
  return dataset;
86
92
  }
93
+ // New factory for Blob/File (local, no full preload)
94
+ static async fromBlobLazy(blob, options = {}) {
95
+ // IMPORTANT: Keep this path consistent with the mount logic in the worker
96
+ const mountPoint = '/working';
97
+ const baseName = `netcdf_lazy_${Date.now()}.nc`;
98
+ const fullPath = `${mountPoint}/${baseName}`;
99
+ console.log('fromBlobLazy: Creating dataset with path:', fullPath);
100
+ const dataset = new NetCDF4(fullPath, 'r', options);
101
+ // Store the raw blob. The worker will mount it via WORKERFS
102
+ dataset.workerSource = { blob, filename: fullPath };
103
+ await dataset.initialize();
104
+ console.log('fromBlobLazy: Initialization complete, calling open()');
105
+ // After worker is set up, open the file
106
+ await dataset.open();
107
+ console.log('fromBlobLazy: Open complete, ncid:', dataset.ncid);
108
+ return dataset;
109
+ }
87
110
  async open() {
88
111
  if (this._isOpen)
89
112
  return;
113
+ console.log('open() called, filename:', this.filename, 'worker:', !!this.worker);
90
114
  if (!this.filename || this.filename.trim() === '') {
91
115
  throw new Error('No filename specified');
92
116
  }
@@ -95,6 +119,19 @@ export class NetCDF4 extends Group {
95
119
  if (!validModes.includes(this.mode)) {
96
120
  throw new Error(`Unsupported mode: ${this.mode}`);
97
121
  }
122
+ // Worker path
123
+ if (this.worker) {
124
+ console.log('open(): Using worker path, waiting for workerReady');
125
+ // Wait for worker to be ready first
126
+ await this.workerReady;
127
+ console.log('open(): Worker ready, calling nc_open with path:', this.filename);
128
+ const modeValue = this.mode === 'r' ? NC_CONSTANTS.NC_NOWRITE : NC_CONSTANTS.NC_WRITE;
129
+ this.ncid = await this.callWorker('open', { path: this.filename, modeValue });
130
+ console.log('open(): Received ncid from worker:', this.ncid);
131
+ this.groupId = this.ncid;
132
+ this._isOpen = true;
133
+ return;
134
+ }
98
135
  if (this.mode === 'w' || this.mode === 'w-') {
99
136
  // Create new file
100
137
  let createMode = NC_CONSTANTS.NC_CLOBBER;
@@ -186,305 +223,171 @@ export class NetCDF4 extends Group {
186
223
  return result.ncid;
187
224
  }
188
225
  async closeFile(ncid) {
189
- const module = this.getModule();
190
- const result = module.nc_close(ncid);
191
- if (result !== NC_CONSTANTS.NC_NOERR) {
192
- throw new Error(`Failed to close NetCDF file with ID: ${ncid} (error: ${result})`);
193
- }
194
- }
195
- getGlobalAttributes() {
196
- const attributes = {};
197
- const module = this.module;
198
- if (!module)
199
- throw new Error("Failed to load module. Ensure module is initialized before calling methods");
200
- const nattsResult = module.nc_inq_natts(this.ncid);
201
- if (nattsResult.result !== NC_CONSTANTS.NC_NOERR) {
202
- throw new Error(`Failed to get number of global attributes (error: ${nattsResult.result})`);
203
- }
204
- const nAtts = nattsResult.natts;
205
- const attNames = [];
206
- for (let i = 0; i < nAtts; i++) {
207
- const name = this.getAttributeName(NC_CONSTANTS.NC_GLOBAL, i);
208
- attNames.push(name);
209
- }
210
- if (attNames.length === 0)
211
- return attributes;
212
- for (const attname of attNames) {
213
- if (!attname)
214
- continue;
215
- attributes[attname] = this.getAttributeValues(NC_CONSTANTS.NC_GLOBAL, attname);
216
- }
217
- return attributes;
218
- }
219
- getFullMetadata() {
220
- const varIds = this.getVarIDs();
221
- const metas = [];
222
- for (const varid of varIds) {
223
- const varMeta = this.getVariableInfo(varid);
224
- const { attributes, ...varDeets } = varMeta;
225
- metas.push({ ...varDeets, ...attributes });
226
- }
227
- return metas;
228
- }
229
- getAttributeValues(varid, attname) {
230
- const module = this.module;
231
- if (!module)
232
- throw new Error("Failed to load module. Ensure module is initialized before calling methods");
233
- const attInfo = module.nc_inq_att(this.ncid, varid, attname);
234
- if (attInfo.result !== NC_CONSTANTS.NC_NOERR) {
235
- console.warn(`Failed to get attribute info for ${attname} (error: ${attInfo.result})`);
236
- return;
226
+ if (this.worker) {
227
+ this.callWorker('close');
237
228
  }
238
- const attType = attInfo.type;
239
- if (!attType)
240
- throw new Error("Failed to allocate memory for attribute type.");
241
- let attValue;
242
- if (attType === 2)
243
- attValue = module.nc_get_att_text(this.ncid, varid, attname, attInfo.len);
244
- else if (attType === 3)
245
- attValue = module.nc_get_att_short(this.ncid, varid, attname, attInfo.len);
246
- else if (attType === 4)
247
- attValue = module.nc_get_att_int(this.ncid, varid, attname, attInfo.len);
248
- else if (attType === 5)
249
- attValue = module.nc_get_att_float(this.ncid, varid, attname, attInfo.len);
250
- else if (attType === 6)
251
- attValue = module.nc_get_att_double(this.ncid, varid, attname, attInfo.len);
252
- else if (attType === 10)
253
- attValue = module.nc_get_att_longlong(this.ncid, varid, attname, attInfo.len);
254
- else
255
- attValue = module.nc_get_att_double(this.ncid, varid, attname, attInfo.len);
256
- return attValue.data;
257
- }
258
- getDimCount() {
259
- const module = this.module;
260
- if (!module)
261
- throw new Error("Failed to load module. Ensure module is initialized before calling methods");
262
- const result = module.nc_inq_ndims(this.ncid);
263
- if (result.result !== NC_CONSTANTS.NC_NOERR) {
264
- throw new Error(`Failed to get number of dimensions (error: ${result.result})`);
265
- }
266
- return result.ndims || 0;
267
- }
268
- getVariables() {
269
- const variables = {};
270
- const module = this.module;
271
- if (!module)
272
- throw new Error("Failed to load module. Ensure module is initialized before calling methods");
273
- const varCount = this.getVarCount();
274
- const dimIds = this.getDimIDs();
275
- for (let varid = 0; varid < varCount; varid++) {
276
- if (dimIds.includes(varid))
277
- continue; //Don't include spatial Vars
278
- const result = module.nc_inq_varname(this.ncid, varid);
279
- if (result.result !== NC_CONSTANTS.NC_NOERR || !result.name) {
280
- console.warn(`Failed to get variable name for varid ${varid} (error: ${result.result})`);
281
- continue;
229
+ else {
230
+ const module = this.module;
231
+ if (!module)
232
+ throw new Error("Failed to load module. Ensure module is initialized before calling methods");
233
+ const result = module.nc_close(ncid);
234
+ if (result !== NC_CONSTANTS.NC_NOERR) {
235
+ throw new Error(`Failed to close NetCDF file with ID: ${ncid} (error: ${result})`);
282
236
  }
283
- variables[result.name] = {
284
- id: varid
237
+ }
238
+ }
239
+ requestId = 0;
240
+ async callWorker(type, payload = {}) {
241
+ if (!this.worker)
242
+ throw new Error("Worker not initialized");
243
+ const id = ++this.requestId;
244
+ return new Promise((resolve, reject) => {
245
+ const handler = (e) => {
246
+ // Only handle messages that match our request ID
247
+ if (e.data.id !== id)
248
+ return;
249
+ if (e.data.success) {
250
+ resolve(e.data.result);
251
+ }
252
+ else {
253
+ reject(new Error(e.data.error || `Worker error in ${type}`));
254
+ }
255
+ this.worker.removeEventListener('message', handler);
285
256
  };
257
+ this.worker.addEventListener('message', handler);
258
+ this.worker.postMessage({
259
+ id, // Include the ID in the request
260
+ type,
261
+ ncid: this.ncid,
262
+ ...payload
263
+ });
264
+ });
265
+ }
266
+ async getGlobalAttributes() {
267
+ if (this.worker) {
268
+ return this.callWorker('getGlobalAttributes');
269
+ }
270
+ else {
271
+ // Main thread path is already synchronous (or could be wrapped in Promise.resolve)
272
+ return NCGet.getGlobalAttributes(this.module, this.ncid);
286
273
  }
287
- return variables;
288
274
  }
289
- getVarIDs() {
290
- const module = this.module;
291
- if (!module)
292
- throw new Error("Failed to load module. Ensure module is initialized before calling methods");
293
- const result = module.nc_inq_varids(this.ncid);
294
- if (result.result !== NC_CONSTANTS.NC_NOERR) {
295
- throw new Error(`Failed to get variable IDs (error: ${result.result})`);
275
+ async getFullMetadata() {
276
+ if (this.worker) {
277
+ return this.callWorker('getFullMetadata');
278
+ }
279
+ else {
280
+ // Main thread path is already synchronous (or could be wrapped in Promise.resolve)
281
+ return NCGet.getFullMetadata(this.module, this.ncid);
296
282
  }
297
- return result.varids || [0];
298
283
  }
299
- getDimIDs() {
300
- const module = this.module;
301
- if (!module)
302
- throw new Error("Failed to load module. Ensure module is initialized before calling methods");
303
- const result = module.nc_inq_dimids(this.ncid, 0);
304
- if (result.result !== NC_CONSTANTS.NC_NOERR) {
305
- throw new Error(`Failed to get dimension IDs (error: ${result.result})`);
284
+ async getAttributeValues(varid, attname) {
285
+ if (this.worker) {
286
+ return this.callWorker('getAttributeValues', { varid, attname });
287
+ }
288
+ else {
289
+ // Main thread path is already synchronous (or could be wrapped in Promise.resolve)
290
+ return NCGet.getAttributeValues(this.module, this.ncid, varid, attname);
306
291
  }
307
- return result.dimids || [0];
308
292
  }
309
- getDim(dimid) {
310
- const module = this.module;
311
- if (!module)
312
- throw new Error("Failed to load module. Ensure module is initialized before calling methods");
313
- const result = module.nc_inq_dim(this.ncid, dimid);
314
- if (result.result !== NC_CONSTANTS.NC_NOERR) {
315
- throw new Error(`Failed to get dim (error: ${result.result})`);
316
- }
317
- const varResult = module.nc_inq_varid(this.ncid, result.name);
318
- const varID = varResult.varid;
319
- const { result: output, ...dim } = result;
320
- const unitResult = this.getAttributeValues(varID, "units");
321
- return { ...dim, units: unitResult, id: varID };
322
- }
323
- getDims() {
324
- const dimIDs = this.getDimIDs();
325
- const dims = {};
326
- for (const dimid of dimIDs) {
327
- const dim = this.getDim(dimid);
328
- dims[dim.name] = {
329
- size: dim.len,
330
- units: dim.units,
331
- id: dim.id
332
- };
293
+ async getDimCount() {
294
+ if (this.worker) {
295
+ return this.callWorker('getDimCount');
296
+ }
297
+ else {
298
+ // Main thread path is already synchronous (or could be wrapped in Promise.resolve)
299
+ return NCGet.getDimCount(this.module, this.ncid);
333
300
  }
334
- return dims;
335
301
  }
336
- getVarCount() {
337
- const module = this.module;
338
- if (!module)
339
- throw new Error("Failed to load module. Ensure module is initialized before calling methods");
340
- const result = module.nc_inq_nvars(this.ncid);
341
- if (result.result !== NC_CONSTANTS.NC_NOERR) {
342
- throw new Error(`Failed to get number of variables (error: ${result.result})`);
302
+ async getVariables() {
303
+ if (this.worker) {
304
+ return this.callWorker('getVariables');
305
+ }
306
+ else {
307
+ // Main thread path is already synchronous (or could be wrapped in Promise.resolve)
308
+ return NCGet.getVariables(this.module, this.ncid);
343
309
  }
344
- return result.nvars || 0;
345
310
  }
346
- getAttributeName(varid, attId) {
347
- const module = this.module;
348
- if (!module)
349
- throw new Error("Failed to load module. Ensure module is initialized before calling methods");
350
- const result = module.nc_inq_attname(this.ncid, varid, attId);
351
- if (result.result !== NC_CONSTANTS.NC_NOERR) {
352
- throw new Error(`Failed to get attribute (error: ${result.result})`);
353
- }
354
- return result.name;
355
- }
356
- getVariableInfo(variable) {
357
- const info = {};
358
- const module = this.module;
359
- if (!module)
360
- throw new Error("Failed to load module. Ensure module is initialized before calling methods");
361
- const isId = typeof variable === "number";
362
- let varid = variable;
363
- if (!isId) {
364
- const result = module.nc_inq_varid(this.ncid, variable);
365
- varid = result.varid;
366
- }
367
- const result = module.nc_inq_var(this.ncid, varid);
368
- if (result.result !== NC_CONSTANTS.NC_NOERR) {
369
- throw new Error(`Failed to get variable info (error: ${result.result})`);
370
- }
371
- const typeMultiplier = DATA_TYPE_SIZE[result.type];
372
- //Dim Info
373
- const dimids = result.dimids;
374
- const dims = [];
375
- const shape = [];
376
- let size = 1;
377
- if (dimids) {
378
- for (const dimid of dimids) {
379
- const dim = this.getDim(dimid);
380
- size *= dim.len;
381
- dims.push(dim);
382
- shape.push(dim.len);
383
- }
311
+ async getVarIDs() {
312
+ if (this.worker) {
313
+ return this.callWorker('getVarIDs');
384
314
  }
385
- //Attribute Info
386
- const attNames = [];
387
- if (result.natts) {
388
- for (let i = 0; i < result.natts; i++) {
389
- const attname = this.getAttributeName(varid, i);
390
- attNames.push(attname);
391
- }
315
+ else {
316
+ // Main thread path is already synchronous (or could be wrapped in Promise.resolve)
317
+ return NCGet.getVarIDs(this.module, this.ncid);
392
318
  }
393
- const atts = {};
394
- if (attNames.length > 0) {
395
- for (const attname of attNames) {
396
- if (!attname)
397
- continue;
398
- atts[attname] = this.getAttributeValues(varid, attname);
399
- }
319
+ }
320
+ async getDimIDs() {
321
+ if (this.worker) {
322
+ return this.callWorker('getDimIDs');
323
+ }
324
+ else {
325
+ // Main thread path is already synchronous (or could be wrapped in Promise.resolve)
326
+ return NCGet.getDimIDs(this.module, this.ncid);
327
+ }
328
+ }
329
+ async getDim(dimid) {
330
+ if (this.worker) {
331
+ return this.callWorker('getDim', { dimid });
332
+ }
333
+ else {
334
+ // Main thread path is already synchronous (or could be wrapped in Promise.resolve)
335
+ return NCGet.getDim(this.module, this.ncid, dimid);
336
+ }
337
+ }
338
+ async getDims() {
339
+ if (this.worker) {
340
+ return this.callWorker('getDims');
400
341
  }
401
- //Chunking Info
402
- let chunks;
403
- const chunkResult = module.nc_inq_var_chunking(this.ncid, varid);
404
- const isChunked = chunkResult.chunking === NC_CONSTANTS.NC_CHUNKED;
405
- if (isChunked) {
406
- chunks = chunkResult.chunkSizes;
342
+ else {
343
+ // Main thread path is already synchronous (or could be wrapped in Promise.resolve)
344
+ return NCGet.getDims(this.module, this.ncid);
345
+ }
346
+ }
347
+ async getVarCount() {
348
+ if (this.worker) {
349
+ return this.callWorker('getVarCount');
407
350
  }
408
351
  else {
409
- chunks = shape;
410
- }
411
- const chunkElements = chunks.reduce((a, b) => a * b, 1);
412
- //Output
413
- info["name"] = result.name;
414
- info["dtype"] = CONSTANT_DTYPE_MAP[result.type];
415
- info['nctype'] = result.type;
416
- info["shape"] = shape;
417
- info['dims'] = dims;
418
- info["size"] = size;
419
- info["totalSize"] = size * typeMultiplier;
420
- info["attributes"] = atts;
421
- info["chunked"] = isChunked;
422
- info["chunks"] = chunks;
423
- info["chunkSize"] = chunkElements * typeMultiplier;
424
- return info;
425
- }
426
- getVariableArray(variable) {
427
- const module = this.module;
428
- if (!module)
429
- throw new Error("Failed to load module. Ensure module is initialized before calling methods");
430
- const isId = typeof variable === "number";
431
- let varid = isId ? variable : 0;
432
- if (!isId) {
433
- const result = module.nc_inq_varid(this.ncid, variable);
434
- varid = result.varid;
435
- }
436
- const info = this.getVariableInfo(varid);
437
- const arraySize = info.size;
438
- const arrayType = info.nctype;
439
- if (!arrayType || !arraySize)
440
- throw new Error("Failed to allocate memory for array");
441
- let arrayData;
442
- if (arrayType === 2)
443
- arrayData = module.nc_get_var_text(this.ncid, varid, arraySize);
444
- else if (arrayType === 3)
445
- arrayData = module.nc_get_var_short(this.ncid, varid, arraySize);
446
- else if (arrayType === 4)
447
- arrayData = module.nc_get_var_int(this.ncid, varid, arraySize);
448
- else if (arrayType === 10)
449
- arrayData = module.nc_get_var_longlong(this.ncid, varid, arraySize);
450
- else if (arrayType === 5)
451
- arrayData = module.nc_get_var_float(this.ncid, varid, arraySize);
452
- else if (arrayType === 6)
453
- arrayData = module.nc_get_var_double(this.ncid, varid, arraySize);
454
- else
455
- arrayData = module.nc_get_var_double(this.ncid, varid, arraySize);
456
- if (!arrayData.data)
457
- throw new Error("Failed to read array data");
458
- return arrayData.data;
459
- }
460
- getSlicedVariableArray(variable, start, count) {
461
- const module = this.module;
462
- if (!module)
463
- throw new Error("Failed to load module. Ensure module is initialized before calling methods");
464
- const isId = typeof variable === "number";
465
- let varid = isId ? variable : 0;
466
- if (!isId) {
467
- const result = module.nc_inq_varid(this.ncid, variable);
468
- varid = result.varid;
469
- }
470
- const info = this.getVariableInfo(varid);
471
- const arrayType = info.nctype;
472
- if (!arrayType)
473
- throw new Error("Failed to allocate memory for array");
474
- let arrayData;
475
- if (arrayType === 3)
476
- arrayData = module.nc_get_vara_short(this.ncid, varid, start, count);
477
- else if (arrayType === 4)
478
- arrayData = module.nc_get_vara_int(this.ncid, varid, start, count);
479
- else if (arrayType === 5)
480
- arrayData = module.nc_get_vara_float(this.ncid, varid, start, count);
481
- else if (arrayType === 6)
482
- arrayData = module.nc_get_vara_double(this.ncid, varid, start, count);
483
- else
484
- arrayData = module.nc_get_vara_double(this.ncid, varid, start, count);
485
- if (!arrayData.data)
486
- throw new Error("Failed to read array data");
487
- return arrayData.data;
352
+ // Main thread path is already synchronous (or could be wrapped in Promise.resolve)
353
+ return NCGet.getVarCount(this.module, this.ncid);
354
+ }
355
+ }
356
+ async getAttributeName(varid, attId) {
357
+ if (this.worker) {
358
+ return this.callWorker('getAttributeName', { varid, attId });
359
+ }
360
+ else {
361
+ // Main thread path is already synchronous (or could be wrapped in Promise.resolve)
362
+ return NCGet.getAttributeName(this.module, this.ncid, varid, attId);
363
+ }
364
+ }
365
+ async getVariableInfo(variable) {
366
+ if (this.worker) {
367
+ return this.callWorker('getVariableInfo', { variable });
368
+ }
369
+ else {
370
+ // Main thread path is already synchronous (or could be wrapped in Promise.resolve)
371
+ return NCGet.getVariableInfo(this.module, this.ncid, variable);
372
+ }
373
+ }
374
+ async getVariableArray(variable) {
375
+ if (this.worker) {
376
+ return this.callWorker('getVariableArray', { variable });
377
+ }
378
+ else {
379
+ // Main thread path is already synchronous (or could be wrapped in Promise.resolve)
380
+ return NCGet.getVariableArray(this.module, this.ncid, variable);
381
+ }
382
+ }
383
+ async getSlicedVariableArray(variable, start, count) {
384
+ if (this.worker) {
385
+ return this.callWorker('getSlicedVariableArray', { variable, start, count });
386
+ }
387
+ else {
388
+ // Main thread path is already synchronous (or could be wrapped in Promise.resolve)
389
+ return NCGet.getSlicedVariableArray(this.module, this.ncid, variable, start, count);
390
+ }
488
391
  }
489
392
  async defineDimension(ncid, name, size) {
490
393
  const module = this.getModule();
@@ -639,6 +542,36 @@ export class NetCDF4 extends Group {
639
542
  nc_enddef: (ncid) => NC_CONSTANTS.NC_NOERR,
640
543
  };
641
544
  }
545
+ async setupWorker() {
546
+ if (!this.workerSource)
547
+ throw new Error('No worker source');
548
+ // 1. Instantiate the worker if it doesn't exist
549
+ if (!this.worker) {
550
+ // Option A: If using Vite/Webpack 5
551
+ this.worker = new Worker(new URL('./netcdf-worker.js', import.meta.url), { type: 'module' });
552
+ }
553
+ this.workerReady = new Promise((resolve, reject) => {
554
+ // Use a named function so we can remove the listener later
555
+ const initHandler = (e) => {
556
+ if (e.data.success) {
557
+ this.worker.removeEventListener('message', initHandler);
558
+ resolve();
559
+ }
560
+ else {
561
+ this.worker.removeEventListener('message', initHandler);
562
+ reject(new Error(e.data.message));
563
+ }
564
+ };
565
+ this.worker.addEventListener('message', initHandler);
566
+ // 3. Send the initialization message
567
+ this.worker.postMessage({
568
+ type: 'init',
569
+ blob: this.workerSource.blob,
570
+ filename: this.workerSource.filename
571
+ });
572
+ });
573
+ return this.workerReady;
574
+ }
642
575
  // Mount memory data in the WASM virtual file system
643
576
  async mountMemoryData() {
644
577
  if (!this.memorySource || !this.module) {