Changeset 287560 in webkit


Ignore:
Timestamp:
Jan 3, 2022 9:12:15 PM (7 months ago)
Author:
ysuzuki@apple.com
Message:

Array.prototype.toLocaleString does not respect deletion of Object.prototype.toLocaleString
https://bugs.webkit.org/show_bug.cgi?id=232723

Reviewed by Alexey Shvayka.

JSTests:

  • ChakraCore/test/Array/toLocaleString.baseline-jsc:
  • stress/array-tolocalestring-delete-tolocalestring.js: Added.

(shouldThrow):

  • stress/array-tolocalestring-empty-separator.js: Added.

(shouldBe):

  • stress/array-tolocalestring-options.js: Added.

(shouldBe):

  • stress/array-tolocalestring-undefined-null.js: Added.

(shouldBe):
(shouldBe.toLocaleString):

Source/JavaScriptCore:

This patch implements ECMA402 Array.prototype.toLocaleString[1]. The new implementation invokes "toLocaleString"
method for each elements.

[1]: https://tc39.es/ecma402/#sup-array.prototype.tolocalestring

  • runtime/ArrayPrototype.cpp:

(JSC::toLocaleString):
(JSC::JSC_DEFINE_HOST_FUNCTION):
(JSC::slowJoin):

Location:
trunk
Files:
4 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChakraCore/test/Array/toLocaleString.baseline-jsc

    r205387 r287560  
    1919
    20203. Array: element toLocaleString not callable
    21 0,[object Object]
     21TypeError : toLocaleString is not callable
    2222
    2323
     
    3131
    32326. Object: element toLocaleString not callable
    33 0,[object Object]
     33TypeError : toLocaleString is not callable
    3434
    3535
  • trunk/JSTests/ChangeLog

    r287546 r287560  
     12022-01-03  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        Array.prototype.toLocaleString does not respect deletion of Object.prototype.toLocaleString
     4        https://bugs.webkit.org/show_bug.cgi?id=232723
     5
     6        Reviewed by Alexey Shvayka.
     7
     8        * ChakraCore/test/Array/toLocaleString.baseline-jsc:
     9        * stress/array-tolocalestring-delete-tolocalestring.js: Added.
     10        (shouldThrow):
     11        * stress/array-tolocalestring-empty-separator.js: Added.
     12        (shouldBe):
     13        * stress/array-tolocalestring-options.js: Added.
     14        (shouldBe):
     15        * stress/array-tolocalestring-undefined-null.js: Added.
     16        (shouldBe):
     17        (shouldBe.toLocaleString):
     18
    1192022-01-03  Yusuke Suzuki  <ysuzuki@apple.com>
    220
  • trunk/LayoutTests/js/dom/script-tests/toString-overrides.js

    r156066 r287560  
    2222shouldBe("[1].toLocaleString()", "'toLocaleString'");
    2323Number.prototype.toLocaleString = "invalid";
    24 shouldBe("[1].toLocaleString()", "'1'");
     24shouldThrow("[1].toLocaleString()");
    2525shouldBe("[/r/].toString()", "'toString2'");
    2626shouldBe("[/r/].toLocaleString()", "'toLocaleString2'");
    2727RegExp.prototype.toLocaleString = "invalid";
    28 shouldBe("[/r/].toLocaleString()", "'toString2'");
     28shouldThrow("[/r/].toLocaleString()", "'toString2'");
    2929
    3030var caught = false;
  • trunk/LayoutTests/js/dom/toString-overrides-expected.txt

    r156066 r287560  
    66PASS [1].toString() is '1'
    77PASS [1].toLocaleString() is 'toLocaleString'
    8 PASS [1].toLocaleString() is '1'
     8PASS [1].toLocaleString() threw exception TypeError: toLocaleString is not callable.
    99PASS [/r/].toString() is 'toString2'
    1010PASS [/r/].toLocaleString() is 'toLocaleString2'
    11 PASS [/r/].toLocaleString() is 'toString2'
     11FAIL [/r/].toLocaleString() should throw toString2. Threw exception TypeError: toLocaleString is not callable.
    1212PASS caught is true
    1313PASS successfullyParsed is true
  • trunk/Source/JavaScriptCore/ChangeLog

    r287546 r287560  
     12022-01-03  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        Array.prototype.toLocaleString does not respect deletion of Object.prototype.toLocaleString
     4        https://bugs.webkit.org/show_bug.cgi?id=232723
     5
     6        Reviewed by Alexey Shvayka.
     7
     8        This patch implements ECMA402 Array.prototype.toLocaleString[1]. The new implementation invokes "toLocaleString"
     9        method for each elements.
     10
     11        [1]: https://tc39.es/ecma402/#sup-array.prototype.tolocalestring
     12
     13        * runtime/ArrayPrototype.cpp:
     14        (JSC::toLocaleString):
     15        (JSC::JSC_DEFINE_HOST_FUNCTION):
     16        (JSC::slowJoin):
     17
    1182022-01-03  Yusuke Suzuki  <ysuzuki@apple.com>
    219
  • trunk/Source/JavaScriptCore/runtime/ArrayPrototype.cpp

    r287136 r287560  
    677677}
    678678
     679static JSString* toLocaleString(JSGlobalObject* globalObject, JSValue value, JSValue locales, JSValue options)
     680{
     681    VM& vm = globalObject->vm();
     682    auto scope = DECLARE_THROW_SCOPE(vm);
     683
     684    JSValue toLocaleStringMethod = value.get(globalObject, vm.propertyNames->toLocaleString);
     685    RETURN_IF_EXCEPTION(scope, { });
     686
     687    auto callData = getCallData(vm, toLocaleStringMethod);
     688    if (callData.type == CallData::Type::None) {
     689        throwTypeError(globalObject, scope, "toLocaleString is not callable"_s);
     690        return { };
     691    }
     692
     693    MarkedArgumentBufferWithSize<2> arguments;
     694    arguments.append(locales);
     695    arguments.append(options);
     696    ASSERT(!arguments.hasOverflowed());
     697
     698    JSValue result = call(globalObject, toLocaleStringMethod, callData, value, arguments);
     699    RETURN_IF_EXCEPTION(scope, { });
     700
     701    RELEASE_AND_RETURN(scope, result.toString(globalObject));
     702}
     703
     704// https://tc39.es/ecma402/#sup-array.prototype.tolocalestring
    679705JSC_DEFINE_HOST_FUNCTION(arrayProtoFuncToLocaleString, (JSGlobalObject* globalObject, CallFrame* callFrame))
    680706{
     
    683709    JSValue thisValue = callFrame->thisValue().toThis(globalObject, ECMAMode::strict());
    684710
     711    JSValue locales = callFrame->argument(0);
     712    JSValue options = callFrame->argument(1);
     713
     714    // 1. Let array be ? ToObject(this value).
    685715    JSObject* thisObject = thisValue.toObject(globalObject);
    686     RETURN_IF_EXCEPTION(scope, encodedJSValue());
    687     uint64_t length = static_cast<uint64_t>(toLength(globalObject, thisObject));
    688     RETURN_IF_EXCEPTION(scope, encodedJSValue());
    689     if (length > std::numeric_limits<unsigned>::max()) {
    690         throwOutOfMemoryError(globalObject, scope);
    691         return encodedJSValue();
    692     }
     716    RETURN_IF_EXCEPTION(scope, { });
    693717
    694718    StringRecursionChecker checker(globalObject, thisObject);
     
    697721        return JSValue::encode(earlyReturnValue);
    698722
    699     JSStringJoiner stringJoiner(globalObject, ',', static_cast<uint32_t>(length));
    700     RETURN_IF_EXCEPTION(scope, encodedJSValue());
    701 
    702     ArgList arguments(callFrame);
    703     for (unsigned i = 0; i < length; ++i) {
    704         JSValue element = thisObject->getIndex(globalObject, i);
    705         RETURN_IF_EXCEPTION(scope, encodedJSValue());
     723    // 2. Let len be ? ToLength(? Get(array, "length")).
     724    uint64_t length = static_cast<uint64_t>(toLength(globalObject, thisObject));
     725    RETURN_IF_EXCEPTION(scope, { });
     726
     727    // 3. Let separator be the String value for the list-separator String appropriate for
     728    // the host environment's current locale (this is derived in an implementation-defined way).
     729    const LChar comma = ',';
     730    JSString* separator = jsSingleCharacterString(vm, comma);
     731
     732    // 4. Let R be the empty String.
     733    if (!length)
     734        return JSValue::encode(jsEmptyString(vm));
     735
     736    // 5. Let k be 0.
     737    JSValue element0 = thisObject->getIndex(globalObject, 0);
     738    RETURN_IF_EXCEPTION(scope, { });
     739
     740    // 6. Repeat, while k < len,
     741    // 6.a. If k > 0, then
     742    // 6.a.i. Set R to the string-concatenation of R and separator.
     743
     744    JSString* r = nullptr;
     745    if (element0.isUndefinedOrNull())
     746        r = jsEmptyString(vm);
     747    else {
     748        r = toLocaleString(globalObject, element0, locales, options);
     749        RETURN_IF_EXCEPTION(scope, { });
     750    }
     751
     752    // 8. Let k be 1.
     753    // 9. Repeat, while k < len
     754    // 9.e Increase k by 1..
     755    for (uint64_t k = 1; k < length; ++k) {
     756        // 6.b. Let nextElement be ? Get(array, ! ToString(k)).
     757        JSValue element = thisObject->getIndex(globalObject, k);
     758        RETURN_IF_EXCEPTION(scope, { });
     759
     760        // c. If nextElement is not undefined or null, then
     761        JSString* next = nullptr;
    706762        if (element.isUndefinedOrNull())
    707             element = jsEmptyString(vm);
     763            next = jsEmptyString(vm);
    708764        else {
    709             JSValue conversionFunction = element.get(globalObject, vm.propertyNames->toLocaleString);
    710             RETURN_IF_EXCEPTION(scope, encodedJSValue());
    711             auto callData = getCallData(vm, conversionFunction);
    712             if (callData.type != CallData::Type::None) {
    713                 element = call(globalObject, conversionFunction, callData, element, arguments);
    714                 RETURN_IF_EXCEPTION(scope, encodedJSValue());
    715             }
    716         }
    717         stringJoiner.append(globalObject, element);
    718         RETURN_IF_EXCEPTION(scope, encodedJSValue());
    719     }
    720 
    721     RELEASE_AND_RETURN(scope, JSValue::encode(stringJoiner.join(globalObject)));
     765            // i. Let S be ? ToString(? Invoke(nextElement, "toLocaleString", « locales, options »)).
     766            // ii. Set R to the string-concatenation of R and S.
     767            next = toLocaleString(globalObject, element, locales, options);
     768            RETURN_IF_EXCEPTION(scope, { });
     769        }
     770
     771        // d. Increase k by 1.
     772        r = jsString(globalObject, r, separator, next);
     773        RETURN_IF_EXCEPTION(scope, { });
     774    }
     775
     776    // 7. Return R.
     777    return JSValue::encode(r);
    722778}
    723779
     
    748804    for (uint64_t k = 1; k < length; ++k) {
    749805        // b. Let element be ? Get(O, ! ToString(k)).
    750         JSValue element = thisObject->get(globalObject, Identifier::fromString(vm, AtomString::number(k)));
     806        JSValue element = thisObject->getIndex(globalObject, k);
    751807        RETURN_IF_EXCEPTION(scope, { });
    752808
Note: See TracChangeset for help on using the changeset viewer.