@@ -40,7 +40,7 @@ const WASM_MODE = getWasmMode();
4040// GC array type (opaque reference)
4141type I16Array = object ;
4242
43- interface WasmExports {
43+ interface WasmExports extends WebAssembly . Exports {
4444 memory : WebAssembly . Memory ;
4545 utf8Count ( str : string ) : number ;
4646 utf8Encode ( str : string , offset : number ) : number ;
@@ -65,11 +65,7 @@ function base64ToBytes(base64: string): Uint8Array {
6565 return new Uint8Array ( Buffer . from ( base64 , "base64" ) ) ;
6666}
6767
68- function tryInitWasm ( ) : void {
69- if ( wasmInstance !== null || wasmInitError !== null ) {
70- return ; // Already initialized or failed
71- }
72-
68+ function tryInitializeWasmInstance ( ) : void {
7369 if ( WASM_MODE === "never" ) {
7470 wasmInitError = new Error ( "MSGPACK_WASM=never: wasm disabled" ) ;
7571 return ;
@@ -85,35 +81,28 @@ function tryInitWasm(): void {
8581 // Requires js-string builtins support (Node.js 24+ / Chrome 130+ / Firefox 134+)
8682 const module : WebAssembly . Module = new ( WebAssembly . Module as any ) ( bytes , { builtins : [ "js-string" ] } ) ;
8783 const instance = new WebAssembly . Instance ( module ) ;
88- wasmInstance = instance . exports as unknown as WasmExports ;
84+ wasmInstance = instance . exports as WasmExports ;
8985 } catch ( e ) {
9086 wasmInitError = e instanceof Error ? e : new Error ( String ( e ) ) ;
9187
9288 if ( WASM_MODE === "force" ) {
93- throw new Error ( `MSGPACK_WASM=force but wasm failed to load: ${ wasmInitError . message } ` ) ;
89+ throw new Error ( `MSGPACK_WASM=force but wasm failed to load: ${ wasmInitError . message } ` , { cause : wasmInitError } ) ;
9490 }
9591 }
9692}
9793
98- // Initialize on module load
99- tryInitWasm ( ) ;
94+ tryInitializeWasmInstance ( ) ;
10095
10196/**
10297 * Whether wasm is available and initialized.
10398 */
10499// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
105100export const WASM_AVAILABLE = wasmInstance !== null ;
106101
107- /**
108- * Get the wasm initialization error, if any.
109- */
110102export function getWasmError ( ) : Error | null {
111103 return wasmInitError ;
112104}
113105
114- /**
115- * Get the raw wasm exports for advanced usage.
116- */
117106export function getWasmExports ( ) : WasmExports | null {
118107 return wasmInstance ;
119108}
@@ -122,39 +111,32 @@ export function getWasmExports(): WasmExports | null {
122111 * Count UTF-8 byte length of a string.
123112 */
124113export function utf8CountWasm ( str : string ) : number {
125- if ( wasmInstance === null ) {
126- throw new Error ( "wasm not initialized" ) ;
127- }
128- return wasmInstance . utf8Count ( str ) ;
114+ return wasmInstance ! . utf8Count ( str ) ;
129115}
130116
131117/**
132118 * Encode string to UTF-8 bytes in the provided buffer.
133119 * Returns the number of bytes written.
134120 */
135121export function utf8EncodeWasm ( str : string , output : Uint8Array , outputOffset : number ) : number {
136- if ( wasmInstance === null ) {
137- throw new Error ( "wasm not initialized" ) ;
138- }
139-
140122 // Estimate max byte length without a full pass over the string.
141123 // Each UTF-16 code unit can produce at most 3 UTF-8 bytes (BMP chars).
142124 // Surrogate pairs (2 code units) produce 4 bytes, so 3 bytes/code unit is safe.
143125 const maxByteLength = str . length * 3 ;
144126
145127 // Ensure wasm memory is large enough
146128 const requiredPages = Math . ceil ( maxByteLength / 65536 ) ;
147- const currentPages = wasmInstance . memory . buffer . byteLength / 65536 ;
129+ const currentPages = wasmInstance ! . memory . buffer . byteLength / 65536 ;
148130
149131 if ( requiredPages > currentPages ) {
150- wasmInstance . memory . grow ( requiredPages - currentPages ) ;
132+ wasmInstance ! . memory . grow ( requiredPages - currentPages ) ;
151133 }
152134
153135 // Encode to wasm memory (uses intoCharCodeArray for bulk char extraction)
154- const bytesWritten = wasmInstance . utf8Encode ( str , 0 ) ;
136+ const bytesWritten = wasmInstance ! . utf8Encode ( str , 0 ) ;
155137
156138 // Copy from wasm memory to output buffer
157- const wasmBytes = new Uint8Array ( wasmInstance . memory . buffer , 0 , bytesWritten ) ;
139+ const wasmBytes = new Uint8Array ( wasmInstance ! . memory . buffer , 0 , bytesWritten ) ;
158140 output . set ( wasmBytes , outputOffset ) ;
159141
160142 return bytesWritten ;
@@ -165,33 +147,29 @@ export function utf8EncodeWasm(str: string, output: Uint8Array, outputOffset: nu
165147 * Uses GC arrays with fromCharCodeArray for efficient string creation.
166148 */
167149export function utf8DecodeWasm ( bytes : Uint8Array , inputOffset : number , byteLength : number ) : string {
168- if ( wasmInstance === null ) {
169- throw new Error ( "wasm not initialized" ) ;
170- }
171-
172150 // Handle empty input
173151 if ( byteLength === 0 ) {
174152 return "" ;
175153 }
176154
177155 // Ensure wasm memory is large enough for UTF-8 input
178156 const requiredPages = Math . ceil ( byteLength / 65536 ) ;
179- const currentPages = wasmInstance . memory . buffer . byteLength / 65536 ;
157+ const currentPages = wasmInstance ! . memory . buffer . byteLength / 65536 ;
180158
181159 if ( requiredPages > currentPages ) {
182- wasmInstance . memory . grow ( requiredPages - currentPages ) ;
160+ wasmInstance ! . memory . grow ( requiredPages - currentPages ) ;
183161 }
184162
185163 // Copy UTF-8 bytes to wasm linear memory at offset 0
186- const wasmBytes = new Uint8Array ( wasmInstance . memory . buffer , 0 , byteLength ) ;
164+ const wasmBytes = new Uint8Array ( wasmInstance ! . memory . buffer , 0 , byteLength ) ;
187165 wasmBytes . set ( bytes . subarray ( inputOffset , inputOffset + byteLength ) ) ;
188166
189167 // Allocate GC array for UTF-16 output (max size = byteLength for ASCII)
190- const arr = wasmInstance . allocArray ( byteLength ) ;
168+ const arr = wasmInstance ! . allocArray ( byteLength ) ;
191169
192170 // Decode UTF-8 to UTF-16 in GC array
193- const codeUnits = wasmInstance . utf8DecodeToArray ( byteLength , arr ) ;
171+ const codeUnits = wasmInstance ! . utf8DecodeToArray ( byteLength , arr ) ;
194172
195173 // Create string directly from GC array using fromCharCodeArray
196- return wasmInstance . arrayToString ( arr , 0 , codeUnits ) ;
174+ return wasmInstance ! . arrayToString ( arr , 0 , codeUnits ) ;
197175}
0 commit comments