Changeset 203147 in webkit
- Timestamp:
- Jul 12, 2016, 6:25:25 PM (10 years ago)
- Location:
- trunk
- Files:
-
- 3 added
- 6 deleted
- 9 edited
-
LayoutTests/ChangeLog (modified) (1 diff)
-
LayoutTests/fast/history/replacestate-nocrash.html (modified) (1 diff)
-
LayoutTests/js/array-join-expected.txt (added)
-
LayoutTests/js/array-join.html (added)
-
LayoutTests/js/script-tests/array-join.js (added)
-
LayoutTests/sputnik/Conformance/15_Native_Objects/15.4_Array/15.4.4/15.4.4.5_Array_prototype_join/S15.4.4.5_A2_T2-expected.txt (deleted)
-
LayoutTests/sputnik/Conformance/15_Native_Objects/15.4_Array/15.4.4/15.4.4.5_Array_prototype_join/S15.4.4.5_A2_T2.html (deleted)
-
LayoutTests/sputnik/Conformance/15_Native_Objects/15.4_Array/15.4.4/15.4.4.5_Array_prototype_join/S15.4.4.5_A4_T1-expected.txt (deleted)
-
LayoutTests/sputnik/Conformance/15_Native_Objects/15.4_Array/15.4.4/15.4.4.5_Array_prototype_join/S15.4.4.5_A4_T1.html (deleted)
-
LayoutTests/sputnik/Conformance/15_Native_Objects/15.4_Array/15.4.4/15.4.4.5_Array_prototype_join/S15.4.4.5_A4_T2-expected.txt (deleted)
-
LayoutTests/sputnik/Conformance/15_Native_Objects/15.4_Array/15.4.4/15.4.4.5_Array_prototype_join/S15.4.4.5_A4_T2.html (deleted)
-
LayoutTests/sputnik/Conformance/15_Native_Objects/15.4_Array/15.4.4/15.4.4.5_Array_prototype_join/S15.4.4.5_A4_T3.html (modified) (1 diff)
-
Source/JavaScriptCore/ChangeLog (modified) (1 diff)
-
Source/JavaScriptCore/runtime/ArrayPrototype.cpp (modified) (4 diffs)
-
Source/JavaScriptCore/runtime/JSArray.h (modified) (1 diff)
-
Source/WTF/ChangeLog (modified) (1 diff)
-
Source/WTF/wtf/text/AtomicString.cpp (modified) (2 diffs)
-
Source/WTF/wtf/text/AtomicString.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r203143 r203147 1 2016-07-12 Benjamin Poulain <bpoulain@apple.com> 2 3 [JSC] Array.prototype.join() fails some conformance tests 4 https://bugs.webkit.org/show_bug.cgi?id=159657 5 6 Reviewed by Saam Barati. 7 8 I removed 3 sputnik tests that are incorrect in the latest spec. 9 In ES5, Array.prototype.join() was using ToUint32 on the argument: 10 https://es5.github.io/#x15.4.4.5 11 In ES6, the function uses ToLength: 12 https://tc39.github.io/ecma262/#sec-array.prototype.join 13 14 The test use Infinity and very large integer as the length. 15 They are guaranteed to time out or run out of memory. 16 Even if we waited the hours it takes to run this, the results would be different 17 from what the tests expect. 18 19 * js/array-join-expected.txt: Added. 20 * js/array-join.html: Added. 21 * js/script-tests/array-join.js: Added. 22 1 23 2016-07-12 Commit Queue <commit-queue@webkit.org> 2 24 -
trunk/LayoutTests/fast/history/replacestate-nocrash.html
r140748 r203147 7 7 8 8 Object.prototype.__defineSetter__("foo",function(){history.replaceState("")}); 9 history.replaceState({foo:1,zzz: Array(1<<22).join("a")});9 history.replaceState({foo:1,zzz:"a".repeat(1<<22)}); 10 10 history.state.length; 11 11 </script> -
trunk/LayoutTests/sputnik/Conformance/15_Native_Objects/15.4_Array/15.4.4/15.4.4.5_Array_prototype_join/S15.4.4.5_A4_T3.html
r203143 r203147 81 81 82 82 //CHECK#1 83 if (obj.join("") !== " xy") {84 testFailed('#1: var obj = {}; obj.join = Array.prototype.join; obj[0] = "x"; obj[1] = "y"; obj[2] = "z"; obj.length = -4294967294; obj.join("") === " xy". Actual: ' + (obj.join("")));83 if (obj.join("") !== "") { 84 testFailed('#1: var obj = {}; obj.join = Array.prototype.join; obj[0] = "x"; obj[1] = "y"; obj[2] = "z"; obj.length = -4294967294; obj.join("") === "". Actual: ' + (obj.join(""))); 85 85 } 86 86 -
trunk/Source/JavaScriptCore/ChangeLog
r203144 r203147 1 2016-07-12 Benjamin Poulain <bpoulain@apple.com> 2 3 [JSC] Array.prototype.join() fails some conformance tests 4 https://bugs.webkit.org/show_bug.cgi?id=159657 5 6 Reviewed by Saam Barati. 7 8 There were a couple of failures: 9 -separator.toString() was called *before* we get the length 10 and process ToLength() on it. 11 -We were using toUInt32() on length instead of ToLength(), 12 failing on big integers and various negative numbers. 13 14 Additionally, I replaced the "fast" ArrayStorage path 15 by a fully generic implementation that does not depends on StringJoiner. 16 17 The reason is StringJoiner was doing poorly on sparse objects 18 in certain cases. 19 If you have a sparse object with a length > INT_MAX but very few 20 indices defined, and you join on the empty string, it should be possible 21 to join the array (albeit very slowly). With StringJoiner, we fail 22 because we try to allocate > INT_MAX empty strings in a contiguous vector. 23 24 * runtime/ArrayPrototype.cpp: 25 (JSC::slowJoin): 26 (JSC::canUseFastJoin): 27 (JSC::fastJoin): 28 (JSC::arrayProtoFuncJoin): 29 (JSC::join): Deleted. 30 * runtime/JSArray.h: 31 (JSC::toLength): 32 1 33 2016-07-12 Mark Lam <mark.lam@apple.com> 2 34 -
trunk/Source/JavaScriptCore/runtime/ArrayPrototype.cpp
r203143 r203147 487 487 } 488 488 489 static inline JSValue join(ExecState& state, JSObject* thisObject, StringView separator) 490 { 491 unsigned length = getLength(&state, thisObject); 492 if (state.hadException()) 493 return jsUndefined(); 494 489 static JSValue slowJoin(ExecState& exec, JSObject* thisObject, JSString* separator, uint64_t length) 490 { 491 // 5. If len is zero, return the empty String. 492 if (!length) 493 return jsEmptyString(&exec); 494 495 VM& vm = exec.vm(); 496 497 // 6. Let element0 be Get(O, "0"). 498 JSValue element0 = thisObject->getIndex(&exec, 0); 499 if (vm.exception()) 500 return JSValue(); 501 502 // 7. If element0 is undefined or null, let R be the empty String; otherwise, let R be ? ToString(element0). 503 JSString* r = nullptr; 504 if (element0.isUndefinedOrNull()) 505 r = jsEmptyString(&exec); 506 else 507 r = element0.toString(&exec); 508 if (vm.exception()) 509 return JSValue(); 510 511 // 8. Let k be 1. 512 // 9. Repeat, while k < len 513 // 9.e Increase k by 1.. 514 for (uint64_t k = 1; k < length; ++k) { 515 // b. Let element be ? Get(O, ! ToString(k)). 516 JSValue element = thisObject->get(&exec, Identifier::fromString(&exec, AtomicString::number(k))); 517 if (vm.exception()) 518 return JSValue(); 519 520 // c. If element is undefined or null, let next be the empty String; otherwise, let next be ? ToString(element). 521 JSString* next = nullptr; 522 if (element.isUndefinedOrNull()) { 523 if (!separator->length()) 524 continue; 525 next = jsEmptyString(&exec); 526 } else 527 next = element.toString(&exec); 528 if (vm.exception()) 529 return JSValue(); 530 531 // a. Let S be the String value produced by concatenating R and sep. 532 // d. Let R be a String value produced by concatenating S and next. 533 r = JSRopeString::create(vm, r, separator, next); 534 } 535 // 10. Return R. 536 return r; 537 } 538 539 static inline bool canUseFastJoin(const JSObject* thisObject) 540 { 541 switch (thisObject->indexingType()) { 542 case ALL_CONTIGUOUS_INDEXING_TYPES: 543 case ALL_INT32_INDEXING_TYPES: 544 case ALL_DOUBLE_INDEXING_TYPES: 545 return true; 546 default: 547 break; 548 } 549 return false; 550 } 551 552 static inline JSValue fastJoin(ExecState& state, JSObject* thisObject, StringView separator, unsigned length) 553 { 495 554 switch (thisObject->indexingType()) { 496 555 case ALL_CONTIGUOUS_INDEXING_TYPES: … … 543 602 return joiner.join(state); 544 603 } 545 case ALL_ARRAY_STORAGE_INDEXING_TYPES: {546 auto& storage = *thisObject->butterfly()->arrayStorage();547 if (length > storage.vectorLength())548 break;549 if (storage.hasHoles() && thisObject->structure(state.vm())->holesMustForwardToPrototype(state.vm()))550 break;551 JSStringJoiner joiner(state, separator, length);552 if (state.hadException())553 return jsUndefined();554 auto data = storage.vector().data();555 for (unsigned i = 0; i < length; ++i) {556 if (JSValue value = data[i].get()) {557 if (!joiner.appendWithoutSideEffects(state, value))558 goto generalCase;559 } else560 joiner.appendEmptyString();561 }562 return joiner.join(state);563 }564 604 } 565 605 … … 581 621 EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec) 582 622 { 623 // 1. Let O be ? ToObject(this value). 583 624 JSObject* thisObject = exec->thisValue().toThis(exec, StrictMode).toObject(exec); 584 625 if (!thisObject) … … 589 630 return JSValue::encode(earlyReturnValue); 590 631 632 // 2. Let len be ? ToLength(? Get(O, "length")). 633 double length = toLength(exec, thisObject); 634 if (exec->hadException()) 635 return JSValue::encode(JSValue()); 636 637 // 3. If separator is undefined, let separator be the single-element String ",". 591 638 JSValue separatorValue = exec->argument(0); 592 639 if (separatorValue.isUndefined()) { 593 640 const LChar comma = ','; 594 return JSValue::encode(join(*exec, thisObject, { &comma, 1 })); 595 } 596 597 JSString* separator = separatorValue.toString(exec); 641 642 if (UNLIKELY(length > std::numeric_limits<unsigned>::max() || !canUseFastJoin(thisObject))) { 643 uint64_t length64 = static_cast<uint64_t>(length); 644 ASSERT(static_cast<double>(length64) == length); 645 JSString* jsSeparator = jsSingleCharacterString(exec, comma); 646 if (exec->hadException()) 647 return JSValue::encode(JSValue()); 648 649 return JSValue::encode(slowJoin(*exec, thisObject, jsSeparator, length64)); 650 } 651 652 unsigned unsignedLength = static_cast<unsigned>(length); 653 ASSERT(static_cast<double>(unsignedLength) == length); 654 return JSValue::encode(fastJoin(*exec, thisObject, { &comma, 1 }, unsignedLength)); 655 } 656 657 // 4. Let sep be ? ToString(separator). 658 JSString* jsSeparator = separatorValue.toString(exec); 598 659 if (exec->hadException()) 599 660 return JSValue::encode(jsUndefined()); 600 return JSValue::encode(join(*exec, thisObject, separator->view(exec).get())); 661 662 if (UNLIKELY(length > std::numeric_limits<unsigned>::max() || !canUseFastJoin(thisObject))) { 663 uint64_t length64 = static_cast<uint64_t>(length); 664 ASSERT(static_cast<double>(length64) == length); 665 return JSValue::encode(slowJoin(*exec, thisObject, jsSeparator, length64)); 666 } 667 668 return JSValue::encode(fastJoin(*exec, thisObject, jsSeparator->view(exec).get(), length)); 601 669 } 602 670 -
trunk/Source/JavaScriptCore/runtime/JSArray.h
r203143 r203147 354 354 } 355 355 356 ALWAYS_INLINE double toLength(ExecState* exec, JSObject* obj) 357 { 358 if (isJSArray(obj)) 359 return jsCast<JSArray*>(obj)->length(); 360 361 VM& vm = exec->vm(); 362 JSValue lengthValue = obj->get(exec, vm.propertyNames->length); 363 if (UNLIKELY(vm.exception())) 364 return PNaN; 365 return lengthValue.toLength(exec); 366 } 367 356 368 } // namespace JSC 357 369 -
trunk/Source/WTF/ChangeLog
r203143 r203147 1 2016-07-12 Benjamin Poulain <bpoulain@apple.com> 2 3 [JSC] Array.prototype.join() fails some conformance tests 4 https://bugs.webkit.org/show_bug.cgi?id=159657 5 6 Reviewed by Saam Barati. 7 8 * wtf/text/AtomicString.cpp: 9 (WTF::AtomicString::number): 10 * wtf/text/AtomicString.h: 11 1 12 2016-07-12 Commit Queue <commit-queue@webkit.org> 2 13 -
trunk/Source/WTF/wtf/text/AtomicString.cpp
r203143 r203147 1 1 /* 2 * Copyright (C) 2004-2008, 2013-2014 Apple Inc. All rights reserved.2 * Copyright (C) 2004-2008, 2013-2014, 2016 Apple Inc. All rights reserved. 3 3 * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com> 4 4 * Copyright (C) 2012 Google Inc. All rights reserved. … … 93 93 } 94 94 95 AtomicString AtomicString::number(unsigned long number) 96 { 97 return numberToStringUnsigned<AtomicString>(number); 98 } 99 100 AtomicString AtomicString::number(unsigned long long number) 101 { 102 return numberToStringUnsigned<AtomicString>(number); 103 } 104 95 105 AtomicString AtomicString::number(double number) 96 106 { -
trunk/Source/WTF/wtf/text/AtomicString.h
r203143 r203147 106 106 WTF_EXPORT_STRING_API static AtomicString number(int); 107 107 WTF_EXPORT_STRING_API static AtomicString number(unsigned); 108 WTF_EXPORT_STRING_API static AtomicString number(unsigned long); 109 WTF_EXPORT_STRING_API static AtomicString number(unsigned long long); 108 110 WTF_EXPORT_STRING_API static AtomicString number(double); 109 111 // If we need more overloads of the number function, we can add all the others that String has, but these seem to do for now.
Note:
See TracChangeset
for help on using the changeset viewer.