diff --git a/runtime/js/99_main.js b/runtime/js/99_main.js index e3b14fdafa..19432745d4 100644 --- a/runtime/js/99_main.js +++ b/runtime/js/99_main.js @@ -37,6 +37,7 @@ const { ObjectHasOwn, ObjectKeys, ObjectGetOwnPropertyDescriptor, + ObjectGetOwnPropertyDescriptors, ObjectPrototypeIsPrototypeOf, ObjectSetPrototypeOf, PromisePrototypeThen, @@ -45,6 +46,7 @@ const { Symbol, SymbolIterator, TypeError, + uncurryThis, } = primordials; const { isNativeError, @@ -459,6 +461,51 @@ function exposeUnstableFeaturesForWindowOrWorkerGlobalScope(unstableFeatures) { } } +function shimTemporalDurationToLocaleString() { + const DurationFormat = Intl.DurationFormat; + if (!DurationFormat) { + // Intl.DurationFormat can be disabled with --v8-flags=--no-harmony-intl-duration-format + return; + } + const DurationFormatPrototype = DurationFormat.prototype; + const formatDuration = uncurryThis(DurationFormatPrototype.format); + + const Duration = Temporal.Duration; + const DurationPrototype = Duration.prototype; + const desc = ObjectGetOwnPropertyDescriptors(DurationPrototype); + const assertDuration = uncurryThis(desc.toLocaleString.value); + const getYears = uncurryThis(desc.years.get); + const getMonths = uncurryThis(desc.months.get); + const getWeeks = uncurryThis(desc.weeks.get); + const getDays = uncurryThis(desc.days.get); + const getHours = uncurryThis(desc.hours.get); + const getMinutes = uncurryThis(desc.minutes.get); + const getSeconds = uncurryThis(desc.seconds.get); + const getMilliseconds = uncurryThis(desc.milliseconds.get); + const getMicroseconds = uncurryThis(desc.microseconds.get); + const getNanoseconds = uncurryThis(desc.nanoseconds.get); + + ObjectAssign(DurationPrototype, { + toLocaleString(locales = undefined, options) { + assertDuration(this); + const durationFormat = new DurationFormat(locales, options); + const duration = { + years: getYears(this), + months: getMonths(this), + weeks: getWeeks(this), + days: getDays(this), + hours: getHours(this), + minutes: getMinutes(this), + seconds: getSeconds(this), + milliseconds: getMilliseconds(this), + microseconds: getMicroseconds(this), + nanoseconds: getNanoseconds(this), + }; + return formatDuration(durationFormat, duration); + }, + }); +} + // NOTE(bartlomieju): remove all the ops that have already been imported using // "virtual op module" (`ext:core/ops`). const NOT_IMPORTED_OPS = [ @@ -821,6 +868,12 @@ function bootstrapMainRuntime(runtimeOptions, warmup = false) { }); delete globalThis.Temporal.Now.timeZone; } + + // deno-lint-ignore prefer-primordials + if (new Temporal.Duration().toLocaleString("en-US") !== "PT0S") { + throw "V8 supports Temporal.Duration.prototype.toLocaleString now, no need to shim it"; + } + shimTemporalDurationToLocaleString(); } // Setup `Deno` global - we're actually overriding already existing global @@ -1024,6 +1077,8 @@ function bootstrapWorkerRuntime( }); delete globalThis.Temporal.Now.timeZone; } + + shimTemporalDurationToLocaleString(); } // Setup `Deno` global - we're actually overriding already existing global diff --git a/tests/specs/run/unstable_temporal_api_patch/main.out b/tests/specs/run/unstable_temporal_api_patch/main.out index a17d3a9e20..ec12b9e463 100644 --- a/tests/specs/run/unstable_temporal_api_patch/main.out +++ b/tests/specs/run/unstable_temporal_api_patch/main.out @@ -5,3 +5,4 @@ iso8601 UTC undefined undefined +1 day, 6 hr, 30 min diff --git a/tests/specs/run/unstable_temporal_api_patch/main.ts b/tests/specs/run/unstable_temporal_api_patch/main.ts index 6a40780535..ff92cf91c2 100644 --- a/tests/specs/run/unstable_temporal_api_patch/main.ts +++ b/tests/specs/run/unstable_temporal_api_patch/main.ts @@ -9,3 +9,6 @@ console.log(zoned.timeZoneId); console.log(zoned.calendar); // @ts-expect-error: undefined check console.log(zoned.timeZone); + +const duration = Temporal.Duration.from("P1DT6H30M"); +console.log(duration.toLocaleString("en-US"));