@bytecodealliance/jco 1.16.0 → 1.17.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 +6 -6
- package/obj/js-component-bindgen-component.core.wasm +0 -0
- package/obj/js-component-bindgen-component.js +1969 -1664
- package/obj/wasm-tools.core.wasm +0 -0
- package/obj/wasm-tools.js +2072 -1687
- package/package.json +94 -95
- package/src/api.js +5 -14
- package/src/browser.js +1 -1
- package/src/cmd/componentize.d.ts +1 -1
- package/src/cmd/componentize.js +14 -18
- package/src/cmd/opt.d.ts +10 -7
- package/src/cmd/opt.js +44 -96
- package/src/cmd/run.d.ts +1 -1
- package/src/cmd/run.js +31 -48
- package/src/cmd/transpile.d.ts +44 -39
- package/src/cmd/transpile.js +253 -316
- package/src/cmd/types.d.ts +15 -12
- package/src/cmd/types.js +27 -36
- package/src/cmd/wasm-tools.d.ts +1 -1
- package/src/cmd/wasm-tools.js +27 -44
- package/src/common.js +43 -57
- package/src/jco.js +200 -347
- package/types/api.d.ts.map +1 -1
- package/types/common.d.ts.map +1 -1
package/obj/wasm-tools.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
"use jco";
|
|
1
|
+
"use jco";
|
|
2
|
+
import { environment, exit as exit$1, stderr, stdin, stdout, terminalInput, terminalOutput, terminalStderr, terminalStdin, terminalStdout } from '@bytecodealliance/preview2-shim/cli';
|
|
2
3
|
import { preopens, types } from '@bytecodealliance/preview2-shim/filesystem';
|
|
3
4
|
import { error, streams } from '@bytecodealliance/preview2-shim/io';
|
|
4
5
|
import { random } from '@bytecodealliance/preview2-shim/random';
|
|
@@ -165,1791 +166,2102 @@ if (getRandomBytes=== undefined) {
|
|
|
165
166
|
}
|
|
166
167
|
|
|
167
168
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
const toUint64 = val => BigInt.asUintN(64, BigInt(val));
|
|
172
|
-
|
|
173
|
-
function toUint32(val) {
|
|
174
|
-
return val >>> 0;
|
|
169
|
+
const _debugLog = (...args) => {
|
|
170
|
+
if (!globalThis?.process?.env?.JCO_DEBUG) { return; }
|
|
171
|
+
console.debug(...args);
|
|
175
172
|
}
|
|
176
|
-
const
|
|
177
|
-
const TEXT_ENCODER_UTF8 = new TextEncoder();
|
|
173
|
+
const ASYNC_DETERMINISM = 'random';
|
|
178
174
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
175
|
+
class GlobalComponentAsyncLowers {
|
|
176
|
+
static map = new Map();
|
|
177
|
+
|
|
178
|
+
constructor() { throw new Error('GlobalComponentAsyncLowers should not be constructed'); }
|
|
179
|
+
|
|
180
|
+
static define(args) {
|
|
181
|
+
const { componentIdx, qualifiedImportFn, fn } = args;
|
|
182
|
+
let inner = GlobalComponentAsyncLowers.map.get(componentIdx);
|
|
183
|
+
if (!inner) {
|
|
184
|
+
inner = new Map();
|
|
185
|
+
GlobalComponentAsyncLowers.map.set(componentIdx, inner);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
inner.set(qualifiedImportFn, fn);
|
|
182
189
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
const
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
190
|
+
|
|
191
|
+
static lookup(componentIdx, qualifiedImportFn) {
|
|
192
|
+
let inner = GlobalComponentAsyncLowers.map.get(componentIdx);
|
|
193
|
+
if (!inner) {
|
|
194
|
+
inner = new Map();
|
|
195
|
+
GlobalComponentAsyncLowers.map.set(componentIdx, inner);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const found = inner.get(qualifiedImportFn);
|
|
199
|
+
if (found) { return found; }
|
|
200
|
+
|
|
201
|
+
// In some cases, async lowers are *not* host provided, and
|
|
202
|
+
// but contain/will call an async function in the host.
|
|
203
|
+
//
|
|
204
|
+
// One such case is `stream.write`/`stream.read` trampolines which are
|
|
205
|
+
// actually re-exported through a patch up container *before*
|
|
206
|
+
// they call the relevant async host trampoline.
|
|
207
|
+
//
|
|
208
|
+
// So the path of execution from a component export would be:
|
|
209
|
+
//
|
|
210
|
+
// async guest export --> stream.write import (host wired) -> guest export (patch component) -> async host trampoline
|
|
211
|
+
//
|
|
212
|
+
// On top of all this, the trampoline that is eventually called is async,
|
|
213
|
+
// so we must await the patched guest export call.
|
|
214
|
+
//
|
|
215
|
+
if (qualifiedImportFn.includes("[stream-write-") || qualifiedImportFn.includes("[stream-read-")) {
|
|
216
|
+
return async (...args) => {
|
|
217
|
+
const [originalFn, ...params] = args;
|
|
218
|
+
return await originalFn(...params);
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// All other cases can call the registered function directly
|
|
223
|
+
return (...args) => {
|
|
224
|
+
const [originalFn, ...params] = args;
|
|
225
|
+
return originalFn(...params);
|
|
226
|
+
};
|
|
199
227
|
}
|
|
200
|
-
table[0] = table[free << 1];
|
|
201
|
-
table[free << 1] = 0;
|
|
202
|
-
table[(free << 1) + 1] = rep | T_FLAG;
|
|
203
|
-
return free;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
function rscTableRemove (table, handle) {
|
|
207
|
-
const scope = table[handle << 1];
|
|
208
|
-
const val = table[(handle << 1) + 1];
|
|
209
|
-
const own = (val & T_FLAG) !== 0;
|
|
210
|
-
const rep = val & ~T_FLAG;
|
|
211
|
-
if (val === 0 || (scope & T_FLAG) !== 0) throw new TypeError('Invalid handle');
|
|
212
|
-
table[handle << 1] = table[0] | T_FLAG;
|
|
213
|
-
table[0] = handle | T_FLAG;
|
|
214
|
-
return { rep, scope, own };
|
|
215
228
|
}
|
|
216
229
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
230
|
+
class GlobalAsyncParamLowers {
|
|
231
|
+
static map = new Map();
|
|
232
|
+
|
|
233
|
+
static generateKey(args) {
|
|
234
|
+
const { componentIdx, iface, fnName } = args;
|
|
235
|
+
if (componentIdx === undefined) { throw new TypeError("missing component idx"); }
|
|
236
|
+
if (iface === undefined) { throw new TypeError("missing iface name"); }
|
|
237
|
+
if (fnName === undefined) { throw new TypeError("missing function name"); }
|
|
238
|
+
return `${componentIdx}-${iface}-${fnName}`;
|
|
222
239
|
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
function createNewCurrentTask(args) {
|
|
230
|
-
_debugLog('[createNewCurrentTask()] args', args);
|
|
231
|
-
const {
|
|
232
|
-
componentIdx,
|
|
233
|
-
isAsync,
|
|
234
|
-
entryFnName,
|
|
235
|
-
parentSubtaskID,
|
|
236
|
-
callbackFnName,
|
|
237
|
-
getCallbackFn,
|
|
238
|
-
getParamsFn,
|
|
239
|
-
stringEncoding,
|
|
240
|
-
errHandling,
|
|
241
|
-
getCalleeParamsFn,
|
|
242
|
-
resultPtr,
|
|
243
|
-
callingWasmExport,
|
|
244
|
-
} = args;
|
|
245
|
-
if (componentIdx === undefined || componentIdx === null) {
|
|
246
|
-
throw new Error('missing/invalid component instance index while starting task');
|
|
240
|
+
|
|
241
|
+
static define(args) {
|
|
242
|
+
const { componentIdx, iface, fnName, fn } = args;
|
|
243
|
+
if (!fn) { throw new TypeError('missing function'); }
|
|
244
|
+
const key = GlobalAsyncParamLowers.generateKey(args);
|
|
245
|
+
GlobalAsyncParamLowers.map.set(key, fn);
|
|
247
246
|
}
|
|
248
|
-
const taskMetas = ASYNC_TASKS_BY_COMPONENT_IDX.get(componentIdx);
|
|
249
|
-
const callbackFn = getCallbackFn ? getCallbackFn() : null;
|
|
250
247
|
|
|
251
|
-
|
|
252
|
-
componentIdx,
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
errHandling,
|
|
261
|
-
});
|
|
248
|
+
static lookup(args) {
|
|
249
|
+
const { componentIdx, iface, fnName } = args;
|
|
250
|
+
const key = GlobalAsyncParamLowers.generateKey(args);
|
|
251
|
+
return GlobalAsyncParamLowers.map.get(key);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
class GlobalComponentMemories {
|
|
256
|
+
static map = new Map();
|
|
262
257
|
|
|
263
|
-
|
|
264
|
-
const newTaskMeta = { id: newTaskID, componentIdx, task: newTask };
|
|
258
|
+
constructor() { throw new Error('GlobalComponentMemories should not be constructed'); }
|
|
265
259
|
|
|
266
|
-
|
|
267
|
-
|
|
260
|
+
static save(args) {
|
|
261
|
+
const { idx, componentIdx, memory } = args;
|
|
262
|
+
let inner = GlobalComponentMemories.map.get(componentIdx);
|
|
263
|
+
if (!inner) {
|
|
264
|
+
inner = [];
|
|
265
|
+
GlobalComponentMemories.map.set(componentIdx, inner);
|
|
266
|
+
}
|
|
267
|
+
inner.push({ memory, idx });
|
|
268
|
+
}
|
|
268
269
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
taskMetas.push(newTaskMeta);
|
|
270
|
+
static getMemoriesForComponentIdx(componentIdx) {
|
|
271
|
+
const metas = GlobalComponentMemories.map.get(componentIdx);
|
|
272
|
+
return metas.map(meta => meta.memory);
|
|
273
273
|
}
|
|
274
274
|
|
|
275
|
-
|
|
275
|
+
static getMemory(componentIdx, idx) {
|
|
276
|
+
const metas = GlobalComponentMemories.map.get(componentIdx);
|
|
277
|
+
return metas.find(meta => meta.idx === idx)?.memory;
|
|
278
|
+
}
|
|
276
279
|
}
|
|
277
280
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
_debugLog('[endCurrentTask()] args', { componentIdx, taskID });
|
|
281
|
+
class RepTable {
|
|
282
|
+
#data = [0, null];
|
|
283
|
+
#target;
|
|
282
284
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
+
constructor(args) {
|
|
286
|
+
this.target = args?.target;
|
|
285
287
|
}
|
|
286
288
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
289
|
+
insert(val) {
|
|
290
|
+
_debugLog('[RepTable#insert()] args', { val, target: this.target });
|
|
291
|
+
const freeIdx = this.#data[0];
|
|
292
|
+
if (freeIdx === 0) {
|
|
293
|
+
this.#data.push(val);
|
|
294
|
+
this.#data.push(null);
|
|
295
|
+
return (this.#data.length >> 1) - 1;
|
|
296
|
+
}
|
|
297
|
+
this.#data[0] = this.#data[freeIdx << 1];
|
|
298
|
+
const placementIdx = freeIdx << 1;
|
|
299
|
+
this.#data[placementIdx] = val;
|
|
300
|
+
this.#data[placementIdx + 1] = null;
|
|
301
|
+
return freeIdx;
|
|
290
302
|
}
|
|
291
|
-
|
|
292
|
-
|
|
303
|
+
|
|
304
|
+
get(rep) {
|
|
305
|
+
_debugLog('[RepTable#get()] args', { rep, target: this.target });
|
|
306
|
+
const baseIdx = rep << 1;
|
|
307
|
+
const val = this.#data[baseIdx];
|
|
308
|
+
return val;
|
|
293
309
|
}
|
|
294
310
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
return;
|
|
300
|
-
}
|
|
311
|
+
contains(rep) {
|
|
312
|
+
_debugLog('[RepTable#contains()] args', { rep, target: this.target });
|
|
313
|
+
const baseIdx = rep << 1;
|
|
314
|
+
return !!this.#data[baseIdx];
|
|
301
315
|
}
|
|
302
316
|
|
|
303
|
-
|
|
304
|
-
|
|
317
|
+
remove(rep) {
|
|
318
|
+
_debugLog('[RepTable#remove()] args', { rep, target: this.target });
|
|
319
|
+
if (this.#data.length === 2) { throw new Error('invalid'); }
|
|
320
|
+
|
|
321
|
+
const baseIdx = rep << 1;
|
|
322
|
+
const val = this.#data[baseIdx];
|
|
323
|
+
if (val === 0) { throw new Error('invalid resource rep (cannot be 0)'); }
|
|
324
|
+
|
|
325
|
+
this.#data[baseIdx] = this.#data[0];
|
|
326
|
+
this.#data[0] = rep;
|
|
327
|
+
|
|
328
|
+
return val;
|
|
329
|
+
}
|
|
305
330
|
|
|
306
|
-
|
|
307
|
-
|
|
331
|
+
clear() {
|
|
332
|
+
_debugLog('[RepTable#clear()] args', { rep, target: this.target });
|
|
333
|
+
this.#data = [0, null];
|
|
334
|
+
}
|
|
308
335
|
}
|
|
309
|
-
const
|
|
336
|
+
const _coinFlip = () => { return Math.random() > 0.5; };
|
|
337
|
+
let SCOPE_ID = 0;
|
|
338
|
+
const I32_MIN = -2_147_483_648;
|
|
339
|
+
const I32_MAX = 2_147_483_647;
|
|
340
|
+
const _typeCheckValidI32 = (n) => typeof n === 'number' && n >= I32_MIN && n <= I32_MAX;
|
|
341
|
+
|
|
342
|
+
const _typeCheckAsyncFn= (f) => {
|
|
343
|
+
return f instanceof ASYNC_FN_CTOR;
|
|
344
|
+
};
|
|
345
|
+
|
|
346
|
+
const ASYNC_FN_CTOR = (async () => {}).constructor;
|
|
310
347
|
const ASYNC_CURRENT_TASK_IDS = [];
|
|
311
348
|
const ASYNC_CURRENT_COMPONENT_IDXS = [];
|
|
312
349
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
CANCEL_PENDING: 'cancel-pending',
|
|
320
|
-
CANCEL_DELIVERED: 'cancel-delivered',
|
|
321
|
-
RESOLVED: 'resolved',
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
static BlockResult = {
|
|
325
|
-
CANCELLED: 'block.cancelled',
|
|
326
|
-
NOT_CANCELLED: 'block.not-cancelled',
|
|
350
|
+
function unpackCallbackResult(result) {
|
|
351
|
+
_debugLog('[unpackCallbackResult()] args', { result });
|
|
352
|
+
if (!(_typeCheckValidI32(result))) { throw new Error('invalid callback return value [' + result + '], not a valid i32'); }
|
|
353
|
+
const eventCode = result & 0xF;
|
|
354
|
+
if (eventCode < 0 || eventCode > 3) {
|
|
355
|
+
throw new Error('invalid async return value [' + eventCode + '], outside callback code range');
|
|
327
356
|
}
|
|
357
|
+
if (result < 0 || result >= 2**32) { throw new Error('invalid callback result'); }
|
|
358
|
+
// TODO: table max length check?
|
|
359
|
+
const waitableSetRep = result >> 4;
|
|
360
|
+
return [eventCode, waitableSetRep];
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
function promiseWithResolvers() {
|
|
364
|
+
if (Promise.withResolvers) {
|
|
365
|
+
return Promise.withResolvers();
|
|
366
|
+
} else {
|
|
367
|
+
let resolve;
|
|
368
|
+
let reject;
|
|
369
|
+
const promise = new Promise((res, rej) => {
|
|
370
|
+
resolve = res;
|
|
371
|
+
reject = rej;
|
|
372
|
+
});
|
|
373
|
+
return { promise, resolve, reject };
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
function _prepareCall(
|
|
378
|
+
memoryIdx,
|
|
379
|
+
getMemoryFn,
|
|
380
|
+
startFn,
|
|
381
|
+
returnFn,
|
|
382
|
+
callerInstanceIdx,
|
|
383
|
+
calleeInstanceIdx,
|
|
384
|
+
taskReturnTypeIdx,
|
|
385
|
+
isCalleeAsyncInt,
|
|
386
|
+
stringEncoding,
|
|
387
|
+
resultCountOrAsync,
|
|
388
|
+
) {
|
|
389
|
+
_debugLog('[_prepareCall()]', {
|
|
390
|
+
callerInstanceIdx,
|
|
391
|
+
calleeInstanceIdx,
|
|
392
|
+
taskReturnTypeIdx,
|
|
393
|
+
isCalleeAsyncInt,
|
|
394
|
+
stringEncoding,
|
|
395
|
+
resultCountOrAsync,
|
|
396
|
+
});
|
|
397
|
+
const argArray = [...arguments];
|
|
328
398
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
399
|
+
// Since Rust will happily pass large u32s over, resultCountOrAsync should be one of:
|
|
400
|
+
// (a) u32 max size => callee is async fn with no result
|
|
401
|
+
// (b) u32 max size - 1 => callee is async fn with result
|
|
402
|
+
// (c) any other value => callee is sync with the given result count
|
|
403
|
+
//
|
|
404
|
+
// Due to JS handling the value as 2s complement, the `resultCountOrAsync` ends up being:
|
|
405
|
+
// (a) -1 as u32 max size
|
|
406
|
+
// (b) -2 as u32 max size - 1
|
|
407
|
+
// (c) x
|
|
408
|
+
//
|
|
409
|
+
// Due to JS mishandling the value as 2s complement, the actual values we get are:
|
|
410
|
+
// see. https://github.com/wasm-bindgen/wasm-bindgen/issues/1388
|
|
411
|
+
let isAsync = false;
|
|
412
|
+
let hasResultPointer = false;
|
|
413
|
+
if (resultCountOrAsync === -1) {
|
|
414
|
+
isAsync = true;
|
|
415
|
+
hasResultPointer = false;
|
|
416
|
+
} else if (resultCountOrAsync === -2) {
|
|
417
|
+
isAsync = true;
|
|
418
|
+
hasResultPointer = true;
|
|
419
|
+
}
|
|
349
420
|
|
|
350
|
-
|
|
421
|
+
const currentCallerTaskMeta = getCurrentTask(callerInstanceIdx);
|
|
422
|
+
if (!currentCallerTaskMeta) {
|
|
423
|
+
throw new Error('invalid/missing current task for caller during prepare call');
|
|
424
|
+
}
|
|
351
425
|
|
|
352
|
-
|
|
426
|
+
const currentCallerTask = currentCallerTaskMeta.task;
|
|
427
|
+
if (!currentCallerTask) {
|
|
428
|
+
throw new Error('unexpectedly missing task in meta for caller during prepare call');
|
|
429
|
+
}
|
|
353
430
|
|
|
354
|
-
|
|
431
|
+
if (currentCallerTask.componentIdx() !== callerInstanceIdx) {
|
|
432
|
+
throw new Error(`task component idx [${ currentCallerTask.componentIdx() }] !== [${ callerInstanceIdx }] (callee ${ calleeInstanceIdx })`);
|
|
433
|
+
}
|
|
355
434
|
|
|
356
|
-
|
|
357
|
-
|
|
435
|
+
let getCalleeParamsFn;
|
|
436
|
+
let resultPtr = null;
|
|
437
|
+
if (hasResultPointer) {
|
|
438
|
+
const directParamsArr = argArray.slice(11);
|
|
439
|
+
getCalleeParamsFn = () => directParamsArr;
|
|
440
|
+
resultPtr = argArray[10];
|
|
441
|
+
} else {
|
|
442
|
+
const directParamsArr = argArray.slice(10);
|
|
443
|
+
getCalleeParamsFn = () => directParamsArr;
|
|
444
|
+
}
|
|
358
445
|
|
|
359
|
-
|
|
446
|
+
let encoding;
|
|
447
|
+
switch (stringEncoding) {
|
|
448
|
+
case 0:
|
|
449
|
+
encoding = 'utf8';
|
|
450
|
+
break;
|
|
451
|
+
case 1:
|
|
452
|
+
encoding = 'utf16';
|
|
453
|
+
break;
|
|
454
|
+
case 2:
|
|
455
|
+
encoding = 'compact-utf16';
|
|
456
|
+
break;
|
|
457
|
+
default:
|
|
458
|
+
throw new Error(`unrecognized string encoding enum [${stringEncoding}]`);
|
|
459
|
+
}
|
|
360
460
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
461
|
+
const [newTask, newTaskID] = createNewCurrentTask({
|
|
462
|
+
componentIdx: calleeInstanceIdx,
|
|
463
|
+
isAsync: isCalleeAsyncInt !== 0,
|
|
464
|
+
getCalleeParamsFn,
|
|
465
|
+
// TODO: find a way to pass the import name through here
|
|
466
|
+
entryFnName: 'task/' + currentCallerTask.id() + '/new-prepare-task',
|
|
467
|
+
stringEncoding,
|
|
468
|
+
});
|
|
364
469
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
470
|
+
const subtask = currentCallerTask.createSubtask({
|
|
471
|
+
componentIdx: callerInstanceIdx,
|
|
472
|
+
parentTask: currentCallerTask,
|
|
473
|
+
childTask: newTask,
|
|
474
|
+
callMetadata: {
|
|
475
|
+
memory: getMemoryFn(),
|
|
476
|
+
memoryIdx,
|
|
477
|
+
resultPtr,
|
|
478
|
+
returnFn,
|
|
479
|
+
startFn,
|
|
480
|
+
}
|
|
481
|
+
});
|
|
368
482
|
|
|
369
|
-
|
|
370
|
-
|
|
483
|
+
newTask.setParentSubtask(subtask);
|
|
484
|
+
// NOTE: This isn't really a return memory idx for the caller, it's for checking
|
|
485
|
+
// against the task.return (which will be called from the callee)
|
|
486
|
+
newTask.setReturnMemoryIdx(memoryIdx);
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
function _asyncStartCall(args, callee, paramCount, resultCount, flags) {
|
|
490
|
+
const { getCallbackFn, callbackIdx, getPostReturnFn, postReturnIdx } = args;
|
|
491
|
+
_debugLog('[_asyncStartCall()] args', args);
|
|
371
492
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
if (opts?.componentIdx === undefined) {
|
|
376
|
-
throw new TypeError('missing component id during task creation');
|
|
377
|
-
}
|
|
378
|
-
this.#componentIdx = opts.componentIdx;
|
|
379
|
-
|
|
380
|
-
this.#state = AsyncTask.State.INITIAL;
|
|
381
|
-
this.#isAsync = opts?.isAsync ?? false;
|
|
382
|
-
this.#entryFnName = opts.entryFnName;
|
|
383
|
-
|
|
384
|
-
const {
|
|
385
|
-
promise: completionPromise,
|
|
386
|
-
resolve: resolveCompletionPromise,
|
|
387
|
-
reject: rejectCompletionPromise,
|
|
388
|
-
} = promiseWithResolvers();
|
|
389
|
-
this.#completionPromise = completionPromise;
|
|
390
|
-
|
|
391
|
-
this.#onResolveHandlers.push((results) => {
|
|
392
|
-
resolveCompletionPromise(results);
|
|
393
|
-
})
|
|
394
|
-
|
|
395
|
-
if (opts.callbackFn) { this.#callbackFn = opts.callbackFn; }
|
|
396
|
-
if (opts.callbackFnName) { this.#callbackFnName = opts.callbackFnName; }
|
|
397
|
-
|
|
398
|
-
if (opts.getCalleeParamsFn) { this.#getCalleeParamsFn = opts.getCalleeParamsFn; }
|
|
399
|
-
|
|
400
|
-
if (opts.stringEncoding) { this.#stringEncoding = opts.stringEncoding; }
|
|
401
|
-
|
|
402
|
-
if (opts.parentSubtask) { this.#parentSubtask = opts.parentSubtask; }
|
|
403
|
-
|
|
404
|
-
this.#needsExclusiveLock = this.isSync() || !this.hasCallback();
|
|
405
|
-
|
|
406
|
-
if (opts.errHandling) { this.#errHandling = opts.errHandling; }
|
|
407
|
-
}
|
|
493
|
+
const taskMeta = getCurrentTask(ASYNC_CURRENT_COMPONENT_IDXS.at(-1), ASYNC_CURRENT_TASK_IDS.at(-1));
|
|
494
|
+
if (!taskMeta) { throw new Error('invalid/missing current async task meta during prepare call'); }
|
|
408
495
|
|
|
409
|
-
|
|
410
|
-
id() { return this.#id; }
|
|
411
|
-
componentIdx() { return this.#componentIdx; }
|
|
412
|
-
isAsync() { return this.#isAsync; }
|
|
413
|
-
entryFnName() { return this.#entryFnName; }
|
|
414
|
-
completionPromise() { return this.#completionPromise; }
|
|
496
|
+
const argArray = [...arguments];
|
|
415
497
|
|
|
416
|
-
|
|
417
|
-
|
|
498
|
+
// NOTE: at this point we know the current task is the one that was started
|
|
499
|
+
// in PrepareCall, so we *should* be able to pop it back off and be left with
|
|
500
|
+
// the previous task
|
|
501
|
+
const preparedTask = taskMeta.task;
|
|
502
|
+
if (!preparedTask) { throw new Error('unexpectedly missing task in task meta during prepare call'); }
|
|
418
503
|
|
|
419
|
-
|
|
504
|
+
if (resultCount < 0 || resultCount > 1) { throw new Error('invalid/unsupported result count'); }
|
|
420
505
|
|
|
421
|
-
|
|
506
|
+
const callbackFnName = 'callback_' + callbackIdx;
|
|
507
|
+
const callbackFn = getCallbackFn();
|
|
508
|
+
preparedTask.setCallbackFn(callbackFn, callbackFnName);
|
|
509
|
+
preparedTask.setPostReturnFn(getPostReturnFn());
|
|
422
510
|
|
|
423
|
-
|
|
424
|
-
getReturnMemoryIdx() { return this.#memoryIdx; }
|
|
511
|
+
const subtask = preparedTask.getParentSubtask();
|
|
425
512
|
|
|
426
|
-
|
|
427
|
-
getReturnLowerFns() { return this.#returnLowerFns; }
|
|
513
|
+
if (resultCount < 0 || resultCount > 1) { throw new Error(`unsupported result count [${ resultCount }]`); }
|
|
428
514
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
this.#parentSubtask = subtask;
|
|
515
|
+
const params = preparedTask.getCalleeParams();
|
|
516
|
+
if (paramCount !== params.length) {
|
|
517
|
+
throw new Error(`unexpected callee param count [${ params.length }], _asyncStartCall invocation expected [${ paramCount }]`);
|
|
433
518
|
}
|
|
434
519
|
|
|
435
|
-
|
|
520
|
+
subtask.setOnProgressFn(() => {
|
|
521
|
+
subtask.setPendingEventFn(() => {
|
|
522
|
+
if (subtask.resolved()) { subtask.deliverResolve(); }
|
|
523
|
+
return {
|
|
524
|
+
code: ASYNC_EVENT_CODE.SUBTASK,
|
|
525
|
+
index: rep,
|
|
526
|
+
result: subtask.getStateNumber(),
|
|
527
|
+
}
|
|
528
|
+
});
|
|
529
|
+
});
|
|
436
530
|
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
let currentSubtask = this.getParentSubtask();
|
|
441
|
-
let task = this;
|
|
442
|
-
while (currentSubtask) {
|
|
443
|
-
task = currentSubtask.getParentTask();
|
|
444
|
-
currentSubtask = task.getParentSubtask();
|
|
445
|
-
}
|
|
446
|
-
return task;
|
|
531
|
+
const subtaskState = subtask.getStateNumber();
|
|
532
|
+
if (subtaskState < 0 || subtaskState > 2**5) {
|
|
533
|
+
throw new Error('invalid subtask state, out of valid range');
|
|
447
534
|
}
|
|
448
535
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
this.#postReturnFn = f;
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
setCallbackFn(f, name) {
|
|
456
|
-
if (!f) { return; }
|
|
457
|
-
if (this.#callbackFn) { throw new Error('callback fn can only be set once'); }
|
|
458
|
-
this.#callbackFn = f;
|
|
459
|
-
this.#callbackFnName = name;
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
getCallbackFnName() {
|
|
463
|
-
if (!this.#callbackFnName) { return undefined; }
|
|
464
|
-
return this.#callbackFnName;
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
runCallbackFn(...args) {
|
|
468
|
-
if (!this.#callbackFn) { throw new Error('on callback function has been set for task'); }
|
|
469
|
-
return this.#callbackFn.apply(null, args);
|
|
470
|
-
}
|
|
536
|
+
const callerComponentState = getOrCreateAsyncState(subtask.componentIdx());
|
|
537
|
+
const rep = callerComponentState.subtasks.insert(subtask);
|
|
538
|
+
subtask.setRep(rep);
|
|
471
539
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
return this.#getCalleeParamsFn();
|
|
475
|
-
}
|
|
540
|
+
const calleeComponentState = getOrCreateAsyncState(preparedTask.componentIdx());
|
|
541
|
+
const calleeBackpressure = calleeComponentState.hasBackpressure();
|
|
476
542
|
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
543
|
+
// Set up a handler on subtask completion to lower results from the call into the caller's memory region.
|
|
544
|
+
//
|
|
545
|
+
// NOTE: during fused guest->guest calls this handler is triggered, but does not actually perform
|
|
546
|
+
// lowering manually, as fused modules provider helper functions that can
|
|
547
|
+
subtask.registerOnResolveHandler((res) => {
|
|
548
|
+
_debugLog('[_asyncStartCall()] handling subtask result', { res, subtaskID: subtask.id() });
|
|
549
|
+
let subtaskCallMeta = subtask.getCallMetadata();
|
|
550
|
+
|
|
551
|
+
// NOTE: in the case of guest -> guest async calls, there may be no memory/realloc present,
|
|
552
|
+
// as the host will intermediate the value storage/movement between calls.
|
|
553
|
+
//
|
|
554
|
+
// We can simply take the value and lower it as a parameter
|
|
555
|
+
if (subtaskCallMeta.memory || subtaskCallMeta.realloc) {
|
|
556
|
+
throw new Error("call metadata unexpectedly contains memory/realloc for guest->guest call");
|
|
482
557
|
}
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
558
|
+
|
|
559
|
+
const callerTask = subtask.getParentTask();
|
|
560
|
+
const calleeTask = preparedTask;
|
|
561
|
+
const callerMemoryIdx = callerTask.getReturnMemoryIdx();
|
|
562
|
+
const callerComponentIdx = callerTask.componentIdx();
|
|
563
|
+
|
|
564
|
+
// If a helper function was provided we are likely in a fused guest->guest call,
|
|
565
|
+
// and the result will be delivered (lift/lowered) via helper function
|
|
566
|
+
if (subtaskCallMeta.returnFn) {
|
|
567
|
+
_debugLog('[_asyncStartCall()] return function present while ahndling subtask result, returning early (skipping lower)');
|
|
568
|
+
return;
|
|
486
569
|
}
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
570
|
+
|
|
571
|
+
// If there is no where to lower the results, exit early
|
|
572
|
+
if (!subtaskCallMeta.resultPtr) {
|
|
573
|
+
_debugLog('[_asyncStartCall()] no result ptr during subtask result handling, returning early (skipping lower)');
|
|
574
|
+
return;
|
|
491
575
|
}
|
|
492
|
-
return true;
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
async enter() {
|
|
496
|
-
_debugLog('[AsyncTask#enter()] args', { taskID: this.#id });
|
|
497
|
-
const cstate = getOrCreateAsyncState(this.#componentIdx);
|
|
498
576
|
|
|
499
|
-
|
|
577
|
+
let callerMemory;
|
|
578
|
+
if (callerMemoryIdx) {
|
|
579
|
+
callerMemory = GlobalComponentMemories.getMemory(callerComponentIdx, callerMemoryIdx);
|
|
580
|
+
} else {
|
|
581
|
+
const callerMemories = GlobalComponentMemories.getMemoriesForComponentIdx(callerComponentIdx);
|
|
582
|
+
if (callerMemories.length != 1) { throw new Error(`unsupported amount of caller memories`); }
|
|
583
|
+
callerMemory = callerMemories[0];
|
|
584
|
+
}
|
|
500
585
|
|
|
501
|
-
if (
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
const result = await this.waitUntil({
|
|
505
|
-
readyFn: () => !cstate.hasBackpressure(),
|
|
506
|
-
cancellable: true,
|
|
507
|
-
});
|
|
508
|
-
|
|
509
|
-
cstate.removeBackpressureWaiter();
|
|
510
|
-
|
|
511
|
-
if (result === AsyncTask.BlockResult.CANCELLED) {
|
|
512
|
-
this.cancel();
|
|
513
|
-
return false;
|
|
514
|
-
}
|
|
586
|
+
if (!callerMemory) {
|
|
587
|
+
throw new Error(`missing memory for to guest->guest call result (subtask [${subtask.id()}])`);
|
|
515
588
|
}
|
|
516
589
|
|
|
517
|
-
|
|
590
|
+
const lowerFns = calleeTask.getReturnLowerFns();
|
|
591
|
+
if (!lowerFns || lowerFns.length === 0) {
|
|
592
|
+
throw new Error(`missing result lower metadata for guest->guests call (subtask [${subtask.id()}])`);
|
|
593
|
+
}
|
|
518
594
|
|
|
519
|
-
|
|
520
|
-
|
|
595
|
+
if (lowerFns.length !== 1) {
|
|
596
|
+
throw new Error(`only single result supported for guest->guest calls (subtask [${subtask.id()}])`);
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
lowerFns[0]({
|
|
600
|
+
realloc: undefined,
|
|
601
|
+
memory: callerMemory,
|
|
602
|
+
vals: [res],
|
|
603
|
+
storagePtr: subtaskCallMeta.resultPtr,
|
|
604
|
+
componentIdx: callerComponentIdx
|
|
605
|
+
});
|
|
606
|
+
|
|
607
|
+
});
|
|
521
608
|
|
|
522
|
-
|
|
523
|
-
|
|
609
|
+
// Build call params
|
|
610
|
+
const subtaskCallMeta = subtask.getCallMetadata();
|
|
611
|
+
let startFnParams = [];
|
|
612
|
+
let calleeParams = [];
|
|
613
|
+
if (subtaskCallMeta.startFn && subtaskCallMeta.resultPtr) {
|
|
614
|
+
// If we're using a fused component start fn and a result pointer is present,
|
|
615
|
+
// then we need to pass the result pointer and other params to the start fn
|
|
616
|
+
startFnParams.push(subtaskCallMeta.resultPtr, ...params);
|
|
617
|
+
} else {
|
|
618
|
+
// if not we need to pass params to the callee instead
|
|
619
|
+
startFnParams.push(...params);
|
|
620
|
+
calleeParams.push(...params);
|
|
524
621
|
}
|
|
525
622
|
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
623
|
+
preparedTask.registerOnResolveHandler((res) => {
|
|
624
|
+
_debugLog('[_asyncStartCall()] signaling subtask completion due to task completion', {
|
|
625
|
+
childTaskID: preparedTask.id(),
|
|
626
|
+
subtaskID: subtask.id(),
|
|
627
|
+
parentTaskID: subtask.getParentTask().id(),
|
|
628
|
+
});
|
|
629
|
+
subtask.onResolve(res);
|
|
630
|
+
});
|
|
631
|
+
|
|
632
|
+
// TODO(fix): start fns sometimes produce results, how should they be used?
|
|
633
|
+
// the result should theoretically be used for flat lowering, but fused components do
|
|
634
|
+
// this automatically!
|
|
635
|
+
subtask.onStart({ startFnParams });
|
|
636
|
+
|
|
637
|
+
_debugLog("[_asyncStartCall()] initial call", {
|
|
638
|
+
task: preparedTask.id(),
|
|
639
|
+
subtaskID: subtask.id(),
|
|
640
|
+
calleeFnName: callee.name,
|
|
641
|
+
});
|
|
642
|
+
|
|
643
|
+
const callbackResult = callee.apply(null, calleeParams);
|
|
644
|
+
|
|
645
|
+
_debugLog("[_asyncStartCall()] after initial call", {
|
|
646
|
+
task: preparedTask.id(),
|
|
647
|
+
subtaskID: subtask.id(),
|
|
648
|
+
calleeFnName: callee.name,
|
|
649
|
+
});
|
|
650
|
+
|
|
651
|
+
const doSubtaskResolve = () => {
|
|
652
|
+
subtask.deliverResolve();
|
|
653
|
+
};
|
|
654
|
+
|
|
655
|
+
// If a single call resolved the subtask and there is no backpressure in the guest,
|
|
656
|
+
// we can return immediately
|
|
657
|
+
if (subtask.resolved() && !calleeBackpressure) {
|
|
658
|
+
_debugLog("[_asyncStartCall()] instantly resolved", {
|
|
659
|
+
calleeComponentIdx: preparedTask.componentIdx(),
|
|
660
|
+
task: preparedTask.id(),
|
|
661
|
+
subtaskID: subtask.id(),
|
|
662
|
+
callerComponentIdx: subtask.componentIdx(),
|
|
543
663
|
});
|
|
544
664
|
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
665
|
+
// If a fused component return function was specified for the subtask,
|
|
666
|
+
// we've likely already called it during resolution of the task.
|
|
667
|
+
//
|
|
668
|
+
// In this case, we do not want to actually return 2 AKA "RETURNED",
|
|
669
|
+
// but the normal started task state, because the fused component expects to get
|
|
670
|
+
// the waitable + the original subtask state (0 AKA "STARTING")
|
|
671
|
+
//
|
|
672
|
+
if (subtask.getCallMetadata().returnFn) {
|
|
673
|
+
return Number(subtask.waitableRep()) << 4 | subtaskState;
|
|
553
674
|
}
|
|
554
675
|
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
return event;
|
|
676
|
+
doSubtaskResolve();
|
|
677
|
+
return AsyncSubtask.State.RETURNED;
|
|
558
678
|
}
|
|
559
679
|
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
if (
|
|
563
|
-
|
|
680
|
+
// Start the (event) driver loop that will resolve the task
|
|
681
|
+
new Promise(async (resolve, reject) => {
|
|
682
|
+
if (subtask.resolved() && calleeBackpressure) {
|
|
683
|
+
await calleeComponentState.waitForBackpressure();
|
|
684
|
+
|
|
685
|
+
_debugLog("[_asyncStartCall()] instantly resolved after cleared backpressure", {
|
|
686
|
+
calleeComponentIdx: preparedTask.componentIdx(),
|
|
687
|
+
task: preparedTask.id(),
|
|
688
|
+
subtaskID: subtask.id(),
|
|
689
|
+
callerComponentIdx: subtask.componentIdx(),
|
|
690
|
+
});
|
|
691
|
+
return;
|
|
564
692
|
}
|
|
565
693
|
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
};
|
|
576
|
-
|
|
577
|
-
// Park this task/execution to be handled later
|
|
578
|
-
const state = getOrCreateAsyncState(this.#componentIdx);
|
|
579
|
-
state.parkTaskOnAwaitable({ awaitable, task: this });
|
|
694
|
+
const started = await preparedTask.enter();
|
|
695
|
+
if (!started) {
|
|
696
|
+
_debugLog('[_asyncStartCall()] task failed early', {
|
|
697
|
+
taskID: preparedTask.id(),
|
|
698
|
+
subtaskID: subtask.id(),
|
|
699
|
+
});
|
|
700
|
+
throw new Error("task failed to start");
|
|
701
|
+
return;
|
|
702
|
+
}
|
|
580
703
|
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
if (!(awaitable instanceof Awaitable)) {
|
|
593
|
-
throw new Error('invalid awaitable during onBlock');
|
|
594
|
-
}
|
|
595
|
-
// TODO: watch for waitable AND cancellation
|
|
596
|
-
// TODO: if it WAS cancelled:
|
|
597
|
-
// - return true
|
|
598
|
-
// - only once per subtask
|
|
599
|
-
// - do not wait on the scheduler
|
|
600
|
-
// - control flow should go to the subtask (only once)
|
|
601
|
-
// - Once subtask blocks/resolves, reqlinquishControl() will tehn resolve request_cancel_end (without scheduler lock release)
|
|
602
|
-
// - control flow goes back to request_cancel
|
|
603
|
-
//
|
|
604
|
-
// Subtask cancellation should work similarly to an async import call -- runs sync up until
|
|
605
|
-
// the subtask blocks or resolves
|
|
606
|
-
//
|
|
607
|
-
throw new Error('AsyncTask#asyncOnBlock() not yet implemented');
|
|
608
|
-
}
|
|
609
|
-
|
|
610
|
-
async yieldUntil(opts) {
|
|
611
|
-
const { readyFn, cancellable } = opts;
|
|
612
|
-
_debugLog('[AsyncTask#yield()] args', { taskID: this.#id, cancellable });
|
|
613
|
-
|
|
614
|
-
const keepGoing = await this.suspendUntil({ readyFn, cancellable });
|
|
615
|
-
if (!keepGoing) {
|
|
616
|
-
return {
|
|
617
|
-
code: ASYNC_EVENT_CODE.TASK_CANCELLED,
|
|
618
|
-
index: 0,
|
|
619
|
-
result: 0,
|
|
620
|
-
};
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
return {
|
|
624
|
-
code: ASYNC_EVENT_CODE.NONE,
|
|
625
|
-
index: 0,
|
|
626
|
-
result: 0,
|
|
627
|
-
};
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
async suspendUntil(opts) {
|
|
631
|
-
const { cancellable, readyFn } = opts;
|
|
632
|
-
_debugLog('[AsyncTask#suspendUntil()] args', { cancellable });
|
|
633
|
-
|
|
634
|
-
const pendingCancelled = this.deliverPendingCancel({ cancellable });
|
|
635
|
-
if (pendingCancelled) { return false; }
|
|
636
|
-
|
|
637
|
-
const completed = await this.immediateSuspendUntil({ readyFn, cancellable });
|
|
638
|
-
return completed;
|
|
639
|
-
}
|
|
640
|
-
|
|
641
|
-
// TODO(threads): equivalent to thread.suspend_until()
|
|
642
|
-
async immediateSuspendUntil(opts) {
|
|
643
|
-
const { cancellable, readyFn } = opts;
|
|
644
|
-
_debugLog('[AsyncTask#immediateSuspendUntil()] args', { cancellable, readyFn });
|
|
704
|
+
// TODO: retrieve/pass along actual fn name the callback corresponds to
|
|
705
|
+
// (at least something like `<lifted fn name>_callback`)
|
|
706
|
+
const fnName = [
|
|
707
|
+
'<task ',
|
|
708
|
+
subtask.parentTaskID(),
|
|
709
|
+
'/subtask ',
|
|
710
|
+
subtask.id(),
|
|
711
|
+
'/task ',
|
|
712
|
+
preparedTask.id(),
|
|
713
|
+
'>',
|
|
714
|
+
].join("");
|
|
645
715
|
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
716
|
+
try {
|
|
717
|
+
_debugLog("[_asyncStartCall()] starting driver loop", { fnName, componentIdx: preparedTask.componentIdx(), });
|
|
718
|
+
await _driverLoop({
|
|
719
|
+
componentState: calleeComponentState,
|
|
720
|
+
task: preparedTask,
|
|
721
|
+
fnName,
|
|
722
|
+
isAsync: true,
|
|
723
|
+
callbackResult,
|
|
724
|
+
resolve,
|
|
725
|
+
reject
|
|
726
|
+
});
|
|
727
|
+
} catch (err) {
|
|
728
|
+
_debugLog("[AsyncStartCall] drive loop call failure", { err });
|
|
649
729
|
}
|
|
650
730
|
|
|
651
|
-
|
|
652
|
-
cstate.addPendingTask(this);
|
|
653
|
-
|
|
654
|
-
const keepGoing = await this.immediateSuspend({ cancellable, readyFn });
|
|
655
|
-
return keepGoing;
|
|
656
|
-
}
|
|
657
|
-
|
|
658
|
-
async immediateSuspend(opts) { // NOTE: equivalent to thread.suspend()
|
|
659
|
-
// TODO(threads): store readyFn on the thread
|
|
660
|
-
const { cancellable, readyFn } = opts;
|
|
661
|
-
_debugLog('[AsyncTask#immediateSuspend()] args', { cancellable, readyFn });
|
|
662
|
-
|
|
663
|
-
const pendingCancelled = this.deliverPendingCancel({ cancellable });
|
|
664
|
-
if (pendingCancelled) { return false; }
|
|
665
|
-
|
|
666
|
-
const cstate = getOrCreateAsyncState(this.#componentIdx);
|
|
731
|
+
});
|
|
667
732
|
|
|
668
|
-
|
|
669
|
-
const taskWait = await cstate.suspendTask({ task: this, readyFn });
|
|
670
|
-
const keepGoing = await taskWait;
|
|
671
|
-
return keepGoing;
|
|
733
|
+
return Number(subtask.waitableRep()) << 4 | subtaskState;
|
|
672
734
|
}
|
|
673
735
|
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
if (cancellable && this.#state === AsyncTask.State.PENDING_CANCEL) {
|
|
679
|
-
this.#state = Task.State.CANCEL_DELIVERED;
|
|
680
|
-
return true;
|
|
681
|
-
}
|
|
682
|
-
|
|
683
|
-
return false;
|
|
736
|
+
function _syncStartCall(callbackIdx) {
|
|
737
|
+
_debugLog('[_syncStartCall()] args', { callbackIdx });
|
|
738
|
+
throw new Error('synchronous start call not implemented!');
|
|
684
739
|
}
|
|
685
740
|
|
|
686
|
-
|
|
741
|
+
let dv = new DataView(new ArrayBuffer());
|
|
742
|
+
const dataView = mem => dv.buffer === mem.buffer ? dv : dv = new DataView(mem.buffer);
|
|
687
743
|
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
}
|
|
693
|
-
if (this.borrowedHandles.length > 0) { throw new Error('task still has borrow handles'); }
|
|
694
|
-
this.cancelled = true;
|
|
695
|
-
this.onResolve(new Error('cancelled'));
|
|
696
|
-
this.#state = AsyncTask.State.RESOLVED;
|
|
744
|
+
const toUint64 = val => BigInt.asUintN(64, BigInt(val));
|
|
745
|
+
|
|
746
|
+
function toUint32(val) {
|
|
747
|
+
return val >>> 0;
|
|
697
748
|
}
|
|
749
|
+
const TEXT_DECODER_UTF8 = new TextDecoder();
|
|
750
|
+
const TEXT_ENCODER_UTF8 = new TextEncoder();
|
|
698
751
|
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
f(taskValue);
|
|
703
|
-
} catch (err) {
|
|
704
|
-
console.error("error during task resolve handler", err);
|
|
705
|
-
throw err;
|
|
706
|
-
}
|
|
707
|
-
}
|
|
708
|
-
|
|
709
|
-
if (this.#postReturnFn) {
|
|
710
|
-
_debugLog('[AsyncTask#onResolve()] running post return ', {
|
|
711
|
-
componentIdx: this.#componentIdx,
|
|
712
|
-
taskID: this.#id,
|
|
713
|
-
});
|
|
714
|
-
this.#postReturnFn();
|
|
752
|
+
function _utf8AllocateAndEncode(s, realloc, memory) {
|
|
753
|
+
if (typeof s !== 'string') {
|
|
754
|
+
throw new TypeError('expected a string, received [' + typeof s + ']');
|
|
715
755
|
}
|
|
756
|
+
if (s.length === 0) { return { ptr: 1, len: 0 }; }
|
|
757
|
+
let buf = TEXT_ENCODER_UTF8.encode(s);
|
|
758
|
+
let ptr = realloc(0, 0, 1, buf.length);
|
|
759
|
+
new Uint8Array(memory.buffer).set(buf, ptr);
|
|
760
|
+
return { ptr, len: buf.length, codepoints: [...s].length };
|
|
716
761
|
}
|
|
717
762
|
|
|
718
|
-
registerOnResolveHandler(f) {
|
|
719
|
-
this.#onResolveHandlers.push(f);
|
|
720
|
-
}
|
|
721
763
|
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
throw new Error(`(component [${this.#componentIdx}]) task [${this.#id}] is already resolved (did you forget to wait for an import?)`);
|
|
731
|
-
}
|
|
732
|
-
if (this.borrowedHandles.length > 0) { throw new Error('task still has borrow handles'); }
|
|
733
|
-
switch (results.length) {
|
|
734
|
-
case 0:
|
|
735
|
-
this.onResolve(undefined);
|
|
736
|
-
break;
|
|
737
|
-
case 1:
|
|
738
|
-
this.onResolve(results[0]);
|
|
739
|
-
break;
|
|
740
|
-
default:
|
|
741
|
-
throw new Error('unexpected number of results');
|
|
764
|
+
const T_FLAG = 1 << 30;
|
|
765
|
+
|
|
766
|
+
function rscTableCreateOwn(table, rep) {
|
|
767
|
+
const free = table[0] & ~T_FLAG;
|
|
768
|
+
if (free === 0) {
|
|
769
|
+
table.push(0);
|
|
770
|
+
table.push(rep | T_FLAG);
|
|
771
|
+
return (table.length >> 1) - 1;
|
|
742
772
|
}
|
|
743
|
-
|
|
773
|
+
table[0] = table[free << 1];
|
|
774
|
+
table[free << 1] = 0;
|
|
775
|
+
table[(free << 1) + 1] = rep | T_FLAG;
|
|
776
|
+
return free;
|
|
744
777
|
}
|
|
745
778
|
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
//
|
|
754
|
-
// see: test/p3/ported/wasmtime/component-async/post-return.js
|
|
755
|
-
//
|
|
756
|
-
// We *should* be able to upgrade this to be more strict and throw at some point,
|
|
757
|
-
// which may involve rewriting the upstream test to surface task return manually somehow.
|
|
758
|
-
//
|
|
759
|
-
//throw new Error(`(component [${this.#componentIdx}]) task [${this.#id}] exited without resolution`);
|
|
760
|
-
_debugLog('[AsyncTask#exit()] task exited without resolution', {
|
|
761
|
-
componentIdx: this.#componentIdx,
|
|
762
|
-
taskID: this.#id,
|
|
763
|
-
subtask: this.getParentSubtask(),
|
|
764
|
-
subtaskID: this.getParentSubtask()?.id(),
|
|
765
|
-
});
|
|
766
|
-
this.#state = AsyncTask.State.RESOLVED;
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
if (this.borrowedHandles > 0) {
|
|
770
|
-
throw new Error('task [${this.#id}] exited without clearing borrowed handles');
|
|
771
|
-
}
|
|
772
|
-
|
|
773
|
-
const state = getOrCreateAsyncState(this.#componentIdx);
|
|
774
|
-
if (!state) { throw new Error('missing async state for component [' + this.#componentIdx + ']'); }
|
|
775
|
-
if (!this.#isAsync && !state.inSyncExportCall) {
|
|
776
|
-
throw new Error('sync task must be run from components known to be in a sync export call');
|
|
777
|
-
}
|
|
778
|
-
state.inSyncExportCall = false;
|
|
779
|
-
|
|
780
|
-
if (this.needsExclusiveLock() && !state.isExclusivelyLocked()) {
|
|
781
|
-
throw new Error('task [' + this.#id + '] exit: component [' + this.#componentIdx + '] should have been exclusively locked');
|
|
779
|
+
function rscTableRemove(table, handle) {
|
|
780
|
+
const scope = table[handle << 1];
|
|
781
|
+
const val = table[(handle << 1) + 1];
|
|
782
|
+
const own = (val & T_FLAG) !== 0;
|
|
783
|
+
const rep = val & ~T_FLAG;
|
|
784
|
+
if (val === 0 || (scope & T_FLAG) !== 0) {
|
|
785
|
+
throw new TypeError("Invalid handle");
|
|
782
786
|
}
|
|
783
|
-
|
|
784
|
-
|
|
787
|
+
table[handle << 1] = table[0] | T_FLAG;
|
|
788
|
+
table[0] = handle | T_FLAG;
|
|
789
|
+
return { rep, scope, own };
|
|
785
790
|
}
|
|
786
791
|
|
|
787
|
-
|
|
792
|
+
let curResourceBorrows = [];
|
|
788
793
|
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
const newSubtask = new AsyncSubtask({
|
|
793
|
-
componentIdx,
|
|
794
|
-
childTask,
|
|
795
|
-
parentTask: this,
|
|
796
|
-
callMetadata,
|
|
797
|
-
});
|
|
798
|
-
this.#subtasks.push(newSubtask);
|
|
799
|
-
return newSubtask;
|
|
800
|
-
}
|
|
801
|
-
|
|
802
|
-
getLatestSubtask() { return this.#subtasks.at(-1); }
|
|
803
|
-
|
|
804
|
-
currentSubtask() {
|
|
805
|
-
_debugLog('[AsyncTask#currentSubtask()]');
|
|
806
|
-
if (this.#subtasks.length === 0) { return undefined; }
|
|
807
|
-
return this.#subtasks.at(-1);
|
|
808
|
-
}
|
|
809
|
-
|
|
810
|
-
endCurrentSubtask() {
|
|
811
|
-
_debugLog('[AsyncTask#endCurrentSubtask()]');
|
|
812
|
-
if (this.#subtasks.length === 0) { throw new Error('cannot end current subtask: no current subtask'); }
|
|
813
|
-
const subtask = this.#subtasks.pop();
|
|
814
|
-
subtask.drop();
|
|
815
|
-
return subtask;
|
|
816
|
-
}
|
|
817
|
-
}
|
|
818
|
-
|
|
819
|
-
function unpackCallbackResult(result) {
|
|
820
|
-
_debugLog('[unpackCallbackResult()] args', { result });
|
|
821
|
-
if (!(_typeCheckValidI32(result))) { throw new Error('invalid callback return value [' + result + '], not a valid i32'); }
|
|
822
|
-
const eventCode = result & 0xF;
|
|
823
|
-
if (eventCode < 0 || eventCode > 3) {
|
|
824
|
-
throw new Error('invalid async return value [' + eventCode + '], outside callback code range');
|
|
794
|
+
function getCurrentTask(componentIdx) {
|
|
795
|
+
if (componentIdx === undefined || componentIdx === null) {
|
|
796
|
+
throw new Error('missing/invalid component instance index [' + componentIdx + '] while getting current task');
|
|
825
797
|
}
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
return [
|
|
798
|
+
const tasks = ASYNC_TASKS_BY_COMPONENT_IDX.get(componentIdx);
|
|
799
|
+
if (tasks === undefined) { return undefined; }
|
|
800
|
+
if (tasks.length === 0) { return undefined; }
|
|
801
|
+
return tasks[tasks.length - 1];
|
|
830
802
|
}
|
|
831
803
|
|
|
832
|
-
function
|
|
833
|
-
|
|
834
|
-
_debugLog('[_lowerImport()] args', { args, params, exportFn });
|
|
804
|
+
function createNewCurrentTask(args) {
|
|
805
|
+
_debugLog('[createNewCurrentTask()] args', args);
|
|
835
806
|
const {
|
|
836
|
-
functionIdx,
|
|
837
807
|
componentIdx,
|
|
838
808
|
isAsync,
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
809
|
+
entryFnName,
|
|
810
|
+
parentSubtaskID,
|
|
811
|
+
callbackFnName,
|
|
812
|
+
getCallbackFn,
|
|
813
|
+
getParamsFn,
|
|
814
|
+
stringEncoding,
|
|
815
|
+
errHandling,
|
|
816
|
+
getCalleeParamsFn,
|
|
817
|
+
resultPtr,
|
|
818
|
+
callingWasmExport,
|
|
845
819
|
} = args;
|
|
820
|
+
if (componentIdx === undefined || componentIdx === null) {
|
|
821
|
+
throw new Error('missing/invalid component instance index while starting task');
|
|
822
|
+
}
|
|
823
|
+
const taskMetas = ASYNC_TASKS_BY_COMPONENT_IDX.get(componentIdx);
|
|
824
|
+
const callbackFn = getCallbackFn ? getCallbackFn() : null;
|
|
846
825
|
|
|
847
|
-
const
|
|
848
|
-
const parentTask = parentTaskMeta?.task;
|
|
849
|
-
if (!parentTask) { throw new Error('missing parent task during lower of import'); }
|
|
850
|
-
|
|
851
|
-
const cstate = getOrCreateAsyncState(componentIdx);
|
|
852
|
-
|
|
853
|
-
const subtask = parentTask.createSubtask({
|
|
826
|
+
const newTask = new AsyncTask({
|
|
854
827
|
componentIdx,
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
828
|
+
isAsync,
|
|
829
|
+
entryFnName,
|
|
830
|
+
callbackFn,
|
|
831
|
+
callbackFnName,
|
|
832
|
+
stringEncoding,
|
|
833
|
+
getCalleeParamsFn,
|
|
834
|
+
resultPtr,
|
|
835
|
+
errHandling,
|
|
862
836
|
});
|
|
863
|
-
parentTask.setReturnMemoryIdx(memoryIdx);
|
|
864
|
-
|
|
865
|
-
const rep = cstate.subtasks.insert(subtask);
|
|
866
|
-
subtask.setRep(rep);
|
|
867
837
|
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
if (subtask.resolved()) { subtask.deliverResolve(); }
|
|
871
|
-
return {
|
|
872
|
-
code: ASYNC_EVENT_CODE.SUBTASK,
|
|
873
|
-
index: rep,
|
|
874
|
-
result: subtask.getStateNumber(),
|
|
875
|
-
}
|
|
876
|
-
});
|
|
877
|
-
});
|
|
838
|
+
const newTaskID = newTask.id();
|
|
839
|
+
const newTaskMeta = { id: newTaskID, componentIdx, task: newTask };
|
|
878
840
|
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
_debugLog('[_lowerImport()] handling subtask result', { res, subtaskID: subtask.id() });
|
|
882
|
-
const { memory, resultPtr, realloc } = subtask.getCallMetadata();
|
|
883
|
-
resultLowerFns[0]({ componentIdx, memory, realloc, vals: [res], storagePtr: resultPtr });
|
|
884
|
-
});
|
|
841
|
+
ASYNC_CURRENT_TASK_IDS.push(newTaskID);
|
|
842
|
+
ASYNC_CURRENT_COMPONENT_IDXS.push(componentIdx);
|
|
885
843
|
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
844
|
+
if (!taskMetas) {
|
|
845
|
+
ASYNC_TASKS_BY_COMPONENT_IDX.set(componentIdx, [newTaskMeta]);
|
|
846
|
+
} else {
|
|
847
|
+
taskMetas.push(newTaskMeta);
|
|
889
848
|
}
|
|
890
849
|
|
|
891
|
-
|
|
892
|
-
// to ensure the subtask state is not modified before the lower call return
|
|
893
|
-
//
|
|
894
|
-
// TODO: we should trigger via subtask state changing, rather than a static wait?
|
|
895
|
-
setTimeout(async () => {
|
|
896
|
-
try {
|
|
897
|
-
_debugLog('[_lowerImport()] calling lowered import', { exportFn, params });
|
|
898
|
-
exportFn.apply(null, params);
|
|
899
|
-
|
|
900
|
-
const task = subtask.getChildTask();
|
|
901
|
-
task.registerOnResolveHandler((res) => {
|
|
902
|
-
_debugLog('[_lowerImport()] cascading subtask completion', {
|
|
903
|
-
childTaskID: task.id(),
|
|
904
|
-
subtaskID: subtask.id(),
|
|
905
|
-
parentTaskID: parentTask.id(),
|
|
906
|
-
});
|
|
907
|
-
|
|
908
|
-
subtask.onResolve(res);
|
|
909
|
-
|
|
910
|
-
cstate.tick();
|
|
911
|
-
});
|
|
912
|
-
} catch (err) {
|
|
913
|
-
console.error("post-lower import fn error:", err);
|
|
914
|
-
throw err;
|
|
915
|
-
}
|
|
916
|
-
}, 100);
|
|
917
|
-
|
|
918
|
-
return Number(subtask.waitableRep()) << 4 | subtaskState;
|
|
850
|
+
return [newTask, newTaskID];
|
|
919
851
|
}
|
|
920
852
|
|
|
921
|
-
function
|
|
922
|
-
|
|
853
|
+
function endCurrentTask(componentIdx, taskID) {
|
|
854
|
+
componentIdx ??= ASYNC_CURRENT_COMPONENT_IDXS.at(-1);
|
|
855
|
+
taskID ??= ASYNC_CURRENT_TASK_IDS.at(-1);
|
|
856
|
+
_debugLog('[endCurrentTask()] args', { componentIdx, taskID });
|
|
923
857
|
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
if (ctx.params.length === 0) { throw new Error('expected at least a single i32 argument'); }
|
|
927
|
-
val = ctx.params[0];
|
|
928
|
-
ctx.params = ctx.params.slice(1);
|
|
929
|
-
} else {
|
|
930
|
-
if (ctx.storageLen < ctx.storagePtr + 1) { throw new Error('not enough storage remaining for lift'); }
|
|
931
|
-
val = new DataView(ctx.memory.buffer).getUint8(ctx.storagePtr);
|
|
932
|
-
ctx.storagePtr += 1;
|
|
933
|
-
ctx.storageLen -= 1;
|
|
858
|
+
if (componentIdx === undefined || componentIdx === null) {
|
|
859
|
+
throw new Error('missing/invalid component instance index while ending current task');
|
|
934
860
|
}
|
|
935
861
|
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
862
|
+
const tasks = ASYNC_TASKS_BY_COMPONENT_IDX.get(componentIdx);
|
|
863
|
+
if (!tasks || !Array.isArray(tasks)) {
|
|
864
|
+
throw new Error('missing/invalid tasks for component instance while ending task');
|
|
865
|
+
}
|
|
866
|
+
if (tasks.length == 0) {
|
|
867
|
+
throw new Error('no current task(s) for component instance while ending task');
|
|
868
|
+
}
|
|
941
869
|
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
if (
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
if (ctx.storageLen < ctx.storagePtr + 2) { throw new Error('not enough storage remaining for lift'); }
|
|
949
|
-
val = new DataView(ctx.memory.buffer).getUint16(ctx.storagePtr);
|
|
950
|
-
ctx.storagePtr += 2;
|
|
951
|
-
ctx.storageLen -= 2;
|
|
870
|
+
if (taskID) {
|
|
871
|
+
const last = tasks[tasks.length - 1];
|
|
872
|
+
if (last.id !== taskID) {
|
|
873
|
+
// throw new Error('current task does not match expected task ID');
|
|
874
|
+
return;
|
|
875
|
+
}
|
|
952
876
|
}
|
|
953
877
|
|
|
954
|
-
|
|
878
|
+
ASYNC_CURRENT_TASK_IDS.pop();
|
|
879
|
+
ASYNC_CURRENT_COMPONENT_IDXS.pop();
|
|
880
|
+
|
|
881
|
+
const taskMeta = tasks.pop();
|
|
882
|
+
return taskMeta.task;
|
|
955
883
|
}
|
|
884
|
+
const ASYNC_TASKS_BY_COMPONENT_IDX = new Map();
|
|
956
885
|
|
|
957
|
-
|
|
958
|
-
|
|
886
|
+
class AsyncTask {
|
|
887
|
+
static _ID = 0n;
|
|
959
888
|
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
if (ctx.storageLen < ctx.storagePtr + 4) { throw new Error('not enough storage remaining for lift'); }
|
|
967
|
-
val = new DataView(ctx.memory.buffer).getUint32(ctx.storagePtr);
|
|
968
|
-
ctx.storagePtr += 4;
|
|
969
|
-
ctx.storageLen -= 4;
|
|
889
|
+
static State = {
|
|
890
|
+
INITIAL: 'initial',
|
|
891
|
+
CANCELLED: 'cancelled',
|
|
892
|
+
CANCEL_PENDING: 'cancel-pending',
|
|
893
|
+
CANCEL_DELIVERED: 'cancel-delivered',
|
|
894
|
+
RESOLVED: 'resolved',
|
|
970
895
|
}
|
|
971
896
|
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
function _liftFlatU64(ctx) {
|
|
976
|
-
_debugLog('[_liftFlatU64()] args', { ctx });
|
|
977
|
-
|
|
978
|
-
let val;
|
|
979
|
-
if (ctx.useDirectParams) {
|
|
980
|
-
if (ctx.params.length === 0) { throw new Error('expected at least one single i64 argument'); }
|
|
981
|
-
if (typeof ctx.params[0] !== 'bigint') { throw new Error('expected bigint'); }
|
|
982
|
-
val = ctx.params[0];
|
|
983
|
-
ctx.params = ctx.params.slice(1);
|
|
984
|
-
} else {
|
|
985
|
-
if (ctx.storageLen < ctx.storagePtr + 8) { throw new Error('not enough storage remaining for lift'); }
|
|
986
|
-
val = new DataView(ctx.memory.buffer).getUint64(ctx.storagePtr);
|
|
987
|
-
ctx.storagePtr += 8;
|
|
988
|
-
ctx.storageLen -= 8;
|
|
897
|
+
static BlockResult = {
|
|
898
|
+
CANCELLED: 'block.cancelled',
|
|
899
|
+
NOT_CANCELLED: 'block.not-cancelled',
|
|
989
900
|
}
|
|
990
901
|
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
902
|
+
#id;
|
|
903
|
+
#componentIdx;
|
|
904
|
+
#state;
|
|
905
|
+
#isAsync;
|
|
906
|
+
#entryFnName = null;
|
|
907
|
+
#subtasks = [];
|
|
996
908
|
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
if (ctx.params.length < 2) { throw new Error('expected at least two u32 arguments'); }
|
|
1000
|
-
const offset = ctx.params[0];
|
|
1001
|
-
if (!Number.isSafeInteger(offset)) { throw new Error('invalid offset'); }
|
|
1002
|
-
const len = ctx.params[1];
|
|
1003
|
-
if (!Number.isSafeInteger(len)) { throw new Error('invalid len'); }
|
|
1004
|
-
val = TEXT_DECODER_UTF8.decode(new DataView(ctx.memory.buffer, offset, len));
|
|
1005
|
-
ctx.params = ctx.params.slice(2);
|
|
1006
|
-
} else {
|
|
1007
|
-
const start = new DataView(ctx.memory.buffer).getUint32(ctx.storagePtr, params[0], true);
|
|
1008
|
-
const codeUnits = new DataView(memory.buffer).getUint32(ctx.storagePtr, params[0] + 4, true);
|
|
1009
|
-
val = TEXT_DECODER_UTF8.decode(new Uint8Array(ctx.memory.buffer, start, codeUnits));
|
|
1010
|
-
ctx.storagePtr += codeUnits;
|
|
1011
|
-
ctx.storageLen -= codeUnits;
|
|
1012
|
-
}
|
|
909
|
+
#onResolveHandlers = [];
|
|
910
|
+
#completionPromise = null;
|
|
1013
911
|
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
912
|
+
#memoryIdx = null;
|
|
913
|
+
|
|
914
|
+
#callbackFn = null;
|
|
915
|
+
#callbackFnName = null;
|
|
916
|
+
|
|
917
|
+
#postReturnFn = null;
|
|
918
|
+
|
|
919
|
+
#getCalleeParamsFn = null;
|
|
920
|
+
|
|
921
|
+
#stringEncoding = null;
|
|
922
|
+
|
|
923
|
+
#parentSubtask = null;
|
|
924
|
+
|
|
925
|
+
#needsExclusiveLock = false;
|
|
926
|
+
|
|
927
|
+
#errHandling;
|
|
928
|
+
|
|
929
|
+
#backpressurePromise;
|
|
930
|
+
#backpressureWaiters = 0n;
|
|
931
|
+
|
|
932
|
+
#returnLowerFns = null;
|
|
933
|
+
|
|
934
|
+
cancelled = false;
|
|
935
|
+
requested = false;
|
|
936
|
+
alwaysTaskReturn = false;
|
|
937
|
+
|
|
938
|
+
returnCalls = 0;
|
|
939
|
+
storage = [0, 0];
|
|
940
|
+
borrowedHandles = {};
|
|
941
|
+
|
|
942
|
+
awaitableResume = null;
|
|
943
|
+
awaitableCancel = null;
|
|
944
|
+
|
|
945
|
+
constructor(opts) {
|
|
946
|
+
this.#id = ++AsyncTask._ID;
|
|
1022
947
|
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
let discriminantByteLen = 1;
|
|
1026
|
-
const [idx, newCtx] = _liftFlatU8(ctx);
|
|
1027
|
-
caseIdx = idx;
|
|
1028
|
-
ctx = newCtx;
|
|
1029
|
-
} else if (casesAndLiftFns.length > 256 && discriminantByteLen < 65536) {
|
|
1030
|
-
discriminantByteLen = 2;
|
|
1031
|
-
const [idx, newCtx] = _liftFlatU16(ctx);
|
|
1032
|
-
caseIdx = idx;
|
|
1033
|
-
ctx = newCtx;
|
|
1034
|
-
} else if (casesAndLiftFns.length > 65536 && discriminantByteLen < 4_294_967_296) {
|
|
1035
|
-
discriminantByteLen = 4;
|
|
1036
|
-
const [idx, newCtx] = _liftFlatU32(ctx);
|
|
1037
|
-
caseIdx = idx;
|
|
1038
|
-
ctx = newCtx;
|
|
1039
|
-
} else {
|
|
1040
|
-
throw new Error('unsupported number of cases [' + casesAndLIftFns.legnth + ']');
|
|
948
|
+
if (opts?.componentIdx === undefined) {
|
|
949
|
+
throw new TypeError('missing component id during task creation');
|
|
1041
950
|
}
|
|
951
|
+
this.#componentIdx = opts.componentIdx;
|
|
1042
952
|
|
|
1043
|
-
|
|
953
|
+
this.#state = AsyncTask.State.INITIAL;
|
|
954
|
+
this.#isAsync = opts?.isAsync ?? false;
|
|
955
|
+
this.#entryFnName = opts.entryFnName;
|
|
1044
956
|
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
}
|
|
957
|
+
const {
|
|
958
|
+
promise: completionPromise,
|
|
959
|
+
resolve: resolveCompletionPromise,
|
|
960
|
+
reject: rejectCompletionPromise,
|
|
961
|
+
} = promiseWithResolvers();
|
|
962
|
+
this.#completionPromise = completionPromise;
|
|
1050
963
|
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
964
|
+
this.#onResolveHandlers.push((results) => {
|
|
965
|
+
resolveCompletionPromise(results);
|
|
966
|
+
})
|
|
1054
967
|
|
|
1055
|
-
|
|
968
|
+
if (opts.callbackFn) { this.#callbackFn = opts.callbackFn; }
|
|
969
|
+
if (opts.callbackFnName) { this.#callbackFnName = opts.callbackFnName; }
|
|
970
|
+
|
|
971
|
+
if (opts.getCalleeParamsFn) { this.#getCalleeParamsFn = opts.getCalleeParamsFn; }
|
|
972
|
+
|
|
973
|
+
if (opts.stringEncoding) { this.#stringEncoding = opts.stringEncoding; }
|
|
974
|
+
|
|
975
|
+
if (opts.parentSubtask) { this.#parentSubtask = opts.parentSubtask; }
|
|
976
|
+
|
|
977
|
+
this.#needsExclusiveLock = this.isSync() || !this.hasCallback();
|
|
978
|
+
|
|
979
|
+
if (opts.errHandling) { this.#errHandling = opts.errHandling; }
|
|
1056
980
|
}
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
981
|
+
|
|
982
|
+
taskState() { return this.#state; }
|
|
983
|
+
id() { return this.#id; }
|
|
984
|
+
componentIdx() { return this.#componentIdx; }
|
|
985
|
+
isAsync() { return this.#isAsync; }
|
|
986
|
+
entryFnName() { return this.#entryFnName; }
|
|
987
|
+
completionPromise() { return this.#completionPromise; }
|
|
988
|
+
|
|
989
|
+
isAsync() { return this.#isAsync; }
|
|
990
|
+
isSync() { return !this.isAsync(); }
|
|
991
|
+
|
|
992
|
+
getErrHandling() { return this.#errHandling; }
|
|
993
|
+
|
|
994
|
+
hasCallback() { return this.#callbackFn !== null; }
|
|
995
|
+
|
|
996
|
+
setReturnMemoryIdx(idx) { this.#memoryIdx = idx; }
|
|
997
|
+
getReturnMemoryIdx() { return this.#memoryIdx; }
|
|
998
|
+
|
|
999
|
+
setReturnLowerFns(fns) { this.#returnLowerFns = fns; }
|
|
1000
|
+
getReturnLowerFns() { return this.#returnLowerFns; }
|
|
1001
|
+
|
|
1002
|
+
setParentSubtask(subtask) {
|
|
1003
|
+
if (!subtask || !(subtask instanceof AsyncSubtask)) { return }
|
|
1004
|
+
if (this.#parentSubtask) { throw new Error('parent subtask can only be set once'); }
|
|
1005
|
+
this.#parentSubtask = subtask;
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
getParentSubtask() { return this.#parentSubtask; }
|
|
1009
|
+
|
|
1010
|
+
// TODO(threads): this is very inefficient, we can pass along a root task,
|
|
1011
|
+
// and ideally do not need this once thread support is in place
|
|
1012
|
+
getRootTask() {
|
|
1013
|
+
let currentSubtask = this.getParentSubtask();
|
|
1014
|
+
let task = this;
|
|
1015
|
+
while (currentSubtask) {
|
|
1016
|
+
task = currentSubtask.getParentTask();
|
|
1017
|
+
currentSubtask = task.getParentSubtask();
|
|
1018
|
+
}
|
|
1019
|
+
return task;
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
setPostReturnFn(f) {
|
|
1023
|
+
if (!f) { return; }
|
|
1024
|
+
if (this.#postReturnFn) { throw new Error('postReturn fn can only be set once'); }
|
|
1025
|
+
this.#postReturnFn = f;
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
setCallbackFn(f, name) {
|
|
1029
|
+
if (!f) { return; }
|
|
1030
|
+
if (this.#callbackFn) { throw new Error('callback fn can only be set once'); }
|
|
1031
|
+
this.#callbackFn = f;
|
|
1032
|
+
this.#callbackFnName = name;
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
getCallbackFnName() {
|
|
1036
|
+
if (!this.#callbackFnName) { return undefined; }
|
|
1037
|
+
return this.#callbackFnName;
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
runCallbackFn(...args) {
|
|
1041
|
+
if (!this.#callbackFn) { throw new Error('on callback function has been set for task'); }
|
|
1042
|
+
return this.#callbackFn.apply(null, args);
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
getCalleeParams() {
|
|
1046
|
+
if (!this.#getCalleeParamsFn) { throw new Error('missing/invalid getCalleeParamsFn'); }
|
|
1047
|
+
return this.#getCalleeParamsFn();
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
mayEnter(task) {
|
|
1051
|
+
const cstate = getOrCreateAsyncState(this.#componentIdx);
|
|
1052
|
+
if (cstate.hasBackpressure()) {
|
|
1053
|
+
_debugLog('[AsyncTask#mayEnter()] disallowed due to backpressure', { taskID: this.#id });
|
|
1054
|
+
return false;
|
|
1055
|
+
}
|
|
1056
|
+
if (!cstate.callingSyncImport()) {
|
|
1057
|
+
_debugLog('[AsyncTask#mayEnter()] disallowed due to sync import call', { taskID: this.#id });
|
|
1058
|
+
return false;
|
|
1059
|
+
}
|
|
1060
|
+
const callingSyncExportWithSyncPending = cstate.callingSyncExport && !task.isAsync;
|
|
1061
|
+
if (!callingSyncExportWithSyncPending) {
|
|
1062
|
+
_debugLog('[AsyncTask#mayEnter()] disallowed due to sync export w/ sync pending', { taskID: this.#id });
|
|
1063
|
+
return false;
|
|
1064
|
+
}
|
|
1065
|
+
return true;
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
async enter() {
|
|
1069
|
+
_debugLog('[AsyncTask#enter()] args', { taskID: this.#id });
|
|
1070
|
+
const cstate = getOrCreateAsyncState(this.#componentIdx);
|
|
1062
1071
|
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1072
|
+
if (this.isSync()) { return true; }
|
|
1073
|
+
|
|
1074
|
+
if (cstate.hasBackpressure()) {
|
|
1075
|
+
cstate.addBackpressureWaiter();
|
|
1076
|
+
|
|
1077
|
+
const result = await this.waitUntil({
|
|
1078
|
+
readyFn: () => !cstate.hasBackpressure(),
|
|
1079
|
+
cancellable: true,
|
|
1080
|
+
});
|
|
1081
|
+
|
|
1082
|
+
cstate.removeBackpressureWaiter();
|
|
1083
|
+
|
|
1084
|
+
if (result === AsyncTask.BlockResult.CANCELLED) {
|
|
1085
|
+
this.cancel();
|
|
1086
|
+
return false;
|
|
1071
1087
|
}
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
if (this.needsExclusiveLock()) { cstate.exclusiveLock(); }
|
|
1091
|
+
|
|
1092
|
+
return true;
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
isRunning() {
|
|
1096
|
+
return this.#state !== AsyncTask.State.RESOLVED;
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
async waitUntil(opts) {
|
|
1100
|
+
const { readyFn, waitableSetRep, cancellable } = opts;
|
|
1101
|
+
_debugLog('[AsyncTask#waitUntil()] args', { taskID: this.#id, waitableSetRep, cancellable });
|
|
1102
|
+
|
|
1103
|
+
const state = getOrCreateAsyncState(this.#componentIdx);
|
|
1104
|
+
const wset = state.waitableSets.get(waitableSetRep);
|
|
1105
|
+
|
|
1106
|
+
let event;
|
|
1107
|
+
|
|
1108
|
+
wset.incrementNumWaiting();
|
|
1109
|
+
|
|
1110
|
+
const keepGoing = await this.suspendUntil({
|
|
1111
|
+
readyFn: () => {
|
|
1112
|
+
const hasPendingEvent = wset.hasPendingEvent();
|
|
1113
|
+
return readyFn() && hasPendingEvent;
|
|
1114
|
+
},
|
|
1115
|
+
cancellable,
|
|
1116
|
+
});
|
|
1117
|
+
|
|
1118
|
+
if (keepGoing) {
|
|
1119
|
+
event = wset.getPendingEvent();
|
|
1072
1120
|
} else {
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
}
|
|
1121
|
+
event = {
|
|
1122
|
+
code: ASYNC_EVENT_CODE.TASK_CANCELLED,
|
|
1123
|
+
index: 0,
|
|
1124
|
+
result: 0,
|
|
1125
|
+
};
|
|
1078
1126
|
}
|
|
1079
1127
|
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
len = _liftFlatU32(ctx);
|
|
1090
|
-
|
|
1091
|
-
ctx.useDirectParams = true;
|
|
1092
|
-
ctx.storagePtr = null;
|
|
1093
|
-
ctx.storageLen = null;
|
|
1094
|
-
} else {
|
|
1095
|
-
dataPtr = _liftFlatU32(ctx);
|
|
1096
|
-
len = _liftFlatU32(ctx);
|
|
1097
|
-
}
|
|
1128
|
+
wset.decrementNumWaiting();
|
|
1129
|
+
|
|
1130
|
+
return event;
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1133
|
+
async onBlock(awaitable) {
|
|
1134
|
+
_debugLog('[AsyncTask#onBlock()] args', { taskID: this.#id, awaitable });
|
|
1135
|
+
if (!(awaitable instanceof Awaitable)) {
|
|
1136
|
+
throw new Error('invalid awaitable during onBlock');
|
|
1098
1137
|
}
|
|
1099
1138
|
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1139
|
+
// Build a promise that this task can await on which resolves when it is awoken
|
|
1140
|
+
const { promise, resolve, reject } = promiseWithResolvers();
|
|
1141
|
+
this.awaitableResume = () => {
|
|
1142
|
+
_debugLog('[AsyncTask] resuming after onBlock', { taskID: this.#id });
|
|
1143
|
+
resolve();
|
|
1144
|
+
};
|
|
1145
|
+
this.awaitableCancel = (err) => {
|
|
1146
|
+
_debugLog('[AsyncTask] rejecting after onBlock', { taskID: this.#id, err });
|
|
1147
|
+
reject(err);
|
|
1148
|
+
};
|
|
1149
|
+
|
|
1150
|
+
// Park this task/execution to be handled later
|
|
1151
|
+
const state = getOrCreateAsyncState(this.#componentIdx);
|
|
1152
|
+
state.parkTaskOnAwaitable({ awaitable, task: this });
|
|
1153
|
+
|
|
1154
|
+
try {
|
|
1155
|
+
await promise;
|
|
1156
|
+
return AsyncTask.BlockResult.NOT_CANCELLED;
|
|
1157
|
+
} catch (err) {
|
|
1158
|
+
// rejection means task cancellation
|
|
1159
|
+
return AsyncTask.BlockResult.CANCELLED;
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
async asyncOnBlock(awaitable) {
|
|
1164
|
+
_debugLog('[AsyncTask#asyncOnBlock()] args', { taskID: this.#id, awaitable });
|
|
1165
|
+
if (!(awaitable instanceof Awaitable)) {
|
|
1166
|
+
throw new Error('invalid awaitable during onBlock');
|
|
1106
1167
|
}
|
|
1168
|
+
// TODO: watch for waitable AND cancellation
|
|
1169
|
+
// TODO: if it WAS cancelled:
|
|
1170
|
+
// - return true
|
|
1171
|
+
// - only once per subtask
|
|
1172
|
+
// - do not wait on the scheduler
|
|
1173
|
+
// - control flow should go to the subtask (only once)
|
|
1174
|
+
// - Once subtask blocks/resolves, reqlinquishControl() will tehn resolve request_cancel_end (without scheduler lock release)
|
|
1175
|
+
// - control flow goes back to request_cancel
|
|
1176
|
+
//
|
|
1177
|
+
// Subtask cancellation should work similarly to an async import call -- runs sync up until
|
|
1178
|
+
// the subtask blocks or resolves
|
|
1179
|
+
//
|
|
1180
|
+
throw new Error('AsyncTask#asyncOnBlock() not yet implemented');
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
async yieldUntil(opts) {
|
|
1184
|
+
const { readyFn, cancellable } = opts;
|
|
1185
|
+
_debugLog('[AsyncTask#yieldUntil()] args', { taskID: this.#id, cancellable });
|
|
1107
1186
|
|
|
1108
|
-
|
|
1187
|
+
const keepGoing = await this.suspendUntil({ readyFn, cancellable });
|
|
1188
|
+
if (!keepGoing) {
|
|
1189
|
+
return {
|
|
1190
|
+
code: ASYNC_EVENT_CODE.TASK_CANCELLED,
|
|
1191
|
+
index: 0,
|
|
1192
|
+
result: 0,
|
|
1193
|
+
};
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1196
|
+
return {
|
|
1197
|
+
code: ASYNC_EVENT_CODE.NONE,
|
|
1198
|
+
index: 0,
|
|
1199
|
+
result: 0,
|
|
1200
|
+
};
|
|
1109
1201
|
}
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1202
|
+
|
|
1203
|
+
async suspendUntil(opts) {
|
|
1204
|
+
const { cancellable, readyFn } = opts;
|
|
1205
|
+
_debugLog('[AsyncTask#suspendUntil()] args', { cancellable });
|
|
1206
|
+
|
|
1207
|
+
const pendingCancelled = this.deliverPendingCancel({ cancellable });
|
|
1208
|
+
if (pendingCancelled) { return false; }
|
|
1209
|
+
|
|
1210
|
+
const completed = await this.immediateSuspendUntil({ readyFn, cancellable });
|
|
1211
|
+
return completed;
|
|
1116
1212
|
}
|
|
1213
|
+
|
|
1214
|
+
// TODO(threads): equivalent to thread.suspend_until()
|
|
1215
|
+
async immediateSuspendUntil(opts) {
|
|
1216
|
+
const { cancellable, readyFn } = opts;
|
|
1217
|
+
_debugLog('[AsyncTask#immediateSuspendUntil()] args', { cancellable, readyFn });
|
|
1218
|
+
|
|
1219
|
+
const ready = readyFn();
|
|
1220
|
+
if (ready && !ASYNC_DETERMINISM && _coinFlip()) {
|
|
1221
|
+
return true;
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1224
|
+
const cstate = getOrCreateAsyncState(this.#componentIdx);
|
|
1225
|
+
cstate.addPendingTask(this);
|
|
1226
|
+
|
|
1227
|
+
const keepGoing = await this.immediateSuspend({ cancellable, readyFn });
|
|
1228
|
+
return keepGoing;
|
|
1229
|
+
}
|
|
1230
|
+
|
|
1231
|
+
async immediateSuspend(opts) { // NOTE: equivalent to thread.suspend()
|
|
1232
|
+
// TODO(threads): store readyFn on the thread
|
|
1233
|
+
const { cancellable, readyFn } = opts;
|
|
1234
|
+
_debugLog('[AsyncTask#immediateSuspend()] args', { cancellable, readyFn });
|
|
1235
|
+
|
|
1236
|
+
const pendingCancelled = this.deliverPendingCancel({ cancellable });
|
|
1237
|
+
if (pendingCancelled) { return false; }
|
|
1238
|
+
|
|
1239
|
+
const cstate = getOrCreateAsyncState(this.#componentIdx);
|
|
1240
|
+
|
|
1241
|
+
// TODO(fix): update this to tick until there is no more action to take.
|
|
1242
|
+
setTimeout(() => cstate.tick(), 0);
|
|
1243
|
+
|
|
1244
|
+
const taskWait = await cstate.suspendTask({ task: this, readyFn });
|
|
1245
|
+
const keepGoing = await taskWait;
|
|
1246
|
+
return keepGoing;
|
|
1117
1247
|
}
|
|
1118
1248
|
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1249
|
+
deliverPendingCancel(opts) {
|
|
1250
|
+
const { cancellable } = opts;
|
|
1251
|
+
_debugLog('[AsyncTask#deliverPendingCancel()] args', { cancellable });
|
|
1252
|
+
|
|
1253
|
+
if (cancellable && this.#state === AsyncTask.State.PENDING_CANCEL) {
|
|
1254
|
+
this.#state = Task.State.CANCEL_DELIVERED;
|
|
1255
|
+
return true;
|
|
1123
1256
|
}
|
|
1257
|
+
|
|
1258
|
+
return false;
|
|
1124
1259
|
}
|
|
1125
1260
|
|
|
1126
|
-
|
|
1127
|
-
_debugLog('[_liftFlatOwn()] args', { size, memory, vals, storagePtr, storageLen });
|
|
1128
|
-
throw new Error('flat lift for owned resources not yet implemented!');
|
|
1129
|
-
}
|
|
1261
|
+
isCancelled() { return this.cancelled }
|
|
1130
1262
|
|
|
1131
|
-
|
|
1132
|
-
_debugLog('[
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
throw new Error('unexpected number (' + vals.length + ') of core vals (expected 1)');
|
|
1263
|
+
cancel() {
|
|
1264
|
+
_debugLog('[AsyncTask#cancel()] args', { });
|
|
1265
|
+
if (!this.taskState() !== AsyncTask.State.CANCEL_DELIVERED) {
|
|
1266
|
+
throw new Error(`(component [${this.#componentIdx}]) task [${this.#id}] invalid task state for cancellation`);
|
|
1136
1267
|
}
|
|
1137
|
-
if (
|
|
1138
|
-
|
|
1139
|
-
new
|
|
1140
|
-
|
|
1268
|
+
if (this.borrowedHandles.length > 0) { throw new Error('task still has borrow handles'); }
|
|
1269
|
+
this.cancelled = true;
|
|
1270
|
+
this.onResolve(new Error('cancelled'));
|
|
1271
|
+
this.#state = AsyncTask.State.RESOLVED;
|
|
1141
1272
|
}
|
|
1142
1273
|
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1274
|
+
onResolve(taskValue) {
|
|
1275
|
+
for (const f of this.#onResolveHandlers) {
|
|
1276
|
+
try {
|
|
1277
|
+
f(taskValue);
|
|
1278
|
+
} catch (err) {
|
|
1279
|
+
console.error("error during task resolve handler", err);
|
|
1280
|
+
throw err;
|
|
1281
|
+
}
|
|
1147
1282
|
}
|
|
1148
|
-
if (vals[0] > 65_535 || vals[0] < 0) { throw new Error('invalid value for core value representing u16'); }
|
|
1149
|
-
new DataView(memory.buffer).setUint16(storagePtr, vals[0], true);
|
|
1150
|
-
return 2;
|
|
1151
|
-
}
|
|
1152
|
-
|
|
1153
|
-
function _lowerFlatU32(ctx) {
|
|
1154
|
-
_debugLog('[_lowerFlatU32()] args', ctx);
|
|
1155
|
-
const { memory, realloc, vals, storagePtr, storageLen } = ctx;
|
|
1156
|
-
if (vals.length !== 1) { throw new Error('expected single value to lower, got (' + vals.length + ')'); }
|
|
1157
|
-
if (vals[0] > 4_294_967_295 || vals[0] < 0) { throw new Error('invalid value for core value representing u32'); }
|
|
1158
1283
|
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1284
|
+
if (this.#postReturnFn) {
|
|
1285
|
+
_debugLog('[AsyncTask#onResolve()] running post return ', {
|
|
1286
|
+
componentIdx: this.#componentIdx,
|
|
1287
|
+
taskID: this.#id,
|
|
1288
|
+
});
|
|
1289
|
+
this.#postReturnFn();
|
|
1290
|
+
}
|
|
1165
1291
|
}
|
|
1166
1292
|
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
if (vals.length !== 1) { throw new Error('unexpected number of core vals'); }
|
|
1170
|
-
if (vals[0] > 18_446_744_073_709_551_615n || vals[0] < 0n) { throw new Error('invalid value for core value representing u64'); }
|
|
1171
|
-
new DataView(memory.buffer).setBigUint64(storagePtr, vals[0], true);
|
|
1172
|
-
return 8;
|
|
1293
|
+
registerOnResolveHandler(f) {
|
|
1294
|
+
this.#onResolveHandlers.push(f);
|
|
1173
1295
|
}
|
|
1174
1296
|
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1297
|
+
resolve(results) {
|
|
1298
|
+
_debugLog('[AsyncTask#resolve()] args', {
|
|
1299
|
+
results,
|
|
1300
|
+
componentIdx: this.#componentIdx,
|
|
1301
|
+
taskID: this.#id,
|
|
1302
|
+
});
|
|
1303
|
+
|
|
1304
|
+
if (this.#state === AsyncTask.State.RESOLVED) {
|
|
1305
|
+
throw new Error(`(component [${this.#componentIdx}]) task [${this.#id}] is already resolved (did you forget to wait for an import?)`);
|
|
1306
|
+
}
|
|
1307
|
+
if (this.borrowedHandles.length > 0) { throw new Error('task still has borrow handles'); }
|
|
1308
|
+
switch (results.length) {
|
|
1309
|
+
case 0:
|
|
1310
|
+
this.onResolve(undefined);
|
|
1311
|
+
break;
|
|
1312
|
+
case 1:
|
|
1313
|
+
this.onResolve(results[0]);
|
|
1314
|
+
break;
|
|
1315
|
+
default:
|
|
1316
|
+
throw new Error('unexpected number of results');
|
|
1195
1317
|
}
|
|
1318
|
+
this.#state = AsyncTask.State.RESOLVED;
|
|
1196
1319
|
}
|
|
1197
1320
|
|
|
1198
|
-
|
|
1199
|
-
|
|
1321
|
+
exit() {
|
|
1322
|
+
_debugLog('[AsyncTask#exit()] args', { });
|
|
1200
1323
|
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1324
|
+
// TODO: ensure there is only one task at a time (scheduler.lock() functionality)
|
|
1325
|
+
if (this.#state !== AsyncTask.State.RESOLVED) {
|
|
1326
|
+
// TODO(fix): only fused, manually specified post returns seem to break this invariant,
|
|
1327
|
+
// as the TaskReturn trampoline is not activated it seems.
|
|
1328
|
+
//
|
|
1329
|
+
// see: test/p3/ported/wasmtime/component-async/post-return.js
|
|
1330
|
+
//
|
|
1331
|
+
// We *should* be able to upgrade this to be more strict and throw at some point,
|
|
1332
|
+
// which may involve rewriting the upstream test to surface task return manually somehow.
|
|
1333
|
+
//
|
|
1334
|
+
//throw new Error(`(component [${this.#componentIdx}]) task [${this.#id}] exited without resolution`);
|
|
1335
|
+
_debugLog('[AsyncTask#exit()] task exited without resolution', {
|
|
1336
|
+
componentIdx: this.#componentIdx,
|
|
1337
|
+
taskID: this.#id,
|
|
1338
|
+
subtask: this.getParentSubtask(),
|
|
1339
|
+
subtaskID: this.getParentSubtask()?.id(),
|
|
1340
|
+
});
|
|
1341
|
+
this.#state = AsyncTask.State.RESOLVED;
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
if (this.borrowedHandles > 0) {
|
|
1345
|
+
throw new Error('task [${this.#id}] exited without clearing borrowed handles');
|
|
1346
|
+
}
|
|
1347
|
+
|
|
1348
|
+
const state = getOrCreateAsyncState(this.#componentIdx);
|
|
1349
|
+
if (!state) { throw new Error('missing async state for component [' + this.#componentIdx + ']'); }
|
|
1350
|
+
if (!this.#isAsync && !state.inSyncExportCall) {
|
|
1351
|
+
throw new Error('sync task must be run from components known to be in a sync export call');
|
|
1352
|
+
}
|
|
1353
|
+
state.inSyncExportCall = false;
|
|
1354
|
+
|
|
1355
|
+
if (this.needsExclusiveLock() && !state.isExclusivelyLocked()) {
|
|
1356
|
+
throw new Error('task [' + this.#id + '] exit: component [' + this.#componentIdx + '] should have been exclusively locked');
|
|
1234
1357
|
}
|
|
1358
|
+
|
|
1359
|
+
state.exclusiveRelease();
|
|
1235
1360
|
}
|
|
1236
1361
|
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1362
|
+
needsExclusiveLock() { return this.#needsExclusiveLock; }
|
|
1363
|
+
|
|
1364
|
+
createSubtask(args) {
|
|
1365
|
+
_debugLog('[AsyncTask#createSubtask()] args', args);
|
|
1366
|
+
const { componentIdx, childTask, callMetadata } = args;
|
|
1367
|
+
const newSubtask = new AsyncSubtask({
|
|
1368
|
+
componentIdx,
|
|
1369
|
+
childTask,
|
|
1370
|
+
parentTask: this,
|
|
1371
|
+
callMetadata,
|
|
1372
|
+
});
|
|
1373
|
+
this.#subtasks.push(newSubtask);
|
|
1374
|
+
return newSubtask;
|
|
1247
1375
|
}
|
|
1248
1376
|
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
const data = new Uint8Array(memory.buffer, start, size);
|
|
1256
|
-
new Uint8Array(memory.buffer, storagePtr, size).set(data);
|
|
1257
|
-
return data.byteLength;
|
|
1377
|
+
getLatestSubtask() { return this.#subtasks.at(-1); }
|
|
1378
|
+
|
|
1379
|
+
currentSubtask() {
|
|
1380
|
+
_debugLog('[AsyncTask#currentSubtask()]');
|
|
1381
|
+
if (this.#subtasks.length === 0) { return undefined; }
|
|
1382
|
+
return this.#subtasks.at(-1);
|
|
1258
1383
|
}
|
|
1259
1384
|
|
|
1260
|
-
|
|
1261
|
-
_debugLog('[
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
new Uint8Array(memory.buffer, storagePtr, size).set(data);
|
|
1268
|
-
return data.byteLength;
|
|
1385
|
+
endCurrentSubtask() {
|
|
1386
|
+
_debugLog('[AsyncTask#endCurrentSubtask()]');
|
|
1387
|
+
if (this.#subtasks.length === 0) { throw new Error('cannot end current subtask: no current subtask'); }
|
|
1388
|
+
const subtask = this.#subtasks.pop();
|
|
1389
|
+
subtask.drop();
|
|
1390
|
+
return subtask;
|
|
1391
|
+
}
|
|
1269
1392
|
}
|
|
1270
1393
|
|
|
1271
|
-
function
|
|
1272
|
-
const
|
|
1273
|
-
|
|
1394
|
+
function _lowerImport(args, exportFn) {
|
|
1395
|
+
const params = [...arguments].slice(2);
|
|
1396
|
+
_debugLog('[_lowerImport()] args', { args, params, exportFn });
|
|
1397
|
+
const {
|
|
1398
|
+
functionIdx,
|
|
1399
|
+
componentIdx,
|
|
1400
|
+
isAsync,
|
|
1401
|
+
paramLiftFns,
|
|
1402
|
+
resultLowerFns,
|
|
1403
|
+
metadata,
|
|
1404
|
+
memoryIdx,
|
|
1405
|
+
getMemoryFn,
|
|
1406
|
+
getReallocFn,
|
|
1407
|
+
} = args;
|
|
1408
|
+
|
|
1409
|
+
const parentTaskMeta = getCurrentTask(componentIdx);
|
|
1410
|
+
const parentTask = parentTaskMeta?.task;
|
|
1411
|
+
if (!parentTask) { throw new Error('missing parent task during lower of import'); }
|
|
1412
|
+
|
|
1413
|
+
const cstate = getOrCreateAsyncState(componentIdx);
|
|
1414
|
+
|
|
1415
|
+
const subtask = parentTask.createSubtask({
|
|
1416
|
+
componentIdx,
|
|
1417
|
+
parentTask,
|
|
1418
|
+
callMetadata: {
|
|
1419
|
+
memoryIdx,
|
|
1420
|
+
memory: getMemoryFn(),
|
|
1421
|
+
realloc: getReallocFn(),
|
|
1422
|
+
resultPtr: params[0],
|
|
1423
|
+
}
|
|
1424
|
+
});
|
|
1425
|
+
parentTask.setReturnMemoryIdx(memoryIdx);
|
|
1426
|
+
|
|
1427
|
+
const rep = cstate.subtasks.insert(subtask);
|
|
1428
|
+
subtask.setRep(rep);
|
|
1429
|
+
|
|
1430
|
+
subtask.setOnProgressFn(() => {
|
|
1431
|
+
subtask.setPendingEventFn(() => {
|
|
1432
|
+
if (subtask.resolved()) { subtask.deliverResolve(); }
|
|
1433
|
+
return {
|
|
1434
|
+
code: ASYNC_EVENT_CODE.SUBTASK,
|
|
1435
|
+
index: rep,
|
|
1436
|
+
result: subtask.getStateNumber(),
|
|
1437
|
+
}
|
|
1438
|
+
});
|
|
1439
|
+
});
|
|
1440
|
+
|
|
1441
|
+
// Set up a handler on subtask completion to lower results from the call into the caller's memory region.
|
|
1442
|
+
subtask.registerOnResolveHandler((res) => {
|
|
1443
|
+
_debugLog('[_lowerImport()] handling subtask result', { res, subtaskID: subtask.id() });
|
|
1444
|
+
const { memory, resultPtr, realloc } = subtask.getCallMetadata();
|
|
1445
|
+
if (resultLowerFns.length === 0) { return; }
|
|
1446
|
+
resultLowerFns[0]({ componentIdx, memory, realloc, vals: [res], storagePtr: resultPtr });
|
|
1447
|
+
});
|
|
1448
|
+
|
|
1449
|
+
const subtaskState = subtask.getStateNumber();
|
|
1450
|
+
if (subtaskState < 0 || subtaskState > 2**5) {
|
|
1451
|
+
throw new Error('invalid subtask state, out of valid range');
|
|
1452
|
+
}
|
|
1453
|
+
|
|
1454
|
+
// NOTE: we must wait a bit before calling the export function,
|
|
1455
|
+
// to ensure the subtask state is not modified before the lower call return
|
|
1456
|
+
//
|
|
1457
|
+
// TODO: we should trigger via subtask state changing, rather than a static wait?
|
|
1458
|
+
setTimeout(async () => {
|
|
1459
|
+
try {
|
|
1460
|
+
_debugLog('[_lowerImport()] calling lowered import', { exportFn, params });
|
|
1461
|
+
exportFn.apply(null, params);
|
|
1462
|
+
|
|
1463
|
+
const task = subtask.getChildTask();
|
|
1464
|
+
task.registerOnResolveHandler((res) => {
|
|
1465
|
+
_debugLog('[_lowerImport()] cascading subtask completion', {
|
|
1466
|
+
childTaskID: task.id(),
|
|
1467
|
+
subtaskID: subtask.id(),
|
|
1468
|
+
parentTaskID: parentTask.id(),
|
|
1469
|
+
});
|
|
1470
|
+
|
|
1471
|
+
subtask.onResolve(res);
|
|
1472
|
+
|
|
1473
|
+
cstate.tick();
|
|
1474
|
+
});
|
|
1475
|
+
} catch (err) {
|
|
1476
|
+
console.error("post-lower import fn error:", err);
|
|
1477
|
+
throw err;
|
|
1478
|
+
}
|
|
1479
|
+
}, 100);
|
|
1274
1480
|
|
|
1275
|
-
return
|
|
1276
|
-
_debugLog('[_lowerFlatResult()] args', { lowerMetas });
|
|
1277
|
-
let lowerFn = _lowerFlatVariant({ discriminantSizeBytes: 1, lowerMetas }, { forResult: true });
|
|
1278
|
-
return lowerFn.apply(null, arguments);
|
|
1279
|
-
};
|
|
1280
|
-
}
|
|
1281
|
-
|
|
1282
|
-
function _lowerFlatOwn(size, memory, vals, storagePtr, storageLen) {
|
|
1283
|
-
_debugLog('[_lowerFlatOwn()] args', { size, memory, vals, storagePtr, storageLen });
|
|
1284
|
-
throw new Error('flat lower for owned resources not yet implemented!');
|
|
1285
|
-
}
|
|
1286
|
-
const ASYNC_STATE = new Map();
|
|
1287
|
-
|
|
1288
|
-
function getOrCreateAsyncState(componentIdx, init) {
|
|
1289
|
-
if (!ASYNC_STATE.has(componentIdx)) {
|
|
1290
|
-
const newState = new ComponentAsyncState({ componentIdx });
|
|
1291
|
-
ASYNC_STATE.set(componentIdx, newState);
|
|
1292
|
-
}
|
|
1293
|
-
return ASYNC_STATE.get(componentIdx);
|
|
1481
|
+
return Number(subtask.waitableRep()) << 4 | subtaskState;
|
|
1294
1482
|
}
|
|
1295
1483
|
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
#componentIdx;
|
|
1300
|
-
#callingAsyncImport = false;
|
|
1301
|
-
#syncImportWait = promiseWithResolvers();
|
|
1302
|
-
#locked = false;
|
|
1303
|
-
#parkedTasks = new Map();
|
|
1304
|
-
#suspendedTasksByTaskID = new Map();
|
|
1305
|
-
#suspendedTaskIDs = [];
|
|
1306
|
-
#pendingTasks = [];
|
|
1307
|
-
#errored = null;
|
|
1484
|
+
function _liftFlatU8(ctx) {
|
|
1485
|
+
_debugLog('[_liftFlatU8()] args', { ctx });
|
|
1486
|
+
let val;
|
|
1308
1487
|
|
|
1309
|
-
|
|
1310
|
-
|
|
1488
|
+
if (ctx.useDirectParams) {
|
|
1489
|
+
if (ctx.params.length === 0) { throw new Error('expected at least a single i32 argument'); }
|
|
1490
|
+
val = ctx.params[0];
|
|
1491
|
+
ctx.params = ctx.params.slice(1);
|
|
1492
|
+
return [val, ctx];
|
|
1493
|
+
}
|
|
1311
1494
|
|
|
1312
|
-
|
|
1313
|
-
|
|
1495
|
+
if (ctx.storageLen !== undefined && ctx.storageLen < ctx.storagePtr + 1) {
|
|
1496
|
+
throw new Error('not enough storage remaining for lift');
|
|
1497
|
+
}
|
|
1498
|
+
val = new DataView(ctx.memory.buffer).getUint8(ctx.storagePtr, true);
|
|
1499
|
+
ctx.storagePtr += 1;
|
|
1500
|
+
if (ctx.storageLen !== undefined) { ctx.storageLen -= 1; }
|
|
1314
1501
|
|
|
1315
|
-
|
|
1502
|
+
return [val, ctx];
|
|
1503
|
+
}
|
|
1504
|
+
|
|
1505
|
+
function _liftFlatU16(ctx) {
|
|
1506
|
+
_debugLog('[_liftFlatU16()] args', { ctx });
|
|
1507
|
+
let val;
|
|
1316
1508
|
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1509
|
+
if (ctx.useDirectParams) {
|
|
1510
|
+
if (params.length === 0) { throw new Error('expected at least a single i32 argument'); }
|
|
1511
|
+
val = ctx.params[0];
|
|
1512
|
+
ctx.params = ctx.params.slice(1);
|
|
1513
|
+
return [val, ctx];
|
|
1514
|
+
}
|
|
1320
1515
|
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
}
|
|
1516
|
+
if (ctx.storageLen !== undefined && ctx.storageLen < ctx.storagePtr + 2) {
|
|
1517
|
+
throw new Error('not enough storage remaining for lift');
|
|
1518
|
+
}
|
|
1519
|
+
val = new DataView(ctx.memory.buffer).getUint16(ctx.storagePtr, true);
|
|
1520
|
+
ctx.storagePtr += 2;
|
|
1521
|
+
if (ctx.storageLen !== undefined) { ctx.storageLen -= 2; }
|
|
1327
1522
|
|
|
1328
|
-
|
|
1523
|
+
return [val, ctx];
|
|
1524
|
+
}
|
|
1525
|
+
|
|
1526
|
+
function _liftFlatU32(ctx) {
|
|
1527
|
+
_debugLog('[_liftFlatU32()] args', { ctx });
|
|
1528
|
+
let val;
|
|
1329
1529
|
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
err = new Error('error elswehere (see other component instance error)')
|
|
1336
|
-
err.componentIdx = this.#componentIdx;
|
|
1337
|
-
}
|
|
1338
|
-
this.#errored = err;
|
|
1530
|
+
if (ctx.useDirectParams) {
|
|
1531
|
+
if (ctx.params.length === 0) { throw new Error('expected at least a single i34 argument'); }
|
|
1532
|
+
val = ctx.params[0];
|
|
1533
|
+
ctx.params = ctx.params.slice(1);
|
|
1534
|
+
return [val, ctx];
|
|
1339
1535
|
}
|
|
1340
1536
|
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
if (typeof val !== 'boolean') { throw new TypeError('invalid setting for async import'); }
|
|
1344
|
-
const prev = this.#callingAsyncImport;
|
|
1345
|
-
this.#callingAsyncImport = val;
|
|
1346
|
-
if (prev === true && this.#callingAsyncImport === false) {
|
|
1347
|
-
this.#notifySyncImportEnd();
|
|
1348
|
-
}
|
|
1537
|
+
if (ctx.storageLen !== undefined && ctx.storageLen < ctx.storagePtr + 4) {
|
|
1538
|
+
throw new Error('not enough storage remaining for lift');
|
|
1349
1539
|
}
|
|
1540
|
+
val = new DataView(ctx.memory.buffer).getUint32(ctx.storagePtr, true);
|
|
1541
|
+
ctx.storagePtr += 4;
|
|
1542
|
+
if (ctx.storageLen !== undefined) { ctx.storageLen -= 4; }
|
|
1350
1543
|
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
}
|
|
1544
|
+
return [val, ctx];
|
|
1545
|
+
}
|
|
1546
|
+
|
|
1547
|
+
function _liftFlatU64(ctx) {
|
|
1548
|
+
_debugLog('[_liftFlatU64()] args', { ctx });
|
|
1549
|
+
let val;
|
|
1356
1550
|
|
|
1357
|
-
|
|
1358
|
-
|
|
1551
|
+
if (ctx.useDirectParams) {
|
|
1552
|
+
if (ctx.params.length === 0) { throw new Error('expected at least one single i64 argument'); }
|
|
1553
|
+
if (typeof ctx.params[0] !== 'bigint') { throw new Error('expected bigint'); }
|
|
1554
|
+
val = ctx.params[0];
|
|
1555
|
+
ctx.params = ctx.params.slice(1);
|
|
1556
|
+
return [val, ctx];
|
|
1359
1557
|
}
|
|
1360
1558
|
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
incrementBackpressure() {
|
|
1364
|
-
const newValue = this.getBackpressure() + 1;
|
|
1365
|
-
if (newValue > 2**16) { throw new Error("invalid backpressure value, overflow"); }
|
|
1366
|
-
this.setBackpressure(newValue);
|
|
1559
|
+
if (ctx.storageLen !== undefined && ctx.storageLen < ctx.storagePtr + 8) {
|
|
1560
|
+
throw new Error('not enough storage remaining for lift');
|
|
1367
1561
|
}
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
}
|
|
1371
|
-
hasBackpressure() { return this.#backpressure > 0; }
|
|
1562
|
+
val = new DataView(ctx.memory.buffer).getUint64(ctx.storagePtr, true);
|
|
1563
|
+
ctx.storagePtr += 8;
|
|
1564
|
+
if (ctx.storageLen !== undefined) { ctx.storageLen -= 8; }
|
|
1372
1565
|
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
clearInterval(interval);
|
|
1390
|
-
cstate.removeBackpressureWaiter();
|
|
1391
|
-
resolve(null);
|
|
1392
|
-
}, 0);
|
|
1393
|
-
});
|
|
1566
|
+
return [val, ctx];
|
|
1567
|
+
}
|
|
1568
|
+
|
|
1569
|
+
function _liftFlatStringUTF8(ctx) {
|
|
1570
|
+
_debugLog('[_liftFlatStringUTF8()] args', { ctx });
|
|
1571
|
+
let val;
|
|
1572
|
+
|
|
1573
|
+
if (ctx.useDirectParams) {
|
|
1574
|
+
if (ctx.params.length < 2) { throw new Error('expected at least two u32 arguments'); }
|
|
1575
|
+
const offset = ctx.params[0];
|
|
1576
|
+
if (!Number.isSafeInteger(offset)) { throw new Error('invalid offset'); }
|
|
1577
|
+
const len = ctx.params[1];
|
|
1578
|
+
if (!Number.isSafeInteger(len)) { throw new Error('invalid len'); }
|
|
1579
|
+
val = TEXT_DECODER_UTF8.decode(new DataView(ctx.memory.buffer, offset, len));
|
|
1580
|
+
ctx.params = ctx.params.slice(2);
|
|
1581
|
+
return [val, ctx];
|
|
1394
1582
|
}
|
|
1395
1583
|
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1584
|
+
const start = new DataView(ctx.memory.buffer).getUint32(ctx.storagePtr, params[0], true);
|
|
1585
|
+
const codeUnits = new DataView(memory.buffer).getUint32(ctx.storagePtr, params[0] + 4, true);
|
|
1586
|
+
val = TEXT_DECODER_UTF8.decode(new Uint8Array(ctx.memory.buffer, start, codeUnits));
|
|
1587
|
+
ctx.storagePtr += codeUnits;
|
|
1588
|
+
if (ctx.storageLen !== undefined) { ctx.storageLen -= codeUnits; }
|
|
1589
|
+
|
|
1590
|
+
return [val, ctx];
|
|
1591
|
+
}
|
|
1592
|
+
|
|
1593
|
+
function _liftFlatVariant(casesAndLiftFns) {
|
|
1594
|
+
return function _liftFlatVariantInner(ctx) {
|
|
1595
|
+
_debugLog('[_liftFlatVariant()] args', { ctx });
|
|
1400
1596
|
|
|
1401
|
-
|
|
1402
|
-
|
|
1597
|
+
const origUseParams = ctx.useDirectParams;
|
|
1598
|
+
|
|
1599
|
+
let caseIdx;
|
|
1600
|
+
if (casesAndLiftFns.length < 256) {
|
|
1601
|
+
let discriminantByteLen = 1;
|
|
1602
|
+
const [idx, newCtx] = _liftFlatU8(ctx);
|
|
1603
|
+
caseIdx = idx;
|
|
1604
|
+
ctx = newCtx;
|
|
1605
|
+
} else if (casesAndLiftFns.length > 256 && discriminantByteLen < 65536) {
|
|
1606
|
+
discriminantByteLen = 2;
|
|
1607
|
+
const [idx, newCtx] = _liftFlatU16(ctx);
|
|
1608
|
+
caseIdx = idx;
|
|
1609
|
+
ctx = newCtx;
|
|
1610
|
+
} else if (casesAndLiftFns.length > 65536 && discriminantByteLen < 4_294_967_296) {
|
|
1611
|
+
discriminantByteLen = 4;
|
|
1612
|
+
const [idx, newCtx] = _liftFlatU32(ctx);
|
|
1613
|
+
caseIdx = idx;
|
|
1614
|
+
ctx = newCtx;
|
|
1615
|
+
} else {
|
|
1616
|
+
throw new Error('unsupported number of cases [' + casesAndLIftFns.legnth + ']');
|
|
1403
1617
|
}
|
|
1404
1618
|
|
|
1405
|
-
const
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1619
|
+
const [ tag, liftFn, size32, alignment32 ] = casesAndLiftFns[caseIdx];
|
|
1620
|
+
|
|
1621
|
+
let val;
|
|
1622
|
+
if (liftFn === null) {
|
|
1623
|
+
val = { tag };
|
|
1624
|
+
return [val, ctx];
|
|
1410
1625
|
}
|
|
1411
1626
|
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
const { event, handlerID } = args;
|
|
1418
|
-
const registeredHandlers = this.#handlerMap.get(event);
|
|
1419
|
-
if (!registeredHandlers) { return; }
|
|
1420
|
-
const found = registeredHandlers.find(h => h.id === handlerID);
|
|
1421
|
-
if (!found) { return; }
|
|
1422
|
-
this.#handlerMap.set(event, this.#handlerMap.get(event).filter(h => h.id !== handlerID));
|
|
1627
|
+
const [newVal, newCtx] = liftFn(ctx);
|
|
1628
|
+
ctx = newCtx;
|
|
1629
|
+
val = { tag, val: newVal };
|
|
1630
|
+
|
|
1631
|
+
return [val, ctx];
|
|
1423
1632
|
}
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1633
|
+
}
|
|
1634
|
+
|
|
1635
|
+
function _liftFlatList(elemLiftFn, alignment32, knownLen) {
|
|
1636
|
+
function _liftFlatListInner(ctx) {
|
|
1637
|
+
_debugLog('[_liftFlatList()] args', { ctx });
|
|
1638
|
+
|
|
1639
|
+
let metaPtr;
|
|
1640
|
+
let dataPtr;
|
|
1641
|
+
let len;
|
|
1642
|
+
if (ctx.useDirectParams) {
|
|
1643
|
+
if (knownLen) {
|
|
1644
|
+
dataPtr = _liftFlatU32(ctx);
|
|
1645
|
+
} else {
|
|
1646
|
+
metaPtr = _liftFlatU32(ctx);
|
|
1647
|
+
}
|
|
1648
|
+
} else {
|
|
1649
|
+
if (knownLen) {
|
|
1650
|
+
dataPtr = _liftFlatU32(ctx);
|
|
1651
|
+
} else {
|
|
1652
|
+
metaPtr = _liftFlatU32(ctx);
|
|
1653
|
+
}
|
|
1431
1654
|
}
|
|
1432
|
-
}
|
|
1433
|
-
|
|
1434
|
-
parkTaskOnAwaitable(args) {
|
|
1435
|
-
if (!args.awaitable) { throw new TypeError('missing awaitable when trying to park'); }
|
|
1436
|
-
if (!args.task) { throw new TypeError('missing task when trying to park'); }
|
|
1437
|
-
const { awaitable, task } = args;
|
|
1438
1655
|
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1656
|
+
if (metaPtr) {
|
|
1657
|
+
if (dataPtr !== undefined) { throw new Error('both meta and data pointers should not be set yet'); }
|
|
1658
|
+
|
|
1659
|
+
if (ctx.useDirectParams) {
|
|
1660
|
+
ctx.useDirectParams = false;
|
|
1661
|
+
ctx.storagePtr = metaPtr;
|
|
1662
|
+
ctx.storageLen = 8;
|
|
1663
|
+
|
|
1664
|
+
dataPtr = _liftFlatU32(ctx);
|
|
1665
|
+
len = _liftFlatU32(ctx);
|
|
1666
|
+
|
|
1667
|
+
ctx.useDirectParams = true;
|
|
1668
|
+
ctx.storagePtr = null;
|
|
1669
|
+
ctx.storageLen = null;
|
|
1670
|
+
} else {
|
|
1671
|
+
dataPtr = _liftFlatU32(ctx);
|
|
1672
|
+
len = _liftFlatU32(ctx);
|
|
1673
|
+
}
|
|
1443
1674
|
}
|
|
1444
|
-
taskList.push(task);
|
|
1445
|
-
|
|
1446
|
-
this.wakeNextTaskForAwaitable(awaitable);
|
|
1447
|
-
}
|
|
1448
|
-
|
|
1449
|
-
wakeNextTaskForAwaitable(awaitable) {
|
|
1450
|
-
if (!awaitable) { throw new TypeError('missing awaitable when waking next task'); }
|
|
1451
|
-
const awaitableID = awaitable.id();
|
|
1452
1675
|
|
|
1453
|
-
const
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1676
|
+
const val = [];
|
|
1677
|
+
for (var i = 0; i < len; i++) {
|
|
1678
|
+
ctx.storagePtr = Math.ceil(ctx.storagePtr / alignment32) * alignment32;
|
|
1679
|
+
const [res, nextCtx] = elemLiftFn(ctx);
|
|
1680
|
+
val.push(res);
|
|
1681
|
+
ctx = nextCtx;
|
|
1457
1682
|
}
|
|
1458
1683
|
|
|
1459
|
-
|
|
1460
|
-
if (!task) { throw new Error('no task in parked list despite previous check'); }
|
|
1461
|
-
|
|
1462
|
-
if (!task.awaitableResume) {
|
|
1463
|
-
throw new Error('task ready due to awaitable is missing resume', { taskID: task.id(), awaitableID });
|
|
1464
|
-
}
|
|
1465
|
-
task.awaitableResume();
|
|
1684
|
+
return [val, ctx];
|
|
1466
1685
|
}
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1686
|
+
}
|
|
1687
|
+
|
|
1688
|
+
function _liftFlatFlags(cases) {
|
|
1689
|
+
return function _liftFlatFlagsInner(ctx) {
|
|
1690
|
+
_debugLog('[_liftFlatFlags()] args', { ctx });
|
|
1691
|
+
throw new Error('flat lift for flags not yet implemented!');
|
|
1471
1692
|
}
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
this.#locked = false
|
|
1693
|
+
}
|
|
1694
|
+
|
|
1695
|
+
function _liftFlatResult(casesAndLiftFns) {
|
|
1696
|
+
return function _liftFlatResultInner(ctx) {
|
|
1697
|
+
_debugLog('[_liftFlatResult()] args', { ctx });
|
|
1698
|
+
return _liftFlatVariant(casesAndLiftFns)(ctx);
|
|
1480
1699
|
}
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1700
|
+
}
|
|
1701
|
+
|
|
1702
|
+
function _liftFlatBorrow(componentTableIdx, size, memory, vals, storagePtr, storageLen) {
|
|
1703
|
+
_debugLog('[_liftFlatBorrow()] args', { size, memory, vals, storagePtr, storageLen });
|
|
1704
|
+
throw new Error('flat lift for borrowed resources not yet implemented!');
|
|
1705
|
+
}
|
|
1706
|
+
|
|
1707
|
+
function _lowerFlatU8(ctx) {
|
|
1708
|
+
_debugLog('[_lowerFlatU8()] args', ctx);
|
|
1709
|
+
const { memory, realloc, vals, storagePtr, storageLen } = ctx;
|
|
1710
|
+
if (vals.length !== 1) {
|
|
1711
|
+
throw new Error('unexpected number (' + vals.length + ') of core vals (expected 1)');
|
|
1486
1712
|
}
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1713
|
+
if (vals[0] > 255 || vals[0] < 0) { throw new Error('invalid value for core value representing u8'); }
|
|
1714
|
+
if (!memory) { throw new Error("missing memory for lower"); }
|
|
1715
|
+
new DataView(memory.buffer).setUint32(storagePtr, vals[0], true);
|
|
1716
|
+
return 1;
|
|
1717
|
+
}
|
|
1718
|
+
|
|
1719
|
+
function _lowerFlatU16(memory, vals, storagePtr, storageLen) {
|
|
1720
|
+
_debugLog('[_lowerFlatU16()] args', { memory, vals, storagePtr, storageLen });
|
|
1721
|
+
if (vals.length !== 1) {
|
|
1722
|
+
throw new Error('unexpected number (' + vals.length + ') of core vals (expected 1)');
|
|
1495
1723
|
}
|
|
1724
|
+
if (vals[0] > 65_535 || vals[0] < 0) { throw new Error('invalid value for core value representing u16'); }
|
|
1725
|
+
new DataView(memory.buffer).setUint16(storagePtr, vals[0], true);
|
|
1726
|
+
return 2;
|
|
1727
|
+
}
|
|
1728
|
+
|
|
1729
|
+
function _lowerFlatU32(ctx) {
|
|
1730
|
+
_debugLog('[_lowerFlatU32()] args', { ctx });
|
|
1731
|
+
const { memory, realloc, vals, storagePtr, storageLen } = ctx;
|
|
1732
|
+
if (vals.length !== 1) { throw new Error('expected single value to lower, got (' + vals.length + ')'); }
|
|
1733
|
+
if (vals[0] > 4_294_967_295 || vals[0] < 0) { throw new Error('invalid value for core value representing u32'); }
|
|
1496
1734
|
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
this.#suspendedTasksByTaskID.set(taskID, meta);
|
|
1501
|
-
this.#suspendedTaskIDs.push(taskID);
|
|
1502
|
-
if (this.#suspendedTasksByTaskID.size < this.#suspendedTaskIDs.length - 10) {
|
|
1503
|
-
this.#suspendedTaskIDs = this.#suspendedTaskIDs.filter(t => t !== null);
|
|
1504
|
-
}
|
|
1505
|
-
}
|
|
1735
|
+
// TODO(refactor): fail loudly on misaligned flat lowers?
|
|
1736
|
+
const rem = ctx.storagePtr % 4;
|
|
1737
|
+
if (rem !== 0) { ctx.storagePtr += (4 - rem); }
|
|
1506
1738
|
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1739
|
+
new DataView(memory.buffer).setUint32(storagePtr, vals[0], true);
|
|
1740
|
+
|
|
1741
|
+
return 4;
|
|
1742
|
+
}
|
|
1743
|
+
|
|
1744
|
+
function _lowerFlatU64(memory, vals, storagePtr, storageLen) {
|
|
1745
|
+
_debugLog('[_lowerFlatU64()] args', { memory, vals, storagePtr, storageLen });
|
|
1746
|
+
if (vals.length !== 1) { throw new Error('unexpected number of core vals'); }
|
|
1747
|
+
if (vals[0] > 18_446_744_073_709_551_615n || vals[0] < 0n) { throw new Error('invalid value for core value representing u64'); }
|
|
1748
|
+
new DataView(memory.buffer).setBigUint64(storagePtr, vals[0], true);
|
|
1749
|
+
return 8;
|
|
1750
|
+
}
|
|
1751
|
+
|
|
1752
|
+
function _lowerFlatRecord(fieldMetas) {
|
|
1753
|
+
return (size, memory, vals, storagePtr, storageLen) => {
|
|
1754
|
+
const params = [...arguments].slice(5);
|
|
1755
|
+
_debugLog('[_lowerFlatRecord()] args', {
|
|
1756
|
+
size,
|
|
1757
|
+
memory,
|
|
1758
|
+
vals,
|
|
1759
|
+
storagePtr,
|
|
1760
|
+
storageLen,
|
|
1761
|
+
params,
|
|
1762
|
+
fieldMetas
|
|
1527
1763
|
});
|
|
1528
1764
|
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
resumeTaskByID(taskID) {
|
|
1533
|
-
const meta = this.#removeSuspendedTaskMeta(taskID);
|
|
1534
|
-
if (!meta) { return; }
|
|
1535
|
-
if (meta.taskID !== taskID) { throw new Error('task ID does not match'); }
|
|
1536
|
-
meta.resume();
|
|
1537
|
-
}
|
|
1538
|
-
|
|
1539
|
-
tick() {
|
|
1540
|
-
_debugLog('[ComponentAsyncState#tick()]', { suspendedTaskIDs: this.#suspendedTaskIDs });
|
|
1541
|
-
let resumedTask = false;
|
|
1542
|
-
for (const taskID of this.#suspendedTaskIDs.filter(t => t !== null)) {
|
|
1543
|
-
const meta = this.#suspendedTasksByTaskID.get(taskID);
|
|
1544
|
-
if (!meta || !meta.readyFn) {
|
|
1545
|
-
throw new Error('missing/invalid task despite ID [' + taskID + '] being present');
|
|
1546
|
-
}
|
|
1547
|
-
if (!meta.readyFn()) { continue; }
|
|
1548
|
-
resumedTask = true;
|
|
1549
|
-
this.resumeTaskByID(taskID);
|
|
1765
|
+
const [start] = vals;
|
|
1766
|
+
if (storageLen !== undefined && size !== undefined && size > storageLen) {
|
|
1767
|
+
throw new Error('not enough storage remaining for record flat lower');
|
|
1550
1768
|
}
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
addPendingTask(task) {
|
|
1555
|
-
this.#pendingTasks.push(task);
|
|
1769
|
+
const data = new Uint8Array(memory.buffer, start, size);
|
|
1770
|
+
new Uint8Array(memory.buffer, storagePtr, size).set(data);
|
|
1771
|
+
return data.byteLength;
|
|
1556
1772
|
}
|
|
1557
1773
|
}
|
|
1558
1774
|
|
|
1559
|
-
function
|
|
1560
|
-
|
|
1561
|
-
getMemoryFn,
|
|
1562
|
-
startFn,
|
|
1563
|
-
returnFn,
|
|
1564
|
-
callerInstanceIdx,
|
|
1565
|
-
calleeInstanceIdx,
|
|
1566
|
-
taskReturnTypeIdx,
|
|
1567
|
-
isCalleeAsyncInt,
|
|
1568
|
-
stringEncoding,
|
|
1569
|
-
resultCountOrAsync,
|
|
1570
|
-
) {
|
|
1571
|
-
_debugLog('[_prepareCall()]', {
|
|
1572
|
-
callerInstanceIdx,
|
|
1573
|
-
calleeInstanceIdx,
|
|
1574
|
-
taskReturnTypeIdx,
|
|
1575
|
-
isCalleeAsyncInt,
|
|
1576
|
-
stringEncoding,
|
|
1577
|
-
resultCountOrAsync,
|
|
1578
|
-
});
|
|
1579
|
-
const argArray = [...arguments];
|
|
1775
|
+
function _lowerFlatVariant(metadata, extra) {
|
|
1776
|
+
const { discriminantSizeBytes, lowerMetas } = metadata;
|
|
1580
1777
|
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1778
|
+
return function _lowerFlatVariantInner(ctx) {
|
|
1779
|
+
_debugLog('[_lowerFlatVariant()] args', ctx);
|
|
1780
|
+
const { memory, realloc, vals, storageLen, componentIdx } = ctx;
|
|
1781
|
+
let storagePtr = ctx.storagePtr;
|
|
1782
|
+
|
|
1783
|
+
const { tag, val } = vals[0];
|
|
1784
|
+
const variant = lowerMetas.find(vm => vm.tag === tag);
|
|
1785
|
+
if (!variant) { throw new Error(`missing/invalid variant, no tag matches [${tag}] (options were ${variantMetas.map(vm => vm.tag)})`); }
|
|
1786
|
+
if (!variant.discriminant) { throw new Error(`missing/invalid discriminant for variant [${variant}]`); }
|
|
1787
|
+
|
|
1788
|
+
let bytesWritten;
|
|
1789
|
+
let discriminantLowerArgs = { memory, realloc, vals: [variant.discriminant], storagePtr, componentIdx }
|
|
1790
|
+
switch (discriminantSizeBytes) {
|
|
1791
|
+
case 1:
|
|
1792
|
+
bytesWritten = _lowerFlatU8(discriminantLowerArgs);
|
|
1793
|
+
break;
|
|
1794
|
+
case 2:
|
|
1795
|
+
bytesWritten = _lowerFlatU16(discriminantLowerArgs);
|
|
1796
|
+
break;
|
|
1797
|
+
case 4:
|
|
1798
|
+
bytesWritten = _lowerFlatU32(discriminantLowerArgs);
|
|
1799
|
+
break;
|
|
1800
|
+
default:
|
|
1801
|
+
throw new Error(`unexpected discriminant size bytes [${discriminantSizeBytes}]`);
|
|
1802
|
+
}
|
|
1803
|
+
if (bytesWritten !== discriminantSizeBytes) {
|
|
1804
|
+
throw new Error("unexpectedly wrote more bytes than discriminant");
|
|
1805
|
+
}
|
|
1806
|
+
storagePtr += bytesWritten;
|
|
1807
|
+
|
|
1808
|
+
bytesWritten += variant.lowerFn({ memory, realloc, vals: [val], storagePtr, storageLen, componentIdx });
|
|
1809
|
+
|
|
1810
|
+
return bytesWritten;
|
|
1601
1811
|
}
|
|
1812
|
+
}
|
|
1813
|
+
|
|
1814
|
+
function _lowerFlatList(args) {
|
|
1815
|
+
const { elemLowerFn } = args;
|
|
1816
|
+
if (!elemLowerFn) { throw new TypeError("missing/invalid element lower fn for list"); }
|
|
1602
1817
|
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1818
|
+
return function _lowerFlatListInner(ctx) {
|
|
1819
|
+
_debugLog('[_lowerFlatList()] args', { ctx });
|
|
1820
|
+
|
|
1821
|
+
if (ctx.params.length < 2) { throw new Error('insufficient params left to lower list'); }
|
|
1822
|
+
const storagePtr = ctx.params[0];
|
|
1823
|
+
const elemCount = ctx.params[1];
|
|
1824
|
+
ctx.params = ctx.params.slice(2);
|
|
1825
|
+
|
|
1826
|
+
if (ctx.useDirectParams) {
|
|
1827
|
+
const list = ctx.vals[0];
|
|
1828
|
+
if (!list) { throw new Error("missing direct param value"); }
|
|
1829
|
+
|
|
1830
|
+
const elemLowerCtx = { storagePtr, memory: ctx.memory };
|
|
1831
|
+
for (let idx = 0; idx < list.length; idx++) {
|
|
1832
|
+
elemLowerCtx.vals = list.slice(idx, idx+1);
|
|
1833
|
+
elemLowerCtx.storagePtr += elemLowerFn(elemLowerCtx);
|
|
1834
|
+
}
|
|
1835
|
+
|
|
1836
|
+
const bytesLowered = elemLowerCtx.storagePtr - ctx.storagePtr;
|
|
1837
|
+
ctx.storagePtr = elemLowerCtx.storagePtr;
|
|
1838
|
+
return bytesLowered;
|
|
1839
|
+
}
|
|
1840
|
+
|
|
1841
|
+
|
|
1842
|
+
if (ctx.vals.length !== 2) {
|
|
1843
|
+
throw new Error('indirect parameter loading must have a pointer and length as vals');
|
|
1844
|
+
}
|
|
1845
|
+
let [valStartPtr, valLen] = ctx.vals;
|
|
1846
|
+
const totalSizeBytes = valLen * size;
|
|
1847
|
+
if (ctx.storageLen !== undefined && totalSizeBytes > ctx.storageLen) {
|
|
1848
|
+
throw new Error('not enough storage remaining for list flat lower');
|
|
1849
|
+
}
|
|
1850
|
+
|
|
1851
|
+
const data = new Uint8Array(memory.buffer, valStartPtr, totalSizeBytes);
|
|
1852
|
+
new Uint8Array(memory.buffer, storagePtr, totalSizeBytes).set(data);
|
|
1853
|
+
|
|
1854
|
+
return totalSizeBytes;
|
|
1606
1855
|
}
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1856
|
+
}
|
|
1857
|
+
|
|
1858
|
+
function _lowerFlatTuple(size, memory, vals, storagePtr, storageLen) {
|
|
1859
|
+
_debugLog('[_lowerFlatTuple()] args', { size, memory, vals, storagePtr, storageLen });
|
|
1860
|
+
let [start, len] = vals;
|
|
1861
|
+
if (storageLen !== undefined && len > storageLen) {
|
|
1862
|
+
throw new Error('not enough storage remaining for tuple flat lower');
|
|
1611
1863
|
}
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1864
|
+
const data = new Uint8Array(memory.buffer, start, len);
|
|
1865
|
+
new Uint8Array(memory.buffer, storagePtr, len).set(data);
|
|
1866
|
+
return data.byteLength;
|
|
1867
|
+
}
|
|
1868
|
+
|
|
1869
|
+
function _lowerFlatEnum(size, memory, vals, storagePtr, storageLen) {
|
|
1870
|
+
_debugLog('[_lowerFlatEnum()] args', { size, memory, vals, storagePtr, storageLen });
|
|
1871
|
+
let [start] = vals;
|
|
1872
|
+
if (storageLen !== undefined && size !== undefined && size > storageLen) {
|
|
1873
|
+
throw new Error('not enough storage remaining for enum flat lower');
|
|
1615
1874
|
}
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1875
|
+
const data = new Uint8Array(memory.buffer, start, size);
|
|
1876
|
+
new Uint8Array(memory.buffer, storagePtr, size).set(data);
|
|
1877
|
+
return data.byteLength;
|
|
1878
|
+
}
|
|
1879
|
+
|
|
1880
|
+
function _lowerFlatOption(size, memory, vals, storagePtr, storageLen) {
|
|
1881
|
+
_debugLog('[_lowerFlatOption()] args', { size, memory, vals, storagePtr, storageLen });
|
|
1882
|
+
let [start] = vals;
|
|
1883
|
+
if (storageLen !== undefined && size !== undefined && size > storageLen) {
|
|
1884
|
+
throw new Error('not enough storage remaining for option flat lower');
|
|
1626
1885
|
}
|
|
1886
|
+
const data = new Uint8Array(memory.buffer, start, size);
|
|
1887
|
+
new Uint8Array(memory.buffer, storagePtr, size).set(data);
|
|
1888
|
+
return data.byteLength;
|
|
1889
|
+
}
|
|
1890
|
+
|
|
1891
|
+
function _lowerFlatResult(lowerMetas) {
|
|
1892
|
+
const invalidTag = lowerMetas.find(t => t.tag !== 'ok' && t.tag !== 'error')
|
|
1893
|
+
if (invalidTag) { throw new Error(`invalid variant tag [${invalidTag}] found for result`); }
|
|
1627
1894
|
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1895
|
+
return function _lowerFlatResultInner() {
|
|
1896
|
+
_debugLog('[_lowerFlatResult()] args', { lowerMetas });
|
|
1897
|
+
let lowerFn = _lowerFlatVariant({ discriminantSizeBytes: 1, lowerMetas }, { forResult: true });
|
|
1898
|
+
return lowerFn.apply(null, arguments);
|
|
1899
|
+
};
|
|
1900
|
+
}
|
|
1901
|
+
|
|
1902
|
+
function _lowerFlatOwn(size, memory, vals, storagePtr, storageLen) {
|
|
1903
|
+
_debugLog('[_lowerFlatOwn()] args', { size, memory, vals, storagePtr, storageLen });
|
|
1904
|
+
throw new Error('flat lower for owned resources not yet implemented!');
|
|
1905
|
+
}
|
|
1906
|
+
const ASYNC_STATE = new Map();
|
|
1907
|
+
|
|
1908
|
+
function getOrCreateAsyncState(componentIdx, init) {
|
|
1909
|
+
if (!ASYNC_STATE.has(componentIdx)) {
|
|
1910
|
+
const newState = new ComponentAsyncState({ componentIdx });
|
|
1911
|
+
ASYNC_STATE.set(componentIdx, newState);
|
|
1641
1912
|
}
|
|
1913
|
+
return ASYNC_STATE.get(componentIdx);
|
|
1914
|
+
}
|
|
1915
|
+
|
|
1916
|
+
class ComponentAsyncState {
|
|
1917
|
+
static EVENT_HANDLER_EVENTS = [ 'backpressure-change' ];
|
|
1642
1918
|
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1919
|
+
#componentIdx;
|
|
1920
|
+
#callingAsyncImport = false;
|
|
1921
|
+
#syncImportWait = promiseWithResolvers();
|
|
1922
|
+
#locked = false;
|
|
1923
|
+
#parkedTasks = new Map();
|
|
1924
|
+
#suspendedTasksByTaskID = new Map();
|
|
1925
|
+
#suspendedTaskIDs = [];
|
|
1926
|
+
#pendingTasks = [];
|
|
1927
|
+
#errored = null;
|
|
1651
1928
|
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
parentTask: currentCallerTask,
|
|
1655
|
-
childTask: newTask,
|
|
1656
|
-
callMetadata: {
|
|
1657
|
-
memory: getMemoryFn(),
|
|
1658
|
-
memoryIdx,
|
|
1659
|
-
resultPtr,
|
|
1660
|
-
returnFn,
|
|
1661
|
-
startFn,
|
|
1662
|
-
}
|
|
1663
|
-
});
|
|
1929
|
+
#backpressure = 0;
|
|
1930
|
+
#backpressureWaiters = 0n;
|
|
1664
1931
|
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
// against the task.return (which will be called from the callee)
|
|
1668
|
-
newTask.setReturnMemoryIdx(memoryIdx);
|
|
1669
|
-
}
|
|
1670
|
-
|
|
1671
|
-
function _asyncStartCall(args, callee, paramCount, resultCount, flags) {
|
|
1672
|
-
const { getCallbackFn, callbackIdx, getPostReturnFn, postReturnIdx } = args;
|
|
1673
|
-
_debugLog('[_asyncStartCall()] args', args);
|
|
1932
|
+
#handlerMap = new Map();
|
|
1933
|
+
#nextHandlerID = 0n;
|
|
1674
1934
|
|
|
1675
|
-
|
|
1676
|
-
if (!taskMeta) { throw new Error('invalid/missing current async task meta during prepare call'); }
|
|
1935
|
+
mayLeave = true;
|
|
1677
1936
|
|
|
1678
|
-
|
|
1937
|
+
#streams;
|
|
1679
1938
|
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
const preparedTask = taskMeta.task;
|
|
1684
|
-
if (!preparedTask) { throw new Error('unexpectedly missing task in task meta during prepare call'); }
|
|
1939
|
+
waitableSets;
|
|
1940
|
+
waitables;
|
|
1941
|
+
subtasks;
|
|
1685
1942
|
|
|
1686
|
-
|
|
1943
|
+
constructor(args) {
|
|
1944
|
+
this.#componentIdx = args.componentIdx;
|
|
1945
|
+
this.waitableSets = new RepTable({ target: `component [${this.#componentIdx}] waitable sets` });
|
|
1946
|
+
this.waitables = new RepTable({ target: `component [${this.#componentIdx}] waitables` });
|
|
1947
|
+
this.subtasks = new RepTable({ target: `component [${this.#componentIdx}] subtasks` });
|
|
1948
|
+
this.#streams = new Map();
|
|
1949
|
+
};
|
|
1687
1950
|
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
preparedTask.setCallbackFn(callbackFn, callbackFnName);
|
|
1691
|
-
preparedTask.setPostReturnFn(getPostReturnFn());
|
|
1951
|
+
componentIdx() { return this.#componentIdx; }
|
|
1952
|
+
streams() { return this.#streams; }
|
|
1692
1953
|
|
|
1693
|
-
|
|
1954
|
+
errored() { return this.#errored !== null; }
|
|
1955
|
+
setErrored(err) {
|
|
1956
|
+
_debugLog('[ComponentAsyncState#setErrored()] component errored', { err, componentIdx: this.#componentIdx });
|
|
1957
|
+
if (this.#errored) { return; }
|
|
1958
|
+
if (!err) {
|
|
1959
|
+
err = new Error('error elswehere (see other component instance error)')
|
|
1960
|
+
err.componentIdx = this.#componentIdx;
|
|
1961
|
+
}
|
|
1962
|
+
this.#errored = err;
|
|
1963
|
+
}
|
|
1694
1964
|
|
|
1695
|
-
|
|
1965
|
+
callingSyncImport(val) {
|
|
1966
|
+
if (val === undefined) { return this.#callingAsyncImport; }
|
|
1967
|
+
if (typeof val !== 'boolean') { throw new TypeError('invalid setting for async import'); }
|
|
1968
|
+
const prev = this.#callingAsyncImport;
|
|
1969
|
+
this.#callingAsyncImport = val;
|
|
1970
|
+
if (prev === true && this.#callingAsyncImport === false) {
|
|
1971
|
+
this.#notifySyncImportEnd();
|
|
1972
|
+
}
|
|
1973
|
+
}
|
|
1696
1974
|
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1975
|
+
#notifySyncImportEnd() {
|
|
1976
|
+
const existing = this.#syncImportWait;
|
|
1977
|
+
this.#syncImportWait = promiseWithResolvers();
|
|
1978
|
+
existing.resolve();
|
|
1700
1979
|
}
|
|
1701
1980
|
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1981
|
+
async waitForSyncImportCallEnd() {
|
|
1982
|
+
await this.#syncImportWait.promise;
|
|
1983
|
+
}
|
|
1984
|
+
|
|
1985
|
+
setBackpressure(v) { this.#backpressure = v; }
|
|
1986
|
+
getBackpressure(v) { return this.#backpressure; }
|
|
1987
|
+
incrementBackpressure() {
|
|
1988
|
+
const newValue = this.getBackpressure() + 1;
|
|
1989
|
+
if (newValue > 2**16) { throw new Error("invalid backpressure value, overflow"); }
|
|
1990
|
+
this.setBackpressure(newValue);
|
|
1991
|
+
}
|
|
1992
|
+
decrementBackpressure() {
|
|
1993
|
+
this.setBackpressure(Math.max(0, this.getBackpressure() - 1));
|
|
1994
|
+
}
|
|
1995
|
+
hasBackpressure() { return this.#backpressure > 0; }
|
|
1996
|
+
|
|
1997
|
+
waitForBackpressure() {
|
|
1998
|
+
let backpressureCleared = false;
|
|
1999
|
+
const cstate = this;
|
|
2000
|
+
cstate.addBackpressureWaiter();
|
|
2001
|
+
const handlerID = this.registerHandler({
|
|
2002
|
+
event: 'backpressure-change',
|
|
2003
|
+
fn: (bp) => {
|
|
2004
|
+
if (bp === 0) {
|
|
2005
|
+
cstate.removeHandler(handlerID);
|
|
2006
|
+
backpressureCleared = true;
|
|
2007
|
+
}
|
|
1709
2008
|
}
|
|
1710
2009
|
});
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
2010
|
+
return new Promise((resolve) => {
|
|
2011
|
+
const interval = setInterval(() => {
|
|
2012
|
+
if (backpressureCleared) { return; }
|
|
2013
|
+
clearInterval(interval);
|
|
2014
|
+
cstate.removeBackpressureWaiter();
|
|
2015
|
+
resolve(null);
|
|
2016
|
+
}, 0);
|
|
2017
|
+
});
|
|
1716
2018
|
}
|
|
1717
2019
|
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
const calleeComponentState = getOrCreateAsyncState(preparedTask.componentIdx());
|
|
1723
|
-
const calleeBackpressure = calleeComponentState.hasBackpressure();
|
|
1724
|
-
|
|
1725
|
-
// Set up a handler on subtask completion to lower results from the call into the caller's memory region.
|
|
1726
|
-
//
|
|
1727
|
-
// NOTE: during fused guest->guest calls this handler is triggered, but does not actually perform
|
|
1728
|
-
// lowering manually, as fused modules provider helper functions that can
|
|
1729
|
-
subtask.registerOnResolveHandler((res) => {
|
|
1730
|
-
_debugLog('[_asyncStartCall()] handling subtask result', { res, subtaskID: subtask.id() });
|
|
1731
|
-
let subtaskCallMeta = subtask.getCallMetadata();
|
|
2020
|
+
registerHandler(args) {
|
|
2021
|
+
const { event, fn } = args;
|
|
2022
|
+
if (!event) { throw new Error("missing handler event"); }
|
|
2023
|
+
if (!fn) { throw new Error("missing handler fn"); }
|
|
1732
2024
|
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
//
|
|
1736
|
-
// We can simply take the value and lower it as a parameter
|
|
1737
|
-
if (subtaskCallMeta.memory || subtaskCallMeta.realloc) {
|
|
1738
|
-
throw new Error("call metadata unexpectedly contains memory/realloc for guest->guest call");
|
|
2025
|
+
if (!ComponentAsyncState.EVENT_HANDLER_EVENTS.includes(event)) {
|
|
2026
|
+
throw new Error(`unrecognized event handler [${event}]`);
|
|
1739
2027
|
}
|
|
1740
2028
|
|
|
1741
|
-
const
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
// If a helper function was provided we are likely in a fused guest->guest call,
|
|
1747
|
-
// and the result will be delivered (lift/lowered) via helper function
|
|
1748
|
-
if (subtaskCallMeta.returnFn) {
|
|
1749
|
-
_debugLog('[_asyncStartCall()] return function present while ahndling subtask result, returning early (skipping lower)');
|
|
1750
|
-
return;
|
|
2029
|
+
const handlerID = this.#nextHandlerID++;
|
|
2030
|
+
let handlers = this.#handlerMap.get(event);
|
|
2031
|
+
if (!handlers) {
|
|
2032
|
+
handlers = [];
|
|
2033
|
+
this.#handlerMap.set(event, handlers)
|
|
1751
2034
|
}
|
|
1752
2035
|
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
2036
|
+
handlers.push({ id: handlerID, fn, event });
|
|
2037
|
+
return handlerID;
|
|
2038
|
+
}
|
|
2039
|
+
|
|
2040
|
+
removeHandler(args) {
|
|
2041
|
+
const { event, handlerID } = args;
|
|
2042
|
+
const registeredHandlers = this.#handlerMap.get(event);
|
|
2043
|
+
if (!registeredHandlers) { return; }
|
|
2044
|
+
const found = registeredHandlers.find(h => h.id === handlerID);
|
|
2045
|
+
if (!found) { return; }
|
|
2046
|
+
this.#handlerMap.set(event, this.#handlerMap.get(event).filter(h => h.id !== handlerID));
|
|
2047
|
+
}
|
|
2048
|
+
|
|
2049
|
+
getBackpressureWaiters() { return this.#backpressureWaiters; }
|
|
2050
|
+
addBackpressureWaiter() { this.#backpressureWaiters++; }
|
|
2051
|
+
removeBackpressureWaiter() {
|
|
2052
|
+
this.#backpressureWaiters--;
|
|
2053
|
+
if (this.#backpressureWaiters < 0) {
|
|
2054
|
+
throw new Error("unexepctedly negative number of backpressure waiters");
|
|
1757
2055
|
}
|
|
2056
|
+
}
|
|
2057
|
+
|
|
2058
|
+
parkTaskOnAwaitable(args) {
|
|
2059
|
+
if (!args.awaitable) { throw new TypeError('missing awaitable when trying to park'); }
|
|
2060
|
+
if (!args.task) { throw new TypeError('missing task when trying to park'); }
|
|
2061
|
+
const { awaitable, task } = args;
|
|
1758
2062
|
|
|
1759
|
-
let
|
|
1760
|
-
if (
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
const callerMemories = GlobalComponentMemories.getMemoriesForComponentIdx(callerComponentIdx);
|
|
1764
|
-
if (callerMemories.length != 1) { throw new Error(`unsupported amount of caller memories`); }
|
|
1765
|
-
callerMemory = callerMemories[0];
|
|
2063
|
+
let taskList = this.#parkedTasks.get(awaitable.id());
|
|
2064
|
+
if (!taskList) {
|
|
2065
|
+
taskList = [];
|
|
2066
|
+
this.#parkedTasks.set(awaitable.id(), taskList);
|
|
1766
2067
|
}
|
|
2068
|
+
taskList.push(task);
|
|
1767
2069
|
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
2070
|
+
this.wakeNextTaskForAwaitable(awaitable);
|
|
2071
|
+
}
|
|
2072
|
+
|
|
2073
|
+
wakeNextTaskForAwaitable(awaitable) {
|
|
2074
|
+
if (!awaitable) { throw new TypeError('missing awaitable when waking next task'); }
|
|
2075
|
+
const awaitableID = awaitable.id();
|
|
1771
2076
|
|
|
1772
|
-
const
|
|
1773
|
-
if (!
|
|
1774
|
-
|
|
2077
|
+
const taskList = this.#parkedTasks.get(awaitableID);
|
|
2078
|
+
if (!taskList || taskList.length === 0) {
|
|
2079
|
+
_debugLog('[ComponentAsyncState] no tasks waiting for awaitable', { awaitableID: awaitable.id() });
|
|
2080
|
+
return;
|
|
1775
2081
|
}
|
|
1776
2082
|
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
}
|
|
2083
|
+
let task = taskList.shift(); // todo(perf)
|
|
2084
|
+
if (!task) { throw new Error('no task in parked list despite previous check'); }
|
|
1780
2085
|
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
2086
|
+
if (!task.awaitableResume) {
|
|
2087
|
+
throw new Error('task ready due to awaitable is missing resume', { taskID: task.id(), awaitableID });
|
|
2088
|
+
}
|
|
2089
|
+
task.awaitableResume();
|
|
2090
|
+
}
|
|
2091
|
+
|
|
2092
|
+
// TODO: we might want to check for pre-locked status here
|
|
2093
|
+
exclusiveLock() {
|
|
2094
|
+
this.#locked = true;
|
|
2095
|
+
}
|
|
2096
|
+
|
|
2097
|
+
exclusiveRelease() {
|
|
2098
|
+
_debugLog('[ComponentAsyncState#exclusiveRelease()] releasing', {
|
|
2099
|
+
locked: this.#locked,
|
|
2100
|
+
componentIdx: this.#componentIdx,
|
|
1787
2101
|
});
|
|
1788
2102
|
|
|
1789
|
-
|
|
2103
|
+
this.#locked = false
|
|
2104
|
+
}
|
|
1790
2105
|
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
if (subtaskCallMeta.startFn && subtaskCallMeta.resultPtr) {
|
|
1796
|
-
// If we're using a fused component start fn and a result pointer is present,
|
|
1797
|
-
// then we need to pass the result pointer and other params to the start fn
|
|
1798
|
-
startFnParams.push(subtaskCallMeta.resultPtr, ...params);
|
|
1799
|
-
} else {
|
|
1800
|
-
// if not we need to pass params to the callee instead
|
|
1801
|
-
startFnParams.push(...params);
|
|
1802
|
-
calleeParams.push(...params);
|
|
2106
|
+
isExclusivelyLocked() { return this.#locked === true; }
|
|
2107
|
+
|
|
2108
|
+
#getSuspendedTaskMeta(taskID) {
|
|
2109
|
+
return this.#suspendedTasksByTaskID.get(taskID);
|
|
1803
2110
|
}
|
|
1804
2111
|
|
|
1805
|
-
|
|
1806
|
-
_debugLog('[
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
}
|
|
2112
|
+
#removeSuspendedTaskMeta(taskID) {
|
|
2113
|
+
_debugLog('[ComponentAsyncState#removeSuspendedTaskMeta()] removing suspended task', { taskID });
|
|
2114
|
+
const idx = this.#suspendedTaskIDs.findIndex(t => t === taskID);
|
|
2115
|
+
const meta = this.#suspendedTasksByTaskID.get(taskID);
|
|
2116
|
+
this.#suspendedTaskIDs[idx] = null;
|
|
2117
|
+
this.#suspendedTasksByTaskID.delete(taskID);
|
|
2118
|
+
return meta;
|
|
2119
|
+
}
|
|
1813
2120
|
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
2121
|
+
#addSuspendedTaskMeta(meta) {
|
|
2122
|
+
if (!meta) { throw new Error('missing task meta'); }
|
|
2123
|
+
const taskID = meta.taskID;
|
|
2124
|
+
this.#suspendedTasksByTaskID.set(taskID, meta);
|
|
2125
|
+
this.#suspendedTaskIDs.push(taskID);
|
|
2126
|
+
if (this.#suspendedTasksByTaskID.size < this.#suspendedTaskIDs.length - 10) {
|
|
2127
|
+
this.#suspendedTaskIDs = this.#suspendedTaskIDs.filter(t => t !== null);
|
|
2128
|
+
}
|
|
2129
|
+
}
|
|
1818
2130
|
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
2131
|
+
suspendTask(args) {
|
|
2132
|
+
// TODO(threads): readyFn is normally on the thread
|
|
2133
|
+
const { task, readyFn } = args;
|
|
2134
|
+
const taskID = task.id();
|
|
2135
|
+
_debugLog('[ComponentAsyncState#suspendTask()]', { taskID });
|
|
2136
|
+
|
|
2137
|
+
if (this.#getSuspendedTaskMeta(taskID)) {
|
|
2138
|
+
throw new Error('task [' + taskID + '] already suspended');
|
|
2139
|
+
}
|
|
2140
|
+
|
|
2141
|
+
const { promise, resolve } = Promise.withResolvers();
|
|
2142
|
+
this.#addSuspendedTaskMeta({
|
|
2143
|
+
task,
|
|
2144
|
+
taskID,
|
|
2145
|
+
readyFn,
|
|
2146
|
+
resume: () => {
|
|
2147
|
+
_debugLog('[ComponentAsyncState#suspendTask()] resuming suspended task', { taskID });
|
|
2148
|
+
// TODO(threads): it's thread cancellation we should be checking for below, not task
|
|
2149
|
+
resolve(!task.isCancelled());
|
|
2150
|
+
},
|
|
2151
|
+
});
|
|
2152
|
+
|
|
2153
|
+
return promise;
|
|
2154
|
+
}
|
|
1824
2155
|
|
|
1825
|
-
|
|
2156
|
+
resumeTaskByID(taskID) {
|
|
2157
|
+
const meta = this.#removeSuspendedTaskMeta(taskID);
|
|
2158
|
+
if (!meta) { return; }
|
|
2159
|
+
if (meta.taskID !== taskID) { throw new Error('task ID does not match'); }
|
|
2160
|
+
meta.resume();
|
|
2161
|
+
}
|
|
1826
2162
|
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
2163
|
+
tick() {
|
|
2164
|
+
_debugLog('[ComponentAsyncState#tick()]', { suspendedTaskIDs: this.#suspendedTaskIDs });
|
|
2165
|
+
const resumableTasks = this.#suspendedTaskIDs.filter(t => t !== null);
|
|
2166
|
+
for (const taskID of resumableTasks) {
|
|
2167
|
+
const meta = this.#suspendedTasksByTaskID.get(taskID);
|
|
2168
|
+
if (!meta || !meta.readyFn) {
|
|
2169
|
+
throw new Error(`missing/invalid task despite ID [${taskID}] being present`);
|
|
2170
|
+
}
|
|
2171
|
+
|
|
2172
|
+
const isReady = meta.readyFn();
|
|
2173
|
+
if (!isReady) { continue; }
|
|
2174
|
+
|
|
2175
|
+
this.resumeTaskByID(taskID);
|
|
2176
|
+
}
|
|
2177
|
+
|
|
2178
|
+
return this.#suspendedTaskIDs.filter(t => t !== null).length === 0;
|
|
2179
|
+
}
|
|
1832
2180
|
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
}
|
|
2181
|
+
addPendingTask(task) {
|
|
2182
|
+
this.#pendingTasks.push(task);
|
|
2183
|
+
}
|
|
1836
2184
|
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
_debugLog("[_asyncStartCall()] instantly resolved", {
|
|
1841
|
-
calleeComponentIdx: preparedTask.componentIdx(),
|
|
1842
|
-
task: preparedTask.id(),
|
|
1843
|
-
subtaskID: subtask.id(),
|
|
1844
|
-
callerComponentIdx: subtask.componentIdx(),
|
|
1845
|
-
});
|
|
2185
|
+
addStreamEnd(args) {
|
|
2186
|
+
_debugLog('[ComponentAsyncState#addStreamEnd()] args', args);
|
|
2187
|
+
const { tableIdx, streamEnd } = args;
|
|
1846
2188
|
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
2189
|
+
let tbl = this.#streams.get(tableIdx);
|
|
2190
|
+
if (!tbl) {
|
|
2191
|
+
tbl = new RepTable({ target: `component [${this.#componentIdx}] streams` });
|
|
2192
|
+
this.#streams.set(tableIdx, tbl);
|
|
2193
|
+
}
|
|
2194
|
+
|
|
2195
|
+
const streamIdx = tbl.insert(streamEnd);
|
|
2196
|
+
return streamIdx;
|
|
2197
|
+
}
|
|
2198
|
+
|
|
2199
|
+
createStream(args) {
|
|
2200
|
+
_debugLog('[ComponentAsyncState#createStream()] args', args);
|
|
2201
|
+
const { tableIdx, elemMeta } = args;
|
|
2202
|
+
if (tableIdx === undefined) { throw new Error("missing table idx while adding stream"); }
|
|
2203
|
+
if (elemMeta === undefined) { throw new Error("missing element metadata while adding stream"); }
|
|
2204
|
+
|
|
2205
|
+
let tbl = this.#streams.get(tableIdx);
|
|
2206
|
+
if (!tbl) {
|
|
2207
|
+
tbl = new RepTable({ target: `component [${this.#componentIdx}] streams` });
|
|
2208
|
+
this.#streams.set(tableIdx, tbl);
|
|
1856
2209
|
}
|
|
1857
2210
|
|
|
1858
|
-
|
|
1859
|
-
|
|
2211
|
+
const stream = new InternalStream({
|
|
2212
|
+
tableIdx,
|
|
2213
|
+
componentIdx: this.#componentIdx,
|
|
2214
|
+
elemMeta,
|
|
2215
|
+
});
|
|
2216
|
+
const writeEndIdx = tbl.insert(stream.getWriteEnd());
|
|
2217
|
+
stream.setWriteEndIdx(writeEndIdx);
|
|
2218
|
+
const readEndIdx = tbl.insert(stream.getReadEnd());
|
|
2219
|
+
stream.setReadEndIdx(readEndIdx);
|
|
2220
|
+
|
|
2221
|
+
const rep = STREAMS.insert(stream);
|
|
2222
|
+
stream.setRep(rep);
|
|
2223
|
+
|
|
2224
|
+
return { writeEndIdx, readEndIdx };
|
|
1860
2225
|
}
|
|
1861
2226
|
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
callerComponentIdx: subtask.componentIdx(),
|
|
1872
|
-
});
|
|
1873
|
-
return;
|
|
2227
|
+
getStreamEnd(args) {
|
|
2228
|
+
_debugLog('[ComponentAsyncState#getStreamEnd()] args', args);
|
|
2229
|
+
const { tableIdx, streamIdx } = args;
|
|
2230
|
+
if (tableIdx === undefined) { throw new Error('missing table idx while retrieveing stream end'); }
|
|
2231
|
+
if (streamIdx === undefined) { throw new Error('missing stream idx while retrieveing stream end'); }
|
|
2232
|
+
|
|
2233
|
+
const tbl = this.#streams.get(tableIdx);
|
|
2234
|
+
if (!tbl) {
|
|
2235
|
+
throw new Error(`missing stream table [${tableIdx}] in component [${this.#componentIdx}] while getting stream`);
|
|
1874
2236
|
}
|
|
1875
2237
|
|
|
1876
|
-
const
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
2238
|
+
const stream = tbl.get(streamIdx);
|
|
2239
|
+
return stream;
|
|
2240
|
+
}
|
|
2241
|
+
|
|
2242
|
+
removeStreamEnd(args) {
|
|
2243
|
+
_debugLog('[ComponentAsyncState#removeStreamEnd()] args', args);
|
|
2244
|
+
const { tableIdx, streamIdx } = args;
|
|
2245
|
+
if (tableIdx === undefined) { throw new Error("missing table idx while removing stream end"); }
|
|
2246
|
+
if (streamIdx === undefined) { throw new Error("missing stream idx while removing stream end"); }
|
|
2247
|
+
|
|
2248
|
+
const tbl = this.#streams.get(tableIdx);
|
|
2249
|
+
if (!tbl) {
|
|
2250
|
+
throw new Error(`missing stream table [${tableIdx}] in component [${this.#componentIdx}] while removing stream end`);
|
|
1884
2251
|
}
|
|
1885
2252
|
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
const fnName = [
|
|
1889
|
-
'<task ',
|
|
1890
|
-
subtask.parentTaskID(),
|
|
1891
|
-
'/subtask ',
|
|
1892
|
-
subtask.id(),
|
|
1893
|
-
'/task ',
|
|
1894
|
-
preparedTask.id(),
|
|
1895
|
-
'>',
|
|
1896
|
-
].join("");
|
|
2253
|
+
const stream = tbl.get(streamIdx);
|
|
2254
|
+
if (!stream) { throw new Error(`component [${this.#componentIdx}] missing stream [${streamIdx}]`); }
|
|
1897
2255
|
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
componentState: calleeComponentState,
|
|
1902
|
-
task: preparedTask,
|
|
1903
|
-
fnName,
|
|
1904
|
-
isAsync: true,
|
|
1905
|
-
callbackResult,
|
|
1906
|
-
resolve,
|
|
1907
|
-
reject
|
|
1908
|
-
});
|
|
1909
|
-
} catch (err) {
|
|
1910
|
-
_debugLog("[AsyncStartCall] drive loop call failure", { err });
|
|
2256
|
+
const removed = tbl.remove(streamIdx);
|
|
2257
|
+
if (!removed) {
|
|
2258
|
+
throw new Error(`missing stream [${streamIdx}] (table [${tableIdx}]) in component [${this.#componentIdx}] while removing stream end`);
|
|
1911
2259
|
}
|
|
1912
2260
|
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
return Number(subtask.waitableRep()) << 4 | subtaskState;
|
|
1916
|
-
}
|
|
1917
|
-
|
|
1918
|
-
function _syncStartCall(callbackIdx) {
|
|
1919
|
-
_debugLog('[_syncStartCall()] args', { callbackIdx });
|
|
1920
|
-
throw new Error('synchronous start call not implemented!');
|
|
1921
|
-
}
|
|
1922
|
-
|
|
1923
|
-
function promiseWithResolvers() {
|
|
1924
|
-
if (Promise.withResolvers) {
|
|
1925
|
-
return Promise.withResolvers();
|
|
1926
|
-
} else {
|
|
1927
|
-
let resolve;
|
|
1928
|
-
let reject;
|
|
1929
|
-
const promise = new Promise((res, rej) => {
|
|
1930
|
-
resolve = res;
|
|
1931
|
-
reject = rej;
|
|
1932
|
-
});
|
|
1933
|
-
return { promise, resolve, reject };
|
|
2261
|
+
return stream;
|
|
1934
2262
|
}
|
|
1935
2263
|
}
|
|
1936
2264
|
|
|
1937
|
-
const _debugLog = (...args) => {
|
|
1938
|
-
if (!globalThis?.process?.env?.JCO_DEBUG) { return; }
|
|
1939
|
-
console.debug(...args);
|
|
1940
|
-
}
|
|
1941
|
-
const ASYNC_DETERMINISM = 'random';
|
|
1942
|
-
const _coinFlip = () => { return Math.random() > 0.5; };
|
|
1943
|
-
const I32_MAX = 2_147_483_647;
|
|
1944
|
-
const I32_MIN = -2_147_483_648;
|
|
1945
|
-
const _typeCheckValidI32 = (n) => typeof n === 'number' && n >= I32_MIN && n <= I32_MAX;
|
|
1946
|
-
|
|
1947
|
-
const _typeCheckAsyncFn= (f) => {
|
|
1948
|
-
return f instanceof ASYNC_FN_CTOR;
|
|
1949
|
-
};
|
|
1950
|
-
|
|
1951
|
-
const ASYNC_FN_CTOR = (async () => {}).constructor;
|
|
1952
|
-
|
|
1953
2265
|
const base64Compile = str => WebAssembly.compile(typeof Buffer !== 'undefined' ? Buffer.from(str, 'base64') : Uint8Array.from(atob(str), b => b.charCodeAt(0)));
|
|
1954
2266
|
|
|
1955
2267
|
const isNode = typeof process !== 'undefined' && process.versions && process.versions.node;
|
|
@@ -1986,62 +2298,6 @@ function getErrorPayload(e) {
|
|
|
1986
2298
|
return e;
|
|
1987
2299
|
}
|
|
1988
2300
|
|
|
1989
|
-
class RepTable {
|
|
1990
|
-
#data = [0, null];
|
|
1991
|
-
#target;
|
|
1992
|
-
|
|
1993
|
-
constructor(args) {
|
|
1994
|
-
if (args?.target) { this.target = args.target }
|
|
1995
|
-
}
|
|
1996
|
-
|
|
1997
|
-
insert(val) {
|
|
1998
|
-
_debugLog('[RepTable#insert()] args', { val, target: this.target });
|
|
1999
|
-
const freeIdx = this.#data[0];
|
|
2000
|
-
if (freeIdx === 0) {
|
|
2001
|
-
this.#data.push(val);
|
|
2002
|
-
this.#data.push(null);
|
|
2003
|
-
return (this.#data.length >> 1) - 1;
|
|
2004
|
-
}
|
|
2005
|
-
this.#data[0] = this.#data[freeIdx << 1];
|
|
2006
|
-
const placementIdx = freeIdx << 1;
|
|
2007
|
-
this.#data[placementIdx] = val;
|
|
2008
|
-
this.#data[placementIdx + 1] = null;
|
|
2009
|
-
return freeIdx;
|
|
2010
|
-
}
|
|
2011
|
-
|
|
2012
|
-
get(rep) {
|
|
2013
|
-
_debugLog('[RepTable#get()] args', { rep, target: this.target });
|
|
2014
|
-
const baseIdx = rep << 1;
|
|
2015
|
-
const val = this.#data[baseIdx];
|
|
2016
|
-
return val;
|
|
2017
|
-
}
|
|
2018
|
-
|
|
2019
|
-
contains(rep) {
|
|
2020
|
-
_debugLog('[RepTable#contains()] args', { rep, target: this.target });
|
|
2021
|
-
const baseIdx = rep << 1;
|
|
2022
|
-
return !!this.#data[baseIdx];
|
|
2023
|
-
}
|
|
2024
|
-
|
|
2025
|
-
remove(rep) {
|
|
2026
|
-
_debugLog('[RepTable#remove()] args', { rep, target: this.target });
|
|
2027
|
-
if (this.#data.length === 2) { throw new Error('invalid'); }
|
|
2028
|
-
|
|
2029
|
-
const baseIdx = rep << 1;
|
|
2030
|
-
const val = this.#data[baseIdx];
|
|
2031
|
-
if (val === 0) { throw new Error('invalid resource rep (cannot be 0)'); }
|
|
2032
|
-
|
|
2033
|
-
this.#data[baseIdx] = this.#data[0];
|
|
2034
|
-
this.#data[0] = rep;
|
|
2035
|
-
|
|
2036
|
-
return val;
|
|
2037
|
-
}
|
|
2038
|
-
|
|
2039
|
-
clear() {
|
|
2040
|
-
_debugLog('[RepTable#clear()] args', { rep, target: this.target });
|
|
2041
|
-
this.#data = [0, null];
|
|
2042
|
-
}
|
|
2043
|
-
}
|
|
2044
|
-
|
|
2045
2301
|
function throwUninitialized() {
|
|
2046
2302
|
throw new TypeError('Wasm uninitialized use `await $init` first');
|
|
2047
2303
|
}
|
|
@@ -2050,65 +2306,6 @@ const hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
|
2050
2306
|
|
|
2051
2307
|
const instantiateCore = WebAssembly.instantiate;
|
|
2052
2308
|
|
|
2053
|
-
class GlobalComponentAsyncLowers {
|
|
2054
|
-
static map = new Map();
|
|
2055
|
-
|
|
2056
|
-
constructor() { throw new Error('GlobalComponentAsyncLowers should not be constructed'); }
|
|
2057
|
-
|
|
2058
|
-
static define(args) {
|
|
2059
|
-
const { componentIdx, qualifiedImportFn, fn } = args;
|
|
2060
|
-
let inner = GlobalComponentAsyncLowers.map.get(componentIdx);
|
|
2061
|
-
if (!inner) {
|
|
2062
|
-
inner = new Map();
|
|
2063
|
-
GlobalComponentAsyncLowers.map.set(componentIdx, inner);
|
|
2064
|
-
}
|
|
2065
|
-
|
|
2066
|
-
inner.set(qualifiedImportFn, fn);
|
|
2067
|
-
}
|
|
2068
|
-
|
|
2069
|
-
static lookup(componentIdx, qualifiedImportFn) {
|
|
2070
|
-
let inner = GlobalComponentAsyncLowers.map.get(componentIdx);
|
|
2071
|
-
if (!inner) {
|
|
2072
|
-
inner = new Map();
|
|
2073
|
-
GlobalComponentAsyncLowers.map.set(componentIdx, inner);
|
|
2074
|
-
}
|
|
2075
|
-
|
|
2076
|
-
const found = inner.get(qualifiedImportFn);
|
|
2077
|
-
if (found) { return found; }
|
|
2078
|
-
|
|
2079
|
-
return (...args) => {
|
|
2080
|
-
const [originalFn, ...params] = args;
|
|
2081
|
-
return originalFn(...params);
|
|
2082
|
-
};
|
|
2083
|
-
}
|
|
2084
|
-
}
|
|
2085
|
-
|
|
2086
|
-
class GlobalComponentMemories {
|
|
2087
|
-
static map = new Map();
|
|
2088
|
-
|
|
2089
|
-
constructor() { throw new Error('GlobalComponentMemories should not be constructed'); }
|
|
2090
|
-
|
|
2091
|
-
static save(args) {
|
|
2092
|
-
const { idx, componentIdx, memory } = args;
|
|
2093
|
-
let inner = GlobalComponentMemories.map.get(componentIdx);
|
|
2094
|
-
if (!inner) {
|
|
2095
|
-
inner = [];
|
|
2096
|
-
GlobalComponentMemories.map.set(componentIdx, inner);
|
|
2097
|
-
}
|
|
2098
|
-
inner.push({ memory, idx });
|
|
2099
|
-
}
|
|
2100
|
-
|
|
2101
|
-
static getMemoriesForComponentIdx(componentIdx) {
|
|
2102
|
-
const metas = GlobalComponentMemories.map.get(componentIdx);
|
|
2103
|
-
return metas.map(meta => meta.memory);
|
|
2104
|
-
}
|
|
2105
|
-
|
|
2106
|
-
static getMemory(componentIdx, idx) {
|
|
2107
|
-
const metas = GlobalComponentMemories.map.get(componentIdx);
|
|
2108
|
-
return metas.find(meta => meta.idx === idx)?.memory;
|
|
2109
|
-
}
|
|
2110
|
-
}
|
|
2111
|
-
|
|
2112
2309
|
|
|
2113
2310
|
let exports0;
|
|
2114
2311
|
let exports1;
|
|
@@ -2125,7 +2322,8 @@ handleTables[2] = handleTable2;
|
|
|
2125
2322
|
|
|
2126
2323
|
function trampoline5() {
|
|
2127
2324
|
_debugLog('[iface="wasi:cli/stderr@0.2.3", function="get-stderr"] [Instruction::CallInterface] (sync, @ enter)');
|
|
2128
|
-
|
|
2325
|
+
let hostProvided = false;
|
|
2326
|
+
hostProvided = getStderr?._isHostProvided;
|
|
2129
2327
|
|
|
2130
2328
|
let parentTask;
|
|
2131
2329
|
let task;
|
|
@@ -2197,7 +2395,8 @@ handleTables[1] = handleTable1;
|
|
|
2197
2395
|
|
|
2198
2396
|
function trampoline8() {
|
|
2199
2397
|
_debugLog('[iface="wasi:cli/stdin@0.2.3", function="get-stdin"] [Instruction::CallInterface] (sync, @ enter)');
|
|
2200
|
-
|
|
2398
|
+
let hostProvided = false;
|
|
2399
|
+
hostProvided = getStdin?._isHostProvided;
|
|
2201
2400
|
|
|
2202
2401
|
let parentTask;
|
|
2203
2402
|
let task;
|
|
@@ -2265,7 +2464,8 @@ let lowered_import_2_metadata = {
|
|
|
2265
2464
|
|
|
2266
2465
|
function trampoline9() {
|
|
2267
2466
|
_debugLog('[iface="wasi:cli/stdout@0.2.3", function="get-stdout"] [Instruction::CallInterface] (sync, @ enter)');
|
|
2268
|
-
|
|
2467
|
+
let hostProvided = false;
|
|
2468
|
+
hostProvided = getStdout?._isHostProvided;
|
|
2269
2469
|
|
|
2270
2470
|
let parentTask;
|
|
2271
2471
|
let task;
|
|
@@ -2353,7 +2553,8 @@ function trampoline10(arg0) {
|
|
|
2353
2553
|
}
|
|
2354
2554
|
}
|
|
2355
2555
|
_debugLog('[iface="wasi:cli/exit@0.2.3", function="exit"] [Instruction::CallInterface] (sync, @ enter)');
|
|
2356
|
-
|
|
2556
|
+
let hostProvided = false;
|
|
2557
|
+
hostProvided = exit?._isHostProvided;
|
|
2357
2558
|
|
|
2358
2559
|
let parentTask;
|
|
2359
2560
|
let task;
|
|
@@ -2414,7 +2615,8 @@ let lowered_import_4_metadata = {
|
|
|
2414
2615
|
|
|
2415
2616
|
function trampoline11(arg0) {
|
|
2416
2617
|
_debugLog('[iface="wasi:cli/environment@0.2.3", function="get-environment"] [Instruction::CallInterface] (sync, @ enter)');
|
|
2417
|
-
|
|
2618
|
+
let hostProvided = false;
|
|
2619
|
+
hostProvided = getEnvironment?._isHostProvided;
|
|
2418
2620
|
|
|
2419
2621
|
let parentTask;
|
|
2420
2622
|
let task;
|
|
@@ -2508,7 +2710,8 @@ function trampoline12(arg0, arg1) {
|
|
|
2508
2710
|
}
|
|
2509
2711
|
curResourceBorrows.push(rsc0);
|
|
2510
2712
|
_debugLog('[iface="wasi:filesystem/types@0.2.3", function="[method]descriptor.get-type"] [Instruction::CallInterface] (sync, @ enter)');
|
|
2511
|
-
|
|
2713
|
+
let hostProvided = false;
|
|
2714
|
+
hostProvided = rsc0.getType?._isHostProvided;
|
|
2512
2715
|
|
|
2513
2716
|
let parentTask;
|
|
2514
2717
|
let task;
|
|
@@ -2806,7 +3009,8 @@ function trampoline13(arg0, arg1) {
|
|
|
2806
3009
|
}
|
|
2807
3010
|
curResourceBorrows.push(rsc0);
|
|
2808
3011
|
_debugLog('[iface="wasi:filesystem/types@0.2.3", function="[method]descriptor.metadata-hash"] [Instruction::CallInterface] (sync, @ enter)');
|
|
2809
|
-
|
|
3012
|
+
let hostProvided = false;
|
|
3013
|
+
hostProvided = rsc0.metadataHash?._isHostProvided;
|
|
2810
3014
|
|
|
2811
3015
|
let parentTask;
|
|
2812
3016
|
let task;
|
|
@@ -3067,7 +3271,8 @@ function trampoline14(arg0, arg1) {
|
|
|
3067
3271
|
}
|
|
3068
3272
|
curResourceBorrows.push(rsc0);
|
|
3069
3273
|
_debugLog('[iface="wasi:filesystem/types@0.2.3", function="filesystem-error-code"] [Instruction::CallInterface] (sync, @ enter)');
|
|
3070
|
-
|
|
3274
|
+
let hostProvided = false;
|
|
3275
|
+
hostProvided = filesystemErrorCode?._isHostProvided;
|
|
3071
3276
|
|
|
3072
3277
|
let parentTask;
|
|
3073
3278
|
let task;
|
|
@@ -3314,7 +3519,8 @@ function trampoline15(arg0, arg1, arg2, arg3, arg4) {
|
|
|
3314
3519
|
var len4 = arg3;
|
|
3315
3520
|
var result4 = TEXT_DECODER_UTF8.decode(new Uint8Array(memory0.buffer, ptr4, len4));
|
|
3316
3521
|
_debugLog('[iface="wasi:filesystem/types@0.2.3", function="[method]descriptor.metadata-hash-at"] [Instruction::CallInterface] (sync, @ enter)');
|
|
3317
|
-
|
|
3522
|
+
let hostProvided = false;
|
|
3523
|
+
hostProvided = rsc0.metadataHashAt?._isHostProvided;
|
|
3318
3524
|
|
|
3319
3525
|
let parentTask;
|
|
3320
3526
|
let task;
|
|
@@ -3571,7 +3777,8 @@ function trampoline16(arg0, arg1, arg2) {
|
|
|
3571
3777
|
}
|
|
3572
3778
|
curResourceBorrows.push(rsc0);
|
|
3573
3779
|
_debugLog('[iface="wasi:filesystem/types@0.2.3", function="[method]descriptor.read-via-stream"] [Instruction::CallInterface] (sync, @ enter)');
|
|
3574
|
-
|
|
3780
|
+
let hostProvided = false;
|
|
3781
|
+
hostProvided = rsc0.readViaStream?._isHostProvided;
|
|
3575
3782
|
|
|
3576
3783
|
let parentTask;
|
|
3577
3784
|
let task;
|
|
@@ -3835,7 +4042,8 @@ function trampoline17(arg0, arg1, arg2) {
|
|
|
3835
4042
|
}
|
|
3836
4043
|
curResourceBorrows.push(rsc0);
|
|
3837
4044
|
_debugLog('[iface="wasi:filesystem/types@0.2.3", function="[method]descriptor.write-via-stream"] [Instruction::CallInterface] (sync, @ enter)');
|
|
3838
|
-
|
|
4045
|
+
let hostProvided = false;
|
|
4046
|
+
hostProvided = rsc0.writeViaStream?._isHostProvided;
|
|
3839
4047
|
|
|
3840
4048
|
let parentTask;
|
|
3841
4049
|
let task;
|
|
@@ -4099,7 +4307,8 @@ function trampoline18(arg0, arg1) {
|
|
|
4099
4307
|
}
|
|
4100
4308
|
curResourceBorrows.push(rsc0);
|
|
4101
4309
|
_debugLog('[iface="wasi:filesystem/types@0.2.3", function="[method]descriptor.append-via-stream"] [Instruction::CallInterface] (sync, @ enter)');
|
|
4102
|
-
|
|
4310
|
+
let hostProvided = false;
|
|
4311
|
+
hostProvided = rsc0.appendViaStream?._isHostProvided;
|
|
4103
4312
|
|
|
4104
4313
|
let parentTask;
|
|
4105
4314
|
let task;
|
|
@@ -4367,7 +4576,8 @@ function trampoline19(arg0, arg1) {
|
|
|
4367
4576
|
}
|
|
4368
4577
|
curResourceBorrows.push(rsc0);
|
|
4369
4578
|
_debugLog('[iface="wasi:filesystem/types@0.2.3", function="[method]descriptor.read-directory"] [Instruction::CallInterface] (sync, @ enter)');
|
|
4370
|
-
|
|
4579
|
+
let hostProvided = false;
|
|
4580
|
+
hostProvided = rsc0.readDirectory?._isHostProvided;
|
|
4371
4581
|
|
|
4372
4582
|
let parentTask;
|
|
4373
4583
|
let task;
|
|
@@ -4631,7 +4841,8 @@ function trampoline20(arg0, arg1) {
|
|
|
4631
4841
|
}
|
|
4632
4842
|
curResourceBorrows.push(rsc0);
|
|
4633
4843
|
_debugLog('[iface="wasi:filesystem/types@0.2.3", function="[method]descriptor.stat"] [Instruction::CallInterface] (sync, @ enter)');
|
|
4634
|
-
|
|
4844
|
+
let hostProvided = false;
|
|
4845
|
+
hostProvided = rsc0.stat?._isHostProvided;
|
|
4635
4846
|
|
|
4636
4847
|
let parentTask;
|
|
4637
4848
|
let task;
|
|
@@ -4971,7 +5182,8 @@ function trampoline21(arg0, arg1, arg2, arg3, arg4) {
|
|
|
4971
5182
|
var len4 = arg3;
|
|
4972
5183
|
var result4 = TEXT_DECODER_UTF8.decode(new Uint8Array(memory0.buffer, ptr4, len4));
|
|
4973
5184
|
_debugLog('[iface="wasi:filesystem/types@0.2.3", function="[method]descriptor.stat-at"] [Instruction::CallInterface] (sync, @ enter)');
|
|
4974
|
-
|
|
5185
|
+
let hostProvided = false;
|
|
5186
|
+
hostProvided = rsc0.statAt?._isHostProvided;
|
|
4975
5187
|
|
|
4976
5188
|
let parentTask;
|
|
4977
5189
|
let task;
|
|
@@ -5331,7 +5543,8 @@ function trampoline22(arg0, arg1, arg2, arg3, arg4, arg5, arg6) {
|
|
|
5331
5543
|
mutateDirectory: Boolean(arg5 & 32),
|
|
5332
5544
|
};
|
|
5333
5545
|
_debugLog('[iface="wasi:filesystem/types@0.2.3", function="[method]descriptor.open-at"] [Instruction::CallInterface] (sync, @ enter)');
|
|
5334
|
-
|
|
5546
|
+
let hostProvided = false;
|
|
5547
|
+
hostProvided = rsc0.openAt?._isHostProvided;
|
|
5335
5548
|
|
|
5336
5549
|
let parentTask;
|
|
5337
5550
|
let task;
|
|
@@ -5595,7 +5808,8 @@ function trampoline23(arg0, arg1) {
|
|
|
5595
5808
|
}
|
|
5596
5809
|
curResourceBorrows.push(rsc0);
|
|
5597
5810
|
_debugLog('[iface="wasi:filesystem/types@0.2.3", function="[method]directory-entry-stream.read-directory-entry"] [Instruction::CallInterface] (sync, @ enter)');
|
|
5598
|
-
|
|
5811
|
+
let hostProvided = false;
|
|
5812
|
+
hostProvided = rsc0.readDirectoryEntry?._isHostProvided;
|
|
5599
5813
|
|
|
5600
5814
|
let parentTask;
|
|
5601
5815
|
let task;
|
|
@@ -5908,7 +6122,8 @@ function trampoline24(arg0, arg1, arg2) {
|
|
|
5908
6122
|
}
|
|
5909
6123
|
curResourceBorrows.push(rsc0);
|
|
5910
6124
|
_debugLog('[iface="wasi:io/streams@0.2.3", function="[method]input-stream.read"] [Instruction::CallInterface] (sync, @ enter)');
|
|
5911
|
-
|
|
6125
|
+
let hostProvided = false;
|
|
6126
|
+
hostProvided = rsc0.read?._isHostProvided;
|
|
5912
6127
|
|
|
5913
6128
|
let parentTask;
|
|
5914
6129
|
let task;
|
|
@@ -5968,8 +6183,24 @@ function trampoline24(arg0, arg1, arg2) {
|
|
|
5968
6183
|
var val3 = e;
|
|
5969
6184
|
var len3 = val3.byteLength;
|
|
5970
6185
|
var ptr3 = realloc0(0, 0, 1, len3 * 1);
|
|
5971
|
-
|
|
5972
|
-
|
|
6186
|
+
|
|
6187
|
+
let valData3;
|
|
6188
|
+
const valLenBytes3 = len3 * 1;
|
|
6189
|
+
if (Array.isArray(val3)) {
|
|
6190
|
+
// Regular array likely containing numbers, write values to memory
|
|
6191
|
+
let offset = 0;
|
|
6192
|
+
const dv3 = new DataView(memory0.buffer);
|
|
6193
|
+
for (const v of val3) {
|
|
6194
|
+
dv3.setUint8(ptr3+ offset, v, true);
|
|
6195
|
+
offset += 1;
|
|
6196
|
+
}
|
|
6197
|
+
} else {
|
|
6198
|
+
// TypedArray / ArrayBuffer-like, direct copy
|
|
6199
|
+
valData3 = new Uint8Array(val3.buffer || val3, val3.byteOffset, valLenBytes3);
|
|
6200
|
+
const out3 = new Uint8Array(memory0.buffer, ptr3,valLenBytes3);
|
|
6201
|
+
out3.set(valData3);
|
|
6202
|
+
}
|
|
6203
|
+
|
|
5973
6204
|
dataView(memory0).setUint32(arg2 + 8, len3, true);
|
|
5974
6205
|
dataView(memory0).setUint32(arg2 + 4, ptr3, true);
|
|
5975
6206
|
break;
|
|
@@ -6034,7 +6265,8 @@ function trampoline25(arg0, arg1, arg2) {
|
|
|
6034
6265
|
}
|
|
6035
6266
|
curResourceBorrows.push(rsc0);
|
|
6036
6267
|
_debugLog('[iface="wasi:io/streams@0.2.3", function="[method]input-stream.blocking-read"] [Instruction::CallInterface] (sync, @ enter)');
|
|
6037
|
-
|
|
6268
|
+
let hostProvided = false;
|
|
6269
|
+
hostProvided = rsc0.blockingRead?._isHostProvided;
|
|
6038
6270
|
|
|
6039
6271
|
let parentTask;
|
|
6040
6272
|
let task;
|
|
@@ -6094,8 +6326,24 @@ function trampoline25(arg0, arg1, arg2) {
|
|
|
6094
6326
|
var val3 = e;
|
|
6095
6327
|
var len3 = val3.byteLength;
|
|
6096
6328
|
var ptr3 = realloc0(0, 0, 1, len3 * 1);
|
|
6097
|
-
|
|
6098
|
-
|
|
6329
|
+
|
|
6330
|
+
let valData3;
|
|
6331
|
+
const valLenBytes3 = len3 * 1;
|
|
6332
|
+
if (Array.isArray(val3)) {
|
|
6333
|
+
// Regular array likely containing numbers, write values to memory
|
|
6334
|
+
let offset = 0;
|
|
6335
|
+
const dv3 = new DataView(memory0.buffer);
|
|
6336
|
+
for (const v of val3) {
|
|
6337
|
+
dv3.setUint8(ptr3+ offset, v, true);
|
|
6338
|
+
offset += 1;
|
|
6339
|
+
}
|
|
6340
|
+
} else {
|
|
6341
|
+
// TypedArray / ArrayBuffer-like, direct copy
|
|
6342
|
+
valData3 = new Uint8Array(val3.buffer || val3, val3.byteOffset, valLenBytes3);
|
|
6343
|
+
const out3 = new Uint8Array(memory0.buffer, ptr3,valLenBytes3);
|
|
6344
|
+
out3.set(valData3);
|
|
6345
|
+
}
|
|
6346
|
+
|
|
6099
6347
|
dataView(memory0).setUint32(arg2 + 8, len3, true);
|
|
6100
6348
|
dataView(memory0).setUint32(arg2 + 4, ptr3, true);
|
|
6101
6349
|
break;
|
|
@@ -6160,7 +6408,8 @@ function trampoline26(arg0, arg1) {
|
|
|
6160
6408
|
}
|
|
6161
6409
|
curResourceBorrows.push(rsc0);
|
|
6162
6410
|
_debugLog('[iface="wasi:io/streams@0.2.3", function="[method]output-stream.check-write"] [Instruction::CallInterface] (sync, @ enter)');
|
|
6163
|
-
|
|
6411
|
+
let hostProvided = false;
|
|
6412
|
+
hostProvided = rsc0.checkWrite?._isHostProvided;
|
|
6164
6413
|
|
|
6165
6414
|
let parentTask;
|
|
6166
6415
|
let task;
|
|
@@ -6283,7 +6532,8 @@ function trampoline27(arg0, arg1, arg2, arg3) {
|
|
|
6283
6532
|
var len3 = arg2;
|
|
6284
6533
|
var result3 = new Uint8Array(memory0.buffer.slice(ptr3, ptr3 + len3 * 1));
|
|
6285
6534
|
_debugLog('[iface="wasi:io/streams@0.2.3", function="[method]output-stream.write"] [Instruction::CallInterface] (sync, @ enter)');
|
|
6286
|
-
|
|
6535
|
+
let hostProvided = false;
|
|
6536
|
+
hostProvided = rsc0.write?._isHostProvided;
|
|
6287
6537
|
|
|
6288
6538
|
let parentTask;
|
|
6289
6539
|
let task;
|
|
@@ -6405,7 +6655,8 @@ function trampoline28(arg0, arg1, arg2, arg3) {
|
|
|
6405
6655
|
var len3 = arg2;
|
|
6406
6656
|
var result3 = new Uint8Array(memory0.buffer.slice(ptr3, ptr3 + len3 * 1));
|
|
6407
6657
|
_debugLog('[iface="wasi:io/streams@0.2.3", function="[method]output-stream.blocking-write-and-flush"] [Instruction::CallInterface] (sync, @ enter)');
|
|
6408
|
-
|
|
6658
|
+
let hostProvided = false;
|
|
6659
|
+
hostProvided = rsc0.blockingWriteAndFlush?._isHostProvided;
|
|
6409
6660
|
|
|
6410
6661
|
let parentTask;
|
|
6411
6662
|
let task;
|
|
@@ -6524,7 +6775,8 @@ function trampoline29(arg0, arg1) {
|
|
|
6524
6775
|
}
|
|
6525
6776
|
curResourceBorrows.push(rsc0);
|
|
6526
6777
|
_debugLog('[iface="wasi:io/streams@0.2.3", function="[method]output-stream.blocking-flush"] [Instruction::CallInterface] (sync, @ enter)');
|
|
6527
|
-
|
|
6778
|
+
let hostProvided = false;
|
|
6779
|
+
hostProvided = rsc0.blockingFlush?._isHostProvided;
|
|
6528
6780
|
|
|
6529
6781
|
let parentTask;
|
|
6530
6782
|
let task;
|
|
@@ -6634,7 +6886,8 @@ let lowered_import_23_metadata = {
|
|
|
6634
6886
|
|
|
6635
6887
|
function trampoline30(arg0, arg1) {
|
|
6636
6888
|
_debugLog('[iface="wasi:random/random@0.2.3", function="get-random-bytes"] [Instruction::CallInterface] (sync, @ enter)');
|
|
6637
|
-
|
|
6889
|
+
let hostProvided = false;
|
|
6890
|
+
hostProvided = getRandomBytes?._isHostProvided;
|
|
6638
6891
|
|
|
6639
6892
|
let parentTask;
|
|
6640
6893
|
let task;
|
|
@@ -6678,8 +6931,24 @@ function trampoline30(arg0, arg1) {
|
|
|
6678
6931
|
var val0 = ret;
|
|
6679
6932
|
var len0 = val0.byteLength;
|
|
6680
6933
|
var ptr0 = realloc0(0, 0, 1, len0 * 1);
|
|
6681
|
-
|
|
6682
|
-
|
|
6934
|
+
|
|
6935
|
+
let valData0;
|
|
6936
|
+
const valLenBytes0 = len0 * 1;
|
|
6937
|
+
if (Array.isArray(val0)) {
|
|
6938
|
+
// Regular array likely containing numbers, write values to memory
|
|
6939
|
+
let offset = 0;
|
|
6940
|
+
const dv0 = new DataView(memory0.buffer);
|
|
6941
|
+
for (const v of val0) {
|
|
6942
|
+
dv0.setUint8(ptr0+ offset, v, true);
|
|
6943
|
+
offset += 1;
|
|
6944
|
+
}
|
|
6945
|
+
} else {
|
|
6946
|
+
// TypedArray / ArrayBuffer-like, direct copy
|
|
6947
|
+
valData0 = new Uint8Array(val0.buffer || val0, val0.byteOffset, valLenBytes0);
|
|
6948
|
+
const out0 = new Uint8Array(memory0.buffer, ptr0,valLenBytes0);
|
|
6949
|
+
out0.set(valData0);
|
|
6950
|
+
}
|
|
6951
|
+
|
|
6683
6952
|
dataView(memory0).setUint32(arg1 + 4, len0, true);
|
|
6684
6953
|
dataView(memory0).setUint32(arg1 + 0, ptr0, true);
|
|
6685
6954
|
_debugLog('[iface="wasi:random/random@0.2.3", function="get-random-bytes"][Instruction::Return]', {
|
|
@@ -6699,7 +6968,8 @@ let lowered_import_24_metadata = {
|
|
|
6699
6968
|
|
|
6700
6969
|
function trampoline31(arg0) {
|
|
6701
6970
|
_debugLog('[iface="wasi:filesystem/preopens@0.2.3", function="get-directories"] [Instruction::CallInterface] (sync, @ enter)');
|
|
6702
|
-
|
|
6971
|
+
let hostProvided = false;
|
|
6972
|
+
hostProvided = getDirectories?._isHostProvided;
|
|
6703
6973
|
|
|
6704
6974
|
let parentTask;
|
|
6705
6975
|
let task;
|
|
@@ -6787,7 +7057,8 @@ handleTables[3] = handleTable3;
|
|
|
6787
7057
|
|
|
6788
7058
|
function trampoline32(arg0) {
|
|
6789
7059
|
_debugLog('[iface="wasi:cli/terminal-stdin@0.2.3", function="get-terminal-stdin"] [Instruction::CallInterface] (sync, @ enter)');
|
|
6790
|
-
|
|
7060
|
+
let hostProvided = false;
|
|
7061
|
+
hostProvided = getTerminalStdin?._isHostProvided;
|
|
6791
7062
|
|
|
6792
7063
|
let parentTask;
|
|
6793
7064
|
let task;
|
|
@@ -6866,7 +7137,8 @@ handleTables[4] = handleTable4;
|
|
|
6866
7137
|
|
|
6867
7138
|
function trampoline33(arg0) {
|
|
6868
7139
|
_debugLog('[iface="wasi:cli/terminal-stdout@0.2.3", function="get-terminal-stdout"] [Instruction::CallInterface] (sync, @ enter)');
|
|
6869
|
-
|
|
7140
|
+
let hostProvided = false;
|
|
7141
|
+
hostProvided = getTerminalStdout?._isHostProvided;
|
|
6870
7142
|
|
|
6871
7143
|
let parentTask;
|
|
6872
7144
|
let task;
|
|
@@ -6941,7 +7213,8 @@ let lowered_import_27_metadata = {
|
|
|
6941
7213
|
|
|
6942
7214
|
function trampoline34(arg0) {
|
|
6943
7215
|
_debugLog('[iface="wasi:cli/terminal-stderr@0.2.3", function="get-terminal-stderr"] [Instruction::CallInterface] (sync, @ enter)');
|
|
6944
|
-
|
|
7216
|
+
let hostProvided = false;
|
|
7217
|
+
hostProvided = getTerminalStderr?._isHostProvided;
|
|
6945
7218
|
|
|
6946
7219
|
let parentTask;
|
|
6947
7220
|
let task;
|
|
@@ -7206,7 +7479,7 @@ GlobalComponentAsyncLowers.define({
|
|
|
7206
7479
|
isAsync: false,
|
|
7207
7480
|
paramLiftFns: [],
|
|
7208
7481
|
metadata: lowered_import_4_metadata,
|
|
7209
|
-
resultLowerFns: [_lowerFlatList.bind(null, 0)],
|
|
7482
|
+
resultLowerFns: [_lowerFlatList({ elemLowerFn: _lowerFlatTuple.bind(null, 0), typeIdx: 0 })],
|
|
7210
7483
|
getCallbackFn: () => null,
|
|
7211
7484
|
getPostReturnFn: () => null,
|
|
7212
7485
|
isCancellable: false,
|
|
@@ -7227,7 +7500,7 @@ GlobalComponentAsyncLowers.define({
|
|
|
7227
7500
|
trampolineIdx: 12,
|
|
7228
7501
|
componentIdx: 0,
|
|
7229
7502
|
isAsync: false,
|
|
7230
|
-
paramLiftFns: [
|
|
7503
|
+
paramLiftFns: [_liftFlatBorrow.bind(null, 6)],
|
|
7231
7504
|
metadata: lowered_import_5_metadata,
|
|
7232
7505
|
resultLowerFns: [_lowerFlatResult([{ discriminant: 0, tag: 'ok', lowerFn: _lowerFlatEnum.bind(null, 0), align32: 1 },{ discriminant: 1, tag: 'error', lowerFn: _lowerFlatEnum.bind(null, 1), align32: 1 },])],
|
|
7233
7506
|
getCallbackFn: () => null,
|
|
@@ -7250,7 +7523,7 @@ GlobalComponentAsyncLowers.define({
|
|
|
7250
7523
|
trampolineIdx: 13,
|
|
7251
7524
|
componentIdx: 0,
|
|
7252
7525
|
isAsync: false,
|
|
7253
|
-
paramLiftFns: [
|
|
7526
|
+
paramLiftFns: [_liftFlatBorrow.bind(null, 6)],
|
|
7254
7527
|
metadata: lowered_import_6_metadata,
|
|
7255
7528
|
resultLowerFns: [_lowerFlatResult([{ discriminant: 0, tag: 'ok', lowerFn: _lowerFlatRecord([{ field: 'lower', lowerFn: _lowerFlatU64, align32: 8 },{ field: 'upper', lowerFn: _lowerFlatU64, align32: 8 },]), align32: 8 },{ discriminant: 1, tag: 'error', lowerFn: _lowerFlatEnum.bind(null, 1), align32: 1 },])],
|
|
7256
7529
|
getCallbackFn: () => null,
|
|
@@ -7273,7 +7546,7 @@ GlobalComponentAsyncLowers.define({
|
|
|
7273
7546
|
trampolineIdx: 14,
|
|
7274
7547
|
componentIdx: 0,
|
|
7275
7548
|
isAsync: false,
|
|
7276
|
-
paramLiftFns: [
|
|
7549
|
+
paramLiftFns: [_liftFlatBorrow.bind(null, 0)],
|
|
7277
7550
|
metadata: lowered_import_7_metadata,
|
|
7278
7551
|
resultLowerFns: [_lowerFlatOption.bind(null, 4)],
|
|
7279
7552
|
getCallbackFn: () => null,
|
|
@@ -7296,7 +7569,7 @@ GlobalComponentAsyncLowers.define({
|
|
|
7296
7569
|
trampolineIdx: 15,
|
|
7297
7570
|
componentIdx: 0,
|
|
7298
7571
|
isAsync: false,
|
|
7299
|
-
paramLiftFns: [
|
|
7572
|
+
paramLiftFns: [_liftFlatBorrow.bind(null, 6),_liftFlatFlags.bind(null, 0),_liftFlatStringUTF8],
|
|
7300
7573
|
metadata: lowered_import_8_metadata,
|
|
7301
7574
|
resultLowerFns: [_lowerFlatResult([{ discriminant: 0, tag: 'ok', lowerFn: _lowerFlatRecord([{ field: 'lower', lowerFn: _lowerFlatU64, align32: 8 },{ field: 'upper', lowerFn: _lowerFlatU64, align32: 8 },]), align32: 8 },{ discriminant: 1, tag: 'error', lowerFn: _lowerFlatEnum.bind(null, 1), align32: 1 },])],
|
|
7302
7575
|
getCallbackFn: () => null,
|
|
@@ -7319,7 +7592,7 @@ GlobalComponentAsyncLowers.define({
|
|
|
7319
7592
|
trampolineIdx: 16,
|
|
7320
7593
|
componentIdx: 0,
|
|
7321
7594
|
isAsync: false,
|
|
7322
|
-
paramLiftFns: [
|
|
7595
|
+
paramLiftFns: [_liftFlatBorrow.bind(null, 6),_liftFlatU64],
|
|
7323
7596
|
metadata: lowered_import_9_metadata,
|
|
7324
7597
|
resultLowerFns: [_lowerFlatResult([{ discriminant: 0, tag: 'ok', lowerFn: _lowerFlatOwn.bind(null, 1), align32: 4 },{ discriminant: 1, tag: 'error', lowerFn: _lowerFlatEnum.bind(null, 1), align32: 1 },])],
|
|
7325
7598
|
getCallbackFn: () => null,
|
|
@@ -7342,7 +7615,7 @@ GlobalComponentAsyncLowers.define({
|
|
|
7342
7615
|
trampolineIdx: 17,
|
|
7343
7616
|
componentIdx: 0,
|
|
7344
7617
|
isAsync: false,
|
|
7345
|
-
paramLiftFns: [
|
|
7618
|
+
paramLiftFns: [_liftFlatBorrow.bind(null, 6),_liftFlatU64],
|
|
7346
7619
|
metadata: lowered_import_10_metadata,
|
|
7347
7620
|
resultLowerFns: [_lowerFlatResult([{ discriminant: 0, tag: 'ok', lowerFn: _lowerFlatOwn.bind(null, 2), align32: 4 },{ discriminant: 1, tag: 'error', lowerFn: _lowerFlatEnum.bind(null, 1), align32: 1 },])],
|
|
7348
7621
|
getCallbackFn: () => null,
|
|
@@ -7365,7 +7638,7 @@ GlobalComponentAsyncLowers.define({
|
|
|
7365
7638
|
trampolineIdx: 18,
|
|
7366
7639
|
componentIdx: 0,
|
|
7367
7640
|
isAsync: false,
|
|
7368
|
-
paramLiftFns: [
|
|
7641
|
+
paramLiftFns: [_liftFlatBorrow.bind(null, 6)],
|
|
7369
7642
|
metadata: lowered_import_11_metadata,
|
|
7370
7643
|
resultLowerFns: [_lowerFlatResult([{ discriminant: 0, tag: 'ok', lowerFn: _lowerFlatOwn.bind(null, 2), align32: 4 },{ discriminant: 1, tag: 'error', lowerFn: _lowerFlatEnum.bind(null, 1), align32: 1 },])],
|
|
7371
7644
|
getCallbackFn: () => null,
|
|
@@ -7388,7 +7661,7 @@ GlobalComponentAsyncLowers.define({
|
|
|
7388
7661
|
trampolineIdx: 19,
|
|
7389
7662
|
componentIdx: 0,
|
|
7390
7663
|
isAsync: false,
|
|
7391
|
-
paramLiftFns: [
|
|
7664
|
+
paramLiftFns: [_liftFlatBorrow.bind(null, 6)],
|
|
7392
7665
|
metadata: lowered_import_12_metadata,
|
|
7393
7666
|
resultLowerFns: [_lowerFlatResult([{ discriminant: 0, tag: 'ok', lowerFn: _lowerFlatOwn.bind(null, 5), align32: 4 },{ discriminant: 1, tag: 'error', lowerFn: _lowerFlatEnum.bind(null, 1), align32: 1 },])],
|
|
7394
7667
|
getCallbackFn: () => null,
|
|
@@ -7411,7 +7684,7 @@ GlobalComponentAsyncLowers.define({
|
|
|
7411
7684
|
trampolineIdx: 20,
|
|
7412
7685
|
componentIdx: 0,
|
|
7413
7686
|
isAsync: false,
|
|
7414
|
-
paramLiftFns: [
|
|
7687
|
+
paramLiftFns: [_liftFlatBorrow.bind(null, 6)],
|
|
7415
7688
|
metadata: lowered_import_13_metadata,
|
|
7416
7689
|
resultLowerFns: [_lowerFlatResult([{ discriminant: 0, tag: 'ok', lowerFn: _lowerFlatRecord([{ field: 'type', lowerFn: _lowerFlatEnum.bind(null, 0), align32: 8 },{ field: 'link-count', lowerFn: _lowerFlatU64, align32: 8 },{ field: 'size', lowerFn: _lowerFlatU64, align32: 8 },{ field: 'data-access-timestamp', lowerFn: _lowerFlatOption.bind(null, 2), align32: 8 },{ field: 'data-modification-timestamp', lowerFn: _lowerFlatOption.bind(null, 2), align32: 8 },{ field: 'status-change-timestamp', lowerFn: _lowerFlatOption.bind(null, 2), align32: 8 },]), align32: 8 },{ discriminant: 1, tag: 'error', lowerFn: _lowerFlatEnum.bind(null, 1), align32: 1 },])],
|
|
7417
7690
|
getCallbackFn: () => null,
|
|
@@ -7434,7 +7707,7 @@ GlobalComponentAsyncLowers.define({
|
|
|
7434
7707
|
trampolineIdx: 21,
|
|
7435
7708
|
componentIdx: 0,
|
|
7436
7709
|
isAsync: false,
|
|
7437
|
-
paramLiftFns: [
|
|
7710
|
+
paramLiftFns: [_liftFlatBorrow.bind(null, 6),_liftFlatFlags.bind(null, 0),_liftFlatStringUTF8],
|
|
7438
7711
|
metadata: lowered_import_14_metadata,
|
|
7439
7712
|
resultLowerFns: [_lowerFlatResult([{ discriminant: 0, tag: 'ok', lowerFn: _lowerFlatRecord([{ field: 'type', lowerFn: _lowerFlatEnum.bind(null, 0), align32: 8 },{ field: 'link-count', lowerFn: _lowerFlatU64, align32: 8 },{ field: 'size', lowerFn: _lowerFlatU64, align32: 8 },{ field: 'data-access-timestamp', lowerFn: _lowerFlatOption.bind(null, 2), align32: 8 },{ field: 'data-modification-timestamp', lowerFn: _lowerFlatOption.bind(null, 2), align32: 8 },{ field: 'status-change-timestamp', lowerFn: _lowerFlatOption.bind(null, 2), align32: 8 },]), align32: 8 },{ discriminant: 1, tag: 'error', lowerFn: _lowerFlatEnum.bind(null, 1), align32: 1 },])],
|
|
7440
7713
|
getCallbackFn: () => null,
|
|
@@ -7457,7 +7730,7 @@ GlobalComponentAsyncLowers.define({
|
|
|
7457
7730
|
trampolineIdx: 22,
|
|
7458
7731
|
componentIdx: 0,
|
|
7459
7732
|
isAsync: false,
|
|
7460
|
-
paramLiftFns: [
|
|
7733
|
+
paramLiftFns: [_liftFlatBorrow.bind(null, 6),_liftFlatFlags.bind(null, 0),_liftFlatStringUTF8,_liftFlatFlags.bind(null, 1),_liftFlatFlags.bind(null, 2)],
|
|
7461
7734
|
metadata: lowered_import_15_metadata,
|
|
7462
7735
|
resultLowerFns: [_lowerFlatResult([{ discriminant: 0, tag: 'ok', lowerFn: _lowerFlatOwn.bind(null, 6), align32: 4 },{ discriminant: 1, tag: 'error', lowerFn: _lowerFlatEnum.bind(null, 1), align32: 1 },])],
|
|
7463
7736
|
getCallbackFn: () => null,
|
|
@@ -7480,7 +7753,7 @@ GlobalComponentAsyncLowers.define({
|
|
|
7480
7753
|
trampolineIdx: 23,
|
|
7481
7754
|
componentIdx: 0,
|
|
7482
7755
|
isAsync: false,
|
|
7483
|
-
paramLiftFns: [
|
|
7756
|
+
paramLiftFns: [_liftFlatBorrow.bind(null, 5)],
|
|
7484
7757
|
metadata: lowered_import_16_metadata,
|
|
7485
7758
|
resultLowerFns: [_lowerFlatResult([{ discriminant: 0, tag: 'ok', lowerFn: _lowerFlatOption.bind(null, 3), align32: 4 },{ discriminant: 1, tag: 'error', lowerFn: _lowerFlatEnum.bind(null, 1), align32: 1 },])],
|
|
7486
7759
|
getCallbackFn: () => null,
|
|
@@ -7503,9 +7776,9 @@ GlobalComponentAsyncLowers.define({
|
|
|
7503
7776
|
trampolineIdx: 24,
|
|
7504
7777
|
componentIdx: 0,
|
|
7505
7778
|
isAsync: false,
|
|
7506
|
-
paramLiftFns: [
|
|
7779
|
+
paramLiftFns: [_liftFlatBorrow.bind(null, 1),_liftFlatU64],
|
|
7507
7780
|
metadata: lowered_import_17_metadata,
|
|
7508
|
-
resultLowerFns: [_lowerFlatResult([{ discriminant: 0, tag: 'ok', lowerFn: _lowerFlatList
|
|
7781
|
+
resultLowerFns: [_lowerFlatResult([{ discriminant: 0, tag: 'ok', lowerFn: _lowerFlatList({ elemLowerFn: _lowerFlatU8, typeIdx: 1 }), align32: 4 },{ discriminant: 1, tag: 'error', lowerFn: _lowerFlatVariant({ discriminantSizeBytes: 1, lowerMetas: [{ discriminant: 0, tag: 'last-operation-failed', lowerFn: _lowerFlatOwn.bind(null, 0), align32: 4, },{ discriminant: 1, tag: 'closed', lowerFn: null, align32: null, },] }), align32: 4 },])],
|
|
7509
7782
|
getCallbackFn: () => null,
|
|
7510
7783
|
getPostReturnFn: () => null,
|
|
7511
7784
|
isCancellable: false,
|
|
@@ -7526,9 +7799,9 @@ GlobalComponentAsyncLowers.define({
|
|
|
7526
7799
|
trampolineIdx: 25,
|
|
7527
7800
|
componentIdx: 0,
|
|
7528
7801
|
isAsync: false,
|
|
7529
|
-
paramLiftFns: [
|
|
7802
|
+
paramLiftFns: [_liftFlatBorrow.bind(null, 1),_liftFlatU64],
|
|
7530
7803
|
metadata: lowered_import_18_metadata,
|
|
7531
|
-
resultLowerFns: [_lowerFlatResult([{ discriminant: 0, tag: 'ok', lowerFn: _lowerFlatList
|
|
7804
|
+
resultLowerFns: [_lowerFlatResult([{ discriminant: 0, tag: 'ok', lowerFn: _lowerFlatList({ elemLowerFn: _lowerFlatU8, typeIdx: 1 }), align32: 4 },{ discriminant: 1, tag: 'error', lowerFn: _lowerFlatVariant({ discriminantSizeBytes: 1, lowerMetas: [{ discriminant: 0, tag: 'last-operation-failed', lowerFn: _lowerFlatOwn.bind(null, 0), align32: 4, },{ discriminant: 1, tag: 'closed', lowerFn: null, align32: null, },] }), align32: 4 },])],
|
|
7532
7805
|
getCallbackFn: () => null,
|
|
7533
7806
|
getPostReturnFn: () => null,
|
|
7534
7807
|
isCancellable: false,
|
|
@@ -7549,7 +7822,7 @@ GlobalComponentAsyncLowers.define({
|
|
|
7549
7822
|
trampolineIdx: 26,
|
|
7550
7823
|
componentIdx: 0,
|
|
7551
7824
|
isAsync: false,
|
|
7552
|
-
paramLiftFns: [
|
|
7825
|
+
paramLiftFns: [_liftFlatBorrow.bind(null, 2)],
|
|
7553
7826
|
metadata: lowered_import_19_metadata,
|
|
7554
7827
|
resultLowerFns: [_lowerFlatResult([{ discriminant: 0, tag: 'ok', lowerFn: _lowerFlatU64, align32: 8 },{ discriminant: 1, tag: 'error', lowerFn: _lowerFlatVariant({ discriminantSizeBytes: 1, lowerMetas: [{ discriminant: 0, tag: 'last-operation-failed', lowerFn: _lowerFlatOwn.bind(null, 0), align32: 4, },{ discriminant: 1, tag: 'closed', lowerFn: null, align32: null, },] }), align32: 4 },])],
|
|
7555
7828
|
getCallbackFn: () => null,
|
|
@@ -7572,7 +7845,7 @@ GlobalComponentAsyncLowers.define({
|
|
|
7572
7845
|
trampolineIdx: 27,
|
|
7573
7846
|
componentIdx: 0,
|
|
7574
7847
|
isAsync: false,
|
|
7575
|
-
paramLiftFns: [
|
|
7848
|
+
paramLiftFns: [_liftFlatBorrow.bind(null, 2),_liftFlatList.bind(null, 1)],
|
|
7576
7849
|
metadata: lowered_import_20_metadata,
|
|
7577
7850
|
resultLowerFns: [_lowerFlatResult([{ discriminant: 0, tag: 'ok', lowerFn: null, align32: null },{ discriminant: 1, tag: 'error', lowerFn: _lowerFlatVariant({ discriminantSizeBytes: 1, lowerMetas: [{ discriminant: 0, tag: 'last-operation-failed', lowerFn: _lowerFlatOwn.bind(null, 0), align32: 4, },{ discriminant: 1, tag: 'closed', lowerFn: null, align32: null, },] }), align32: 4 },])],
|
|
7578
7851
|
getCallbackFn: () => null,
|
|
@@ -7595,7 +7868,7 @@ GlobalComponentAsyncLowers.define({
|
|
|
7595
7868
|
trampolineIdx: 28,
|
|
7596
7869
|
componentIdx: 0,
|
|
7597
7870
|
isAsync: false,
|
|
7598
|
-
paramLiftFns: [
|
|
7871
|
+
paramLiftFns: [_liftFlatBorrow.bind(null, 2),_liftFlatList.bind(null, 1)],
|
|
7599
7872
|
metadata: lowered_import_21_metadata,
|
|
7600
7873
|
resultLowerFns: [_lowerFlatResult([{ discriminant: 0, tag: 'ok', lowerFn: null, align32: null },{ discriminant: 1, tag: 'error', lowerFn: _lowerFlatVariant({ discriminantSizeBytes: 1, lowerMetas: [{ discriminant: 0, tag: 'last-operation-failed', lowerFn: _lowerFlatOwn.bind(null, 0), align32: 4, },{ discriminant: 1, tag: 'closed', lowerFn: null, align32: null, },] }), align32: 4 },])],
|
|
7601
7874
|
getCallbackFn: () => null,
|
|
@@ -7618,7 +7891,7 @@ GlobalComponentAsyncLowers.define({
|
|
|
7618
7891
|
trampolineIdx: 29,
|
|
7619
7892
|
componentIdx: 0,
|
|
7620
7893
|
isAsync: false,
|
|
7621
|
-
paramLiftFns: [
|
|
7894
|
+
paramLiftFns: [_liftFlatBorrow.bind(null, 2)],
|
|
7622
7895
|
metadata: lowered_import_22_metadata,
|
|
7623
7896
|
resultLowerFns: [_lowerFlatResult([{ discriminant: 0, tag: 'ok', lowerFn: null, align32: null },{ discriminant: 1, tag: 'error', lowerFn: _lowerFlatVariant({ discriminantSizeBytes: 1, lowerMetas: [{ discriminant: 0, tag: 'last-operation-failed', lowerFn: _lowerFlatOwn.bind(null, 0), align32: 4, },{ discriminant: 1, tag: 'closed', lowerFn: null, align32: null, },] }), align32: 4 },])],
|
|
7624
7897
|
getCallbackFn: () => null,
|
|
@@ -7643,7 +7916,7 @@ GlobalComponentAsyncLowers.define({
|
|
|
7643
7916
|
isAsync: false,
|
|
7644
7917
|
paramLiftFns: [_liftFlatU64],
|
|
7645
7918
|
metadata: lowered_import_23_metadata,
|
|
7646
|
-
resultLowerFns: [_lowerFlatList
|
|
7919
|
+
resultLowerFns: [_lowerFlatList({ elemLowerFn: _lowerFlatU8, typeIdx: 1 })],
|
|
7647
7920
|
getCallbackFn: () => null,
|
|
7648
7921
|
getPostReturnFn: () => null,
|
|
7649
7922
|
isCancellable: false,
|
|
@@ -7666,7 +7939,7 @@ GlobalComponentAsyncLowers.define({
|
|
|
7666
7939
|
isAsync: false,
|
|
7667
7940
|
paramLiftFns: [],
|
|
7668
7941
|
metadata: lowered_import_24_metadata,
|
|
7669
|
-
resultLowerFns: [_lowerFlatList.bind(null, 2)],
|
|
7942
|
+
resultLowerFns: [_lowerFlatList({ elemLowerFn: _lowerFlatTuple.bind(null, 29), typeIdx: 2 })],
|
|
7670
7943
|
getCallbackFn: () => null,
|
|
7671
7944
|
getPostReturnFn: () => null,
|
|
7672
7945
|
isCancellable: false,
|
|
@@ -7829,8 +8102,24 @@ function print(arg0) {
|
|
|
7829
8102
|
var val0 = arg0;
|
|
7830
8103
|
var len0 = val0.byteLength;
|
|
7831
8104
|
var ptr0 = realloc1(0, 0, 1, len0 * 1);
|
|
7832
|
-
|
|
7833
|
-
|
|
8105
|
+
|
|
8106
|
+
let valData0;
|
|
8107
|
+
const valLenBytes0 = len0 * 1;
|
|
8108
|
+
if (Array.isArray(val0)) {
|
|
8109
|
+
// Regular array likely containing numbers, write values to memory
|
|
8110
|
+
let offset = 0;
|
|
8111
|
+
const dv0 = new DataView(memory0.buffer);
|
|
8112
|
+
for (const v of val0) {
|
|
8113
|
+
dv0.setUint8(ptr0+ offset, v, true);
|
|
8114
|
+
offset += 1;
|
|
8115
|
+
}
|
|
8116
|
+
} else {
|
|
8117
|
+
// TypedArray / ArrayBuffer-like, direct copy
|
|
8118
|
+
valData0 = new Uint8Array(val0.buffer || val0, val0.byteOffset, valLenBytes0);
|
|
8119
|
+
const out0 = new Uint8Array(memory0.buffer, ptr0,valLenBytes0);
|
|
8120
|
+
out0.set(valData0);
|
|
8121
|
+
}
|
|
8122
|
+
|
|
7834
8123
|
_debugLog('[iface="local:wasm-tools/tools", function="print"][Instruction::CallWasm] enter', {
|
|
7835
8124
|
funcName: 'print',
|
|
7836
8125
|
paramCount: 2,
|
|
@@ -7905,8 +8194,24 @@ function componentNew(arg0, arg1) {
|
|
|
7905
8194
|
var val0 = arg0;
|
|
7906
8195
|
var len0 = val0.byteLength;
|
|
7907
8196
|
var ptr0 = realloc1(0, 0, 1, len0 * 1);
|
|
7908
|
-
|
|
7909
|
-
|
|
8197
|
+
|
|
8198
|
+
let valData0;
|
|
8199
|
+
const valLenBytes0 = len0 * 1;
|
|
8200
|
+
if (Array.isArray(val0)) {
|
|
8201
|
+
// Regular array likely containing numbers, write values to memory
|
|
8202
|
+
let offset = 0;
|
|
8203
|
+
const dv0 = new DataView(memory0.buffer);
|
|
8204
|
+
for (const v of val0) {
|
|
8205
|
+
dv0.setUint8(ptr0+ offset, v, true);
|
|
8206
|
+
offset += 1;
|
|
8207
|
+
}
|
|
8208
|
+
} else {
|
|
8209
|
+
// TypedArray / ArrayBuffer-like, direct copy
|
|
8210
|
+
valData0 = new Uint8Array(val0.buffer || val0, val0.byteOffset, valLenBytes0);
|
|
8211
|
+
const out0 = new Uint8Array(memory0.buffer, ptr0,valLenBytes0);
|
|
8212
|
+
out0.set(valData0);
|
|
8213
|
+
}
|
|
8214
|
+
|
|
7910
8215
|
var variant5 = arg1;
|
|
7911
8216
|
let variant5_0;
|
|
7912
8217
|
let variant5_1;
|
|
@@ -7933,8 +8238,24 @@ function componentNew(arg0, arg1) {
|
|
|
7933
8238
|
var val3 = tuple1_1;
|
|
7934
8239
|
var len3 = val3.byteLength;
|
|
7935
8240
|
var ptr3 = realloc1(0, 0, 1, len3 * 1);
|
|
7936
|
-
|
|
7937
|
-
|
|
8241
|
+
|
|
8242
|
+
let valData3;
|
|
8243
|
+
const valLenBytes3 = len3 * 1;
|
|
8244
|
+
if (Array.isArray(val3)) {
|
|
8245
|
+
// Regular array likely containing numbers, write values to memory
|
|
8246
|
+
let offset = 0;
|
|
8247
|
+
const dv3 = new DataView(memory0.buffer);
|
|
8248
|
+
for (const v of val3) {
|
|
8249
|
+
dv3.setUint8(ptr3+ offset, v, true);
|
|
8250
|
+
offset += 1;
|
|
8251
|
+
}
|
|
8252
|
+
} else {
|
|
8253
|
+
// TypedArray / ArrayBuffer-like, direct copy
|
|
8254
|
+
valData3 = new Uint8Array(val3.buffer || val3, val3.byteOffset, valLenBytes3);
|
|
8255
|
+
const out3 = new Uint8Array(memory0.buffer, ptr3,valLenBytes3);
|
|
8256
|
+
out3.set(valData3);
|
|
8257
|
+
}
|
|
8258
|
+
|
|
7938
8259
|
dataView(memory0).setUint32(base + 12, len3, true);
|
|
7939
8260
|
dataView(memory0).setUint32(base + 8, ptr3, true);
|
|
7940
8261
|
}
|
|
@@ -8016,8 +8337,24 @@ function componentWit(arg0) {
|
|
|
8016
8337
|
var val0 = arg0;
|
|
8017
8338
|
var len0 = val0.byteLength;
|
|
8018
8339
|
var ptr0 = realloc1(0, 0, 1, len0 * 1);
|
|
8019
|
-
|
|
8020
|
-
|
|
8340
|
+
|
|
8341
|
+
let valData0;
|
|
8342
|
+
const valLenBytes0 = len0 * 1;
|
|
8343
|
+
if (Array.isArray(val0)) {
|
|
8344
|
+
// Regular array likely containing numbers, write values to memory
|
|
8345
|
+
let offset = 0;
|
|
8346
|
+
const dv0 = new DataView(memory0.buffer);
|
|
8347
|
+
for (const v of val0) {
|
|
8348
|
+
dv0.setUint8(ptr0+ offset, v, true);
|
|
8349
|
+
offset += 1;
|
|
8350
|
+
}
|
|
8351
|
+
} else {
|
|
8352
|
+
// TypedArray / ArrayBuffer-like, direct copy
|
|
8353
|
+
valData0 = new Uint8Array(val0.buffer || val0, val0.byteOffset, valLenBytes0);
|
|
8354
|
+
const out0 = new Uint8Array(memory0.buffer, ptr0,valLenBytes0);
|
|
8355
|
+
out0.set(valData0);
|
|
8356
|
+
}
|
|
8357
|
+
|
|
8021
8358
|
_debugLog('[iface="local:wasm-tools/tools", function="component-wit"][Instruction::CallWasm] enter', {
|
|
8022
8359
|
funcName: 'component-wit',
|
|
8023
8360
|
paramCount: 2,
|
|
@@ -8100,8 +8437,24 @@ function componentEmbed(arg0) {
|
|
|
8100
8437
|
var val2 = e;
|
|
8101
8438
|
var len2 = val2.byteLength;
|
|
8102
8439
|
var ptr2 = realloc1(0, 0, 1, len2 * 1);
|
|
8103
|
-
|
|
8104
|
-
|
|
8440
|
+
|
|
8441
|
+
let valData2;
|
|
8442
|
+
const valLenBytes2 = len2 * 1;
|
|
8443
|
+
if (Array.isArray(val2)) {
|
|
8444
|
+
// Regular array likely containing numbers, write values to memory
|
|
8445
|
+
let offset = 0;
|
|
8446
|
+
const dv2 = new DataView(memory0.buffer);
|
|
8447
|
+
for (const v of val2) {
|
|
8448
|
+
dv2.setUint8(ptr2+ offset, v, true);
|
|
8449
|
+
offset += 1;
|
|
8450
|
+
}
|
|
8451
|
+
} else {
|
|
8452
|
+
// TypedArray / ArrayBuffer-like, direct copy
|
|
8453
|
+
valData2 = new Uint8Array(val2.buffer || val2, val2.byteOffset, valLenBytes2);
|
|
8454
|
+
const out2 = new Uint8Array(memory0.buffer, ptr2,valLenBytes2);
|
|
8455
|
+
out2.set(valData2);
|
|
8456
|
+
}
|
|
8457
|
+
|
|
8105
8458
|
dataView(memory0).setUint32(ptr0 + 8, len2, true);
|
|
8106
8459
|
dataView(memory0).setUint32(ptr0 + 4, ptr2, true);
|
|
8107
8460
|
}
|
|
@@ -8343,8 +8696,24 @@ function metadataShow(arg0) {
|
|
|
8343
8696
|
var val0 = arg0;
|
|
8344
8697
|
var len0 = val0.byteLength;
|
|
8345
8698
|
var ptr0 = realloc1(0, 0, 1, len0 * 1);
|
|
8346
|
-
|
|
8347
|
-
|
|
8699
|
+
|
|
8700
|
+
let valData0;
|
|
8701
|
+
const valLenBytes0 = len0 * 1;
|
|
8702
|
+
if (Array.isArray(val0)) {
|
|
8703
|
+
// Regular array likely containing numbers, write values to memory
|
|
8704
|
+
let offset = 0;
|
|
8705
|
+
const dv0 = new DataView(memory0.buffer);
|
|
8706
|
+
for (const v of val0) {
|
|
8707
|
+
dv0.setUint8(ptr0+ offset, v, true);
|
|
8708
|
+
offset += 1;
|
|
8709
|
+
}
|
|
8710
|
+
} else {
|
|
8711
|
+
// TypedArray / ArrayBuffer-like, direct copy
|
|
8712
|
+
valData0 = new Uint8Array(val0.buffer || val0, val0.byteOffset, valLenBytes0);
|
|
8713
|
+
const out0 = new Uint8Array(memory0.buffer, ptr0,valLenBytes0);
|
|
8714
|
+
out0.set(valData0);
|
|
8715
|
+
}
|
|
8716
|
+
|
|
8348
8717
|
_debugLog('[iface="local:wasm-tools/tools", function="metadata-show"][Instruction::CallWasm] enter', {
|
|
8349
8718
|
funcName: 'metadata-show',
|
|
8350
8719
|
paramCount: 2,
|
|
@@ -8502,8 +8871,24 @@ function metadataAdd(arg0, arg1) {
|
|
|
8502
8871
|
var val0 = arg0;
|
|
8503
8872
|
var len0 = val0.byteLength;
|
|
8504
8873
|
var ptr0 = realloc1(0, 0, 1, len0 * 1);
|
|
8505
|
-
|
|
8506
|
-
|
|
8874
|
+
|
|
8875
|
+
let valData0;
|
|
8876
|
+
const valLenBytes0 = len0 * 1;
|
|
8877
|
+
if (Array.isArray(val0)) {
|
|
8878
|
+
// Regular array likely containing numbers, write values to memory
|
|
8879
|
+
let offset = 0;
|
|
8880
|
+
const dv0 = new DataView(memory0.buffer);
|
|
8881
|
+
for (const v of val0) {
|
|
8882
|
+
dv0.setUint8(ptr0+ offset, v, true);
|
|
8883
|
+
offset += 1;
|
|
8884
|
+
}
|
|
8885
|
+
} else {
|
|
8886
|
+
// TypedArray / ArrayBuffer-like, direct copy
|
|
8887
|
+
valData0 = new Uint8Array(val0.buffer || val0, val0.byteOffset, valLenBytes0);
|
|
8888
|
+
const out0 = new Uint8Array(memory0.buffer, ptr0,valLenBytes0);
|
|
8889
|
+
out0.set(valData0);
|
|
8890
|
+
}
|
|
8891
|
+
|
|
8507
8892
|
var vec7 = arg1;
|
|
8508
8893
|
var len7 = vec7.length;
|
|
8509
8894
|
var result7 = realloc1(0, 0, 4, len7 * 16);
|