Skip to content

feat: build V8 with ICU so Intl is available - #9

Draft
aleclarson wants to merge 1 commit into
NativeScript:mainfrom
aleclarson:feat/enable-icu
Draft

aleclarson wants to merge 1 commit into
NativeScript:mainfrom
aleclarson:feat/enable-icu

Conversation

@aleclarson

Copy link
Copy Markdown

Refs NativeScript/NativeScript#11563

Summary

Both matrix scripts set v8_enable_i18n_support=false, carried over from the 10.3 build. That removes Intl entirely. It also leaves localeCompare, toLocale*String, locale case mapping, String#normalize and RegExp \p{…} missing or locale-blind on Android and iOS.

This PR turns i18n on and keeps icu_use_data_file=false, so the ICU data is linked into the libraries:

Target ICU data filter (chosen by third_party/icu/BUILD.gn) Raw icudtl.dat size
Android, all ABIs android 8.9 MiB
iOS device/simulator, Catalyst ios 6.2 MiB
tvOS (use_blink=true) common 10.3 MiB

Why embedded data

  • No runtime changes needed to load ICU. With static data, V8::InitializeICU returns true without doing anything (src/init/icu_util.cc), so neither runtime has to find, extract or map an icudtl.dat.
  • iOS needs no packaging change. ICU's code and its icudata object land under obj/third_party/icu, which the existing libv8_third_party sweep already picks up. On Android, v8_monolith is a complete static lib and includes them too.
  • No symbol clashes with the system ICU. Chromium's ICU keeps version-suffixed symbols (ucol_open_<ver>), so it can't collide with Apple's libicucore.

This is meant to settle the open questions in the issue (on by default or a separate flavor, embedded data or one shared data file) with real numbers. A shared data file would store the data once per APK instead of once per ABI. That's a follow-up for both runtimes if the size here is too high.

Size

Baseline is release v8-14.9.207.39-8. I'll fill in the new column from this PR's CI artifacts. Archive size is an upper bound. The real app-size delta needs a runtime linked against these libraries, since the linker drops unused ICU code.

Artifact Before (tar.gz) After (tar.gz)
android-arm64-v8a 18.3 MiB TBD
android-x86_64 19.1 MiB TBD
ios-arm64-device 11.1 MiB TBD
ios-arm64-simulator 11.1 MiB TBD

Known follow-ups in the runtimes (not part of this PR)

  • Default locale. ICU takes its default locale from POSIX env (LANG/LC_*), which Android and iOS apps don't set, so V8 falls back to en-US. Explicit locales (new Intl.NumberFormat('de')) work. Following the device locale needs the runtimes to set ICU's default locale before V8::Initialize.
  • Default time zone. ICU on Android reads persist.sys.timezone, so that should just work. iOS should be checked on device.
  • Exported symbols. ICU is compiled with default visibility, so it may show up in the dynamic exports of libNativeScript.so / NativeScript.framework. Worth checking once linked.

Test plan

  • python3 tests/apple-args.py: new test_every_variant_embeds_icu checks all seven Apple variants get v8_enable_i18n_support=true and icu_use_data_file=false
  • CI matrix builds all Android ABIs and Apple variants
  • Link the Android and iOS runtimes against the CI artifacts; check typeof Intl === 'object', new Intl.PluralRules('en').select(1), /\p{L}/u.test('é') and 'a'.localeCompare('B', 'en')
  • Record the app-size delta per platform

Both scripts carried v8_enable_i18n_support=false over from the 10.3
build. That removes Intl entirely and leaves localeCompare,
toLocale*String, locale case mapping, String#normalize and RegExp \p{...}
missing or locale-blind on Android and iOS.

Turn i18n on and keep icu_use_data_file=false, so the ICU data is linked
into the libraries: V8::InitializeICU is then a no-op and neither runtime
needs code changes or an icudtl.dat to load. On iOS the ICU objects,
data included, land in libv8_third_party through the existing
obj/third_party sweep.

Refs NativeScript/NativeScript#11563
@coderabbitai

coderabbitai Bot commented Oct 27, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: b19ef2b2-8ee0-45a7-b176-10c679e0b5ba

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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.

1 participant