Skip to content

feat(intl): implement Intl.Locale (#5344)#5390

Closed
proggeramlug wants to merge 1 commit into
mainfrom
worktree-intl-locale-5344
Closed

feat(intl): implement Intl.Locale (#5344)#5390
proggeramlug wants to merge 1 commit into
mainfrom
worktree-intl-locale-5344

Conversation

@proggeramlug

@proggeramlug proggeramlug commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Implements Intl.Locale (issue #5344, the largest missing-constructor bucket in the intl402 tail), backed by icu_locale_core's data-free BCP-47 / UTS #35 parser. Previously new Intl.Locale(...) threw "undefined is not a constructor", which also blocked many other intl402 tests that construct a Locale during setup.

What's implemented

  • Constructortag (string or Locale instance) + options, with ApplyOptionsToTag / ApplyUnicodeExtensionToTag resolution in spec-mandated order (language, script, region, variants, then ca/co/hc/kf/kn/nu). Validation: invalid subtags / out-of-range enums / empty or <3-char keyword type values → RangeError; non-string/non-object tag → TypeError.
  • Getters (real prototype accessors, { get, enumerable:false, configurable:true }): baseName, language, script, region, variants, calendar, caseFirst, collation, hourCycle, numberingSystem, numeric.
  • Methods: toString, maximize, minimize (the latter two are best-effort — likely-subtags need CLDR data, out of scope for the data-free parser).

Notable wiring

  • ensure_function_prototype_object gains a Locale gate (mirroring the existing Temporal one) so new Intl.Locale() returns the populated prototype instead of shadowing it with a fresh empty one.
  • The intl-locale feature now enables icu_locale_core/alloc explicitly (it was previously only pulled in transitively by temporal), so the auto-optimize build of a Temporal-free program that touches Intl.Locale links cleanly.
  • Feature detection enables intl-locale on any Intl.Locale reference.

Results

scripts/test262_subset.py --dir intl402/Locale --all-features (node v26 oracle): 0 → 86/151 (57%).

Remaining failures are out of scope or known gaps:

  • ~25 need CLDR data — the 2023 Locale-Info methods (getCalendars/getWeekInfo/getTimeZones/…) and alias / likely-subtags resolution (moro, SUAM, islamiccislamic-civil, maximize/minimize). These need icu_locale + CLDR, not the data-free icu_locale_core.
  • ~7 Symbol.toStringTag — pre-existing Perry limitation (Object.prototype.toString ignores inherited Symbol.toStringTag; affects the existing Intl formatters too).
  • ~7 newTarget-detection / node-version artifacts, ~4 firstDayOfWeek (deferred), a few validation edges.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added Intl.Locale API support, including new Intl.Locale(...), toString, and maximize/minimize.
    • Implemented locale parsing and properties/options (language, script, region, variants, and Unicode extension values like calendar, collation, numbering system, numeric, etc.), with validation and RangeError for structurally invalid input.
  • Bug Fixes
    • Improved handling of Intl.Locale constructor prototypes to preserve any pre-populated prototype object.
  • Build/Tooling
    • Improved feature detection for Intl.Locale usage to recognize more Intl.*.Locale-related access patterns.

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8332c77f-ba35-43b0-8367-f596569d7269

📥 Commits

Reviewing files that changed from the base of the PR and between fe4e134 and 422839a.

📒 Files selected for processing (5)
  • crates/perry-runtime/Cargo.toml
  • crates/perry-runtime/src/intl.rs
  • crates/perry-runtime/src/intl/locale.rs
  • crates/perry-runtime/src/object/class_registry.rs
  • crates/perry/src/commands/compile/collect_modules/feature_detect.rs
🚧 Files skipped from review as they are similar to previous changes (3)
  • crates/perry/src/commands/compile/collect_modules/feature_detect.rs
  • crates/perry-runtime/Cargo.toml
  • crates/perry-runtime/src/object/class_registry.rs

📝 Walkthrough

Walkthrough

Adds Intl.Locale support behind the intl-locale feature flag. This includes a BCP-47/UTS#35 parsing and canonicalization pipeline using icu_locale_core, a full constructor with options application, property getters, prototype installation into the Intl namespace, a prototype registry guard matching the existing Temporal pattern, and a HIR-level feature detection trigger.

Changes

Intl.Locale implementation

Layer / File(s) Summary
Feature configuration and module setup
crates/perry-runtime/Cargo.toml, crates/perry-runtime/src/intl.rs
intl-locale feature gains icu_locale_core/alloc sub-feature; locale submodule introduced with feature-gated re-exports of install_locale_constructor and is_locale_ctor; install_intl_namespace updated to conditionally invoke the constructor installer.
Locale parsing and validation pipeline
crates/perry-runtime/src/intl/locale.rs
Defines KEY_LOCALE_TAG and LOCALE_PROTO_BITS thread-local cell; implements BCP-47 tag parsing via icu_locale_core, unicode-extension keyword reading, option validation and subtag application (raising RangeError on invalid values), and canonical locale string construction via build_locale_string; includes is_locale_ctor identity check for constructor recognition.
Constructor thunk and instance methods
crates/perry-runtime/src/intl/locale.rs
Constructor thunk allocates Intl.Locale instances with internal [[Kind]] and [[Locale]] fields and prototype linkage from LOCALE_PROTO_BITS; toString returns the stored canonical tag; maximize and minimize clone the stored tag into new Locale wrappers preserving the prototype chain.
Property getter implementations
crates/perry-runtime/src/intl/locale.rs
All exported property getters (baseName, language, script, region, variants, calendar, caseFirst, collation, hourCycle, numberingSystem, numeric) re-parse the stored canonical locale string on demand and return the corresponding value or undefined; numeric includes boolean semantics based on -u-kn presence/value.
Prototype installation and namespace wiring
crates/perry-runtime/src/intl/locale.rs
install_proto_getter allocates getter closures and installs them as non-settable configurable accessors on the prototype; install_locale_constructor creates the prototype, installs methods and accessor getters, sets Symbol.toStringTag to "Intl.Locale", caches prototype bits in LOCALE_PROTO_BITS, and registers the constructor on the Intl namespace object.
Prototype registry guard and feature detection
crates/perry-runtime/src/object/class_registry.rs, crates/perry/src/commands/compile/collect_modules/feature_detect.rs
ensure_function_prototype_object is extended to preserve pre-populated .prototype for Intl.Locale constructors via is_locale_ctor, mirroring the Temporal guard. HIR feature detection gains a property: "Locale" match to set ctx.uses_intl_locale.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

  • PerryTS/perry#5344: Directly addresses the missing Intl.Locale constructor implementation with feature detection, which resolves the "Locale: 137" constructor failures reported in test262 intl402 test suite failures.

Possibly related PRs

  • PerryTS/perry#5320: Both PRs are tied to the shared intl-locale ICU feature gate—main PR extends feature detection and runtime to add Intl.Locale, while the retrieved PR uses the same gate for locale-tag canonicalization powering Intl.getCanonicalLocales/supportedLocalesOf.
  • PerryTS/perry#5359: Both PRs implement Intl.Locale by modifying crates/perry-runtime/src/intl.rs (wiring/installation and constructor/prototype setup), so changes are directly in the same codepath.

Poem

🐇 A hop through BCP-47 land,
Where locale tags meet a careful hand,
The bunny parsed each script and region,
With icu_locale_core as its legion.
RangeError for the ones gone wrong,
And Intl.Locale joins the throng! 🌍

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(intl): implement Intl.Locale (#5344)' clearly and concisely summarizes the main feature being added—the implementation of the Intl.Locale constructor—which is the primary focus of all changes in the pull request.
Description check ✅ Passed The description covers the main feature implementation, lists concrete changes across multiple files, explains notable wiring/infrastructure changes, provides test results, and includes the required checklist with all items marked. The description is comprehensive and well-structured.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch worktree-intl-locale-5344
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch worktree-intl-locale-5344

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

@proggeramlug proggeramlug force-pushed the worktree-intl-locale-5344 branch from fa812b5 to fe4e134 Compare June 18, 2026 09:32
Adds `Intl.Locale` backed by `icu_locale_core`'s data-free BCP-47 / UTS #35
parser (the `intl-locale` feature, auto-enabled when a program references
`Intl.Locale`). Previously the constructor was absent — `new Intl.Locale(...)`
threw "undefined is not a constructor", which also blocked many other
intl402 tests that build a Locale during setup.

Implemented:
- Constructor: tag (string or `Locale` instance) + options, with
  ApplyOptionsToTag / ApplyUnicodeExtensionToTag resolution in spec order
  (language, script, region, variants, then ca/co/hc/kf/kn/nu). Structural
  validation: invalid subtags / out-of-range enums / empty or <3-char
  keyword `type` values → RangeError; non-string/non-object tag → TypeError.
- Accessor getters on the prototype (real `{ get, enumerable:false,
  configurable:true }` accessors): baseName, language, script, region,
  variants, calendar, caseFirst, collation, hourCycle, numberingSystem,
  numeric.
- Methods: toString, maximize, minimize. maximize/minimize are best-effort
  (likely-subtags need CLDR data — out of scope for the data-free parser).

The prototype is populated at globalThis init and stamped on the ctor's
`prototype` dynamic prop; `ensure_function_prototype_object` now returns it
via a Locale gate mirroring Temporal's, so `new Intl.Locale()` no longer
shadows it with a fresh empty prototype.

Makes the `intl-locale` feature self-sufficient by enabling
`icu_locale_core/alloc` (it was previously only pulled in transitively by
`temporal`), so the auto-optimize build of a Temporal-free program that
touches `Intl.Locale` links cleanly.

test262 intl402/Locale: 0 -> 86/151 (57%). Remaining failures need CLDR data
(the Locale-Info `getCalendars`/`getWeekInfo`/... methods, alias and
likely-subtags resolution) or are the known `newTarget`-detection and
inherited-`Symbol.toStringTag` runtime gaps (the latter affects the existing
Intl formatters too).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@proggeramlug proggeramlug force-pushed the worktree-intl-locale-5344 branch from fe4e134 to 422839a Compare June 18, 2026 09:40
@proggeramlug proggeramlug reopened this Jun 18, 2026
@proggeramlug

Copy link
Copy Markdown
Contributor Author

Superseded by #5359, which already implemented Intl.Locale for #5344 and merged to main (commit b0e9f48) while this was in progress. #5359's implementation is strictly more complete (it includes a likely-subtags table for maximize/minimize, which this PR deferred), so there's nothing here to add. Closing as a duplicate.

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