Skip to content

Commit a57caa3

Browse files
authored
fix: prevent WASM out-of-bounds trap in concurrent generate calls (#111)
When multiple `icpBindgen` plugin instances run concurrently (e.g. several `.did` files processed during Vite's `buildStart`), the WASM `GenerateResul`t object could be held across await boundaries in `writeBindings()`. This was observed to cause intermittent `"Out of bounds memory access"` traps on the `service_ts` getter. Extract all strings from the WASM object synchronously immediately after `wasmGenerate()` and free it explicitly, so that `writeBindings` operates only on plain JS strings. Ref: #109
1 parent c7bc48a commit a57caa3

File tree

1 file changed

+24
-3
lines changed

1 file changed

+24
-3
lines changed

src/core/generate/index.ts

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { basename, resolve } from 'node:path';
22
import { prepareBinding } from './bindings.ts';
33
import { ensureDir, writeFileSafe } from './fs.ts';
4-
import { type WasmGenerateResult, wasmGenerate, wasmInit } from './rs.ts';
4+
import { wasmGenerate, wasmInit } from './rs.ts';
55

66
const DID_FILE_EXTENSION = '.did';
77

@@ -122,17 +122,38 @@ export async function generate(options: GenerateOptions) {
122122
},
123123
});
124124

125+
// Extract all strings from the WASM object synchronously before any async
126+
// work and free it explicitly. The GenerateResult is backed by WASM linear
127+
// memory and registered with a FinalizationRegistry whose cleanup timing
128+
// is engine-dependent. Holding the object across await boundaries has been
129+
// observed to cause "Out of bounds memory access" traps when multiple
130+
// generate() calls run concurrently (e.g. several Vite plugin instances).
131+
const bindings = {
132+
declarations_js: result.declarations_js,
133+
declarations_ts: result.declarations_ts,
134+
interface_ts: result.interface_ts,
135+
service_ts: result.service_ts,
136+
};
137+
result.free();
138+
125139
await writeBindings({
126-
bindings: result,
140+
bindings,
127141
outDir,
128142
outputFileName,
129143
output,
130144
force,
131145
});
132146
}
133147

148+
type Bindings = {
149+
declarations_js: string;
150+
declarations_ts: string;
151+
interface_ts: string;
152+
service_ts: string;
153+
};
154+
134155
type WriteBindingsOptions = {
135-
bindings: WasmGenerateResult;
156+
bindings: Bindings;
136157
outDir: string;
137158
outputFileName: string;
138159
output: GenerateOutputOptions;

0 commit comments

Comments
 (0)