Changeset 242047 in webkit


Ignore:
Timestamp:
Feb 25, 2019 10:32:18 AM (5 years ago)
Author:
ysuzuki@apple.com
Message:

[JSC] Drop direct references to Intl constructors by rewriting Intl JS builtins in C++
https://bugs.webkit.org/show_bug.cgi?id=194976

Reviewed by Michael Saboff.

This patch paves the way to making IntlObject allocation lazy by removing direct references
to Intl constructors (Intl.Collator etc.) from builtin JS. To achieve that,

  1. We implement String.prototype.toLocaleCompare and Number.prototype.toLocaleString in C++ instead of JS builtins. Since these functions end up calling ICU C++ runtime, writing them in JS does not offer performance improvement.
  1. We remove @DateTimeFormat constructor reference, and instead, exposing @dateTimeFormat function, which returns formatted string directly. We still have JS builtins for DateTimeFormat things because the initialization of its "options" JSObject involves many get_by_id / put_by_id things, which are efficient in JS. But we avoid exposing @DateTimeFormat directly, so that Intl constructors can be lazily allocated.
  • CMakeLists.txt:
  • DerivedSources-input.xcfilelist:
  • DerivedSources.make:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • builtins/BuiltinNames.h:
  • builtins/DatePrototype.js:

(toLocaleString):
(toLocaleDateString):
(toLocaleTimeString):

  • builtins/NumberPrototype.js: Removed.
  • builtins/StringPrototype.js:

(intrinsic.StringPrototypeReplaceIntrinsic.replace):
(globalPrivate.getDefaultCollator): Deleted.

  • runtime/JSGlobalObject.cpp:

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

  • runtime/JSGlobalObject.h:
  • runtime/JSGlobalObjectFunctions.cpp:

(JSC::globalFuncDateTimeFormat):

  • runtime/JSGlobalObjectFunctions.h:
  • runtime/NumberPrototype.cpp:

(JSC::NumberPrototype::finishCreation):
(JSC::throwVMToThisNumberError):
(JSC::numberProtoFuncToExponential):
(JSC::numberProtoFuncToFixed):
(JSC::numberProtoFuncToPrecision):
(JSC::numberProtoFuncToString):
(JSC::numberProtoFuncToLocaleString):
(JSC::numberProtoFuncValueOf):

  • runtime/StringPrototype.cpp:

(JSC::StringPrototype::finishCreation):
(JSC::stringProtoFuncLocaleCompare):

Location:
trunk/Source/JavaScriptCore
Files:
1 deleted
14 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/CMakeLists.txt

    r242019 r242047  
    11891189    ${JAVASCRIPTCORE_DIR}/builtins/ModuleLoader.js
    11901190    ${JAVASCRIPTCORE_DIR}/builtins/NumberConstructor.js
    1191     ${JAVASCRIPTCORE_DIR}/builtins/NumberPrototype.js
    11921191    ${JAVASCRIPTCORE_DIR}/builtins/ObjectConstructor.js
    11931192    ${JAVASCRIPTCORE_DIR}/builtins/PromiseConstructor.js
  • trunk/Source/JavaScriptCore/ChangeLog

    r242019 r242047  
     12019-02-25  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        [JSC] Drop direct references to Intl constructors by rewriting Intl JS builtins in C++
     4        https://bugs.webkit.org/show_bug.cgi?id=194976
     5
     6        Reviewed by Michael Saboff.
     7
     8        This patch paves the way to making IntlObject allocation lazy by removing direct references
     9        to Intl constructors (Intl.Collator etc.) from builtin JS. To achieve that,
     10
     11        1. We implement String.prototype.toLocaleCompare and Number.prototype.toLocaleString in C++
     12           instead of JS builtins. Since these functions end up calling ICU C++ runtime, writing them in
     13           JS does not offer performance improvement.
     14
     15        2. We remove @DateTimeFormat constructor reference, and instead, exposing @dateTimeFormat function,
     16           which returns formatted string directly. We still have JS builtins for DateTimeFormat things
     17           because the initialization of its "options" JSObject involves many get_by_id / put_by_id things,
     18           which are efficient in JS. But we avoid exposing @DateTimeFormat directly, so that Intl constructors
     19           can be lazily allocated.
     20
     21        * CMakeLists.txt:
     22        * DerivedSources-input.xcfilelist:
     23        * DerivedSources.make:
     24        * JavaScriptCore.xcodeproj/project.pbxproj:
     25        * builtins/BuiltinNames.h:
     26        * builtins/DatePrototype.js:
     27        (toLocaleString):
     28        (toLocaleDateString):
     29        (toLocaleTimeString):
     30        * builtins/NumberPrototype.js: Removed.
     31        * builtins/StringPrototype.js:
     32        (intrinsic.StringPrototypeReplaceIntrinsic.replace):
     33        (globalPrivate.getDefaultCollator): Deleted.
     34        * runtime/JSGlobalObject.cpp:
     35        (JSC::JSGlobalObject::init):
     36        (JSC::JSGlobalObject::visitChildren):
     37        (JSC::JSGlobalObject::defaultCollator):
     38        * runtime/JSGlobalObject.h:
     39        * runtime/JSGlobalObjectFunctions.cpp:
     40        (JSC::globalFuncDateTimeFormat):
     41        * runtime/JSGlobalObjectFunctions.h:
     42        * runtime/NumberPrototype.cpp:
     43        (JSC::NumberPrototype::finishCreation):
     44        (JSC::throwVMToThisNumberError):
     45        (JSC::numberProtoFuncToExponential):
     46        (JSC::numberProtoFuncToFixed):
     47        (JSC::numberProtoFuncToPrecision):
     48        (JSC::numberProtoFuncToString):
     49        (JSC::numberProtoFuncToLocaleString):
     50        (JSC::numberProtoFuncValueOf):
     51        * runtime/StringPrototype.cpp:
     52        (JSC::StringPrototype::finishCreation):
     53        (JSC::stringProtoFuncLocaleCompare):
     54
    1552019-02-24  Devin Rousso  <drousso@apple.com>
    256
  • trunk/Source/JavaScriptCore/DerivedSources-input.xcfilelist

    r242019 r242047  
    4444$(PROJECT_DIR)/builtins/ModuleLoader.js
    4545$(PROJECT_DIR)/builtins/NumberConstructor.js
    46 $(PROJECT_DIR)/builtins/NumberPrototype.js
    4746$(PROJECT_DIR)/builtins/ObjectConstructor.js
    4847$(PROJECT_DIR)/builtins/PromiseConstructor.js
  • trunk/Source/JavaScriptCore/DerivedSources.make

    r242019 r242047  
    106106    $(JavaScriptCore)/builtins/ModuleLoader.js \
    107107    $(JavaScriptCore)/builtins/NumberConstructor.js \
    108     $(JavaScriptCore)/builtins/NumberPrototype.js \
    109108    $(JavaScriptCore)/builtins/ObjectConstructor.js \
    110109    $(JavaScriptCore)/builtins/PromiseConstructor.js \
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r241929 r242047  
    20322032                        dstSubfolderSpec = 16;
    20332033                        files = (
     2034                                53C3D5E521ECE7720087FDFC /* basic.js in Copy Support Script */,
    20342035                                52D13091221CE176009C836C /* foo.js in Copy Support Script */,
    2035                                 53C3D5E521ECE7720087FDFC /* basic.js in Copy Support Script */,
    20362036                                FECB8B2A1D25CB5A006F2463 /* testapi-function-overrides.js in Copy Support Script */,
    20372037                                5DBB151B131D0B310056AD36 /* testapi.js in Copy Support Script */,
     
    40664066                A1587D731B4DC1C600D69849 /* IntlDateTimeFormatConstructor.lut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IntlDateTimeFormatConstructor.lut.h; sourceTree = "<group>"; };
    40674067                A1587D741B4DC1C600D69849 /* IntlDateTimeFormatPrototype.lut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IntlDateTimeFormatPrototype.lut.h; sourceTree = "<group>"; };
    4068                 A15DE5C51C0FBF8D0089133D /* NumberPrototype.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = NumberPrototype.js; sourceTree = "<group>"; };
    40694068                A1712B3A11C7B212007A5315 /* RegExpCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegExpCache.cpp; sourceTree = "<group>"; };
    40704069                A1712B3E11C7B228007A5315 /* RegExpCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegExpCache.h; sourceTree = "<group>"; };
     
    81938192                                E30677971B8BC6F5003F87F0 /* ModuleLoader.js */,
    81948193                                A52704861D027C8800354C37 /* NumberConstructor.js */,
    8195                                 A15DE5C51C0FBF8D0089133D /* NumberPrototype.js */,
    81968194                                7CF9BC5C1B65D9B1009DB1EF /* ObjectConstructor.js */,
    81978195                                7CF9BC5E1B65D9B1009DB1EF /* PromiseConstructor.js */,
     
    92609258                                8BC064891E1ABA6400B2B8CA /* JSAsyncGeneratorFunction.h in Headers */,
    92619259                                BC18C4180E16F5CD00B34460 /* JSBase.h in Headers */,
     9260                                79872C48221BBAF3008C6969 /* JSBaseInternal.h in Headers */,
    92629261                                140D17D70E8AD4A9000CD17D /* JSBasePrivate.h in Headers */,
    92639262                                868921C21F9C0CB7001159F6 /* JSBigInt.h in Headers */,
     
    97669765                                0FF42749158EBE91004CB9FF /* udis86_types.h in Headers */,
    97679766                                A7E5AB391799E4B200D2833D /* UDis86Disassembler.h in Headers */,
    9768                                 79872C48221BBAF3008C6969 /* JSBaseInternal.h in Headers */,
    97699767                                A7A8AF4117ADB5F3005AB174 /* Uint16Array.h in Headers */,
    97709768                                866739D313BFDE710023D87C /* Uint16WithFraction.h in Headers */,
  • trunk/Source/JavaScriptCore/builtins/BuiltinNames.h

    r241644 r242047  
    127127    macro(asyncGeneratorQueueItemPrevious) \
    128128    macro(generatorResumeMode) \
    129     macro(Collator) \
    130     macro(DateTimeFormat) \
    131     macro(NumberFormat) \
    132     macro(PluralRules) \
     129    macro(dateTimeFormat) \
    133130    macro(intlSubstituteValue) \
    134131    macro(thisTimeValue) \
    135     macro(thisNumberValue) \
    136132    macro(newTargetLocal) \
    137133    macro(derivedConstructor) \
  • trunk/Source/JavaScriptCore/builtins/DatePrototype.js

    r231460 r242047  
    7878    var options = toDateTimeOptionsAnyAll(@argument(1));
    7979    var locales = @argument(0);
    80 
    81     var dateFormat = new @DateTimeFormat(locales, options);
    82     return dateFormat.format(value);
     80    return @dateTimeFormat(locales, options, value);
    8381}
    8482
     
    128126    var options = toDateTimeOptionsDateDate(@argument(1));
    129127    var locales = @argument(0);
    130 
    131     var dateFormat = new @DateTimeFormat(locales, options);
    132     return dateFormat.format(value);
     128    return @dateTimeFormat(locales, options, value);
    133129}
    134130
     
    177173    var options = toDateTimeOptionsTimeTime(@argument(1));
    178174    var locales = @argument(0);
    179 
    180     var dateFormat = new @DateTimeFormat(locales, options);
    181     return dateFormat.format(value);
     175    return @dateTimeFormat(locales, options, value);
    182176}
  • trunk/Source/JavaScriptCore/builtins/StringPrototype.js

    r239761 r242047  
    238238    return thisString.@replaceUsingStringSearch(searchString, replace);
    239239}
    240    
    241 @globalPrivate
    242 function getDefaultCollator()
    243 {
    244     "use strict";
    245 
    246     return @getDefaultCollator.collator || (@getDefaultCollator.collator = new @Collator());
    247 }
    248    
    249 function localeCompare(that/*, locales, options */)
    250 {
    251     "use strict";
    252 
    253     // 13.1.1 String.prototype.localeCompare (that [, locales [, options ]]) (ECMA-402 2.0)
    254     // http://ecma-international.org/publications/standards/Ecma-402.htm
    255 
    256     // 1. Let O be RequireObjectCoercible(this value).
    257     if (@isUndefinedOrNull(this))
    258         @throwTypeError("String.prototype.localeCompare requires that |this| not be null or undefined");
    259 
    260     // 2. Let S be ToString(O).
    261     // 3. ReturnIfAbrupt(S).
    262     var thisString = @toString(this);
    263 
    264     // 4. Let That be ToString(that).
    265     // 5. ReturnIfAbrupt(That).
    266     var thatString = @toString(that);
    267 
    268     // Avoid creating a new collator every time for defaults.
    269     var locales = @argument(1);
    270     var options = @argument(2);
    271     if (locales === @undefined && options === @undefined)
    272         return @getDefaultCollator().compare(thisString, thatString);
    273 
    274     // 6. Let collator be Construct(%Collator%, «locales, options»).
    275     // 7. ReturnIfAbrupt(collator).
    276     var collator = new @Collator(locales, options);
    277 
    278     // 8. Return CompareStrings(collator, S, That).
    279     return collator.compare(thisString, thatString);
    280 }
    281240
    282241function search(regexp)
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp

    r241769 r242047  
    179179
    180180#if ENABLE(INTL)
     181#include "IntlCollator.h"
    181182#include "IntlObject.h"
    182183#include <unicode/ucol.h>
     
    831832    JSFunction* privateFuncInstanceOf = JSFunction::create(vm, this, 0, String(), objectPrivateFuncInstanceOf);
    832833    JSFunction* privateFuncThisTimeValue = JSFunction::create(vm, this, 0, String(), dateProtoFuncGetTime);
    833     JSFunction* privateFuncThisNumberValue = JSFunction::create(vm, this, 0, String(), numberProtoFuncValueOf);
     834#if ENABLE(INTL)
     835    JSFunction* privateFuncDateTimeFormat = JSFunction::create(vm, this, 0, String(), globalFuncDateTimeFormat);
     836#endif
    834837    JSFunction* privateFuncIsArrayConstructor = JSFunction::create(vm, this, 0, String(), arrayConstructorPrivateFuncIsArrayConstructor);
    835838    JSFunction* privateFuncIsArraySlow = JSFunction::create(vm, this, 0, String(), arrayConstructorPrivateFuncIsArraySlow);
     
    921924        GlobalPropertyInfo(vm.propertyNames->builtinNames().SetPrivateName(), setConstructor, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
    922925        GlobalPropertyInfo(vm.propertyNames->builtinNames().thisTimeValuePrivateName(), privateFuncThisTimeValue, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
    923         GlobalPropertyInfo(vm.propertyNames->builtinNames().thisNumberValuePrivateName(), privateFuncThisNumberValue, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
    924926#if ENABLE(INTL)
    925         GlobalPropertyInfo(vm.propertyNames->builtinNames().CollatorPrivateName(), intl->getDirect(vm, vm.propertyNames->Collator), PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
    926         GlobalPropertyInfo(vm.propertyNames->builtinNames().DateTimeFormatPrivateName(), intl->getDirect(vm, vm.propertyNames->DateTimeFormat), PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
    927         GlobalPropertyInfo(vm.propertyNames->builtinNames().NumberFormatPrivateName(), intl->getDirect(vm, vm.propertyNames->NumberFormat), PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
    928         GlobalPropertyInfo(vm.propertyNames->builtinNames().PluralRulesPrivateName(), intl->getDirect(vm, vm.propertyNames->PluralRules), PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
     927        GlobalPropertyInfo(vm.propertyNames->builtinNames().dateTimeFormatPrivateName(), privateFuncDateTimeFormat, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
    929928#endif // ENABLE(INTL)
    930929
     
    15691568#if ENABLE(INTL)
    15701569    visitor.append(thisObject->m_intlObject);
     1570    visitor.append(thisObject->m_defaultCollator);
    15711571#endif
    15721572    visitor.append(thisObject->m_nullGetterFunction);
     
    18661866    return m_intlPluralRulesAvailableLocales;
    18671867}
     1868
     1869IntlCollator* JSGlobalObject::defaultCollator(ExecState* exec)
     1870{
     1871    VM& vm = exec->vm();
     1872    auto scope = DECLARE_THROW_SCOPE(vm);
     1873
     1874    if (m_defaultCollator)
     1875        return m_defaultCollator.get();
     1876
     1877    IntlCollator* collator = IntlCollator::create(vm, intlObject()->collatorStructure());
     1878    collator->initializeCollator(*exec, jsUndefined(), jsUndefined());
     1879    RETURN_IF_EXCEPTION(scope, nullptr);
     1880    m_defaultCollator.set(vm, this, collator);
     1881    return collator;
     1882}
     1883
    18681884#endif // ENABLE(INTL)
    18691885
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h

    r241741 r242047  
    8484class InputCursor;
    8585class IntlObject;
     86class IntlCollator;
    8687class JSArrayBuffer;
    8788class JSArrayBufferPrototype;
     
    277278#if ENABLE(INTL)
    278279    WriteBarrier<IntlObject> m_intlObject;
     280    WriteBarrier<IntlCollator> m_defaultCollator;
    279281#endif
    280282    WriteBarrier<NullGetterFunction> m_nullGetterFunction;
     
    588590#if ENABLE(INTL)
    589591    IntlObject* intlObject() const { return m_intlObject.get(); }
     592    IntlCollator* defaultCollator(ExecState*);
    590593#endif
    591594
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp

    r241256 r242047  
    3232#include "IndirectEvalExecutable.h"
    3333#include "Interpreter.h"
     34#include "IntlDateTimeFormat.h"
     35#include "IntlObject.h"
    3436#include "JSCInlines.h"
    3537#include "JSFunction.h"
     
    831833}
    832834
     835#if ENABLE(INTL)
     836EncodedJSValue JSC_HOST_CALL globalFuncDateTimeFormat(ExecState* exec)
     837{
     838    VM& vm = exec->vm();
     839    auto scope = DECLARE_THROW_SCOPE(vm);
     840
     841    JSGlobalObject* globalObject = exec->lexicalGlobalObject();
     842    IntlDateTimeFormat* dateTimeFormat = IntlDateTimeFormat::create(vm, globalObject->intlObject()->dateTimeFormatStructure());
     843    dateTimeFormat->initializeDateTimeFormat(*exec, exec->argument(0), exec->argument(1));
     844    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     845    double value = exec->argument(2).toNumber(exec);
     846    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     847    RELEASE_AND_RETURN(scope, JSValue::encode(dateTimeFormat->format(*exec, value)));
     848}
     849#endif
     850
    833851} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.h

    r233122 r242047  
    5656EncodedJSValue JSC_HOST_CALL globalFuncImportModule(ExecState*);
    5757EncodedJSValue JSC_HOST_CALL globalFuncPropertyIsEnumerable(ExecState*);
     58EncodedJSValue JSC_HOST_CALL globalFuncDateTimeFormat(ExecState*);
    5859
    5960double jsToNumber(StringView);
  • trunk/Source/JavaScriptCore/runtime/NumberPrototype.cpp

    r241244 r242047  
    2525#include "BigInteger.h"
    2626#include "Error.h"
    27 #include "JSCBuiltins.h"
     27#include "IntlNumberFormat.h"
     28#include "IntlObject.h"
    2829#include "JSCInlines.h"
    2930#include "JSFunction.h"
     
    8182
    8283    JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->toString, numberProtoFuncToString, static_cast<unsigned>(PropertyAttribute::DontEnum), 1, NumberPrototypeToStringIntrinsic);
    83 #if ENABLE(INTL)
    84     JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("toLocaleString", numberPrototypeToLocaleStringCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
    85 #endif // ENABLE(INTL)
    86 
    8784    ASSERT(inherits(vm, info()));
    8885}
     
    108105
    109106    return false;
     107}
     108
     109static ALWAYS_INLINE EncodedJSValue throwVMToThisNumberError(ExecState* exec, ThrowScope& scope, JSValue thisValue)
     110{
     111    auto typeString = asString(jsTypeStringForValue(exec->vm(), exec->lexicalGlobalObject(), thisValue))->value(exec);
     112    scope.assertNoException();
     113    return throwVMTypeError(exec, scope, WTF::makeString("thisNumberValue called on incompatible ", typeString));
    110114}
    111115
     
    409413    double x;
    410414    if (!toThisNumber(vm, exec->thisValue(), x))
    411         return throwVMTypeError(exec, scope);
     415        return throwVMToThisNumberError(exec, scope, exec->thisValue());
    412416
    413417    // Perform ToInteger on the argument before remaining steps.
     
    446450    double x;
    447451    if (!toThisNumber(vm, exec->thisValue(), x))
    448         return throwVMTypeError(exec, scope);
     452        return throwVMToThisNumberError(exec, scope, exec->thisValue());
    449453
    450454    // Get the argument.
     
    483487    double x;
    484488    if (!toThisNumber(vm, exec->thisValue(), x))
    485         return throwVMTypeError(exec, scope);
     489        return throwVMToThisNumberError(exec, scope, exec->thisValue());
    486490
    487491    // Perform ToInteger on the argument before remaining steps.
     
    580584    double doubleValue;
    581585    if (!toThisNumber(vm, state->thisValue(), doubleValue))
    582         return throwVMTypeError(state, scope);
     586        return throwVMToThisNumberError(state, scope, state->thisValue());
    583587
    584588    auto radix = extractToStringRadixArgument(state, state->argument(0), scope);
     
    595599    double x;
    596600    if (!toThisNumber(vm, exec->thisValue(), x))
    597         return throwVMTypeError(exec, scope);
    598 
     601        return throwVMToThisNumberError(exec, scope, exec->thisValue());
     602
     603#if ENABLE(INTL)
     604    JSGlobalObject* globalObject = exec->lexicalGlobalObject();
     605    IntlNumberFormat* numberFormat = IntlNumberFormat::create(vm, globalObject->intlObject()->numberFormatStructure());
     606    numberFormat->initializeNumberFormat(*exec, exec->argument(0), exec->argument(1));
     607    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     608    RELEASE_AND_RETURN(scope, JSValue::encode(numberFormat->formatNumber(*exec, x)));
     609#else
    599610    return JSValue::encode(jsNumber(x).toString(exec));
     611#endif
    600612}
    601613
     
    608620    JSValue thisValue = exec->thisValue();
    609621    if (!toThisNumber(vm, thisValue, x))
    610         return throwVMTypeError(exec, scope, WTF::makeString("thisNumberValue called on incompatible ", asString(jsTypeStringForValue(exec, thisValue))->value(exec)));
     622        return throwVMToThisNumberError(exec, scope, exec->thisValue());
    611623    return JSValue::encode(jsNumber(x));
    612624}
  • trunk/Source/JavaScriptCore/runtime/StringPrototype.cpp

    r241991 r242047  
    3030#include "FrameTracers.h"
    3131#include "InterpreterInlines.h"
     32#include "IntlCollator.h"
    3233#include "IntlObject.h"
    3334#include "JITCodeInlines.h"
     
    144145    JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION("toLowerCase", stringProtoFuncToLowerCase, static_cast<unsigned>(PropertyAttribute::DontEnum), 0, StringPrototypeToLowerCaseIntrinsic);
    145146    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("toUpperCase", stringProtoFuncToUpperCase, static_cast<unsigned>(PropertyAttribute::DontEnum), 0);
     147    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("localeCompare", stringProtoFuncLocaleCompare, static_cast<unsigned>(PropertyAttribute::DontEnum), 1);
    146148#if ENABLE(INTL)
    147     JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("localeCompare", stringPrototypeLocaleCompareCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
    148149    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("toLocaleLowerCase", stringProtoFuncToLocaleLowerCase, static_cast<unsigned>(PropertyAttribute::DontEnum), 0);
    149150    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("toLocaleUpperCase", stringProtoFuncToLocaleUpperCase, static_cast<unsigned>(PropertyAttribute::DontEnum), 0);
    150151#else
    151     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("localeCompare", stringProtoFuncLocaleCompare, static_cast<unsigned>(PropertyAttribute::DontEnum), 1);
    152152    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("toLocaleLowerCase", stringProtoFuncToLowerCase, static_cast<unsigned>(PropertyAttribute::DontEnum), 0);
    153153    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("toLocaleUpperCase", stringProtoFuncToUpperCase, static_cast<unsigned>(PropertyAttribute::DontEnum), 0);
     
    14871487EncodedJSValue JSC_HOST_CALL stringProtoFuncLocaleCompare(ExecState* exec)
    14881488{
    1489     VM& vm = exec->vm();
    1490     auto scope = DECLARE_THROW_SCOPE(vm);
    1491 
     1489    // 13.1.1 String.prototype.localeCompare (that [, locales [, options ]]) (ECMA-402 2.0)
     1490    // http://ecma-international.org/publications/standards/Ecma-402.htm
     1491
     1492    VM& vm = exec->vm();
     1493    auto scope = DECLARE_THROW_SCOPE(vm);
     1494
     1495    // 1. Let O be RequireObjectCoercible(this value).
    14921496    JSValue thisValue = exec->thisValue();
    14931497    if (!checkObjectCoercible(thisValue))
    1494         return throwVMTypeError(exec, scope);
    1495     String s = thisValue.toWTFString(exec);
    1496     RETURN_IF_EXCEPTION(scope, encodedJSValue());
    1497 
    1498     JSValue a0 = exec->argument(0);
    1499     String str = a0.toWTFString(exec);
    1500     RETURN_IF_EXCEPTION(scope, encodedJSValue());
    1501     return JSValue::encode(jsNumber(Collator().collate(s, str)));
     1498        return throwVMTypeError(exec, scope, "String.prototype.localeCompare requires that |this| not be null or undefined"_s);
     1499
     1500    // 2. Let S be ToString(O).
     1501    // 3. ReturnIfAbrupt(S).
     1502    String string = thisValue.toWTFString(exec);
     1503    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     1504
     1505    // 4. Let That be ToString(that).
     1506    // 5. ReturnIfAbrupt(That).
     1507    JSValue thatValue = exec->argument(0);
     1508    String that = thatValue.toWTFString(exec);
     1509    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     1510
     1511#if ENABLE(INTL)
     1512    JSGlobalObject* globalObject = exec->lexicalGlobalObject();
     1513    JSValue locales = exec->argument(1);
     1514    JSValue options = exec->argument(2);
     1515    IntlCollator* collator = nullptr;
     1516    if (locales.isUndefined() && options.isUndefined()) {
     1517        collator = globalObject->defaultCollator(exec);
     1518        RETURN_IF_EXCEPTION(scope, encodedJSValue());
     1519    } else {
     1520        collator = IntlCollator::create(vm, globalObject->intlObject()->collatorStructure());
     1521        collator->initializeCollator(*exec, locales, options);
     1522        RETURN_IF_EXCEPTION(scope, encodedJSValue());
     1523    }
     1524    RELEASE_AND_RETURN(scope, JSValue::encode(collator->compareStrings(*exec, string, that)));
     1525#else
     1526    return JSValue::encode(jsNumber(Collator().collate(string, that)));
     1527#endif
    15021528}
    15031529
Note: See TracChangeset for help on using the changeset viewer.