Skip to content

fix(v8): accept UTF-8 labels and decode UTF-16LE - #6038

Closed
thisisanubhav wants to merge 1 commit into
clockworklabs:masterfrom
thisisanubhav:fix-5994-textdecoder
Closed

thisisanubhav wants to merge 1 commit into
clockworklabs:masterfrom
thisisanubhav:fix-5994-textdecoder

Conversation

@thisisanubhav

Copy link
Copy Markdown

Description of Changes

Fixes #5994.

The V8 host previously rejected new TextDecoder('utf8') and new TextDecoder('utf-16le'). Both are constructed eagerly by the h3-js@4.5.0 browser bundle, so the dependency could not finish module evaluation even though its UTF-16 decoder is unused.

  • Recognize the WHATWG labels for UTF-8 and UTF-16LE, trim ASCII whitespace, normalize case, and report the canonical encoding name.
  • Add non-streaming UTF-16LE decoding in the existing JavaScript builtin: explicit little-endian byte reads, surrogate pairs, replacement/fatal errors, leading BOM removal, and buffer-view offsets. A pending high surrogate plus an odd trailing byte produces one EOF error.
  • Accept omitted decode input as empty bytes.
  • Add a V8 host regression module reproducing dependency-style eager construction and covering aliases, decoding, malformed sequences, options, shared buffers, odd view offsets, repeated calls, and large input.

Compatibility: this remains a subset of TextDecoder. UTF-16BE and other encodings, streaming, and ignoreBOM: true remain unsupported. The existing native UTF-8 decode path (including its existing BOM behavior) is unchanged. UTF-16LE is implemented in JavaScript, without a new native API or dependency. The separate CLI success-exit behavior after module-evaluation errors is outside this fix.

API and ABI breaking changes

None. Previously rejected labels now work; the public host ABI is unchanged.

Rollback safety impact

n/a

Expected complexity level and risk

  1. Limited to the V8 text-encoding builtin and its regression test. UTF-16LE performance has not been benchmarked. Native host execution still needs upstream CI validation as described below.

Testing

  • Passed Prettier 3 checks for both JavaScript files, RUSTUP_TOOLCHAIN=stable rustfmt --check --edition 2024 crates/core/src/host/v8/mod.rs, and git diff --check.
  • Passed the checked-in regression module in Node v25.8.1 V8 using a temporary vm.SourceTextModule harness (node --experimental-vm-modules /tmp/issue-5994-check.mjs). Only the unchanged native UTF-8 primitives were shimmed; UTF-16LE executed the production implementation.
  • Passed 84,025 UTF-16LE differential cases against Node's TextDecoder in both replacement and fatal modes: every zero-, one-, and two-byte input, surrogate/BOM boundary combinations, and deterministic random inputs.
  • Evaluated the unmodified h3-js@4.5.0 browser bundle in that context: latLngToCell(37.775938728915946, -122.41795063018799, 9) returned 8928308280fffff; gridDisk(cell, 1) returned seven cells. Master reproduced the utf8 failure and, after changing only that label, the utf-16le failure.
  • Native host test not run locally: the offline Cargo attempt stopped before compilation because the workspace's iai-callgrind Git dependency was not cached. Disk was critically low (256–416 MiB free; ENOSPC constraint), so no further dependencies were downloaded or large builds attempted. Formatting used the installed stable toolchain (Rust 1.97.1), rather than the pinned 1.96.1 toolchain.
  • Upstream CI/reviewer check: cargo test --locked -p spacetimedb-core text_decoder_dependency_construction_and_decoding. No standalone publish/build flow was run locally.

@CLAassistant

CLAassistant commented Oct 1, 2026 •

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@coolreader18

Copy link
Copy Markdown
Contributor

I'm going to close this in favor of #6045, though I might nab the test file if that's okay.

@coolreader18

coolreader18 commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

@thisisanubhav would you please sign the CLA?

@thisisanubhav

Copy link
Copy Markdown
Author

@coolreader18 CLA signed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TypeScript module TextDecoder rejects valid utf8/utf-16le labels, breaking h3-js imports

3 participants