@vercel/python-analysis 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1999 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1896 -71
- package/dist/semantic/entrypoints.d.ts +28 -0
- package/dist/semantic/load.d.ts +4 -0
- package/dist/wasm/interfaces/wasi-cli-environment.d.ts +2 -0
- package/dist/wasm/interfaces/wasi-cli-exit.d.ts +3 -0
- package/dist/wasm/interfaces/wasi-cli-stderr.d.ts +3 -0
- package/dist/wasm/interfaces/wasi-io-error.d.ts +9 -0
- package/dist/wasm/interfaces/wasi-io-streams.d.ts +18 -0
- package/dist/wasm/vercel_python_analysis.core.wasm +0 -0
- package/dist/wasm/vercel_python_analysis.core2.wasm +0 -0
- package/dist/wasm/vercel_python_analysis.core3.wasm +0 -0
- package/dist/wasm/vercel_python_analysis.d.ts +47 -0
- package/dist/wasm/vercel_python_analysis.js +1106 -0
- package/package.json +20 -4
- package/dist/manifest/package.js +0 -422
- package/dist/manifest/pep440.js +0 -63
- package/dist/manifest/pep508.js +0 -70
- package/dist/manifest/pipfile/schema.js +0 -44
- package/dist/manifest/pipfile/schema.zod.js +0 -97
- package/dist/manifest/pipfile/types.js +0 -16
- package/dist/manifest/pipfile-parser.js +0 -262
- package/dist/manifest/pyproject/schema.js +0 -56
- package/dist/manifest/pyproject/schema.zod.js +0 -94
- package/dist/manifest/pyproject/types.js +0 -16
- package/dist/manifest/python-selector.js +0 -185
- package/dist/manifest/python-specifiers.js +0 -156
- package/dist/manifest/requirement/schema.js +0 -35
- package/dist/manifest/requirement/schema.zod.js +0 -49
- package/dist/manifest/requirement/types.js +0 -16
- package/dist/manifest/requirements-txt-parser.js +0 -400
- package/dist/manifest/uv-config/schema.js +0 -35
- package/dist/manifest/uv-config/schema.zod.js +0 -48
- package/dist/manifest/uv-config/types.js +0 -16
- package/dist/manifest/uv-python-version-parser.js +0 -268
- package/dist/types.js +0 -16
- package/dist/util/config.js +0 -100
- package/dist/util/error.js +0 -54
- package/dist/util/fs.js +0 -75
- package/dist/util/type.js +0 -30
|
@@ -0,0 +1,1106 @@
|
|
|
1
|
+
export function instantiate(getCoreModule, imports, instantiateCore = WebAssembly.instantiate) {
|
|
2
|
+
|
|
3
|
+
let dv = new DataView(new ArrayBuffer());
|
|
4
|
+
const dataView = mem => dv.buffer === mem.buffer ? dv : dv = new DataView(mem.buffer);
|
|
5
|
+
|
|
6
|
+
const utf8Encoder = new TextEncoder();
|
|
7
|
+
let utf8EncodedLen = 0;
|
|
8
|
+
function utf8Encode(s, realloc, memory) {
|
|
9
|
+
if (typeof s !== 'string') throw new TypeError('expected a string');
|
|
10
|
+
if (s.length === 0) {
|
|
11
|
+
utf8EncodedLen = 0;
|
|
12
|
+
return 1;
|
|
13
|
+
}
|
|
14
|
+
let buf = utf8Encoder.encode(s);
|
|
15
|
+
let ptr = realloc(0, 0, 1, buf.length);
|
|
16
|
+
new Uint8Array(memory.buffer).set(buf, ptr);
|
|
17
|
+
utf8EncodedLen = buf.length;
|
|
18
|
+
return ptr;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const T_FLAG = 1 << 30;
|
|
22
|
+
|
|
23
|
+
function rscTableCreateOwn (table, rep) {
|
|
24
|
+
const free = table[0] & ~T_FLAG;
|
|
25
|
+
if (free === 0) {
|
|
26
|
+
table.push(0);
|
|
27
|
+
table.push(rep | T_FLAG);
|
|
28
|
+
return (table.length >> 1) - 1;
|
|
29
|
+
}
|
|
30
|
+
table[0] = table[free << 1];
|
|
31
|
+
table[free << 1] = 0;
|
|
32
|
+
table[(free << 1) + 1] = rep | T_FLAG;
|
|
33
|
+
return free;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function rscTableRemove (table, handle) {
|
|
37
|
+
const scope = table[handle << 1];
|
|
38
|
+
const val = table[(handle << 1) + 1];
|
|
39
|
+
const own = (val & T_FLAG) !== 0;
|
|
40
|
+
const rep = val & ~T_FLAG;
|
|
41
|
+
if (val === 0 || (scope & T_FLAG) !== 0) throw new TypeError('Invalid handle');
|
|
42
|
+
table[handle << 1] = table[0] | T_FLAG;
|
|
43
|
+
table[0] = handle | T_FLAG;
|
|
44
|
+
return { rep, scope, own };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
let curResourceBorrows = [];
|
|
48
|
+
|
|
49
|
+
let NEXT_TASK_ID = 0n;
|
|
50
|
+
function startCurrentTask(componentIdx, isAsync, entryFnName) {
|
|
51
|
+
_debugLog('[startCurrentTask()] args', { componentIdx, isAsync });
|
|
52
|
+
if (componentIdx === undefined || componentIdx === null) {
|
|
53
|
+
throw new Error('missing/invalid component instance index while starting task');
|
|
54
|
+
}
|
|
55
|
+
const tasks = ASYNC_TASKS_BY_COMPONENT_IDX.get(componentIdx);
|
|
56
|
+
|
|
57
|
+
const nextId = ++NEXT_TASK_ID;
|
|
58
|
+
const newTask = new AsyncTask({ id: nextId, componentIdx, isAsync, entryFnName });
|
|
59
|
+
const newTaskMeta = { id: nextId, componentIdx, task: newTask };
|
|
60
|
+
|
|
61
|
+
ASYNC_CURRENT_TASK_IDS.push(nextId);
|
|
62
|
+
ASYNC_CURRENT_COMPONENT_IDXS.push(componentIdx);
|
|
63
|
+
|
|
64
|
+
if (!tasks) {
|
|
65
|
+
ASYNC_TASKS_BY_COMPONENT_IDX.set(componentIdx, [newTaskMeta]);
|
|
66
|
+
return nextId;
|
|
67
|
+
} else {
|
|
68
|
+
tasks.push(newTaskMeta);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return nextId;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function endCurrentTask(componentIdx, taskId) {
|
|
75
|
+
_debugLog('[endCurrentTask()] args', { componentIdx });
|
|
76
|
+
componentIdx ??= ASYNC_CURRENT_COMPONENT_IDXS.at(-1);
|
|
77
|
+
taskId ??= ASYNC_CURRENT_TASK_IDS.at(-1);
|
|
78
|
+
if (componentIdx === undefined || componentIdx === null) {
|
|
79
|
+
throw new Error('missing/invalid component instance index while ending current task');
|
|
80
|
+
}
|
|
81
|
+
const tasks = ASYNC_TASKS_BY_COMPONENT_IDX.get(componentIdx);
|
|
82
|
+
if (!tasks || !Array.isArray(tasks)) {
|
|
83
|
+
throw new Error('missing/invalid tasks for component instance while ending task');
|
|
84
|
+
}
|
|
85
|
+
if (tasks.length == 0) {
|
|
86
|
+
throw new Error('no current task(s) for component instance while ending task');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (taskId) {
|
|
90
|
+
const last = tasks[tasks.length - 1];
|
|
91
|
+
if (last.id !== taskId) {
|
|
92
|
+
throw new Error('current task does not match expected task ID');
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
ASYNC_CURRENT_TASK_IDS.pop();
|
|
97
|
+
ASYNC_CURRENT_COMPONENT_IDXS.pop();
|
|
98
|
+
|
|
99
|
+
return tasks.pop();
|
|
100
|
+
}
|
|
101
|
+
const ASYNC_TASKS_BY_COMPONENT_IDX = new Map();
|
|
102
|
+
const ASYNC_CURRENT_TASK_IDS = [];
|
|
103
|
+
const ASYNC_CURRENT_COMPONENT_IDXS = [];
|
|
104
|
+
|
|
105
|
+
class AsyncTask {
|
|
106
|
+
static State = {
|
|
107
|
+
INITIAL: 'initial',
|
|
108
|
+
CANCELLED: 'cancelled',
|
|
109
|
+
CANCEL_PENDING: 'cancel-pending',
|
|
110
|
+
CANCEL_DELIVERED: 'cancel-delivered',
|
|
111
|
+
RESOLVED: 'resolved',
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
static BlockResult = {
|
|
115
|
+
CANCELLED: 'block.cancelled',
|
|
116
|
+
NOT_CANCELLED: 'block.not-cancelled',
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
#id;
|
|
120
|
+
#componentIdx;
|
|
121
|
+
#state;
|
|
122
|
+
#isAsync;
|
|
123
|
+
#onResolve = null;
|
|
124
|
+
#entryFnName = null;
|
|
125
|
+
#subtasks = [];
|
|
126
|
+
#completionPromise = null;
|
|
127
|
+
|
|
128
|
+
cancelled = false;
|
|
129
|
+
requested = false;
|
|
130
|
+
alwaysTaskReturn = false;
|
|
131
|
+
|
|
132
|
+
returnCalls = 0;
|
|
133
|
+
storage = [0, 0];
|
|
134
|
+
borrowedHandles = {};
|
|
135
|
+
|
|
136
|
+
awaitableResume = null;
|
|
137
|
+
awaitableCancel = null;
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
constructor(opts) {
|
|
141
|
+
if (opts?.id === undefined) { throw new TypeError('missing task ID during task creation'); }
|
|
142
|
+
this.#id = opts.id;
|
|
143
|
+
if (opts?.componentIdx === undefined) {
|
|
144
|
+
throw new TypeError('missing component id during task creation');
|
|
145
|
+
}
|
|
146
|
+
this.#componentIdx = opts.componentIdx;
|
|
147
|
+
this.#state = AsyncTask.State.INITIAL;
|
|
148
|
+
this.#isAsync = opts?.isAsync ?? false;
|
|
149
|
+
this.#entryFnName = opts.entryFnName;
|
|
150
|
+
|
|
151
|
+
const {
|
|
152
|
+
promise: completionPromise,
|
|
153
|
+
resolve: resolveCompletionPromise,
|
|
154
|
+
reject: rejectCompletionPromise,
|
|
155
|
+
} = Promise.withResolvers();
|
|
156
|
+
this.#completionPromise = completionPromise;
|
|
157
|
+
|
|
158
|
+
this.#onResolve = (results) => {
|
|
159
|
+
// TODO: handle external facing cancellation (should likely be a rejection)
|
|
160
|
+
resolveCompletionPromise(results);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
taskState() { return this.#state.slice(); }
|
|
165
|
+
id() { return this.#id; }
|
|
166
|
+
componentIdx() { return this.#componentIdx; }
|
|
167
|
+
isAsync() { return this.#isAsync; }
|
|
168
|
+
entryFnName() { return this.#entryFnName; }
|
|
169
|
+
completionPromise() { return this.#completionPromise; }
|
|
170
|
+
|
|
171
|
+
mayEnter(task) {
|
|
172
|
+
const cstate = getOrCreateAsyncState(this.#componentIdx);
|
|
173
|
+
if (!cstate.backpressure) {
|
|
174
|
+
_debugLog('[AsyncTask#mayEnter()] disallowed due to backpressure', { taskID: this.#id });
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
if (!cstate.callingSyncImport()) {
|
|
178
|
+
_debugLog('[AsyncTask#mayEnter()] disallowed due to sync import call', { taskID: this.#id });
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
const callingSyncExportWithSyncPending = cstate.callingSyncExport && !task.isAsync;
|
|
182
|
+
if (!callingSyncExportWithSyncPending) {
|
|
183
|
+
_debugLog('[AsyncTask#mayEnter()] disallowed due to sync export w/ sync pending', { taskID: this.#id });
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
return true;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
async enter() {
|
|
190
|
+
_debugLog('[AsyncTask#enter()] args', { taskID: this.#id });
|
|
191
|
+
|
|
192
|
+
// TODO: assert scheduler locked
|
|
193
|
+
// TODO: trap if on the stack
|
|
194
|
+
|
|
195
|
+
const cstate = getOrCreateAsyncState(this.#componentIdx);
|
|
196
|
+
|
|
197
|
+
let mayNotEnter = !this.mayEnter(this);
|
|
198
|
+
const componentHasPendingTasks = cstate.pendingTasks > 0;
|
|
199
|
+
if (mayNotEnter || componentHasPendingTasks) {
|
|
200
|
+
throw new Error('in enter()'); // TODO: remove
|
|
201
|
+
cstate.pendingTasks.set(this.#id, new Awaitable(new Promise()));
|
|
202
|
+
|
|
203
|
+
const blockResult = await this.onBlock(awaitable);
|
|
204
|
+
if (blockResult) {
|
|
205
|
+
// TODO: find this pending task in the component
|
|
206
|
+
const pendingTask = cstate.pendingTasks.get(this.#id);
|
|
207
|
+
if (!pendingTask) {
|
|
208
|
+
throw new Error('pending task [' + this.#id + '] not found for component instance');
|
|
209
|
+
}
|
|
210
|
+
cstate.pendingTasks.remove(this.#id);
|
|
211
|
+
this.#onResolve(new Error('failed enter'));
|
|
212
|
+
return false;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
mayNotEnter = !this.mayEnter(this);
|
|
216
|
+
if (!mayNotEnter || !cstate.startPendingTask) {
|
|
217
|
+
throw new Error('invalid component entrance/pending task resolution');
|
|
218
|
+
}
|
|
219
|
+
cstate.startPendingTask = false;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
if (!this.isAsync) { cstate.callingSyncExport = true; }
|
|
223
|
+
|
|
224
|
+
return true;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
async waitForEvent(opts) {
|
|
228
|
+
const { waitableSetRep, isAsync } = opts;
|
|
229
|
+
_debugLog('[AsyncTask#waitForEvent()] args', { taskID: this.#id, waitableSetRep, isAsync });
|
|
230
|
+
|
|
231
|
+
if (this.#isAsync !== isAsync) {
|
|
232
|
+
throw new Error('async waitForEvent called on non-async task');
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (this.status === AsyncTask.State.CANCEL_PENDING) {
|
|
236
|
+
this.#state = AsyncTask.State.CANCEL_DELIVERED;
|
|
237
|
+
return {
|
|
238
|
+
code: ASYNC_EVENT_CODE.TASK_CANCELLED,
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const state = getOrCreateAsyncState(this.#componentIdx);
|
|
243
|
+
const waitableSet = state.waitableSets.get(waitableSetRep);
|
|
244
|
+
if (!waitableSet) { throw new Error('missing/invalid waitable set'); }
|
|
245
|
+
|
|
246
|
+
waitableSet.numWaiting += 1;
|
|
247
|
+
let event = null;
|
|
248
|
+
|
|
249
|
+
while (event == null) {
|
|
250
|
+
const awaitable = new Awaitable(waitableSet.getPendingEvent());
|
|
251
|
+
const waited = await this.blockOn({ awaitable, isAsync, isCancellable: true });
|
|
252
|
+
if (waited) {
|
|
253
|
+
if (this.#state !== AsyncTask.State.INITIAL) {
|
|
254
|
+
throw new Error('task should be in initial state found [' + this.#state + ']');
|
|
255
|
+
}
|
|
256
|
+
this.#state = AsyncTask.State.CANCELLED;
|
|
257
|
+
return {
|
|
258
|
+
code: ASYNC_EVENT_CODE.TASK_CANCELLED,
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
event = waitableSet.poll();
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
waitableSet.numWaiting -= 1;
|
|
266
|
+
return event;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
waitForEventSync(opts) {
|
|
270
|
+
throw new Error('AsyncTask#yieldSync() not implemented')
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
async pollForEvent(opts) {
|
|
274
|
+
const { waitableSetRep, isAsync } = opts;
|
|
275
|
+
_debugLog('[AsyncTask#pollForEvent()] args', { taskID: this.#id, waitableSetRep, isAsync });
|
|
276
|
+
|
|
277
|
+
if (this.#isAsync !== isAsync) {
|
|
278
|
+
throw new Error('async pollForEvent called on non-async task');
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
throw new Error('AsyncTask#pollForEvent() not implemented');
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
pollForEventSync(opts) {
|
|
285
|
+
throw new Error('AsyncTask#yieldSync() not implemented')
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
async blockOn(opts) {
|
|
289
|
+
const { awaitable, isCancellable, forCallback } = opts;
|
|
290
|
+
_debugLog('[AsyncTask#blockOn()] args', { taskID: this.#id, awaitable, isCancellable, forCallback });
|
|
291
|
+
|
|
292
|
+
if (awaitable.resolved() && !ASYNC_DETERMINISM && _coinFlip()) {
|
|
293
|
+
return AsyncTask.BlockResult.NOT_CANCELLED;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
const cstate = getOrCreateAsyncState(this.#componentIdx);
|
|
297
|
+
if (forCallback) { cstate.exclusiveRelease(); }
|
|
298
|
+
|
|
299
|
+
let cancelled = await this.onBlock(awaitable);
|
|
300
|
+
if (cancelled === AsyncTask.BlockResult.CANCELLED && !isCancellable) {
|
|
301
|
+
const secondCancel = await this.onBlock(awaitable);
|
|
302
|
+
if (secondCancel !== AsyncTask.BlockResult.NOT_CANCELLED) {
|
|
303
|
+
throw new Error('uncancellable task was canceled despite second onBlock()');
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
if (forCallback) {
|
|
308
|
+
const acquired = new Awaitable(cstate.exclusiveLock());
|
|
309
|
+
cancelled = await this.onBlock(acquired);
|
|
310
|
+
if (cancelled === AsyncTask.BlockResult.CANCELLED) {
|
|
311
|
+
const secondCancel = await this.onBlock(acquired);
|
|
312
|
+
if (secondCancel !== AsyncTask.BlockResult.NOT_CANCELLED) {
|
|
313
|
+
throw new Error('uncancellable callback task was canceled despite second onBlock()');
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
if (cancelled === AsyncTask.BlockResult.CANCELLED) {
|
|
319
|
+
if (this.#state !== AsyncTask.State.INITIAL) {
|
|
320
|
+
throw new Error('cancelled task is not at initial state');
|
|
321
|
+
}
|
|
322
|
+
if (isCancellable) {
|
|
323
|
+
this.#state = AsyncTask.State.CANCELLED;
|
|
324
|
+
return AsyncTask.BlockResult.CANCELLED;
|
|
325
|
+
} else {
|
|
326
|
+
this.#state = AsyncTask.State.CANCEL_PENDING;
|
|
327
|
+
return AsyncTask.BlockResult.NOT_CANCELLED;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
return AsyncTask.BlockResult.NOT_CANCELLED;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
async onBlock(awaitable) {
|
|
335
|
+
_debugLog('[AsyncTask#onBlock()] args', { taskID: this.#id, awaitable });
|
|
336
|
+
if (!(awaitable instanceof Awaitable)) {
|
|
337
|
+
throw new Error('invalid awaitable during onBlock');
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// Build a promise that this task can await on which resolves when it is awoken
|
|
341
|
+
const { promise, resolve, reject } = Promise.withResolvers();
|
|
342
|
+
this.awaitableResume = () => {
|
|
343
|
+
_debugLog('[AsyncTask] resuming after onBlock', { taskID: this.#id });
|
|
344
|
+
resolve();
|
|
345
|
+
};
|
|
346
|
+
this.awaitableCancel = (err) => {
|
|
347
|
+
_debugLog('[AsyncTask] rejecting after onBlock', { taskID: this.#id, err });
|
|
348
|
+
reject(err);
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
// Park this task/execution to be handled later
|
|
352
|
+
const state = getOrCreateAsyncState(this.#componentIdx);
|
|
353
|
+
state.parkTaskOnAwaitable({ awaitable, task: this });
|
|
354
|
+
|
|
355
|
+
try {
|
|
356
|
+
await promise;
|
|
357
|
+
return AsyncTask.BlockResult.NOT_CANCELLED;
|
|
358
|
+
} catch (err) {
|
|
359
|
+
// rejection means task cancellation
|
|
360
|
+
return AsyncTask.BlockResult.CANCELLED;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
async asyncOnBlock(awaitable) {
|
|
365
|
+
_debugLog('[AsyncTask#asyncOnBlock()] args', { taskID: this.#id, awaitable });
|
|
366
|
+
if (!(awaitable instanceof Awaitable)) {
|
|
367
|
+
throw new Error('invalid awaitable during onBlock');
|
|
368
|
+
}
|
|
369
|
+
// TODO: watch for waitable AND cancellation
|
|
370
|
+
// TODO: if it WAS cancelled:
|
|
371
|
+
// - return true
|
|
372
|
+
// - only once per subtask
|
|
373
|
+
// - do not wait on the scheduler
|
|
374
|
+
// - control flow should go to the subtask (only once)
|
|
375
|
+
// - Once subtask blocks/resolves, reqlinquishControl() will tehn resolve request_cancel_end (without scheduler lock release)
|
|
376
|
+
// - control flow goes back to request_cancel
|
|
377
|
+
//
|
|
378
|
+
// Subtask cancellation should work similarly to an async import call -- runs sync up until
|
|
379
|
+
// the subtask blocks or resolves
|
|
380
|
+
//
|
|
381
|
+
throw new Error('AsyncTask#asyncOnBlock() not yet implemented');
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
async yield(opts) {
|
|
385
|
+
const { isCancellable, forCallback } = opts;
|
|
386
|
+
_debugLog('[AsyncTask#yield()] args', { taskID: this.#id, isCancellable, forCallback });
|
|
387
|
+
|
|
388
|
+
if (isCancellable && this.status === AsyncTask.State.CANCEL_PENDING) {
|
|
389
|
+
this.#state = AsyncTask.State.CANCELLED;
|
|
390
|
+
return {
|
|
391
|
+
code: ASYNC_EVENT_CODE.TASK_CANCELLED,
|
|
392
|
+
payload: [0, 0],
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// TODO: Awaitables need to *always* trigger the parking mechanism when they're done...?
|
|
397
|
+
// TODO: Component async state should remember which awaitables are done and work to clear tasks waiting
|
|
398
|
+
|
|
399
|
+
const blockResult = await this.blockOn({
|
|
400
|
+
awaitable: new Awaitable(new Promise(resolve => setTimeout(resolve, 0))),
|
|
401
|
+
isCancellable,
|
|
402
|
+
forCallback,
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
if (blockResult === AsyncTask.BlockResult.CANCELLED) {
|
|
406
|
+
if (this.#state !== AsyncTask.State.INITIAL) {
|
|
407
|
+
throw new Error('task should be in initial state found [' + this.#state + ']');
|
|
408
|
+
}
|
|
409
|
+
this.#state = AsyncTask.State.CANCELLED;
|
|
410
|
+
return {
|
|
411
|
+
code: ASYNC_EVENT_CODE.TASK_CANCELLED,
|
|
412
|
+
payload: [0, 0],
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
return {
|
|
417
|
+
code: ASYNC_EVENT_CODE.NONE,
|
|
418
|
+
payload: [0, 0],
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
yieldSync(opts) {
|
|
423
|
+
throw new Error('AsyncTask#yieldSync() not implemented')
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
cancel() {
|
|
427
|
+
_debugLog('[AsyncTask#cancel()] args', { });
|
|
428
|
+
if (!this.taskState() !== AsyncTask.State.CANCEL_DELIVERED) {
|
|
429
|
+
throw new Error('invalid task state for cancellation');
|
|
430
|
+
}
|
|
431
|
+
if (this.borrowedHandles.length > 0) { throw new Error('task still has borrow handles'); }
|
|
432
|
+
|
|
433
|
+
this.#onResolve(new Error('cancelled'));
|
|
434
|
+
this.#state = AsyncTask.State.RESOLVED;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
resolve(results) {
|
|
438
|
+
_debugLog('[AsyncTask#resolve()] args', { results });
|
|
439
|
+
if (this.#state === AsyncTask.State.RESOLVED) {
|
|
440
|
+
throw new Error('task is already resolved');
|
|
441
|
+
}
|
|
442
|
+
if (this.borrowedHandles.length > 0) { throw new Error('task still has borrow handles'); }
|
|
443
|
+
this.#onResolve(results.length === 1 ? results[0] : results);
|
|
444
|
+
this.#state = AsyncTask.State.RESOLVED;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
exit() {
|
|
448
|
+
_debugLog('[AsyncTask#exit()] args', { });
|
|
449
|
+
|
|
450
|
+
// TODO: ensure there is only one task at a time (scheduler.lock() functionality)
|
|
451
|
+
if (this.#state !== AsyncTask.State.RESOLVED) {
|
|
452
|
+
throw new Error('task exited without resolution');
|
|
453
|
+
}
|
|
454
|
+
if (this.borrowedHandles > 0) {
|
|
455
|
+
throw new Error('task exited without clearing borrowed handles');
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
const state = getOrCreateAsyncState(this.#componentIdx);
|
|
459
|
+
if (!state) { throw new Error('missing async state for component [' + this.#componentIdx + ']'); }
|
|
460
|
+
if (!this.#isAsync && !state.inSyncExportCall) {
|
|
461
|
+
throw new Error('sync task must be run from components known to be in a sync export call');
|
|
462
|
+
}
|
|
463
|
+
state.inSyncExportCall = false;
|
|
464
|
+
|
|
465
|
+
this.startPendingTask();
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
startPendingTask(args) {
|
|
469
|
+
_debugLog('[AsyncTask#startPendingTask()] args', args);
|
|
470
|
+
throw new Error('AsyncTask#startPendingTask() not implemented');
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
createSubtask(args) {
|
|
474
|
+
_debugLog('[AsyncTask#createSubtask()] args', args);
|
|
475
|
+
const newSubtask = new AsyncSubtask({
|
|
476
|
+
componentIdx: this.componentIdx(),
|
|
477
|
+
taskID: this.id(),
|
|
478
|
+
memoryIdx: args?.memoryIdx,
|
|
479
|
+
});
|
|
480
|
+
this.#subtasks.push(newSubtask);
|
|
481
|
+
return newSubtask;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
currentSubtask() {
|
|
485
|
+
_debugLog('[AsyncTask#currentSubtask()]');
|
|
486
|
+
if (this.#subtasks.length === 0) { throw new Error('no current subtask'); }
|
|
487
|
+
return this.#subtasks.at(-1);
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
endCurrentSubtask() {
|
|
491
|
+
_debugLog('[AsyncTask#endCurrentSubtask()]');
|
|
492
|
+
if (this.#subtasks.length === 0) { throw new Error('cannot end current subtask: no current subtask'); }
|
|
493
|
+
const subtask = this.#subtasks.pop();
|
|
494
|
+
subtask.drop();
|
|
495
|
+
return subtask;
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
function unpackCallbackResult(result) {
|
|
500
|
+
_debugLog('[unpackCallbackResult()] args', { result });
|
|
501
|
+
if (!(_typeCheckValidI32(result))) { throw new Error('invalid callback return value [' + result + '], not a valid i32'); }
|
|
502
|
+
const eventCode = result & 0xF;
|
|
503
|
+
if (eventCode < 0 || eventCode > 3) {
|
|
504
|
+
throw new Error('invalid async return value [' + eventCode + '], outside callback code range');
|
|
505
|
+
}
|
|
506
|
+
if (result < 0 || result >= 2**32) { throw new Error('invalid callback result'); }
|
|
507
|
+
// TODO: table max length check?
|
|
508
|
+
const waitableSetIdx = result >> 4;
|
|
509
|
+
return [eventCode, waitableSetIdx];
|
|
510
|
+
}
|
|
511
|
+
const ASYNC_STATE = new Map();
|
|
512
|
+
|
|
513
|
+
function getOrCreateAsyncState(componentIdx, init) {
|
|
514
|
+
if (!ASYNC_STATE.has(componentIdx)) {
|
|
515
|
+
ASYNC_STATE.set(componentIdx, new ComponentAsyncState());
|
|
516
|
+
}
|
|
517
|
+
return ASYNC_STATE.get(componentIdx);
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
class ComponentAsyncState {
|
|
521
|
+
#callingAsyncImport = false;
|
|
522
|
+
#syncImportWait = Promise.withResolvers();
|
|
523
|
+
#lock = null;
|
|
524
|
+
|
|
525
|
+
mayLeave = true;
|
|
526
|
+
waitableSets = new RepTable();
|
|
527
|
+
waitables = new RepTable();
|
|
528
|
+
|
|
529
|
+
#parkedTasks = new Map();
|
|
530
|
+
|
|
531
|
+
callingSyncImport(val) {
|
|
532
|
+
if (val === undefined) { return this.#callingAsyncImport; }
|
|
533
|
+
if (typeof val !== 'boolean') { throw new TypeError('invalid setting for async import'); }
|
|
534
|
+
const prev = this.#callingAsyncImport;
|
|
535
|
+
this.#callingAsyncImport = val;
|
|
536
|
+
if (prev === true && this.#callingAsyncImport === false) {
|
|
537
|
+
this.#notifySyncImportEnd();
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
#notifySyncImportEnd() {
|
|
542
|
+
const existing = this.#syncImportWait;
|
|
543
|
+
this.#syncImportWait = Promise.withResolvers();
|
|
544
|
+
existing.resolve();
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
async waitForSyncImportCallEnd() {
|
|
548
|
+
await this.#syncImportWait.promise;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
parkTaskOnAwaitable(args) {
|
|
552
|
+
if (!args.awaitable) { throw new TypeError('missing awaitable when trying to park'); }
|
|
553
|
+
if (!args.task) { throw new TypeError('missing task when trying to park'); }
|
|
554
|
+
const { awaitable, task } = args;
|
|
555
|
+
|
|
556
|
+
let taskList = this.#parkedTasks.get(awaitable.id());
|
|
557
|
+
if (!taskList) {
|
|
558
|
+
taskList = [];
|
|
559
|
+
this.#parkedTasks.set(awaitable.id(), taskList);
|
|
560
|
+
}
|
|
561
|
+
taskList.push(task);
|
|
562
|
+
|
|
563
|
+
this.wakeNextTaskForAwaitable(awaitable);
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
wakeNextTaskForAwaitable(awaitable) {
|
|
567
|
+
if (!awaitable) { throw new TypeError('missing awaitable when waking next task'); }
|
|
568
|
+
const awaitableID = awaitable.id();
|
|
569
|
+
|
|
570
|
+
const taskList = this.#parkedTasks.get(awaitableID);
|
|
571
|
+
if (!taskList || taskList.length === 0) {
|
|
572
|
+
_debugLog('[ComponentAsyncState] no tasks waiting for awaitable', { awaitableID: awaitable.id() });
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
let task = taskList.shift(); // todo(perf)
|
|
577
|
+
if (!task) { throw new Error('no task in parked list despite previous check'); }
|
|
578
|
+
|
|
579
|
+
if (!task.awaitableResume) {
|
|
580
|
+
throw new Error('task ready due to awaitable is missing resume', { taskID: task.id(), awaitableID });
|
|
581
|
+
}
|
|
582
|
+
task.awaitableResume();
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
async exclusiveLock() { // TODO: use atomics
|
|
586
|
+
if (this.#lock === null) {
|
|
587
|
+
this.#lock = { ticket: 0n };
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
// Take a ticket for the next valid usage
|
|
591
|
+
const ticket = ++this.#lock.ticket;
|
|
592
|
+
|
|
593
|
+
_debugLog('[ComponentAsyncState#exclusiveLock()] locking', {
|
|
594
|
+
currentTicket: ticket - 1n,
|
|
595
|
+
ticket
|
|
596
|
+
});
|
|
597
|
+
|
|
598
|
+
// If there is an active promise, then wait for it
|
|
599
|
+
let finishedTicket;
|
|
600
|
+
while (this.#lock.promise) {
|
|
601
|
+
finishedTicket = await this.#lock.promise;
|
|
602
|
+
if (finishedTicket === ticket - 1n) { break; }
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
const { promise, resolve } = Promise.withResolvers();
|
|
606
|
+
this.#lock = {
|
|
607
|
+
ticket,
|
|
608
|
+
promise,
|
|
609
|
+
resolve,
|
|
610
|
+
};
|
|
611
|
+
|
|
612
|
+
return this.#lock.promise;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
exclusiveRelease() {
|
|
616
|
+
_debugLog('[ComponentAsyncState#exclusiveRelease()] releasing', {
|
|
617
|
+
currentTicket: this.#lock === null ? 'none' : this.#lock.ticket,
|
|
618
|
+
});
|
|
619
|
+
|
|
620
|
+
if (this.#lock === null) { return; }
|
|
621
|
+
|
|
622
|
+
const existingLock = this.#lock;
|
|
623
|
+
this.#lock = null;
|
|
624
|
+
existingLock.resolve(existingLock.ticket);
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
isExclusivelyLocked() { return this.#lock !== null; }
|
|
628
|
+
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
function prepareCall(memoryIdx) {
|
|
632
|
+
_debugLog('[prepareCall()] args', { memoryIdx });
|
|
633
|
+
|
|
634
|
+
const taskMeta = getCurrentTask(ASYNC_CURRENT_COMPONENT_IDXS.at(-1), ASYNC_CURRENT_TASK_IDS.at(-1));
|
|
635
|
+
if (!taskMeta) { throw new Error('invalid/missing current async task meta during prepare call'); }
|
|
636
|
+
|
|
637
|
+
const task = taskMeta.task;
|
|
638
|
+
if (!task) { throw new Error('unexpectedly missing task in task meta during prepare call'); }
|
|
639
|
+
|
|
640
|
+
const state = getOrCreateAsyncState(task.componentIdx());
|
|
641
|
+
if (!state) {
|
|
642
|
+
throw new Error('invalid/missing async state for component instance [' + componentInstanceID + ']');
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
const subtask = task.createSubtask({
|
|
646
|
+
memoryIdx,
|
|
647
|
+
});
|
|
648
|
+
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
function asyncStartCall(callbackIdx, postReturnIdx) {
|
|
652
|
+
_debugLog('[asyncStartCall()] args', { callbackIdx, postReturnIdx });
|
|
653
|
+
|
|
654
|
+
const taskMeta = getCurrentTask(ASYNC_CURRENT_COMPONENT_IDXS.at(-1), ASYNC_CURRENT_TASK_IDS.at(-1));
|
|
655
|
+
if (!taskMeta) { throw new Error('invalid/missing current async task meta during prepare call'); }
|
|
656
|
+
|
|
657
|
+
const task = taskMeta.task;
|
|
658
|
+
if (!task) { throw new Error('unexpectedly missing task in task meta during prepare call'); }
|
|
659
|
+
|
|
660
|
+
const subtask = task.currentSubtask();
|
|
661
|
+
if (!subtask) { throw new Error('invalid/missing subtask during async start call'); }
|
|
662
|
+
|
|
663
|
+
return Number(subtask.waitableRep()) << 4 | subtask.getStateNumber();
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
function syncStartCall(callbackIdx) {
|
|
667
|
+
_debugLog('[syncStartCall()] args', { callbackIdx });
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
if (!Promise.withResolvers) {
|
|
671
|
+
Promise.withResolvers = () => {
|
|
672
|
+
let resolve;
|
|
673
|
+
let reject;
|
|
674
|
+
const promise = new Promise((res, rej) => {
|
|
675
|
+
resolve = res;
|
|
676
|
+
reject = rej;
|
|
677
|
+
});
|
|
678
|
+
return { promise, resolve, reject };
|
|
679
|
+
};
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
const _debugLog = (...args) => {
|
|
683
|
+
if (!globalThis?.process?.env?.JCO_DEBUG) { return; }
|
|
684
|
+
console.debug(...args);
|
|
685
|
+
}
|
|
686
|
+
const ASYNC_DETERMINISM = 'random';
|
|
687
|
+
const _coinFlip = () => { return Math.random() > 0.5; };
|
|
688
|
+
const I32_MAX = 2_147_483_647;
|
|
689
|
+
const I32_MIN = -2_147_483_648;
|
|
690
|
+
const _typeCheckValidI32 = (n) => typeof n === 'number' && n >= I32_MIN && n <= I32_MAX;
|
|
691
|
+
|
|
692
|
+
const isNode = typeof process !== 'undefined' && process.versions && process.versions.node;
|
|
693
|
+
let _fs;
|
|
694
|
+
async function fetchCompile (url) {
|
|
695
|
+
if (isNode) {
|
|
696
|
+
_fs = _fs || await import('node:fs/promises');
|
|
697
|
+
return WebAssembly.compile(await _fs.readFile(url));
|
|
698
|
+
}
|
|
699
|
+
return fetch(url).then(WebAssembly.compileStreaming);
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
const symbolCabiDispose = Symbol.for('cabiDispose');
|
|
703
|
+
|
|
704
|
+
const symbolRscHandle = Symbol('handle');
|
|
705
|
+
|
|
706
|
+
const symbolRscRep = Symbol.for('cabiRep');
|
|
707
|
+
|
|
708
|
+
const symbolDispose = Symbol.dispose || Symbol.for('dispose');
|
|
709
|
+
|
|
710
|
+
const handleTables = [];
|
|
711
|
+
|
|
712
|
+
function getErrorPayload(e) {
|
|
713
|
+
if (e && hasOwnProperty.call(e, 'payload')) return e.payload;
|
|
714
|
+
if (e instanceof Error) throw e;
|
|
715
|
+
return e;
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
class RepTable {
|
|
719
|
+
#data = [0, null];
|
|
720
|
+
|
|
721
|
+
insert(val) {
|
|
722
|
+
_debugLog('[RepTable#insert()] args', { val });
|
|
723
|
+
const freeIdx = this.#data[0];
|
|
724
|
+
if (freeIdx === 0) {
|
|
725
|
+
this.#data.push(val);
|
|
726
|
+
this.#data.push(null);
|
|
727
|
+
return (this.#data.length >> 1) - 1;
|
|
728
|
+
}
|
|
729
|
+
this.#data[0] = this.#data[freeIdx << 1];
|
|
730
|
+
const placementIdx = freeIdx << 1;
|
|
731
|
+
this.#data[placementIdx] = val;
|
|
732
|
+
this.#data[placementIdx + 1] = null;
|
|
733
|
+
return freeIdx;
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
get(rep) {
|
|
737
|
+
_debugLog('[RepTable#get()] args', { rep });
|
|
738
|
+
const baseIdx = rep << 1;
|
|
739
|
+
const val = this.#data[baseIdx];
|
|
740
|
+
return val;
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
contains(rep) {
|
|
744
|
+
_debugLog('[RepTable#contains()] args', { rep });
|
|
745
|
+
const baseIdx = rep << 1;
|
|
746
|
+
return !!this.#data[baseIdx];
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
remove(rep) {
|
|
750
|
+
_debugLog('[RepTable#remove()] args', { rep });
|
|
751
|
+
if (this.#data.length === 2) { throw new Error('invalid'); }
|
|
752
|
+
|
|
753
|
+
const baseIdx = rep << 1;
|
|
754
|
+
const val = this.#data[baseIdx];
|
|
755
|
+
if (val === 0) { throw new Error('invalid resource rep (cannot be 0)'); }
|
|
756
|
+
|
|
757
|
+
this.#data[baseIdx] = this.#data[0];
|
|
758
|
+
this.#data[0] = rep;
|
|
759
|
+
|
|
760
|
+
return val;
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
clear() {
|
|
764
|
+
_debugLog('[RepTable#clear()] args', { rep });
|
|
765
|
+
this.#data = [0, null];
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
function throwInvalidBool() {
|
|
770
|
+
throw new TypeError('invalid variant discriminant for bool');
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
const hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
774
|
+
|
|
775
|
+
|
|
776
|
+
if (!getCoreModule) getCoreModule = (name) => fetchCompile(new URL(`./${name}`, import.meta.url));
|
|
777
|
+
const module0 = getCoreModule('vercel_python_analysis.core.wasm');
|
|
778
|
+
const module1 = getCoreModule('vercel_python_analysis.core2.wasm');
|
|
779
|
+
const module2 = getCoreModule('vercel_python_analysis.core3.wasm');
|
|
780
|
+
|
|
781
|
+
const { getEnvironment } = imports['wasi:cli/environment'];
|
|
782
|
+
const { exit } = imports['wasi:cli/exit'];
|
|
783
|
+
const { getStderr } = imports['wasi:cli/stderr'];
|
|
784
|
+
const { Error: Error$1 } = imports['wasi:io/error'];
|
|
785
|
+
const { OutputStream } = imports['wasi:io/streams'];
|
|
786
|
+
let gen = (function* _initGenerator () {
|
|
787
|
+
let exports0;
|
|
788
|
+
const handleTable1 = [T_FLAG, 0];
|
|
789
|
+
const captureTable1= new Map();
|
|
790
|
+
let captureCnt1 = 0;
|
|
791
|
+
handleTables[1] = handleTable1;
|
|
792
|
+
|
|
793
|
+
function trampoline1() {
|
|
794
|
+
_debugLog('[iface="wasi:cli/stderr@0.2.6", function="get-stderr"] [Instruction::CallInterface] (async? sync, @ enter)');
|
|
795
|
+
const _interface_call_currentTaskID = startCurrentTask(0, false, 'get-stderr');
|
|
796
|
+
const ret = getStderr();
|
|
797
|
+
_debugLog('[iface="wasi:cli/stderr@0.2.6", function="get-stderr"] [Instruction::CallInterface] (sync, @ post-call)');
|
|
798
|
+
endCurrentTask(0);
|
|
799
|
+
if (!(ret instanceof OutputStream)) {
|
|
800
|
+
throw new TypeError('Resource error: Not a valid "OutputStream" resource.');
|
|
801
|
+
}
|
|
802
|
+
var handle0 = ret[symbolRscHandle];
|
|
803
|
+
if (!handle0) {
|
|
804
|
+
const rep = ret[symbolRscRep] || ++captureCnt1;
|
|
805
|
+
captureTable1.set(rep, ret);
|
|
806
|
+
handle0 = rscTableCreateOwn(handleTable1, rep);
|
|
807
|
+
}
|
|
808
|
+
_debugLog('[iface="wasi:cli/stderr@0.2.6", function="get-stderr"][Instruction::Return]', {
|
|
809
|
+
funcName: 'get-stderr',
|
|
810
|
+
paramCount: 1,
|
|
811
|
+
async: false,
|
|
812
|
+
postReturn: false
|
|
813
|
+
});
|
|
814
|
+
return handle0;
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
|
|
818
|
+
function trampoline3(arg0) {
|
|
819
|
+
let variant0;
|
|
820
|
+
switch (arg0) {
|
|
821
|
+
case 0: {
|
|
822
|
+
variant0= {
|
|
823
|
+
tag: 'ok',
|
|
824
|
+
val: undefined
|
|
825
|
+
};
|
|
826
|
+
break;
|
|
827
|
+
}
|
|
828
|
+
case 1: {
|
|
829
|
+
variant0= {
|
|
830
|
+
tag: 'err',
|
|
831
|
+
val: undefined
|
|
832
|
+
};
|
|
833
|
+
break;
|
|
834
|
+
}
|
|
835
|
+
default: {
|
|
836
|
+
throw new TypeError('invalid variant discriminant for expected');
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
_debugLog('[iface="wasi:cli/exit@0.2.6", function="exit"] [Instruction::CallInterface] (async? sync, @ enter)');
|
|
840
|
+
const _interface_call_currentTaskID = startCurrentTask(0, false, 'exit');
|
|
841
|
+
exit(variant0);
|
|
842
|
+
_debugLog('[iface="wasi:cli/exit@0.2.6", function="exit"] [Instruction::CallInterface] (sync, @ post-call)');
|
|
843
|
+
endCurrentTask(0);
|
|
844
|
+
_debugLog('[iface="wasi:cli/exit@0.2.6", function="exit"][Instruction::Return]', {
|
|
845
|
+
funcName: 'exit',
|
|
846
|
+
paramCount: 0,
|
|
847
|
+
async: false,
|
|
848
|
+
postReturn: false
|
|
849
|
+
});
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
let exports1;
|
|
853
|
+
let memory0;
|
|
854
|
+
let realloc0;
|
|
855
|
+
const handleTable0 = [T_FLAG, 0];
|
|
856
|
+
const captureTable0= new Map();
|
|
857
|
+
let captureCnt0 = 0;
|
|
858
|
+
handleTables[0] = handleTable0;
|
|
859
|
+
|
|
860
|
+
function trampoline4(arg0, arg1, arg2, arg3) {
|
|
861
|
+
var handle1 = arg0;
|
|
862
|
+
var rep2 = handleTable1[(handle1 << 1) + 1] & ~T_FLAG;
|
|
863
|
+
var rsc0 = captureTable1.get(rep2);
|
|
864
|
+
if (!rsc0) {
|
|
865
|
+
rsc0 = Object.create(OutputStream.prototype);
|
|
866
|
+
Object.defineProperty(rsc0, symbolRscHandle, { writable: true, value: handle1});
|
|
867
|
+
Object.defineProperty(rsc0, symbolRscRep, { writable: true, value: rep2});
|
|
868
|
+
}
|
|
869
|
+
curResourceBorrows.push(rsc0);
|
|
870
|
+
var ptr3 = arg1;
|
|
871
|
+
var len3 = arg2;
|
|
872
|
+
var result3 = new Uint8Array(memory0.buffer.slice(ptr3, ptr3 + len3 * 1));
|
|
873
|
+
_debugLog('[iface="wasi:io/streams@0.2.6", function="[method]output-stream.blocking-write-and-flush"] [Instruction::CallInterface] (async? sync, @ enter)');
|
|
874
|
+
const _interface_call_currentTaskID = startCurrentTask(0, false, '[method]output-stream.blocking-write-and-flush');
|
|
875
|
+
let ret;
|
|
876
|
+
try {
|
|
877
|
+
ret = { tag: 'ok', val: rsc0.blockingWriteAndFlush(result3)};
|
|
878
|
+
} catch (e) {
|
|
879
|
+
ret = { tag: 'err', val: getErrorPayload(e) };
|
|
880
|
+
}
|
|
881
|
+
_debugLog('[iface="wasi:io/streams@0.2.6", function="[method]output-stream.blocking-write-and-flush"] [Instruction::CallInterface] (sync, @ post-call)');
|
|
882
|
+
for (const rsc of curResourceBorrows) {
|
|
883
|
+
rsc[symbolRscHandle] = undefined;
|
|
884
|
+
}
|
|
885
|
+
curResourceBorrows = [];
|
|
886
|
+
endCurrentTask(0);
|
|
887
|
+
var variant6 = ret;
|
|
888
|
+
switch (variant6.tag) {
|
|
889
|
+
case 'ok': {
|
|
890
|
+
const e = variant6.val;
|
|
891
|
+
dataView(memory0).setInt8(arg3 + 0, 0, true);
|
|
892
|
+
break;
|
|
893
|
+
}
|
|
894
|
+
case 'err': {
|
|
895
|
+
const e = variant6.val;
|
|
896
|
+
dataView(memory0).setInt8(arg3 + 0, 1, true);
|
|
897
|
+
var variant5 = e;
|
|
898
|
+
switch (variant5.tag) {
|
|
899
|
+
case 'last-operation-failed': {
|
|
900
|
+
const e = variant5.val;
|
|
901
|
+
dataView(memory0).setInt8(arg3 + 4, 0, true);
|
|
902
|
+
if (!(e instanceof Error$1)) {
|
|
903
|
+
throw new TypeError('Resource error: Not a valid "Error" resource.');
|
|
904
|
+
}
|
|
905
|
+
var handle4 = e[symbolRscHandle];
|
|
906
|
+
if (!handle4) {
|
|
907
|
+
const rep = e[symbolRscRep] || ++captureCnt0;
|
|
908
|
+
captureTable0.set(rep, e);
|
|
909
|
+
handle4 = rscTableCreateOwn(handleTable0, rep);
|
|
910
|
+
}
|
|
911
|
+
dataView(memory0).setInt32(arg3 + 8, handle4, true);
|
|
912
|
+
break;
|
|
913
|
+
}
|
|
914
|
+
case 'closed': {
|
|
915
|
+
dataView(memory0).setInt8(arg3 + 4, 1, true);
|
|
916
|
+
break;
|
|
917
|
+
}
|
|
918
|
+
default: {
|
|
919
|
+
throw new TypeError(`invalid variant tag value \`${JSON.stringify(variant5.tag)}\` (received \`${variant5}\`) specified for \`StreamError\``);
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
break;
|
|
923
|
+
}
|
|
924
|
+
default: {
|
|
925
|
+
throw new TypeError('invalid variant specified for result');
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
_debugLog('[iface="wasi:io/streams@0.2.6", function="[method]output-stream.blocking-write-and-flush"][Instruction::Return]', {
|
|
929
|
+
funcName: '[method]output-stream.blocking-write-and-flush',
|
|
930
|
+
paramCount: 0,
|
|
931
|
+
async: false,
|
|
932
|
+
postReturn: false
|
|
933
|
+
});
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
|
|
937
|
+
function trampoline5(arg0, arg1) {
|
|
938
|
+
var handle1 = arg0;
|
|
939
|
+
var rep2 = handleTable0[(handle1 << 1) + 1] & ~T_FLAG;
|
|
940
|
+
var rsc0 = captureTable0.get(rep2);
|
|
941
|
+
if (!rsc0) {
|
|
942
|
+
rsc0 = Object.create(Error$1.prototype);
|
|
943
|
+
Object.defineProperty(rsc0, symbolRscHandle, { writable: true, value: handle1});
|
|
944
|
+
Object.defineProperty(rsc0, symbolRscRep, { writable: true, value: rep2});
|
|
945
|
+
}
|
|
946
|
+
curResourceBorrows.push(rsc0);
|
|
947
|
+
_debugLog('[iface="wasi:io/error@0.2.6", function="[method]error.to-debug-string"] [Instruction::CallInterface] (async? sync, @ enter)');
|
|
948
|
+
const _interface_call_currentTaskID = startCurrentTask(0, false, '[method]error.to-debug-string');
|
|
949
|
+
const ret = rsc0.toDebugString();
|
|
950
|
+
_debugLog('[iface="wasi:io/error@0.2.6", function="[method]error.to-debug-string"] [Instruction::CallInterface] (sync, @ post-call)');
|
|
951
|
+
for (const rsc of curResourceBorrows) {
|
|
952
|
+
rsc[symbolRscHandle] = undefined;
|
|
953
|
+
}
|
|
954
|
+
curResourceBorrows = [];
|
|
955
|
+
endCurrentTask(0);
|
|
956
|
+
var ptr3 = utf8Encode(ret, realloc0, memory0);
|
|
957
|
+
var len3 = utf8EncodedLen;
|
|
958
|
+
dataView(memory0).setUint32(arg1 + 4, len3, true);
|
|
959
|
+
dataView(memory0).setUint32(arg1 + 0, ptr3, true);
|
|
960
|
+
_debugLog('[iface="wasi:io/error@0.2.6", function="[method]error.to-debug-string"][Instruction::Return]', {
|
|
961
|
+
funcName: '[method]error.to-debug-string',
|
|
962
|
+
paramCount: 0,
|
|
963
|
+
async: false,
|
|
964
|
+
postReturn: false
|
|
965
|
+
});
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
|
|
969
|
+
function trampoline6(arg0) {
|
|
970
|
+
_debugLog('[iface="wasi:cli/environment@0.2.6", function="get-environment"] [Instruction::CallInterface] (async? sync, @ enter)');
|
|
971
|
+
const _interface_call_currentTaskID = startCurrentTask(0, false, 'get-environment');
|
|
972
|
+
const ret = getEnvironment();
|
|
973
|
+
_debugLog('[iface="wasi:cli/environment@0.2.6", function="get-environment"] [Instruction::CallInterface] (sync, @ post-call)');
|
|
974
|
+
endCurrentTask(0);
|
|
975
|
+
var vec3 = ret;
|
|
976
|
+
var len3 = vec3.length;
|
|
977
|
+
var result3 = realloc0(0, 0, 4, len3 * 16);
|
|
978
|
+
for (let i = 0; i < vec3.length; i++) {
|
|
979
|
+
const e = vec3[i];
|
|
980
|
+
const base = result3 + i * 16;var [tuple0_0, tuple0_1] = e;
|
|
981
|
+
var ptr1 = utf8Encode(tuple0_0, realloc0, memory0);
|
|
982
|
+
var len1 = utf8EncodedLen;
|
|
983
|
+
dataView(memory0).setUint32(base + 4, len1, true);
|
|
984
|
+
dataView(memory0).setUint32(base + 0, ptr1, true);
|
|
985
|
+
var ptr2 = utf8Encode(tuple0_1, realloc0, memory0);
|
|
986
|
+
var len2 = utf8EncodedLen;
|
|
987
|
+
dataView(memory0).setUint32(base + 12, len2, true);
|
|
988
|
+
dataView(memory0).setUint32(base + 8, ptr2, true);
|
|
989
|
+
}
|
|
990
|
+
dataView(memory0).setUint32(arg0 + 4, len3, true);
|
|
991
|
+
dataView(memory0).setUint32(arg0 + 0, result3, true);
|
|
992
|
+
_debugLog('[iface="wasi:cli/environment@0.2.6", function="get-environment"][Instruction::Return]', {
|
|
993
|
+
funcName: 'get-environment',
|
|
994
|
+
paramCount: 0,
|
|
995
|
+
async: false,
|
|
996
|
+
postReturn: false
|
|
997
|
+
});
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
let exports2;
|
|
1001
|
+
function trampoline0(handle) {
|
|
1002
|
+
const handleEntry = rscTableRemove(handleTable1, handle);
|
|
1003
|
+
if (handleEntry.own) {
|
|
1004
|
+
|
|
1005
|
+
const rsc = captureTable1.get(handleEntry.rep);
|
|
1006
|
+
if (rsc) {
|
|
1007
|
+
if (rsc[symbolDispose]) rsc[symbolDispose]();
|
|
1008
|
+
captureTable1.delete(handleEntry.rep);
|
|
1009
|
+
} else if (OutputStream[symbolCabiDispose]) {
|
|
1010
|
+
OutputStream[symbolCabiDispose](handleEntry.rep);
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
function trampoline2(handle) {
|
|
1015
|
+
const handleEntry = rscTableRemove(handleTable0, handle);
|
|
1016
|
+
if (handleEntry.own) {
|
|
1017
|
+
|
|
1018
|
+
const rsc = captureTable0.get(handleEntry.rep);
|
|
1019
|
+
if (rsc) {
|
|
1020
|
+
if (rsc[symbolDispose]) rsc[symbolDispose]();
|
|
1021
|
+
captureTable0.delete(handleEntry.rep);
|
|
1022
|
+
} else if (Error$1[symbolCabiDispose]) {
|
|
1023
|
+
Error$1[symbolCabiDispose](handleEntry.rep);
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
Promise.all([module0, module1, module2]).catch(() => {});
|
|
1028
|
+
({ exports: exports0 } = yield instantiateCore(yield module1));
|
|
1029
|
+
({ exports: exports1 } = yield instantiateCore(yield module0, {
|
|
1030
|
+
'wasi:cli/environment@0.2.0': {
|
|
1031
|
+
'get-environment': exports0['2'],
|
|
1032
|
+
},
|
|
1033
|
+
'wasi:cli/exit@0.2.0': {
|
|
1034
|
+
exit: trampoline3,
|
|
1035
|
+
},
|
|
1036
|
+
'wasi:cli/stderr@0.2.4': {
|
|
1037
|
+
'get-stderr': trampoline1,
|
|
1038
|
+
},
|
|
1039
|
+
'wasi:io/error@0.2.4': {
|
|
1040
|
+
'[method]error.to-debug-string': exports0['1'],
|
|
1041
|
+
'[resource-drop]error': trampoline2,
|
|
1042
|
+
},
|
|
1043
|
+
'wasi:io/streams@0.2.4': {
|
|
1044
|
+
'[method]output-stream.blocking-write-and-flush': exports0['0'],
|
|
1045
|
+
'[resource-drop]output-stream': trampoline0,
|
|
1046
|
+
},
|
|
1047
|
+
}));
|
|
1048
|
+
memory0 = exports1.memory;
|
|
1049
|
+
realloc0 = exports1.cabi_realloc;
|
|
1050
|
+
({ exports: exports2 } = yield instantiateCore(yield module2, {
|
|
1051
|
+
'': {
|
|
1052
|
+
$imports: exports0.$imports,
|
|
1053
|
+
'0': trampoline4,
|
|
1054
|
+
'1': trampoline5,
|
|
1055
|
+
'2': trampoline6,
|
|
1056
|
+
},
|
|
1057
|
+
}));
|
|
1058
|
+
let exports1ContainsAppOrHandler;
|
|
1059
|
+
|
|
1060
|
+
function containsAppOrHandler(arg0) {
|
|
1061
|
+
var ptr0 = utf8Encode(arg0, realloc0, memory0);
|
|
1062
|
+
var len0 = utf8EncodedLen;
|
|
1063
|
+
_debugLog('[iface="contains-app-or-handler", function="contains-app-or-handler"][Instruction::CallWasm] enter', {
|
|
1064
|
+
funcName: 'contains-app-or-handler',
|
|
1065
|
+
paramCount: 2,
|
|
1066
|
+
async: false,
|
|
1067
|
+
postReturn: false,
|
|
1068
|
+
});
|
|
1069
|
+
const _wasm_call_currentTaskID = startCurrentTask(0, false, 'exports1ContainsAppOrHandler');
|
|
1070
|
+
const ret = exports1ContainsAppOrHandler(ptr0, len0);
|
|
1071
|
+
endCurrentTask(0);
|
|
1072
|
+
var bool1 = ret;
|
|
1073
|
+
_debugLog('[iface="contains-app-or-handler", function="contains-app-or-handler"][Instruction::Return]', {
|
|
1074
|
+
funcName: 'contains-app-or-handler',
|
|
1075
|
+
paramCount: 1,
|
|
1076
|
+
async: false,
|
|
1077
|
+
postReturn: false
|
|
1078
|
+
});
|
|
1079
|
+
return bool1 == 0 ? false : (bool1 == 1 ? true : throwInvalidBool());
|
|
1080
|
+
}
|
|
1081
|
+
exports1ContainsAppOrHandler = exports1['contains-app-or-handler'];
|
|
1082
|
+
|
|
1083
|
+
return { containsAppOrHandler, };
|
|
1084
|
+
})();
|
|
1085
|
+
let promise, resolve, reject;
|
|
1086
|
+
function runNext (value) {
|
|
1087
|
+
try {
|
|
1088
|
+
let done;
|
|
1089
|
+
do {
|
|
1090
|
+
({ value, done } = gen.next(value));
|
|
1091
|
+
} while (!(value instanceof Promise) && !done);
|
|
1092
|
+
if (done) {
|
|
1093
|
+
if (resolve) return resolve(value);
|
|
1094
|
+
else return value;
|
|
1095
|
+
}
|
|
1096
|
+
if (!promise) promise = new Promise((_resolve, _reject) => (resolve = _resolve, reject = _reject));
|
|
1097
|
+
value.then(nextVal => done ? resolve() : runNext(nextVal), reject);
|
|
1098
|
+
}
|
|
1099
|
+
catch (e) {
|
|
1100
|
+
if (reject) reject(e);
|
|
1101
|
+
else throw e;
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
const maybeSyncReturn = runNext(null);
|
|
1105
|
+
return promise || maybeSyncReturn;
|
|
1106
|
+
}
|