Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
bc3b39f
spec(rust-i18n): implement Rust port of Node.js i18n transcode
logan-gatlin Aug 12, 2026
ec13e83
spec(rust-i18n): round 1 refactor
logan-gatlin Aug 12, 2026
d3d6397
restructure
logan-gatlin Aug 18, 2026
7994a28
accept unsafe cost of isolate ptr
logan-gatlin Aug 20, 2026
db353ea
deslop
logan-gatlin Aug 20, 2026
0c4b252
Remove patch
logan-gatlin Aug 20, 2026
97eea93
remove shim
logan-gatlin Aug 21, 2026
99caa09
rust/i18n: use c_char instead of hardcoded i8 for ucnv_convertEx poin…
logan-gatlin Aug 21, 2026
4d7e098
edit agent md
logan-gatlin Aug 21, 2026
d5feef8
fix comment
logan-gatlin Aug 21, 2026
70564b8
rust/i18n: centralize V8 FFI callback handling
logan-gatlin Sep 9, 2026
6ecd413
rust/i18n: use rust_icu_sys for ICU bindings
logan-gatlin Sep 9, 2026
5533431
rust/i18n: zero transcoder backing stores
logan-gatlin Sep 14, 2026
dfebe30
rust/i18n: port simdutf codecs to safe Rust
logan-gatlin Sep 28, 2026
66a716a
rust/i18n: port transcoding to safe Rust
logan-gatlin Sep 28, 2026
c889da8
rust/i18n: use shared Encoding directly
logan-gatlin Sep 28, 2026
b0d1ceb
rust/i18n: optimize transcoder test corpus
logan-gatlin Sep 29, 2026
32b258b
rust/i18n: give the transcode differential test a large timeout
logan-gatlin Sep 29, 2026
fac5acc
rust/i18n: isolate FFI and split Rust tests
logan-gatlin Oct 8, 2026
386478d
rust/i18n: use ICU and simdutf through FFI
logan-gatlin Oct 8, 2026
b7cb584
rust/i18n: use size_of for UTF-16 byte calculations
logan-gatlin Oct 8, 2026
de2cbda
rust/i18n: drop stale NODEJS_EXCEPTIONS_RUST reference
logan-gatlin Oct 14, 2026
9665d29
ci: sync rust_icu_sys ICU version in v8_update.py
logan-gatlin Oct 14, 2026
db9e3e6
rust/i18n: give the transcode differential test an enormous timeout
logan-gatlin Oct 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions build/deps/rust.MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,14 @@ crate.annotation(
"//:patches/rust/crates/hyper/parse-error-explanation.patch",
],
)
crate.annotation(
# rust_icu's checked-in bindings and symbol-renaming macro are selected by this value. Keep it
# synchronized with U_ICU_VERSION_MAJOR_NUM of the Chromium ICU commit pinned in
# build/deps/gen/deps.MODULE.bazel. ci/v8_update.py updates it; see docs/v8-updates.md.
build_script_env = {"BAZEL": "1"},
crate = "rust_icu_sys",
rustc_env = {"RUST_ICU_MAJOR_VERSION_NUMBER": "78"},
Comment thread
logan-gatlin marked this conversation as resolved.
)
crate.from_cargo(
# TODO(cleanup): This name is a bit misleading now that we don't vendor. We can clean it up as a
# followup.
Expand Down
3 changes: 3 additions & 0 deletions build/wd_rust_crate.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ def wd_rust_crate(
deps = [],
link_deps = [],
proc_macro_deps = [],
rustc_env = {},
data = [],
test_env = {},
test_tags = [],
Expand Down Expand Up @@ -174,6 +175,7 @@ def wd_rust_crate(
srcs = srcs,
deps = deps,
link_deps = link_deps + ["@@//deps:rust_runtime"],
rustc_env = rustc_env,
visibility = visibility,
data = data,
proc_macro_deps = proc_macro_deps,
Expand All @@ -195,6 +197,7 @@ def wd_rust_crate(
size = test_size,
tags = test_tags,
crate_features = crate_features,
rustc_env = rustc_env,
deps = test_deps,
proc_macro_deps = test_proc_macro_deps,
)
Expand Down
53 changes: 53 additions & 0 deletions ci/v8_update.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@
# Keep the aligned markers in sync with the corresponding comments in
# build/deps/deps.jsonc.

# rust_icu_sys selects its bindings and versioned ICU symbol names from this
# pin, which must match the major version of the ICU that V8 links.
RUST_ICU_VERSION_PINS = (
ROOT / "build/deps/rust.MODULE.bazel",
ROOT / "src/rust/i18n/BUILD.bazel",
)
RUST_ICU_VERSION = re.compile(r'(?<="RUST_ICU_MAJOR_VERSION_NUMBER": ")\d+(?=")')


def run(args, *, cwd=ROOT, check=True, env=None, stdout=None):
print("+", shlex.join(map(str, args)), flush=True)
Expand Down Expand Up @@ -103,6 +111,41 @@ def _update_aligned_dependencies():
DEPS.write_text(jsonc.dumps(doc) + "\n")


def _icu_major_version(commit):
with urlopen(
"https://chromium.googlesource.com/chromium/deps/icu/+/"
f"{commit}/source/common/unicode/uvernum.h?format=TEXT",
timeout=30,
) as response:
header = base64.b64decode(response.read()).decode()
match = re.search(
r"(?<=^#define U_ICU_VERSION_MAJOR_NUM )\d+$", header, re.MULTILINE
)
return match.group()


def _update_rust_icu_version():
path, _ = V8_DEPENDENCIES["com_googlesource_chromium_icu"]
commit = _v8_dependency_commit(path, (CHECKOUT / "DEPS").read_text())
version = _icu_major_version(commit)
changed = False
for pin in RUST_ICU_VERSION_PINS:
text = pin.read_text()
old = RUST_ICU_VERSION.findall(text)
if len(old) != 1:
raise ValueError(
f"expected one RUST_ICU_MAJOR_VERSION_NUMBER in {pin}, found {len(old)}"
)
if old != [version]:
pin.write_text(RUST_ICU_VERSION.sub(version, text))
changed = True
if changed:
print(
f"Updated RUST_ICU_MAJOR_VERSION_NUMBER to {version}. Check that the pinned "
f"rust_icu_sys provides bindgen/lib_{version}.rs; update the crate if it does not."
)


def _update_module(tag, patch_names):
text = MODULE.read_text()
text = re.sub(
Expand Down Expand Up @@ -220,6 +263,16 @@ def finish_update(target):

_update_module(target, patch_names)
_update_aligned_dependencies()
# The Rust ICU pin must match the ICU that Bazel builds, so regenerate the
# ICU repository from its new commit before deriving the pin.
run(
[
sys.executable,
ROOT / "build/deps/update-deps.py",
"com_googlesource_chromium_icu",
]
)
_update_rust_icu_version()


def parse_args():
Expand Down
35 changes: 35 additions & 0 deletions deps/rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions deps/rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ pico-args = "0"
rand = { version = "0.9", default-features = false, features = ["os_rng", "thread_rng"] }
ruff_python_ast = { git = "https://github.com/astral-sh/ruff", tag = "0.12.1" }
ruff_python_parser = { git = "https://github.com/astral-sh/ruff", tag = "0.12.1" }
# Use rust_icu's checked-in bindings for the Chromium ICU version linked by workerd. ICU itself is
# supplied by Bazel, so bindgen, icu-config, and rust_icu's library-linking features stay disabled.
rust_icu_sys = { version = "5.8", default-features = false, features = ["renaming", "icu_version_in_env"] }
# ring rather than aws-lc-rs: its crates.io package builds with plain cc (no cmake/NASM).
rustls = { version = "0.23", default-features = false, features = ["ring", "std", "tls12"] }
rustls-platform-verifier = "0.7"
Expand Down
13 changes: 12 additions & 1 deletion docs/v8-updates.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,13 @@ from the V8 directory.
figure out what version of the github code V8 depends on. Instead, it should be safe
to just bump these dependencies to the latest version on github.

If the new `com_googlesource_chromium_icu` commit changes `U_ICU_VERSION_MAJOR_NUM`
(in `source/common/unicode/uvernum.h`), update `RUST_ICU_MAJOR_VERSION_NUMBER` in both
`build/deps/rust.MODULE.bazel` and `src/rust/i18n/BUILD.bazel`. A stale value fails the
build with undefined `<function>_<version>` ICU symbols, or missing items in
`rust_icu_sys` if the two values disagree. If `rust_icu_sys` has no `bindgen/lib_<version>.rs`
for the new version, update the crate as well.

11. Check workerd's tests pass with the updated V8.

```sh
Expand Down Expand Up @@ -122,6 +129,10 @@ rebases the patches, regenerates `patches/v8/*.patch`, and updates:
- the `dragonbox`, `fast_float`, `fp16`, and `highway` commits in
`build/deps/deps.jsonc`.

It also regenerates `com_googlesource_chromium_icu` in `build/deps/gen/deps.MODULE.bazel`
and sets `RUST_ICU_MAJOR_VERSION_NUMBER` in `build/deps/rust.MODULE.bazel` and
`src/rust/i18n/BUILD.bazel` to the major version of the new ICU commit (see step 10).

If the rebase stops because of conflicts, resolve and continue it in the temporary
checkout:

Expand All @@ -143,7 +154,7 @@ python3 ci/v8_update.py finish <new_version>
Do not run `finish` until the rebase has completed. It regenerates the patches and
updates the pins listed above.

The helper does not run `update-deps.py`. Compare the old and new V8 `DEPS` files for
The helper runs `update-deps.py` only for ICU. Compare the old and new V8 `DEPS` files for
changes to `dragonbox`, `fast_float`, `fp16`, `highway`, `perfetto`, and `simdutf`, then
run the dependency updater for each changed revision:

Expand Down
24 changes: 24 additions & 0 deletions src/rust/i18n/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
load("//:build/wd_rust_crate.bzl", "wd_rust_crate")

wd_rust_crate(
name = "i18n",
cxx_bridge_deps = [
"//src/rust/jsg",
"@simdutf",
"@workerd-v8//:v8",
],
cxx_bridge_src = "ffi.rs",
# ICU, which rust_icu_sys binds to, is linked through V8.
link_deps = ["@workerd-v8//:v8"],
# rust_icu_sys's `versioned_function!` expands in this crate and reads the ICU version from
# here. Keep it synchronized with the rust_icu_sys annotation in build/deps/rust.MODULE.bazel;
# ci/v8_update.py updates both.
rustc_env = {"RUST_ICU_MAJOR_VERSION_NUMBER": "78"},
test_deps = ["//src/rust/jsg-test"],
visibility = ["//visibility:public"],
deps = [
"//src/rust/jsg",
"@crates_vendor//:rust_icu_sys",
"@crates_vendor//:thiserror",
],
)
Loading
Loading