Changeset 260349 in webkit


Ignore:
Timestamp:
Apr 19, 2020 10:15:35 PM (4 years ago)
Author:
Ross Kirsling
Message:

[ECMA-402] Intl.RelativeTimeFormat missing in WebKit
https://bugs.webkit.org/show_bug.cgi?id=209770

Reviewed by Darin Adler.

JSTests:

  • stress/intl-relativetimeformat.js: Added.
  • test262/config.yaml:

Enable Intl.RelativeTimeFormat feature with flag.

  • test262/expectations.yaml:

Mark known failures.
Test for locale validation is not specific to RelativeTimeFormat and should be investigated separately.
Tests for Polish appear to be wrong and should be corrected in test262.

Source/JavaScriptCore:

This patch implements the recent ECMA-402 feature Intl.RelativeTimeFormat.

RelativeTimeFormat has format / formatToParts functions like NumberFormat / DateTimeFormat
and is used to turn a number and unit into a formatted relative time string, e.g.:

new Intl.RelativeTimeFormat('en').format(10, 'day')

'in 10 days'

new Intl.RelativeTimeFormat('en', { numeric: 'auto' }).format(0, 'day')

'today'

Implementation of RelativeTimeFormat#formatToParts makes direct use of NumberFormat#formatToParts,
as the relative time string consists of at most one formatted number with optional literal text on either side.

This feature is runtime-guarded by the useIntlRelativeTimeFormat option.

  • CMakeLists.txt:
  • DerivedSources-input.xcfilelist:
  • DerivedSources-output.xcfilelist:
  • DerivedSources.make:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • Sources.txt:
  • runtime/CommonIdentifiers.h:
  • runtime/IntlRelativeTimeFormat.cpp: Added.
  • runtime/IntlRelativeTimeFormat.h: Added.
  • runtime/IntlRelativeTimeFormatConstructor.cpp: Added.
  • runtime/IntlRelativeTimeFormatConstructor.h: Added.
  • runtime/IntlRelativeTimeFormatPrototype.cpp: Added.
  • runtime/IntlRelativeTimeFormatPrototype.h: Added.
  • runtime/JSGlobalObject.cpp:

(JSC::JSGlobalObject::init):
(JSC::JSGlobalObject::visitChildren):

  • runtime/JSGlobalObject.h:

(JSC::JSGlobalObject::relativeTimeFormatStructure):

  • runtime/OptionsList.h:
  • runtime/VM.cpp:

(JSC::VM::VM):

  • runtime/VM.h:

Add feature and runtime option.

  • runtime/IntlDateTimeFormat.cpp:

(JSC::IntlDateTimeFormat::formatToParts):

  • runtime/IntlPluralRules.cpp:

(JSC::IntlPluralRules::initializePluralRules):
(JSC::IntlPluralRules::resolvedOptions):
Make "type" a property name.

  • runtime/IntlNumberFormat.cpp:

(JSC::IntlNumberFormat::initializeNumberFormat):
(JSC::IntlNumberFormat::resolvedOptions):
(JSC::IntlNumberFormat::formatToPartsInternal):
(JSC::IntlNumberFormat::formatToParts):

  • runtime/IntlNumberFormat.h:

Factor out formatToPartsInternal so that RelativeTimeFormat can use it with its own UNumberFormat.
(This logic is too complicated to duplicate; it's because ICU won't split, e.g., "10,000" into parts for us.)

  • runtime/IntlObject.cpp:

(JSC::IntlObject::IntlObject):
(JSC::IntlObject::create):
(JSC::IntlObject::finishCreation):
(JSC::intlAvailableLocales):
(JSC::intlCollatorAvailableLocales):
(JSC::isUnicodeLocaleIdentifierType):
(JSC::supportedLocales):
(JSC::intlDateTimeFormatAvailableLocales): Deleted.
(JSC::intlNumberFormatAvailableLocales): Deleted.

  • runtime/IntlObject.h:

(JSC::intlDateTimeFormatAvailableLocales):
(JSC::intlNumberFormatAvailableLocales):
(JSC::intlPluralRulesAvailableLocales):
(JSC::intlRelativeTimeFormatAvailableLocales):
Perform three corrections for Intl classes:

  1. Collator should be the only class with unique "available locales". [unum|udat]_getAvailable exist but they've deferred to uloc_getAvailable for 20 years.
  2. isUnicodeLocaleIdentifierType isn't just alphanum{3,8} but rather alphanum{3,8} (sep alphanum{3,8})*. This is my own mistake from r239941.
  3. supportedLocalesOf entries should not be frozen. Changed in https://github.com/tc39/ecma402/pull/278.
  • tools/JSDollarVM.cpp:

(JSC::functionICUVersion):
(JSC::JSDollarVM::finishCreation):
Add $vm.icuVersion so that we can add per-line skips to stress tests.

Tools:

  • Scripts/run-jsc-stress-tests:

Add runIntlRelativeTimeFormatEnabled.

Location:
trunk
Files:
6 added
25 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r260332 r260349  
     12020-04-19  Ross Kirsling  <ross.kirsling@sony.com>
     2
     3        [ECMA-402] Intl.RelativeTimeFormat missing in WebKit
     4        https://bugs.webkit.org/show_bug.cgi?id=209770
     5
     6        Reviewed by Darin Adler.
     7
     8        * stress/intl-relativetimeformat.js: Added.
     9
     10        * test262/config.yaml:
     11        Enable Intl.RelativeTimeFormat feature with flag.
     12
     13        * test262/expectations.yaml:
     14        Mark known failures.
     15        Test for locale validation is not specific to RelativeTimeFormat and should be investigated separately.
     16        Tests for Polish appear to be wrong and should be corrected in test262.
     17
    1182020-04-18  Keith Miller  <keith_miller@apple.com>
    219
  • trunk/JSTests/test262/config.yaml

    r260273 r260349  
    33flags:
    44  BigInt: useBigInt
     5  Intl.RelativeTimeFormat: useIntlRelativeTimeFormat
    56  WeakRef: useWeakRefs
    67  class-fields-public: usePublicClassFields
     
    3132    - Intl.Locale
    3233    - Intl.NumberFormat-unified
    33     - Intl.RelativeTimeFormat
    3434    - Intl.Segmenter
    3535  paths:
     
    154154    - test/intl402/DateTimeFormat/prototype/format/related-year-zh.js
    155155    - test/intl402/DateTimeFormat/prototype/formatToParts/related-year-zh.js
     156
     157    # requires ICU 65 (https://unicode-org.atlassian.net/browse/ICU-20654)
     158    - test/intl402/RelativeTimeFormat/prototype/format/en-us-numeric-auto.js
     159    - test/intl402/RelativeTimeFormat/prototype/formatToParts/en-us-numeric-auto.js
  • trunk/JSTests/test262/expectations.yaml

    r260332 r260349  
    19361936  default: 'Test262Error: newTarget.prototype is undefined Expected SameValue(«[object Object]», «[object Object]») to be true'
    19371937  strict mode: 'Test262Error: newTarget.prototype is undefined Expected SameValue(«[object Object]», «[object Object]») to be true'
     1938test/intl402/RelativeTimeFormat/constructor/constructor/locales-valid.js:
     1939  default: 'Test262Error: Grandfathered Expected a RangeError to be thrown but no exception was thrown at all'
     1940  strict mode: 'Test262Error: Grandfathered Expected a RangeError to be thrown but no exception was thrown at all'
     1941test/intl402/RelativeTimeFormat/constructor/constructor/proto-from-ctor-realm.js:
     1942  default: 'Test262Error: newTarget.prototype is undefined Expected SameValue(«[object Intl.RelativeTimeFormat]», «[object Intl.RelativeTimeFormat]») to be true'
     1943  strict mode: 'Test262Error: newTarget.prototype is undefined Expected SameValue(«[object Intl.RelativeTimeFormat]», «[object Intl.RelativeTimeFormat]») to be true'
     1944test/intl402/RelativeTimeFormat/prototype/format/pl-pl-style-long.js:
     1945  default: 'Test262Error: Expected SameValue(«za 1000 sekund», «za 1 000 sekund») to be true'
     1946  strict mode: 'Test262Error: Expected SameValue(«za 1000 sekund», «za 1 000 sekund») to be true'
     1947test/intl402/RelativeTimeFormat/prototype/format/pl-pl-style-narrow.js:
     1948  default: 'Test262Error: Expected SameValue(«za 1000 s», «za 1 000 s») to be true'
     1949  strict mode: 'Test262Error: Expected SameValue(«za 1000 s», «za 1 000 s») to be true'
     1950test/intl402/RelativeTimeFormat/prototype/format/pl-pl-style-short.js:
     1951  default: 'Test262Error: Expected SameValue(«za 1000 sek.», «za 1 000 sek.») to be true'
     1952  strict mode: 'Test262Error: Expected SameValue(«za 1000 sek.», «za 1 000 sek.») to be true'
     1953test/intl402/RelativeTimeFormat/prototype/formatToParts/pl-pl-style-long.js:
     1954  default: 'Test262Error: formatToParts(1000, second): length Expected SameValue(«3», «5») to be true'
     1955  strict mode: 'Test262Error: formatToParts(1000, second): length Expected SameValue(«3», «5») to be true'
     1956test/intl402/RelativeTimeFormat/prototype/formatToParts/pl-pl-style-narrow.js:
     1957  default: 'Test262Error: formatToParts(1000, second): length Expected SameValue(«3», «5») to be true'
     1958  strict mode: 'Test262Error: formatToParts(1000, second): length Expected SameValue(«3», «5») to be true'
     1959test/intl402/RelativeTimeFormat/prototype/formatToParts/pl-pl-style-short.js:
     1960  default: 'Test262Error: formatToParts(1000, second): length Expected SameValue(«3», «5») to be true'
     1961  strict mode: 'Test262Error: formatToParts(1000, second): length Expected SameValue(«3», «5») to be true'
    19381962test/intl402/language-tags-invalid.js:
    19391963  default: 'Test262Error: Test data "de-gregory-gregory" is a canonicalized and structurally valid language tag.'
    19401964  strict mode: 'Test262Error: Test data "de-gregory-gregory" is a canonicalized and structurally valid language tag.'
    1941 test/intl402/supportedLocalesOf-returned-array-elements-are-not-frozen.js:
    1942   default: 'Test262Error: Property 0 of object returned by SupportedLocales is not writable. Expected SameValue(«false», «true») to be true (Testing with Collator.)'
    1943   strict mode: 'Test262Error: Property 0 of object returned by SupportedLocales is not writable. Expected SameValue(«false», «true») to be true (Testing with Collator.)'
    19441965test/language/arguments-object/mapped/nonconfigurable-nonenumerable-nonwritable-descriptors-set-by-arguments.js:
    19451966  default: 'Test262Error: Expected obj[0] to have enumerable:false.'
  • trunk/Source/JavaScriptCore/CMakeLists.txt

    r260331 r260349  
    7676    runtime/IntlPluralRulesConstructor.cpp
    7777    runtime/IntlPluralRulesPrototype.cpp
     78    runtime/IntlRelativeTimeFormatConstructor.cpp
     79    runtime/IntlRelativeTimeFormatPrototype.cpp
    7880    runtime/JSDataViewPrototype.cpp
    7981    runtime/JSGlobalObject.cpp
  • trunk/Source/JavaScriptCore/ChangeLog

    r260346 r260349  
     12020-04-19  Ross Kirsling  <ross.kirsling@sony.com>
     2
     3        [ECMA-402] Intl.RelativeTimeFormat missing in WebKit
     4        https://bugs.webkit.org/show_bug.cgi?id=209770
     5
     6        Reviewed by Darin Adler.
     7
     8        This patch implements the recent ECMA-402 feature Intl.RelativeTimeFormat.
     9
     10        RelativeTimeFormat has format / formatToParts functions like NumberFormat / DateTimeFormat
     11        and is used to turn a number and unit into a formatted relative time string, e.g.:
     12
     13          new Intl.RelativeTimeFormat('en').format(10, 'day')
     14          > 'in 10 days'
     15
     16          new Intl.RelativeTimeFormat('en', { numeric: 'auto' }).format(0, 'day')
     17          > 'today'
     18
     19        Implementation of RelativeTimeFormat#formatToParts makes direct use of NumberFormat#formatToParts,
     20        as the relative time string consists of at most one formatted number with optional literal text on either side.
     21
     22        This feature is runtime-guarded by the `useIntlRelativeTimeFormat` option.
     23
     24        * CMakeLists.txt:
     25        * DerivedSources-input.xcfilelist:
     26        * DerivedSources-output.xcfilelist:
     27        * DerivedSources.make:
     28        * JavaScriptCore.xcodeproj/project.pbxproj:
     29        * Sources.txt:
     30        * runtime/CommonIdentifiers.h:
     31        * runtime/IntlRelativeTimeFormat.cpp: Added.
     32        * runtime/IntlRelativeTimeFormat.h: Added.
     33        * runtime/IntlRelativeTimeFormatConstructor.cpp: Added.
     34        * runtime/IntlRelativeTimeFormatConstructor.h: Added.
     35        * runtime/IntlRelativeTimeFormatPrototype.cpp: Added.
     36        * runtime/IntlRelativeTimeFormatPrototype.h: Added.
     37        * runtime/JSGlobalObject.cpp:
     38        (JSC::JSGlobalObject::init):
     39        (JSC::JSGlobalObject::visitChildren):
     40        * runtime/JSGlobalObject.h:
     41        (JSC::JSGlobalObject::relativeTimeFormatStructure):
     42        * runtime/OptionsList.h:
     43        * runtime/VM.cpp:
     44        (JSC::VM::VM):
     45        * runtime/VM.h:
     46        Add feature and runtime option.
     47
     48        * runtime/IntlDateTimeFormat.cpp:
     49        (JSC::IntlDateTimeFormat::formatToParts):
     50        * runtime/IntlPluralRules.cpp:
     51        (JSC::IntlPluralRules::initializePluralRules):
     52        (JSC::IntlPluralRules::resolvedOptions):
     53        Make "type" a property name.
     54
     55        * runtime/IntlNumberFormat.cpp:
     56        (JSC::IntlNumberFormat::initializeNumberFormat):
     57        (JSC::IntlNumberFormat::resolvedOptions):
     58        (JSC::IntlNumberFormat::formatToPartsInternal):
     59        (JSC::IntlNumberFormat::formatToParts):
     60        * runtime/IntlNumberFormat.h:
     61        Factor out formatToPartsInternal so that RelativeTimeFormat can use it with its own UNumberFormat.
     62        (This logic is too complicated to duplicate; it's because ICU won't split, e.g., "10,000" into parts for us.)
     63
     64        * runtime/IntlObject.cpp:
     65        (JSC::IntlObject::IntlObject):
     66        (JSC::IntlObject::create):
     67        (JSC::IntlObject::finishCreation):
     68        (JSC::intlAvailableLocales):
     69        (JSC::intlCollatorAvailableLocales):
     70        (JSC::isUnicodeLocaleIdentifierType):
     71        (JSC::supportedLocales):
     72        (JSC::intlDateTimeFormatAvailableLocales): Deleted.
     73        (JSC::intlNumberFormatAvailableLocales): Deleted.
     74        * runtime/IntlObject.h:
     75        (JSC::intlDateTimeFormatAvailableLocales):
     76        (JSC::intlNumberFormatAvailableLocales):
     77        (JSC::intlPluralRulesAvailableLocales):
     78        (JSC::intlRelativeTimeFormatAvailableLocales):
     79        Perform three corrections for Intl classes:
     80          1. Collator should be the only class with unique "available locales".
     81             [unum|udat]_getAvailable exist but they've deferred to uloc_getAvailable for 20 years.
     82          2. isUnicodeLocaleIdentifierType isn't just `alphanum{3,8}` but rather `alphanum{3,8} (sep alphanum{3,8})*`.
     83             This is my own mistake from r239941.
     84          3. supportedLocalesOf entries should not be frozen.
     85             Changed in https://github.com/tc39/ecma402/pull/278.
     86
     87        * tools/JSDollarVM.cpp:
     88        (JSC::functionICUVersion):
     89        (JSC::JSDollarVM::finishCreation):
     90        Add $vm.icuVersion so that we can add per-line skips to stress tests.
     91
    1922020-04-19  Yusuke Suzuki  <ysuzuki@apple.com>
    293
  • trunk/Source/JavaScriptCore/DerivedSources-input.xcfilelist

    r257410 r260349  
    143143$(PROJECT_DIR)/runtime/IntlPluralRulesConstructor.cpp
    144144$(PROJECT_DIR)/runtime/IntlPluralRulesPrototype.cpp
     145$(PROJECT_DIR)/runtime/IntlRelativeTimeFormatConstructor.cpp
     146$(PROJECT_DIR)/runtime/IntlRelativeTimeFormatPrototype.cpp
    145147$(PROJECT_DIR)/runtime/JSDataViewPrototype.cpp
    146148$(PROJECT_DIR)/runtime/JSGlobalObject.cpp
  • trunk/Source/JavaScriptCore/DerivedSources-output.xcfilelist

    r253335 r260349  
    3434$(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/IntlPluralRulesConstructor.lut.h
    3535$(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/IntlPluralRulesPrototype.lut.h
     36$(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/IntlRelativeTimeFormatConstructor.lut.h
     37$(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/IntlRelativeTimeFormatPrototype.lut.h
    3638$(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/JSCBuiltins.h
    3739$(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/JSDataViewPrototype.lut.h
  • trunk/Source/JavaScriptCore/DerivedSources.make

    r257410 r260349  
    154154    IntlPluralRulesConstructor.lut.h \
    155155    IntlPluralRulesPrototype.lut.h \
     156    IntlRelativeTimeFormatConstructor.lut.h \
     157    IntlRelativeTimeFormatPrototype.lut.h \
    156158    JSDataViewPrototype.lut.h \
    157159    JSGlobalObject.lut.h \
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r260331 r260349  
    43354335                A1FE1EB01C2C537E00A289FF /* DatePrototype.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = DatePrototype.js; sourceTree = "<group>"; };
    43364336                A27958D7FA1142B0AC9E364D /* WasmContextInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmContextInlines.h; sourceTree = "<group>"; };
     4337                A3BF884B24480BDE001B9F35 /* IntlRelativeTimeFormatPrototype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IntlRelativeTimeFormatPrototype.cpp; sourceTree = "<group>"; };
     4338                A3BF884C24480BDF001B9F35 /* IntlRelativeTimeFormatPrototype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IntlRelativeTimeFormatPrototype.h; sourceTree = "<group>"; };
     4339                A3BF884D24480BDF001B9F35 /* IntlRelativeTimeFormatConstructor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IntlRelativeTimeFormatConstructor.cpp; sourceTree = "<group>"; };
     4340                A3BF884E24480BE0001B9F35 /* IntlRelativeTimeFormatConstructor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IntlRelativeTimeFormatConstructor.h; sourceTree = "<group>"; };
     4341                A3BF884F24480BE0001B9F35 /* IntlRelativeTimeFormat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IntlRelativeTimeFormat.cpp; sourceTree = "<group>"; };
     4342                A3BF885024480BE1001B9F35 /* IntlRelativeTimeFormat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IntlRelativeTimeFormat.h; sourceTree = "<group>"; };
    43374343                A3FF9BC52234746600B1A9AB /* YarrFlags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = YarrFlags.h; path = yarr/YarrFlags.h; sourceTree = "<group>"; };
    43384344                A3FF9BC62234746600B1A9AB /* YarrFlags.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = YarrFlags.cpp; path = yarr/YarrFlags.cpp; sourceTree = "<group>"; };
     
    72667272                                7D5FB19120744BF1005DDF64 /* IntlPluralRulesPrototype.cpp */,
    72677273                                7D5FB18D20744AE8005DDF64 /* IntlPluralRulesPrototype.h */,
     7274                                A3BF884F24480BE0001B9F35 /* IntlRelativeTimeFormat.cpp */,
     7275                                A3BF885024480BE1001B9F35 /* IntlRelativeTimeFormat.h */,
     7276                                A3BF884D24480BDF001B9F35 /* IntlRelativeTimeFormatConstructor.cpp */,
     7277                                A3BF884E24480BE0001B9F35 /* IntlRelativeTimeFormatConstructor.h */,
     7278                                A3BF884B24480BDE001B9F35 /* IntlRelativeTimeFormatPrototype.cpp */,
     7279                                A3BF884C24480BDF001B9F35 /* IntlRelativeTimeFormatPrototype.h */,
    72687280                                0F275F2C1ECE079600620D47 /* Intrinsic.cpp */,
    72697281                                86BF642A148DB2B5004DE36A /* Intrinsic.h */,
  • trunk/Source/JavaScriptCore/Sources.txt

    r260273 r260349  
    820820runtime/IntlPluralRulesConstructor.cpp
    821821runtime/IntlPluralRulesPrototype.cpp
     822runtime/IntlRelativeTimeFormat.cpp
     823runtime/IntlRelativeTimeFormatConstructor.cpp
     824runtime/IntlRelativeTimeFormatPrototype.cpp
    822825runtime/IteratorOperations.cpp
    823826runtime/IteratorPrototype.cpp
  • trunk/Source/JavaScriptCore/runtime/CommonIdentifiers.h

    r260181 r260349  
    5050    macro(Reflect) \
    5151    macro(RegExp) \
     52    macro(RelativeTimeFormat) \
    5253    macro(RemotePlayback) \
    5354    macro(Set) \
     
    179180    macro(stackTraceLimit) \
    180181    macro(sticky) \
     182    macro(style) \
    181183    macro(subarray) \
    182184    macro(summary) \
     
    194196    macro(toPrecision) \
    195197    macro(toString) \
     198    macro(type) \
    196199    macro(uid) \
    197200    macro(unicode) \
  • trunk/Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp

    r260237 r260349  
    10301030
    10311031    auto resultString = String(result.data(), resultLength);
    1032     auto typePropertyName = Identifier::fromString(vm, "type");
    10331032    auto literalString = jsNontrivialString(vm, "literal"_s);
    10341033
     
    10441043            auto value = jsString(vm, resultString.substring(previousEndIndex, beginIndex - previousEndIndex));
    10451044            JSObject* part = constructEmptyObject(globalObject);
    1046             part->putDirect(vm, typePropertyName, literalString);
     1045            part->putDirect(vm, vm.propertyNames->type, literalString);
    10471046            part->putDirect(vm, vm.propertyNames->value, value);
    10481047            parts->push(globalObject, part);
     
    10551054            auto value = jsString(vm, resultString.substring(beginIndex, endIndex - beginIndex));
    10561055            JSObject* part = constructEmptyObject(globalObject);
    1057             part->putDirect(vm, typePropertyName, type);
     1056            part->putDirect(vm, vm.propertyNames->type, type);
    10581057            part->putDirect(vm, vm.propertyNames->value, value);
    10591058            parts->push(globalObject, part);
  • trunk/Source/JavaScriptCore/runtime/IntlNumberFormat.cpp

    r259941 r260349  
    33 * Copyright (C) 2016 Sukolsak Sakshuwong (sukolsak@gmail.com)
    44 * Copyright (C) 2016-2020 Apple Inc. All rights reserved.
     5 * Copyright (C) 2020 Sony Interactive Entertainment Inc.
    56 *
    67 * Redistribution and use in source and binary forms, with or without
     
    196197    m_numberingSystem = result.get("nu"_s);
    197198
    198     String styleString = intlStringOption(globalObject, options, Identifier::fromString(vm, "style"), { "decimal", "percent", "currency" }, "style must be either \"decimal\", \"percent\", or \"currency\"", "decimal");
     199    String styleString = intlStringOption(globalObject, options, vm.propertyNames->style, { "decimal", "percent", "currency" }, "style must be either \"decimal\", \"percent\", or \"currency\"", "decimal");
    199200    RETURN_IF_EXCEPTION(scope, void());
    200201    if (styleString == "decimal")
     
    442443    options->putDirect(vm, vm.propertyNames->locale, jsString(vm, m_locale));
    443444    options->putDirect(vm, vm.propertyNames->numberingSystem, jsString(vm, m_numberingSystem));
    444     options->putDirect(vm, Identifier::fromString(vm, "style"), jsNontrivialString(vm, styleString(m_style)));
     445    options->putDirect(vm, vm.propertyNames->style, jsNontrivialString(vm, styleString(m_style)));
    445446    if (m_style == Style::Currency) {
    446447        options->putDirect(vm, Identifier::fromString(vm, "currency"), jsNontrivialString(vm, m_currency));
     
    504505}
    505506
    506 JSValue IntlNumberFormat::formatToParts(JSGlobalObject* globalObject, double value)
     507void IntlNumberFormat::formatToPartsInternal(JSGlobalObject* globalObject, double value, const String& formatted, UFieldPositionIterator* iterator, JSArray* parts, JSString* unit)
    507508{
    508509    VM& vm = globalObject->vm();
    509510    auto scope = DECLARE_THROW_SCOPE(vm);
    510511
    511     // FormatNumberToParts (ECMA-402)
    512     // https://tc39.github.io/ecma402/#sec-formatnumbertoparts
    513     // https://tc39.github.io/ecma402/#sec-partitionnumberpattern
    514 
    515     if (!m_initializedNumberFormat)
    516         return throwTypeError(globalObject, scope, "Intl.NumberFormat.prototype.formatToParts called on value that's not an object initialized as a NumberFormat"_s);
    517 
    518     UErrorCode status = U_ZERO_ERROR;
    519     auto fieldItr = std::unique_ptr<UFieldPositionIterator, UFieldPositionIteratorDeleter>(ufieldpositer_open(&status));
    520     if (U_FAILURE(status))
    521         return throwTypeError(globalObject, scope, "failed to open field position iterator"_s);
    522 
    523     status = U_ZERO_ERROR;
    524     Vector<UChar, 32> result(32);
    525     auto resultLength = unum_formatDoubleForFields(m_numberFormat.get(), value, result.data(), result.size(), fieldItr.get(), &status);
    526     if (status == U_BUFFER_OVERFLOW_ERROR) {
    527         status = U_ZERO_ERROR;
    528         result.grow(resultLength);
    529         unum_formatDoubleForFields(m_numberFormat.get(), value, result.data(), resultLength, fieldItr.get(), &status);
    530     }
    531     if (U_FAILURE(status))
    532         return throwTypeError(globalObject, scope, "failed to format a number."_s);
     512    auto stringLength = formatted.length();
    533513
    534514    int32_t literalFieldType = -1;
    535     auto literalField = IntlNumberFormatField(literalFieldType, resultLength);
    536     Vector<IntlNumberFormatField> fields(resultLength, literalField);
     515    auto literalField = IntlNumberFormatField(literalFieldType, stringLength);
     516    Vector<IntlNumberFormatField, 32> fields(stringLength, literalField);
    537517    int32_t beginIndex = 0;
    538518    int32_t endIndex = 0;
    539     auto fieldType = ufieldpositer_next(fieldItr.get(), &beginIndex, &endIndex);
     519    auto fieldType = ufieldpositer_next(iterator, &beginIndex, &endIndex);
    540520    while (fieldType >= 0) {
    541521        auto size = endIndex - beginIndex;
     
    545525                fields[i] = IntlNumberFormatField(fieldType, size);
    546526        }
    547         fieldType = ufieldpositer_next(fieldItr.get(), &beginIndex, &endIndex);
    548     }
     527        fieldType = ufieldpositer_next(iterator, &beginIndex, &endIndex);
     528    }
     529
     530    auto literalString = jsNontrivialString(vm, "literal"_s);
     531    Identifier unitName;
     532    if (unit)
     533        unitName = Identifier::fromString(vm, "unit");
     534
     535    size_t currentIndex = 0;
     536    while (currentIndex < stringLength) {
     537        auto startIndex = currentIndex;
     538        auto fieldType = fields[currentIndex].type;
     539        while (currentIndex < stringLength && fields[currentIndex].type == fieldType)
     540            ++currentIndex;
     541        auto partType = fieldType == literalFieldType ? literalString : jsString(vm, partTypeString(UNumberFormatFields(fieldType), value));
     542        auto partValue = jsSubstring(vm, formatted, startIndex, currentIndex - startIndex);
     543        JSObject* part = constructEmptyObject(globalObject);
     544        part->putDirect(vm, vm.propertyNames->type, partType);
     545        part->putDirect(vm, vm.propertyNames->value, partValue);
     546        if (unit)
     547            part->putDirect(vm, unitName, unit);
     548        parts->push(globalObject, part);
     549        RETURN_IF_EXCEPTION(scope, void());
     550    }
     551}
     552
     553JSValue IntlNumberFormat::formatToParts(JSGlobalObject* globalObject, double value)
     554{
     555    VM& vm = globalObject->vm();
     556    auto scope = DECLARE_THROW_SCOPE(vm);
     557
     558    // FormatNumberToParts (ECMA-402)
     559    // https://tc39.github.io/ecma402/#sec-formatnumbertoparts
     560    // https://tc39.github.io/ecma402/#sec-partitionnumberpattern
     561
     562    if (!m_initializedNumberFormat)
     563        return throwTypeError(globalObject, scope, "Intl.NumberFormat.prototype.formatToParts called on value that's not an object initialized as a NumberFormat"_s);
     564
     565    UErrorCode status = U_ZERO_ERROR;
     566    auto fieldItr = std::unique_ptr<UFieldPositionIterator, UFieldPositionIteratorDeleter>(ufieldpositer_open(&status));
     567    if (U_FAILURE(status))
     568        return throwTypeError(globalObject, scope, "failed to open field position iterator"_s);
     569
     570    Vector<UChar, 32> result(32);
     571    auto resultLength = unum_formatDoubleForFields(m_numberFormat.get(), value, result.data(), result.size(), fieldItr.get(), &status);
     572    if (status == U_BUFFER_OVERFLOW_ERROR) {
     573        status = U_ZERO_ERROR;
     574        result.grow(resultLength);
     575        unum_formatDoubleForFields(m_numberFormat.get(), value, result.data(), resultLength, fieldItr.get(), &status);
     576    }
     577    if (U_FAILURE(status))
     578        return throwTypeError(globalObject, scope, "failed to format a number."_s);
     579
     580    auto resultString = String(result.data(), resultLength);
    549581
    550582    JSArray* parts = JSArray::tryCreate(vm, globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous), 0);
    551583    if (!parts)
    552584        return throwOutOfMemoryError(globalObject, scope);
    553     unsigned index = 0;
    554 
    555     auto resultString = String(result.data(), resultLength);
    556     auto typePropertyName = Identifier::fromString(vm, "type");
    557     auto literalString = jsNontrivialString(vm, "literal"_s);
    558 
    559     int32_t currentIndex = 0;
    560     while (currentIndex < resultLength) {
    561         auto startIndex = currentIndex;
    562         auto fieldType = fields[currentIndex].type;
    563         while (currentIndex < resultLength && fields[currentIndex].type == fieldType)
    564             ++currentIndex;
    565         auto partType = fieldType == literalFieldType ? literalString : jsString(vm, partTypeString(UNumberFormatFields(fieldType), value));
    566         auto partValue = jsSubstring(vm, resultString, startIndex, currentIndex - startIndex);
    567         JSObject* part = constructEmptyObject(globalObject);
    568         part->putDirect(vm, typePropertyName, partType);
    569         part->putDirect(vm, vm.propertyNames->value, partValue);
    570         parts->putDirectIndex(globalObject, index++, part);
    571         RETURN_IF_EXCEPTION(scope, { });
    572     }
     585
     586    formatToPartsInternal(globalObject, value, resultString, fieldItr.get(), parts);
     587    RETURN_IF_EXCEPTION(scope, { });
    573588
    574589    return parts;
  • trunk/Source/JavaScriptCore/runtime/IntlNumberFormat.h

    r260265 r260349  
    11/*
    22 * Copyright (C) 2015 Andy VanWagoner (andy@vanwagoner.family)
     3 * Copyright (C) 2020 Sony Interactive Entertainment Inc.
    34 *
    45 * Redistribution and use in source and binary forms, with or without
     
    5859    JSValue format(JSGlobalObject*, double);
    5960    JSValue format(JSGlobalObject*, JSBigInt*);
    60     JSValue formatToParts(JSGlobalObject*, double value);
     61    JSValue formatToParts(JSGlobalObject*, double);
    6162    JSObject* resolvedOptions(JSGlobalObject*);
    6263
    6364    JSBoundFunction* boundFormat() const { return m_boundFormat.get(); }
    6465    void setBoundFormat(VM&, JSBoundFunction*);
     66
     67    static void formatToPartsInternal(JSGlobalObject*, double, const String& formatted, UFieldPositionIterator*, JSArray*, JSString* unit = nullptr);
    6568
    6669protected:
  • trunk/Source/JavaScriptCore/runtime/IntlObject.cpp

    r260237 r260349  
    33 * Copyright (C) 2015 Sukolsak Sakshuwong (sukolsak@gmail.com)
    44 * Copyright (C) 2016-2020 Apple Inc. All rights reserved.
     5 * Copyright (C) 2020 Sony Interactive Entertainment Inc.
    56 *
    67 * Redistribution and use in source and binary forms, with or without
     
    4041#include "IntlPluralRulesConstructor.h"
    4142#include "IntlPluralRulesPrototype.h"
     43#include "IntlRelativeTimeFormatConstructor.h"
     44#include "IntlRelativeTimeFormatPrototype.h"
    4245#include "JSCInlines.h"
    4346#include "JSCJSValueInlines.h"
     
    4649#include "Options.h"
    4750#include <unicode/ucol.h>
    48 #include <unicode/udat.h>
    4951#include <unicode/uloc.h>
    50 #include <unicode/unum.h>
    5152#include <unicode/unumsys.h>
    5253#include <wtf/Assertions.h>
     
    115116
    116117IntlObject::IntlObject(VM& vm, Structure* structure)
    117     : JSNonFinalObject(vm, structure)
    118 {
    119 }
    120 
    121 IntlObject* IntlObject::create(VM& vm, Structure* structure)
     118    : Base(vm, structure)
     119{
     120}
     121
     122IntlObject* IntlObject::create(VM& vm, JSGlobalObject* globalObject, Structure* structure)
    122123{
    123124    IntlObject* object = new (NotNull, allocateCell<IntlObject>(vm.heap)) IntlObject(vm, structure);
    124     object->finishCreation(vm);
     125    object->finishCreation(vm, globalObject);
    125126    return object;
     127}
     128
     129void IntlObject::finishCreation(VM& vm, JSGlobalObject* globalObject)
     130{
     131    Base::finishCreation(vm);
     132    if (Options::useIntlRelativeTimeFormat()) {
     133        auto* relativeTimeFormatConstructor = IntlRelativeTimeFormatConstructor::create(vm, IntlRelativeTimeFormatConstructor::createStructure(vm, globalObject, globalObject->functionPrototype()), jsCast<IntlRelativeTimeFormatPrototype*>(globalObject->relativeTimeFormatStructure()->storedPrototypeObject()));
     134        putDirectWithoutTransition(vm, vm.propertyNames->RelativeTimeFormat, relativeTimeFormatConstructor, static_cast<unsigned>(PropertyAttribute::DontEnum));
     135    }
    126136}
    127137
     
    165175}
    166176
     177const HashSet<String>& intlAvailableLocales()
     178{
     179    static NeverDestroyed<HashSet<String>> cachedAvailableLocales;
     180    HashSet<String>& availableLocales = cachedAvailableLocales.get();
     181
     182    static std::once_flag initializeOnce;
     183    std::call_once(initializeOnce, [&] {
     184        ASSERT(availableLocales.isEmpty());
     185        int32_t count = uloc_countAvailable();
     186        for (int32_t i = 0; i < count; ++i) {
     187            String locale = convertICULocaleToBCP47LanguageTag(uloc_getAvailable(i));
     188            if (!locale.isEmpty())
     189                availableLocales.add(locale);
     190        }
     191        addMissingScriptLocales(availableLocales);
     192    });
     193    return availableLocales;
     194}
     195
    167196const HashSet<String>& intlCollatorAvailableLocales()
    168197{
     
    184213}
    185214
    186 const HashSet<String>& intlDateTimeFormatAvailableLocales()
    187 {
    188     static NeverDestroyed<HashSet<String>> cachedAvailableLocales;
    189     HashSet<String>& availableLocales = cachedAvailableLocales.get();
    190 
    191     static std::once_flag initializeOnce;
    192     std::call_once(initializeOnce, [&] {
    193         ASSERT(availableLocales.isEmpty());
    194         int32_t count = udat_countAvailable();
    195         for (int32_t i = 0; i < count; ++i) {
    196             String locale = convertICULocaleToBCP47LanguageTag(udat_getAvailable(i));
    197             if (!locale.isEmpty())
    198                 availableLocales.add(locale);
    199         }
    200         addMissingScriptLocales(availableLocales);
    201     });
    202     return availableLocales;
    203 }
    204 
    205 const HashSet<String>& intlNumberFormatAvailableLocales()
    206 {
    207     static NeverDestroyed<HashSet<String>> cachedAvailableLocales;
    208     HashSet<String>& availableLocales = cachedAvailableLocales.get();
    209 
    210     static std::once_flag initializeOnce;
    211     std::call_once(initializeOnce, [&] {
    212         ASSERT(availableLocales.isEmpty());
    213         int32_t count = unum_countAvailable();
    214         for (int32_t i = 0; i < count; ++i) {
    215             String locale = convertICULocaleToBCP47LanguageTag(unum_getAvailable(i));
    216             if (!locale.isEmpty())
    217                 availableLocales.add(locale);
    218         }
    219         addMissingScriptLocales(availableLocales);
    220     });
    221     return availableLocales;
    222 }
    223 
    224215bool intlBooleanOption(JSGlobalObject* globalObject, JSValue options, PropertyName property, bool& usesFallback)
    225216{
     
    329320    ASSERT(!string.isNull());
    330321
    331     auto length = string.length();
    332     if (length < 3 || length > 8)
    333         return false;
    334 
    335     for (auto character : string.codeUnits()) {
    336         if (!isASCIIAlphanumeric(character))
     322    for (auto part : string.splitAllowingEmptyEntries('-')) {
     323        auto length = part.length();
     324        if (length < 3 || length > 8)
    337325            return false;
     326
     327        for (auto character : part.codeUnits()) {
     328            if (!isASCIIAlphanumeric(character))
     329                return false;
     330        }
    338331    }
    339332
     
    980973
    981974    PropertyDescriptor desc;
    982     desc.setConfigurable(false);
    983     desc.setWritable(false);
    984975
    985976    size_t len = keys.size();
  • trunk/Source/JavaScriptCore/runtime/IntlObject.h

    r260265 r260349  
    22 * Copyright (C) 2015 Andy VanWagoner (andy@vanwagoner.family)
    33 * Copyright (C) 2019-2020 Apple Inc. All rights reserved.
     4 * Copyright (C) 2020 Sony Interactive Entertainment Inc.
    45 *
    56 * Redistribution and use in source and binary forms, with or without
     
    4445    }
    4546
    46     static IntlObject* create(VM&, Structure*);
     47    static IntlObject* create(VM&, JSGlobalObject*, Structure*);
    4748    static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
    4849
     
    5152private:
    5253    IntlObject(VM&, Structure*);
     54    void finishCreation(VM&, JSGlobalObject*);
    5355};
    5456
    5557String defaultLocale(JSGlobalObject*);
     58const HashSet<String>& intlAvailableLocales();
    5659const HashSet<String>& intlCollatorAvailableLocales();
    57 const HashSet<String>& intlDateTimeFormatAvailableLocales();
    58 const HashSet<String>& intlNumberFormatAvailableLocales();
    59 inline const HashSet<String>& intlPluralRulesAvailableLocales() { return intlNumberFormatAvailableLocales(); }
     60inline const HashSet<String>& intlDateTimeFormatAvailableLocales() { return intlAvailableLocales(); }
     61inline const HashSet<String>& intlNumberFormatAvailableLocales() { return intlAvailableLocales(); }
     62inline const HashSet<String>& intlPluralRulesAvailableLocales() { return intlAvailableLocales(); }
     63inline const HashSet<String>& intlRelativeTimeFormatAvailableLocales() { return intlAvailableLocales(); }
    6064
    6165bool intlBooleanOption(JSGlobalObject*, JSValue options, PropertyName, bool& usesFallback);
  • trunk/Source/JavaScriptCore/runtime/IntlPluralRules.cpp

    r259767 r260349  
    128128    }
    129129
    130     String typeString = intlStringOption(globalObject, options, Identifier::fromString(vm, "type"), { "cardinal", "ordinal" }, "type must be \"cardinal\" or \"ordinal\"", "cardinal");
     130    String typeString = intlStringOption(globalObject, options, vm.propertyNames->type, { "cardinal", "ordinal" }, "type must be \"cardinal\" or \"ordinal\"", "cardinal");
    131131    RETURN_IF_EXCEPTION(scope, void());
    132132    m_type = typeString == "ordinal" ? UPLURAL_TYPE_ORDINAL : UPLURAL_TYPE_CARDINAL;
     
    202202    JSObject* options = constructEmptyObject(globalObject);
    203203    options->putDirect(vm, vm.propertyNames->locale, jsNontrivialString(vm, m_locale));
    204     options->putDirect(vm, Identifier::fromString(vm, "type"), jsNontrivialString(vm, m_type == UPLURAL_TYPE_ORDINAL ? "ordinal"_s : "cardinal"_s));
     204    options->putDirect(vm, vm.propertyNames->type, jsNontrivialString(vm, m_type == UPLURAL_TYPE_ORDINAL ? "ordinal"_s : "cardinal"_s));
    205205    options->putDirect(vm, Identifier::fromString(vm, "minimumIntegerDigits"), jsNumber(m_minimumIntegerDigits));
    206206    options->putDirect(vm, Identifier::fromString(vm, "minimumFractionDigits"), jsNumber(m_minimumFractionDigits));
  • trunk/Source/JavaScriptCore/runtime/IntlRelativeTimeFormat.h

    r260348 r260349  
    11/*
    2  * Copyright (C) 2015 Andy VanWagoner (andy@vanwagoner.family)
     2 * Copyright (C) 2020 Sony Interactive Entertainment Inc.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2727
    2828#include "JSObject.h"
    29 #include <unicode/unum.h>
     29#include <unicode/ufieldpositer.h>
     30#include <unicode/ureldatefmt.h>
    3031
    3132namespace JSC {
    3233
    33 class JSBoundFunction;
    34 
    35 class IntlNumberFormat final : public JSNonFinalObject {
     34class IntlRelativeTimeFormat final : public JSNonFinalObject {
    3635public:
    3736    using Base = JSNonFinalObject;
     
    4140    static void destroy(JSCell* cell)
    4241    {
    43         static_cast<IntlNumberFormat*>(cell)->IntlNumberFormat::~IntlNumberFormat();
     42        static_cast<IntlRelativeTimeFormat*>(cell)->IntlRelativeTimeFormat::~IntlRelativeTimeFormat();
    4443    }
    4544
     
    4746    static IsoSubspace* subspaceFor(VM& vm)
    4847    {
    49         return vm.intlNumberFormatSpace<mode>();
     48        return vm.intlRelativeTimeFormatSpace<mode>();
    5049    }
    5150
    52     static IntlNumberFormat* create(VM&, Structure*);
     51    static IntlRelativeTimeFormat* create(VM&, Structure*);
    5352    static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
    5453
    5554    DECLARE_INFO;
    5655
    57     void initializeNumberFormat(JSGlobalObject*, JSValue locales, JSValue optionsValue);
    58     JSValue format(JSGlobalObject*, double);
    59     JSValue format(JSGlobalObject*, JSBigInt*);
    60     JSValue formatToParts(JSGlobalObject*, double value);
     56    void initializeRelativeTimeFormat(JSGlobalObject*, JSValue locales, JSValue options);
     57    JSValue format(JSGlobalObject*, double, StringView unitString);
     58    JSValue formatToParts(JSGlobalObject*, double, StringView unitString);
    6159    JSObject* resolvedOptions(JSGlobalObject*);
    6260
    63     JSBoundFunction* boundFormat() const { return m_boundFormat.get(); }
    64     void setBoundFormat(VM&, JSBoundFunction*);
    65 
    66 protected:
    67     IntlNumberFormat(VM&, Structure*);
     61private:
     62    IntlRelativeTimeFormat(VM&, Structure*);
    6863    void finishCreation(VM&);
    6964    static void visitChildren(JSCell*, SlotVisitor&);
    7065
    71 private:
    72     enum class Style : uint8_t { Decimal, Percent, Currency };
    73     enum class CurrencyDisplay : uint8_t { Code, Symbol, Name };
     66    String formatInternal(JSGlobalObject*, double, StringView unit);
    7467
     68    struct URelativeDateTimeFormatterDeleter {
     69        void operator()(URelativeDateTimeFormatter*) const;
     70    };
    7571    struct UNumberFormatDeleter {
    7672        void operator()(UNumberFormat*) const;
    7773    };
    7874
    79     static ASCIILiteral styleString(Style);
    80     static ASCIILiteral currencyDisplayString(CurrencyDisplay);
     75    std::unique_ptr<URelativeDateTimeFormatter, URelativeDateTimeFormatterDeleter> m_relativeDateTimeFormatter;
     76    std::unique_ptr<UNumberFormat, UNumberFormatDeleter> m_numberFormat;
    8177
    8278    String m_locale;
    8379    String m_numberingSystem;
    84     String m_currency;
    85     std::unique_ptr<UNumberFormat, UNumberFormatDeleter> m_numberFormat;
    86     WriteBarrier<JSBoundFunction> m_boundFormat;
    87     unsigned m_minimumIntegerDigits { 1 };
    88     unsigned m_minimumFractionDigits { 0 };
    89     unsigned m_maximumFractionDigits { 3 };
    90     unsigned m_minimumSignificantDigits { 0 };
    91     unsigned m_maximumSignificantDigits { 0 };
    92     Style m_style { Style::Decimal };
    93     CurrencyDisplay m_currencyDisplay;
    94     bool m_useGrouping { true };
    95     bool m_initializedNumberFormat { false };
    96 
    97     struct UFieldPositionIteratorDeleter {
    98         void operator()(UFieldPositionIterator*) const;
    99     };
    100 
    101     struct IntlNumberFormatField {
    102         int32_t type;
    103         int32_t size;
    104         IntlNumberFormatField(int32_t type, int32_t size)
    105             : type(type)
    106             , size(size)
    107         { }
    108     };
    109 
    110     static ASCIILiteral partTypeString(UNumberFormatFields, double);
     80    UDateRelativeDateTimeFormatterStyle m_style { UDAT_STYLE_LONG };
     81    bool m_numeric { true };
    11182};
    11283
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp

    r260312 r260349  
    8787#include "IntlPluralRules.h"
    8888#include "IntlPluralRulesPrototype.h"
     89#include "IntlRelativeTimeFormat.h"
     90#include "IntlRelativeTimeFormatPrototype.h"
    8991#include "IteratorPrototype.h"
    9092#include "JSAPIWrapperObject.h"
     
    960962            init.set(IntlPluralRules::createStructure(init.vm, globalObject, pluralRulesPrototype));
    961963        });
     964    m_relativeTimeFormatStructure.initLater(
     965        [] (const Initializer<Structure>& init) {
     966            JSGlobalObject* globalObject = jsCast<JSGlobalObject*>(init.owner);
     967            IntlRelativeTimeFormatPrototype* relativeTimeFormatPrototype = IntlRelativeTimeFormatPrototype::create(init.vm, IntlRelativeTimeFormatPrototype::createStructure(init.vm, globalObject, globalObject->objectPrototype()));
     968            init.set(IntlRelativeTimeFormat::createStructure(init.vm, globalObject, relativeTimeFormatPrototype));
     969        });
    962970    m_defaultCollator.initLater(
    963971        [] (const Initializer<IntlCollator>& init) {
     
    971979        });
    972980
    973     IntlObject* intl = IntlObject::create(vm, IntlObject::createStructure(vm, this, m_objectPrototype.get()));
     981    IntlObject* intl = IntlObject::create(vm, this, IntlObject::createStructure(vm, this, m_objectPrototype.get()));
    974982    putDirectWithoutTransition(vm, vm.propertyNames->Intl, intl, static_cast<unsigned>(PropertyAttribute::DontEnum));
    975983
     
    17701778    thisObject->m_dateTimeFormatStructure.visit(visitor);
    17711779    thisObject->m_pluralRulesStructure.visit(visitor);
     1780    thisObject->m_relativeTimeFormatStructure.visit(visitor);
    17721781
    17731782    visitor.append(thisObject->m_nullGetterFunction);
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h

    r260331 r260349  
    295295    LazyProperty<JSGlobalObject, Structure> m_dateTimeFormatStructure;
    296296    LazyProperty<JSGlobalObject, Structure> m_pluralRulesStructure;
     297    LazyProperty<JSGlobalObject, Structure> m_relativeTimeFormatStructure;
    297298
    298299    WriteBarrier<NullGetterFunction> m_nullGetterFunction;
     
    789790    Structure* dateTimeFormatStructure() { return m_dateTimeFormatStructure.get(this); }
    790791    Structure* pluralRulesStructure() { return m_pluralRulesStructure.get(this); }
     792    Structure* relativeTimeFormatStructure() { return m_relativeTimeFormatStructure.get(this); }
    791793
    792794    JS_EXPORT_PRIVATE void setRemoteDebuggingEnabled(bool);
  • trunk/Source/JavaScriptCore/runtime/OptionsList.h

    r260345 r260349  
    485485    v(Bool, useWeakRefs, false, Normal, "Expose the WeakRef constructor.") \
    486486    v(Bool, useBigInt, true, Normal, "If true, we will enable BigInt support.") \
     487    v(Bool, useIntlRelativeTimeFormat, false, Normal, "Expose the Intl.RelativeTimeFormat constructor.") \
    487488    v(Bool, useArrayAllocationProfiling, true, Normal, "If true, we will use our normal array allocation profiling. If false, the allocation profile will always claim to be undecided.") \
    488489    v(Bool, forcePolyProto, false, Normal, "If true, create_this will always create an object with a poly proto structure.") \
  • trunk/Source/JavaScriptCore/runtime/VM.cpp

    r260331 r260349  
    7878#include "IntlNumberFormat.h"
    7979#include "IntlPluralRules.h"
     80#include "IntlRelativeTimeFormat.h"
    8081#include "IsoHeapCellType.h"
    8182#include "IsoInlinedHeapCellType.h"
     
    341342    , intlNumberFormatHeapCellType(IsoHeapCellType::create<IntlNumberFormat>())
    342343    , intlPluralRulesHeapCellType(IsoHeapCellType::create<IntlPluralRules>())
     344    , intlRelativeTimeFormatHeapCellType(IsoHeapCellType::create<IntlRelativeTimeFormat>())
    343345#if ENABLE(WEBASSEMBLY)
    344346    , webAssemblyCodeBlockHeapCellType(IsoHeapCellType::create<JSWebAssemblyCodeBlock>())
     
    15121514DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(intlNumberFormatSpace, intlNumberFormatHeapCellType.get(), IntlNumberFormat)
    15131515DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(intlPluralRulesSpace, intlPluralRulesHeapCellType.get(), IntlPluralRules)
     1516DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(intlRelativeTimeFormatSpace, intlRelativeTimeFormatHeapCellType.get(), IntlRelativeTimeFormat)
    15141517#if ENABLE(WEBASSEMBLY)
    15151518DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(jsToWasmICCalleeSpace, cellHeapCellType.get(), JSToWasmICCallee)
  • trunk/Source/JavaScriptCore/runtime/VM.h

    r260331 r260349  
    129129class IntlNumberFormat;
    130130class IntlPluralRules;
     131class IntlRelativeTimeFormat;
    131132class JSAPIGlobalObject;
    132133class JSAPIWrapperGlobalObject;
     
    402403    std::unique_ptr<IsoHeapCellType> intlNumberFormatHeapCellType;
    403404    std::unique_ptr<IsoHeapCellType> intlPluralRulesHeapCellType;
     405    std::unique_ptr<IsoHeapCellType> intlRelativeTimeFormatHeapCellType;
    404406#if ENABLE(WEBASSEMBLY)
    405407    std::unique_ptr<IsoHeapCellType> webAssemblyCodeBlockHeapCellType;
     
    558560    DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(intlNumberFormatSpace)
    559561    DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(intlPluralRulesSpace)
     562    DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(intlRelativeTimeFormatSpace)
    560563#if ENABLE(WEBASSEMBLY)
    561564    DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(jsToWasmICCalleeSpace)
  • trunk/Source/JavaScriptCore/tools/JSDollarVM.cpp

    r260331 r260349  
    5454#include "VMInspector.h"
    5555#include "WasmCapabilities.h"
     56#include <unicode/uversion.h>
    5657#include <wtf/Atomics.h>
    5758#include <wtf/CPUTime.h>
     
    29782979}
    29792980
     2981static EncodedJSValue JSC_HOST_CALL functionICUVersion(JSGlobalObject*, CallFrame*)
     2982{
     2983    UVersionInfo versionInfo;
     2984    u_getVersion(versionInfo);
     2985    return JSValue::encode(jsNumber(versionInfo[0]));
     2986}
     2987
    29802988void JSDollarVM::finishCreation(VM& vm)
    29812989{
     
    31153123
    31163124    addFunction(vm, "setUserPreferredLanguages", functionSetUserPreferredLanguages, 1);
     3125    addFunction(vm, "icuVersion", functionICUVersion, 0);
    31173126
    31183127    m_objectDoingSideEffectPutWithoutCorrectSlotStatusStructure.set(vm, this, ObjectDoingSideEffectPutWithoutCorrectSlotStatus::createStructure(vm, globalObject, jsNull()));
  • trunk/Tools/ChangeLog

    r260341 r260349  
     12020-04-19  Ross Kirsling  <ross.kirsling@sony.com>
     2
     3        [ECMA-402] Intl.RelativeTimeFormat missing in WebKit
     4        https://bugs.webkit.org/show_bug.cgi?id=209770
     5
     6        Reviewed by Darin Adler.
     7
     8        * Scripts/run-jsc-stress-tests:
     9        Add runIntlRelativeTimeFormatEnabled.
     10
    1112020-04-19  Don Olmstead  <don.olmstead@sony.com>
    212
  • trunk/Tools/Scripts/run-jsc-stress-tests

    r260331 r260349  
    711711end
    712712
     713def runIntlRelativeTimeFormatEnabled(*optionalTestSpecificOptions)
     714    run("intl-relativetimeformat-enabled", "--useIntlRelativeTimeFormat=true" , *(FTL_OPTIONS + optionalTestSpecificOptions))
     715end
     716
    713717def runFTLNoCJIT(*optionalTestSpecificOptions)
    714718    run("misc-ftl-no-cjit", *(FTL_OPTIONS + NO_CJIT_OPTIONS + optionalTestSpecificOptions))
Note: See TracChangeset for help on using the changeset viewer.