fix(wasm): #1037 — String.fromCharCode returned undefined on --target web - #1043
Merged
Conversation
…et web `Expr::StringFromCharCode`/`StringFromCodePoint` in `crates/perry-codegen-wasm/src/emit.rs` emitted a `mem_call` to the bridge name `string_from_char_code` (snake_case). The runtime's `__memDispatch` table only registers `string_fromCharCode` (camelCase), so the call fell through to `__classDispatch(code, "string_from_char_code", [])`, which returned undefined. `s += String.fromCharCode(0)` then appended the string `"undefined"` (9 chars) per iteration — matching the 16-iter repro of length 144. Fixed both arms to emit the camelCase bridge name. Regression test in `tests/wasm/20_string_from_char_code.ts` covers `+=`, `=` + `+`, 16-iter and 4-iter shapes, plus `fromCodePoint`. Bundled fix: the wasm test runner at `tests/wasm/run_wasm_tests.sh` was failing every test because `wasm_runtime.js` injects a `<style>` tag at module load (`document.head.appendChild`); added a minimal DOM polyfill so the harness can execute the wasm in Node again. Same-suite baseline (pre-fix, my test removed) and post-fix: identical 7 pre-existing failures, none caused by this change.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Expr::StringFromCharCodeandExpr::StringFromCodePointin the WASM emitter were callingmem_callwith the bridge namestring_from_char_code(snake_case). The runtime's__memDispatchtable only hasstring_fromCharCode(camelCase). The mismatch mademem_callfall through to__classDispatch(code, "string_from_char_code", []), which returned undefined.s += String.fromCharCode(0)then concatenated"undefined"(9 chars) per iteration — Ralph's 16-iter repro produced length 144 = 16 × 9.(The "9× growth ratio matches handle-ID digit count" hypothesis from the issue comment was a coincidence:
'undefined'.lengthis 9.)Fix
Two-character edit per arm —
string_from_char_code→string_fromCharCode. Same bridge dispatches bothString.fromCharCodeandString.fromCodePoint(the StringFromCodePoint arm is currently a BMP-only stub aliased to fromCharCode).Variant matrix (Ralph's table, all on
--target wasm)result += 'x'(literal)result += String.fromCharCode(0)result = result + String.fromCharCode(0)result += String.fromCharCode(0)String.fromCodePoint(65)Bundled harness fix
tests/wasm/run_wasm_tests.shwas failing every test withdocument is not defined—wasm_runtime.jsinjects a<style>element at module load (document.head.appendChild) since the web-UI ship. Added a minimaldocument/windowpolyfill to the Node eval block in the runner. Local-only — CI doesn't execute this script.Same-suite results (binary built from origin/main, my new test removed):
12 pass, 7 fail (
05_objects_arrays,10_higher_order,11_map_set_json,14_regex_date,17_class_field_splice,18_module_splice,19_ffi_imports).With fix applied: identical 7 pre-existing failures + 1 new passing test (
20_string_from_char_code). No regressions.Out of scope (worth a follow-up)
The audit found seven other bridge names with the same snake_case/camelCase mismatch, all in the
_ => Handle instance method calls on objectscatch-all inExpr::NativeMethodCall(emit.rs:5588..5840):string_char_at,string_index_of,string_to_lower_case,string_to_upper_case,string_starts_with,string_ends_with,string_pad_start,string_pad_end. They are unreachable for normalstr.charAt(i)etc. — those hitemit_method_call(emit.rs:4081, camelCase, correct) — so the bugs are latent. Not touching them here to keep the PR focused on the user-visible bug from #1037; happy to sweep in a follow-up.Test plan
cd tests/wasm && ../../target/release/perry compile 20_string_from_char_code.ts --target wasm -o /tmp/t.htmlthen run via the harness →len: 16✓PERRY_ALLOW_PERRY_FEATURES=1 ./tests/wasm/run_wasm_tests.sh→ no new failures vs. origin/main baselinecargo build --release -p perrysucceeds,cargo test --release -p perry-codegen-wasmsucceeds@honeide/editorreproducer that the keyword-tokenizer no longer hangs (this PR fixes the underlying wasm runtime: post-parse hang —object_get_dynamicrepeats indefinitely with identical args after keyword tokenizer enters its outer loop #1037 mechanism; the editor exercises it viabuildBlockDepthString)Closes #1037.