Skip to content

Commit f1a364d

Browse files
vados-cosmonicgfxclaude
committed
fix(bindgen): bindgen runtime bugs
This commit contains runtime bugs reported by Wado compiler toolchain developers (see wado-lang/wado#714). While the original PR had a few changes that Jco isn't ready to take just yet, there are many that are absolutely right for inclusion: - waitable-set.wait missing suspending - waitable-set.wait invalid waitForEvent() call - missing intrinsic deps - lowerFlatVariant empty payload crash Co-Authored-By: FUJI Goro <g.psy.va@gmail.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent afd30ca commit f1a364d

File tree

5 files changed

+48
-19
lines changed

5 files changed

+48
-19
lines changed

crates/js-component-bindgen/src/intrinsics/lower.rs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -542,14 +542,17 @@ impl LowerIntrinsic {
542542
543543
ctx.resultPtr = originalPtr + payloadOffset32;
544544
545-
const payloadBytesWritten = lowerFn({{
546-
memory,
547-
realloc,
548-
vals: [val],
549-
storagePtr,
550-
storageLen,
551-
componentIdx,
552-
}});
545+
let payloadBytesWritten = 0;
546+
if (lowerFn) {{
547+
lowerFn({{
548+
memory,
549+
realloc,
550+
vals: [val],
551+
storagePtr,
552+
storageLen,
553+
componentIdx,
554+
}});
555+
}}
553556
let bytesWritten = payloadOffset + payloadBytesWritten;
554557
555558
const rem = ctx.storagePtr % align32;

crates/js-component-bindgen/src/intrinsics/mod.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1213,6 +1213,9 @@ pub fn render_intrinsics(args: RenderIntrinsicsArgs) -> Source {
12131213
if args
12141214
.intrinsics
12151215
.contains(&Intrinsic::Waitable(WaitableIntrinsic::WaitableSetPoll))
1216+
|| args
1217+
.intrinsics
1218+
.contains(&Intrinsic::Waitable(WaitableIntrinsic::WaitableSetWait))
12161219
{
12171220
args.intrinsics
12181221
.extend([&Intrinsic::Host(HostIntrinsic::StoreEventInComponentMemory)]);
@@ -1268,6 +1271,22 @@ pub fn render_intrinsics(args: RenderIntrinsicsArgs) -> Source {
12681271
]);
12691272
}
12701273

1274+
if args
1275+
.intrinsics
1276+
.contains(&Intrinsic::Lower(LowerIntrinsic::LowerFlatResult))
1277+
{
1278+
args.intrinsics
1279+
.insert(Intrinsic::Lower(LowerIntrinsic::LowerFlatVariant));
1280+
}
1281+
1282+
if args
1283+
.intrinsics
1284+
.contains(&Intrinsic::Lower(LowerIntrinsic::LowerFlatOption))
1285+
{
1286+
args.intrinsics
1287+
.insert(Intrinsic::Lower(LowerIntrinsic::LowerFlatVariant));
1288+
}
1289+
12711290
if args
12721291
.intrinsics
12731292
.contains(&Intrinsic::Lower(LowerIntrinsic::LowerFlatVariant))
@@ -1364,10 +1383,14 @@ pub fn render_intrinsics(args: RenderIntrinsicsArgs) -> Source {
13641383
if args
13651384
.intrinsics
13661385
.contains(&Intrinsic::AsyncStream(AsyncStreamIntrinsic::StreamWrite))
1386+
|| args
1387+
.intrinsics
1388+
.contains(&Intrinsic::AsyncStream(AsyncStreamIntrinsic::StreamRead))
13671389
{
13681390
args.intrinsics.extend([
13691391
&Intrinsic::GlobalBufferManager,
13701392
&Intrinsic::AsyncTask(AsyncTaskIntrinsic::AsyncBlockedConstant),
1393+
&Intrinsic::AsyncEventCodeEnum,
13711394
]);
13721395
}
13731396

crates/js-component-bindgen/src/intrinsics/p3/async_stream.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1140,7 +1140,7 @@ impl AsyncStreamIntrinsic {
11401140
r#"
11411141
class {host_stream_class_name} {{
11421142
#componentIdx;
1143-
#streamEndIdx;
1143+
#streamEndWaitableIdx;
11441144
#streamTableIdx;
11451145
11461146
#payloadLiftFn;
@@ -1162,24 +1162,26 @@ impl AsyncStreamIntrinsic {
11621162
if (!args.payloadLowerFn) {{ throw new TypeError("missing payload lower fn"); }}
11631163
this.#payloadLowerFn = args.payloadLowerFn;
11641164
1165-
if (args.streamEndIdx === undefined) {{ throw new Error("missing stream idx"); }}
1165+
if (args.streamEndWaitableIdx === undefined) {{ throw new Error("missing stream idx"); }}
11661166
if (args.streamTableIdx === undefined) {{ throw new Error("missing stream table idx"); }}
1167-
this.#streamEndIdx = args.streamEndIdx;
1167+
this.#streamEndWaitableIdx = args.streamEndWaitableIdx;
11681168
this.#streamTableIdx = args.streamTableIdx;
11691169
11701170
this.#isUnitStream = args.isUnitStream;
11711171
}}
11721172
1173+
setRep(r) {{ this.#rep = r; }}
1174+
11731175
createUserStream(args) {{
11741176
if (this.#userStream) {{ return this.#userStream; }}
11751177
if (this.#rep === null) {{ throw new Error("unexpectedly missing rep for host stream"); }}
11761178
11771179
const cstate = {get_or_create_async_state_fn}(this.#componentIdx);
11781180
if (!cstate) {{ throw new Error(`missing async state for component [${{this.#componentIdx}}]`); }}
11791181
1180-
const streamEnd = cstate.getStreamEnd({{ tableIdx: this.#streamTableIdx, streamEndIdx: this.#streamEndIdx }});
1182+
const streamEnd = cstate.getStreamEnd({{ tableIdx: this.#streamTableIdx, streamEndWaitableIdx: this.#streamEndWaitableIdx }});
11811183
if (!streamEnd) {{
1182-
throw new Error(`missing stream [${{this.#streamEndIdx}}] (table [${{this.#streamTableIdx}}], component [${{this.#componentIdx}}]`);
1184+
throw new Error(`missing stream [${{this.#streamEndWaitableIdx}}] (table [${{this.#streamTableIdx}}], component [${{this.#componentIdx}}]`);
11831185
}}
11841186
11851187
return new {external_stream_class}({{
@@ -1366,7 +1368,7 @@ impl AsyncStreamIntrinsic {
13661368
{debug_log_fn}('[{stream_new_from_lift_fn}()] args', {{ ctx }});
13671369
const {{
13681370
componentIdx,
1369-
streamEndIdx,
1371+
streamEndWaitableIdx,
13701372
streamTableIdx,
13711373
payloadLiftFn,
13721374
payloadTypeSize32,
@@ -1376,7 +1378,7 @@ impl AsyncStreamIntrinsic {
13761378
13771379
const stream = new {host_stream_class}({{
13781380
componentIdx,
1379-
streamEndIdx,
1381+
streamEndWaitableIdx,
13801382
streamTableIdx,
13811383
payloadLiftFn: payloadLiftFn,
13821384
payloadLowerFn: payloadLowerFn,

crates/js-component-bindgen/src/intrinsics/p3/waitable.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -392,8 +392,9 @@ impl WaitableIntrinsic {
392392
throw Error(`task component [${{task.componentIdx}}] !== executing component [${{componentIdx}}]`);
393393
}}
394394
395-
const event = await task.waitForEvent({{ waitableSetRep, isAsync }});
396-
return {store_event_in_component_memory_fn}(memory, task, event, resultPtr);
395+
const memory = getMemoryFn();
396+
const event = await task.waitUntil({{ waitableSetRep, readyFn: () => true, cancellable: false }});
397+
return {store_event_in_component_memory_fn}({{ memory, ptr: resultPtr, event }});
397398
}}
398399
"#));
399400
}

crates/js-component-bindgen/src/transpile_bindgen.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1202,12 +1202,12 @@ impl<'a> Instantiator<'a, '_> {
12021202
uwriteln!(
12031203
self.src.js,
12041204
r#"
1205-
const trampoline{i} = {waitable_set_wait_fn}.bind(null, {{
1205+
const trampoline{i} = new WebAssembly.Suspending({waitable_set_wait_fn}.bind(null, {{
12061206
componentIdx: {instance_idx},
12071207
isAsync: {async_},
12081208
memoryIdx: {memory_idx},
12091209
getMemoryFn: () => memory{memory_idx},
1210-
}});
1210+
}}));
12111211
"#,
12121212
);
12131213
}

0 commit comments

Comments
 (0)