Changeset 209011 in webkit
- Timestamp:
- Nov 28, 2016 1:26:10 PM (7 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r209007 r209011 1 2016-11-24 Mark Lam <mark.lam@apple.com> 2 3 Fix exception scope verification failures in ArrayConstructor.cpp and ArrayPrototype.cpp. 4 https://bugs.webkit.org/show_bug.cgi?id=164972 5 6 Reviewed by Geoffrey Garen. 7 8 * runtime/ArrayConstructor.cpp: 9 (JSC::constructArrayWithSizeQuirk): 10 * runtime/ArrayPrototype.cpp: 11 (JSC::getProperty): 12 (JSC::putLength): 13 (JSC::speciesWatchpointsValid): 14 (JSC::speciesConstructArray): 15 (JSC::shift): 16 (JSC::unshift): 17 (JSC::arrayProtoFuncToString): 18 (JSC::arrayProtoFuncToLocaleString): 19 (JSC::slowJoin): 20 (JSC::fastJoin): 21 (JSC::arrayProtoFuncJoin): 22 (JSC::arrayProtoFuncPop): 23 (JSC::arrayProtoFuncPush): 24 (JSC::arrayProtoFuncReverse): 25 (JSC::arrayProtoFuncShift): 26 (JSC::arrayProtoFuncSlice): 27 (JSC::arrayProtoFuncSplice): 28 (JSC::arrayProtoFuncUnShift): 29 (JSC::arrayProtoFuncIndexOf): 30 (JSC::arrayProtoFuncLastIndexOf): 31 (JSC::concatAppendOne): 32 (JSC::arrayProtoPrivateFuncConcatMemcpy): 33 (JSC::ArrayPrototype::attemptToInitializeSpeciesWatchpoint): 34 1 35 2016-11-28 Mark Lam <mark.lam@apple.com> 2 36 -
trunk/Source/JavaScriptCore/runtime/ArrayConstructor.cpp
r206065 r209011 71 71 VM& vm = exec->vm(); 72 72 auto scope = DECLARE_THROW_SCOPE(vm); 73 if (!length.isNumber()) 73 if (!length.isNumber()) { 74 scope.release(); 74 75 return constructArrayNegativeIndexed(exec, profile, globalObject, &length, 1, newTarget); 76 } 75 77 76 78 uint32_t n = length.toUInt32(exec); 77 79 if (n != length.toNumber(exec)) 78 80 return throwException(exec, scope, createRangeError(exec, ASCIILiteral("Array size is not a small enough positive integer."))); 81 scope.release(); 79 82 return constructEmptyArray(exec, profile, globalObject, n, newTarget); 80 83 } -
trunk/Source/JavaScriptCore/runtime/ArrayPrototype.cpp
r208767 r209011 150 150 static ALWAYS_INLINE JSValue getProperty(ExecState* exec, JSObject* object, unsigned index) 151 151 { 152 VM& vm = exec->vm(); 153 auto scope = DECLARE_THROW_SCOPE(vm); 154 152 155 if (JSValue result = object->tryGetIndexQuickly(index)) 153 156 return result; … … 157 160 // somewhere in the prototype chain. 158 161 PropertySlot slot(object, PropertySlot::InternalMethodType::HasProperty); 159 if (!object->getPropertySlot(exec, index, slot)) 160 return JSValue(); 161 if (UNLIKELY(slot.isTaintedByOpaqueObject())) 162 bool hasProperty = object->getPropertySlot(exec, index, slot); 163 ASSERT(!scope.exception() || !hasProperty); 164 if (!hasProperty) 165 return { }; 166 if (UNLIKELY(slot.isTaintedByOpaqueObject())) { 167 scope.release(); 162 168 return object->get(exec, index); 169 } 170 scope.release(); 163 171 return slot.getValue(exec, index); 164 172 } … … 167 175 { 168 176 PutPropertySlot slot(obj); 169 return obj->methodTable( )->put(obj, exec, vm.propertyNames->length, value, slot);177 return obj->methodTable(vm)->put(obj, exec, vm.propertyNames->length, value, slot); 170 178 } 171 179 … … 186 194 inline bool speciesWatchpointsValid(ExecState* exec, JSObject* thisObject) 187 195 { 196 VM& vm = exec->vm(); 197 auto scope = DECLARE_THROW_SCOPE(vm); 198 188 199 ArrayPrototype* arrayPrototype = thisObject->globalObject()->arrayPrototype(); 189 200 ArrayPrototype::SpeciesWatchpointStatus status = arrayPrototype->speciesWatchpointStatus(); 190 if (UNLIKELY(status == ArrayPrototype::SpeciesWatchpointStatus::Uninitialized)) 201 if (UNLIKELY(status == ArrayPrototype::SpeciesWatchpointStatus::Uninitialized)) { 191 202 status = arrayPrototype->attemptToInitializeSpeciesWatchpoint(exec); 203 RETURN_IF_EXCEPTION(scope, false); 204 } 192 205 ASSERT(status != ArrayPrototype::SpeciesWatchpointStatus::Uninitialized); 193 206 return !thisObject->hasCustomProperties() … … 213 226 // ECMA 9.4.2.3: https://tc39.github.io/ecma262/#sec-arrayspeciescreate 214 227 JSValue constructor = jsUndefined(); 215 if (LIKELY(isArray(exec, thisObject))) { 228 bool thisIsArray = isArray(exec, thisObject); 229 RETURN_IF_EXCEPTION(scope, exceptionResult()); 230 if (LIKELY(thisIsArray)) { 216 231 // Fast path in the normal case where the user has not set an own constructor and the Array.prototype.constructor is normal. 217 232 // We need prototype check for subclasses of Array, which are Array objects but have a different prototype by default. 218 if (LIKELY(speciesWatchpointsValid(exec, thisObject))) 233 bool isValid = speciesWatchpointsValid(exec, thisObject); 234 RETURN_IF_EXCEPTION(scope, exceptionResult()); 235 if (LIKELY(isValid)) 219 236 return std::make_pair(SpeciesConstructResult::FastPath, nullptr); 220 237 221 constructor = thisObject->get(exec, exec->propertyNames().constructor);238 constructor = thisObject->get(exec, vm.propertyNames->constructor); 222 239 RETURN_IF_EXCEPTION(scope, exceptionResult()); 223 240 if (constructor.isConstructor()) { … … 227 244 } 228 245 if (constructor.isObject()) { 229 constructor = constructor.get(exec, exec->propertyNames().speciesSymbol);246 constructor = constructor.get(exec, vm.propertyNames->speciesSymbol); 230 247 RETURN_IF_EXCEPTION(scope, exceptionResult()); 231 248 if (constructor.isNull()) … … 295 312 unsigned from = k + currentCount; 296 313 unsigned to = k + resultCount; 297 if (JSValue value = getProperty(exec, thisObj, from)) { 298 RETURN_IF_EXCEPTION(scope, void()); 314 JSValue value = getProperty(exec, thisObj, from); 315 RETURN_IF_EXCEPTION(scope, void()); 316 if (value) { 299 317 thisObj->putByIndexInline(exec, to, value, true); 300 318 RETURN_IF_EXCEPTION(scope, void()); 301 } else if (!thisObj->methodTable(vm)->deletePropertyByIndex(thisObj, exec, to)) { 302 throwTypeError(exec, scope, ASCIILiteral(UnableToDeletePropertyError)); 303 return; 319 } else { 320 bool success = thisObj->methodTable(vm)->deletePropertyByIndex(thisObj, exec, to); 321 RETURN_IF_EXCEPTION(scope, void()); 322 if (!success) { 323 throwTypeError(exec, scope, ASCIILiteral(UnableToDeletePropertyError)); 324 return; 325 } 304 326 } 305 327 } 306 328 for (unsigned k = length; k > length - count; --k) { 307 if (!thisObj->methodTable(vm)->deletePropertyByIndex(thisObj, exec, k - 1)) { 329 bool success = thisObj->methodTable(vm)->deletePropertyByIndex(thisObj, exec, k - 1); 330 RETURN_IF_EXCEPTION(scope, void()); 331 if (!success) { 308 332 throwTypeError(exec, scope, ASCIILiteral(UnableToDeletePropertyError)); 309 333 return; … … 332 356 if (isJSArray(thisObj)) { 333 357 JSArray* array = asArray(thisObj); 334 if (array->length() == length && array->unshiftCount<shiftCountMode>(exec, header, count)) 335 return; 358 if (array->length() == length) { 359 bool handled = array->unshiftCount<shiftCountMode>(exec, header, count); 360 ASSERT(!scope.exception() || handled); 361 if (handled) 362 return; 363 } 336 364 } 337 365 … … 339 367 unsigned from = k + currentCount - 1; 340 368 unsigned to = k + resultCount - 1; 341 if (JSValue value = getProperty(exec, thisObj, from)) { 369 JSValue value = getProperty(exec, thisObj, from); 370 RETURN_IF_EXCEPTION(scope, void()); 371 if (value) { 372 thisObj->putByIndexInline(exec, to, value, true); 342 373 RETURN_IF_EXCEPTION(scope, void()); 343 thisObj->putByIndexInline(exec, to, value, true); 344 } else if (!thisObj->methodTable(vm)->deletePropertyByIndex(thisObj, exec, to)) { 345 throwTypeError(exec, scope, ASCIILiteral(UnableToDeletePropertyError)); 346 return; 347 } 348 RETURN_IF_EXCEPTION(scope, void()); 374 } else { 375 bool success = thisObj->methodTable(vm)->deletePropertyByIndex(thisObj, exec, to); 376 RETURN_IF_EXCEPTION(scope, void()); 377 if (UNLIKELY(!success)) { 378 throwTypeError(exec, scope, ASCIILiteral(UnableToDeletePropertyError)); 379 return; 380 } 381 } 349 382 } 350 383 } … … 361 394 362 395 // 2. Let func be the result of calling the [[Get]] internal method of array with argument "join". 363 JSValue function = JSValue(thisObject).get(exec, exec->propertyNames().join);396 JSValue function = JSValue(thisObject).get(exec, vm.propertyNames->join); 364 397 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 365 398 … … 379 412 380 413 // 4. Return the result of calling the [[Call]] internal method of func providing array as the this value and an empty arguments list. 381 if (!isJSArray(thisObject) || callType != CallType::Host || callData.native.function != arrayProtoFuncJoin) 414 if (!isJSArray(thisObject) || callType != CallType::Host || callData.native.function != arrayProtoFuncJoin) { 415 scope.release(); 382 416 return JSValue::encode(call(exec, function, callType, callData, thisObject, exec->emptyList())); 417 } 383 418 384 419 ASSERT(isJSArray(thisValue)); … … 388 423 389 424 StringRecursionChecker checker(exec, thisArray); 425 ASSERT(!scope.exception() || checker.earlyReturnValue()); 390 426 if (JSValue earlyReturnValue = checker.earlyReturnValue()) 391 427 return JSValue::encode(earlyReturnValue); … … 404 440 } 405 441 442 scope.release(); 406 443 return JSValue::encode(joiner.join(*exec)); 407 444 } … … 420 457 421 458 StringRecursionChecker checker(exec, thisObject); 459 ASSERT(!scope.exception() || checker.earlyReturnValue()); 422 460 if (JSValue earlyReturnValue = checker.earlyReturnValue()) 423 461 return JSValue::encode(earlyReturnValue); … … 434 472 element = jsEmptyString(exec); 435 473 else { 436 JSValue conversionFunction = element.get(exec, exec->propertyNames().toLocaleString);474 JSValue conversionFunction = element.get(exec, vm.propertyNames->toLocaleString); 437 475 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 438 476 CallData callData; … … 452 490 if (element.isUndefinedOrNull()) 453 491 continue; 454 JSValue conversionFunction = element.get(exec, exec->propertyNames().toLocaleString);492 JSValue conversionFunction = element.get(exec, vm.propertyNames->toLocaleString); 455 493 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 456 494 CallData callData; … … 465 503 #endif // !ENABLE(INTL) 466 504 505 scope.release(); 467 506 return JSValue::encode(stringJoiner.join(*exec)); 468 507 } … … 504 543 // 6. Let element0 be Get(O, "0"). 505 544 JSValue element0 = thisObject->getIndex(&exec, 0); 506 RETURN_IF_EXCEPTION(scope, JSValue());545 RETURN_IF_EXCEPTION(scope, { }); 507 546 508 547 // 7. If element0 is undefined or null, let R be the empty String; otherwise, let R be ? ToString(element0). … … 512 551 else 513 552 r = element0.toString(&exec); 514 RETURN_IF_EXCEPTION(scope, JSValue());553 RETURN_IF_EXCEPTION(scope, { }); 515 554 516 555 // 8. Let k be 1. … … 520 559 // b. Let element be ? Get(O, ! ToString(k)). 521 560 JSValue element = thisObject->get(&exec, Identifier::fromString(&exec, AtomicString::number(k))); 522 RETURN_IF_EXCEPTION(scope, JSValue());561 RETURN_IF_EXCEPTION(scope, { }); 523 562 524 563 // c. If element is undefined or null, let next be the empty String; otherwise, let next be ? ToString(element). … … 530 569 } else 531 570 next = element.toString(&exec); 532 RETURN_IF_EXCEPTION(scope, JSValue());571 RETURN_IF_EXCEPTION(scope, { }); 533 572 534 573 // a. Let S be the String value produced by concatenating R and sep. 535 574 // d. Let R be a String value produced by concatenating S and next. 536 575 r = jsString(&exec, r, separator, next); 537 RETURN_IF_EXCEPTION(scope, JSValue());576 RETURN_IF_EXCEPTION(scope, { }); 538 577 } 539 578 // 10. Return R. … … 566 605 break; 567 606 JSStringJoiner joiner(state, separator, length); 568 RETURN_IF_EXCEPTION(scope, JSValue());607 RETURN_IF_EXCEPTION(scope, { }); 569 608 auto data = butterfly.contiguous().data(); 570 609 bool holesKnownToBeOK = false; … … 582 621 } 583 622 } 623 scope.release(); 584 624 return joiner.join(state); 585 625 } … … 589 629 break; 590 630 JSStringJoiner joiner(state, separator, length); 591 RETURN_IF_EXCEPTION(scope, JSValue());631 RETURN_IF_EXCEPTION(scope, { }); 592 632 auto data = butterfly.contiguousDouble().data(); 593 633 bool holesKnownToBeOK = false; … … 605 645 } 606 646 } 647 scope.release(); 607 648 return joiner.join(state); 608 649 } … … 611 652 generalCase: 612 653 JSStringJoiner joiner(state, separator, length); 613 RETURN_IF_EXCEPTION(scope, JSValue());654 RETURN_IF_EXCEPTION(scope, { }); 614 655 for (unsigned i = 0; i < length; ++i) { 615 656 JSValue element = thisObject->getIndex(&state, i); 616 RETURN_IF_EXCEPTION(scope, JSValue());657 RETURN_IF_EXCEPTION(scope, { }); 617 658 joiner.append(state, element); 618 RETURN_IF_EXCEPTION(scope, JSValue()); 619 } 659 RETURN_IF_EXCEPTION(scope, { }); 660 } 661 scope.release(); 620 662 return joiner.join(state); 621 663 } … … 628 670 // 1. Let O be ? ToObject(this value). 629 671 JSObject* thisObject = exec->thisValue().toThis(exec, StrictMode).toObject(exec); 630 if (!thisObject) 631 return JSValue::encode(JSValue()); 672 ASSERT(!!scope.exception() == !thisObject); 673 if (UNLIKELY(!thisObject)) 674 return encodedJSValue(); 632 675 633 676 StringRecursionChecker checker(exec, thisObject); 677 ASSERT(!scope.exception() || checker.earlyReturnValue()); 634 678 if (JSValue earlyReturnValue = checker.earlyReturnValue()) 635 679 return JSValue::encode(earlyReturnValue); … … 650 694 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 651 695 696 scope.release(); 652 697 return JSValue::encode(slowJoin(*exec, thisObject, jsSeparator, length64)); 653 698 } … … 655 700 unsigned unsignedLength = static_cast<unsigned>(length); 656 701 ASSERT(static_cast<double>(unsignedLength) == length); 702 703 scope.release(); 657 704 return JSValue::encode(fastJoin(*exec, thisObject, { &comma, 1 }, unsignedLength)); 658 705 } … … 665 712 uint64_t length64 = static_cast<uint64_t>(length); 666 713 ASSERT(static_cast<double>(length64) == length); 714 715 scope.release(); 667 716 return JSValue::encode(slowJoin(*exec, thisObject, jsSeparator, length64)); 668 717 } … … 682 731 JSValue thisValue = exec->thisValue().toThis(exec, StrictMode); 683 732 684 if (isJSArray(thisValue)) 733 if (isJSArray(thisValue)) { 734 scope.release(); 685 735 return JSValue::encode(asArray(thisValue)->pop(exec)); 736 } 686 737 687 738 JSObject* thisObj = thisValue.toObject(exec); 688 if (!thisObj) 689 return JSValue::encode(JSValue()); 739 ASSERT(!!scope.exception() == !thisObj); 740 if (UNLIKELY(!thisObj)) 741 return encodedJSValue(); 690 742 unsigned length = getLength(exec, thisObj); 691 743 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 692 744 693 JSValue result;694 745 if (length == 0) { 746 scope.release(); 695 747 putLength(exec, vm, thisObj, jsNumber(length)); 696 result = jsUndefined(); 697 } else { 698 result = thisObj->get(exec, length - 1); 699 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 700 if (!thisObj->methodTable(vm)->deletePropertyByIndex(thisObj, exec, length - 1)) { 701 throwTypeError(exec, scope, ASCIILiteral(UnableToDeletePropertyError)); 702 return JSValue::encode(jsUndefined()); 703 } 704 putLength(exec, vm, thisObj, jsNumber(length - 1)); 705 } 748 return JSValue::encode(jsUndefined()); 749 } 750 751 JSValue result = thisObj->get(exec, length - 1); 752 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 753 bool success = thisObj->methodTable(vm)->deletePropertyByIndex(thisObj, exec, length - 1); 754 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 755 if (UNLIKELY(!success)) { 756 throwTypeError(exec, scope, ASCIILiteral(UnableToDeletePropertyError)); 757 return encodedJSValue(); 758 } 759 scope.release(); 760 putLength(exec, vm, thisObj, jsNumber(length - 1)); 706 761 return JSValue::encode(result); 707 762 } … … 715 770 if (isJSArray(thisValue) && exec->argumentCount() == 1) { 716 771 JSArray* array = asArray(thisValue); 772 scope.release(); 717 773 array->push(exec, exec->uncheckedArgument(0)); 718 774 return JSValue::encode(jsNumber(array->length())); … … 720 776 721 777 JSObject* thisObj = thisValue.toObject(exec); 722 if (!thisObj) 723 return JSValue::encode(JSValue()); 778 ASSERT(!!scope.exception() == !thisObj); 779 if (UNLIKELY(!thisObj)) 780 return encodedJSValue(); 724 781 unsigned length = getLength(exec, thisObj); 725 782 RETURN_IF_EXCEPTION(scope, encodedJSValue()); … … 728 785 // Check for integer overflow; where safe we can do a fast put by index. 729 786 if (length + n >= length) 730 thisObj->methodTable( )->putByIndex(thisObj, exec, length + n, exec->uncheckedArgument(n), true);787 thisObj->methodTable(vm)->putByIndex(thisObj, exec, length + n, exec->uncheckedArgument(n), true); 731 788 else { 732 789 PutPropertySlot slot(thisObj); 733 790 Identifier propertyName = Identifier::fromString(exec, JSValue(static_cast<int64_t>(length) + static_cast<int64_t>(n)).toWTFString(exec)); 734 thisObj->methodTable( )->put(thisObj, exec, propertyName, exec->uncheckedArgument(n), slot);791 thisObj->methodTable(vm)->put(thisObj, exec, propertyName, exec->uncheckedArgument(n), slot); 735 792 } 736 793 RETURN_IF_EXCEPTION(scope, encodedJSValue()); … … 738 795 739 796 JSValue newLength(static_cast<int64_t>(length) + static_cast<int64_t>(exec->argumentCount())); 797 scope.release(); 740 798 putLength(exec, vm, thisObj, newLength); 741 799 return JSValue::encode(newLength); … … 748 806 749 807 JSObject* thisObject = exec->thisValue().toThis(exec, StrictMode).toObject(exec); 750 if (!thisObject) 751 return JSValue::encode(JSValue()); 808 ASSERT(!!scope.exception() == !thisObject); 809 if (UNLIKELY(!thisObject)) 810 return encodedJSValue(); 752 811 753 812 unsigned length = getLength(exec, thisObject); … … 810 869 thisObject->putByIndexInline(exec, lower, upperValue, true); 811 870 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 812 } else if (!thisObject->methodTable(vm)->deletePropertyByIndex(thisObject, exec, lower)) { 813 if (!scope.exception()) 871 } else { 872 bool success = thisObject->methodTable(vm)->deletePropertyByIndex(thisObject, exec, lower); 873 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 874 if (UNLIKELY(!success)) { 814 875 throwTypeError(exec, scope, ASCIILiteral(UnableToDeletePropertyError)); 815 return JSValue::encode(JSValue()); 876 return encodedJSValue(); 877 } 816 878 } 817 879 … … 819 881 thisObject->putByIndexInline(exec, upper, lowerValue, true); 820 882 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 821 } else if (!thisObject->methodTable(vm)->deletePropertyByIndex(thisObject, exec, upper)) { 822 if (!scope.exception()) 883 } else { 884 bool success = thisObject->methodTable(vm)->deletePropertyByIndex(thisObject, exec, upper); 885 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 886 if (UNLIKELY(!success)) { 823 887 throwTypeError(exec, scope, ASCIILiteral(UnableToDeletePropertyError)); 824 return JSValue::encode(JSValue()); 888 return encodedJSValue(); 889 } 825 890 } 826 891 } … … 833 898 auto scope = DECLARE_THROW_SCOPE(vm); 834 899 JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec); 835 if (!thisObj) 836 return JSValue::encode(JSValue()); 900 ASSERT(!!scope.exception() == !thisObj); 901 if (UNLIKELY(!thisObj)) 902 return encodedJSValue(); 837 903 unsigned length = getLength(exec, thisObj); 838 904 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 839 905 840 JSValue result;841 906 if (length == 0) { 907 scope.release(); 842 908 putLength(exec, vm, thisObj, jsNumber(length)); 843 result = jsUndefined(); 844 } else { 845 result = thisObj->getIndex(exec, 0); 846 shift<JSArray::ShiftCountForShift>(exec, thisObj, 0, 1, 0, length); 847 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 848 putLength(exec, vm, thisObj, jsNumber(length - 1)); 849 } 909 return JSValue::encode(jsUndefined()); 910 } 911 912 JSValue result = thisObj->getIndex(exec, 0); 913 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 914 shift<JSArray::ShiftCountForShift>(exec, thisObj, 0, 1, 0, length); 915 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 916 scope.release(); 917 putLength(exec, vm, thisObj, jsNumber(length - 1)); 850 918 return JSValue::encode(result); 851 919 } … … 857 925 auto scope = DECLARE_THROW_SCOPE(vm); 858 926 JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec); 859 if (!thisObj) 860 return JSValue::encode(JSValue()); 927 ASSERT(!!scope.exception() == !thisObj); 928 if (UNLIKELY(!thisObj)) 929 return encodedJSValue(); 861 930 unsigned length = getLength(exec, thisObj); 862 931 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 863 932 864 933 unsigned begin = argumentClampedIndexFromStartOrEnd(exec, 0, length); 934 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 865 935 unsigned end = argumentClampedIndexFromStartOrEnd(exec, 1, length, length); 936 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 866 937 867 938 std::pair<SpeciesConstructResult, JSObject*> speciesResult = speciesConstructArray(exec, thisObj, end - begin); 868 939 // We can only get an exception if we call some user function. 940 ASSERT(!!scope.exception() == (speciesResult.first == SpeciesConstructResult::Exception)); 869 941 if (UNLIKELY(speciesResult.first == SpeciesConstructResult::Exception)) 870 return JSValue::encode(jsUndefined()); 871 872 if (LIKELY(speciesResult.first == SpeciesConstructResult::FastPath && isJSArray(thisObj) && length == getLength(exec, thisObj))) { 942 return encodedJSValue(); 943 944 bool okToDoFastPath = speciesResult.first == SpeciesConstructResult::FastPath && isJSArray(thisObj) && length == getLength(exec, thisObj); 945 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 946 if (LIKELY(okToDoFastPath)) { 873 947 if (JSArray* result = asArray(thisObj)->fastSlice(*exec, begin, end - begin)) 874 948 return JSValue::encode(result); … … 887 961 JSValue v = getProperty(exec, thisObj, k); 888 962 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 889 if (v) 963 if (v) { 890 964 result->putDirectIndex(exec, n, v, 0, PutDirectIndexShouldThrow); 965 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 966 } 891 967 } 892 968 scope.release(); … … 903 979 904 980 JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec); 905 if (!thisObj) 906 return JSValue::encode(JSValue()); 981 ASSERT(!!scope.exception() == !thisObj); 982 if (UNLIKELY(!thisObj)) 983 return encodedJSValue(); 907 984 unsigned length = getLength(exec, thisObj); 908 985 RETURN_IF_EXCEPTION(scope, encodedJSValue()); … … 910 987 if (!exec->argumentCount()) { 911 988 std::pair<SpeciesConstructResult, JSObject*> speciesResult = speciesConstructArray(exec, thisObj, 0); 912 if (speciesResult.first == SpeciesConstructResult::Exception) 913 return JSValue::encode(jsUndefined()); 989 ASSERT(!!scope.exception() == (speciesResult.first == SpeciesConstructResult::Exception)); 990 if (UNLIKELY(speciesResult.first == SpeciesConstructResult::Exception)) 991 return encodedJSValue(); 914 992 915 993 JSObject* result; … … 929 1007 930 1008 unsigned actualStart = argumentClampedIndexFromStartOrEnd(exec, 0, length); 1009 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 931 1010 932 1011 unsigned actualDeleteCount = length - actualStart; 933 1012 if (exec->argumentCount() > 1) { 934 1013 double deleteCount = exec->uncheckedArgument(1).toInteger(exec); 1014 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 935 1015 if (deleteCount < 0) 936 1016 actualDeleteCount = 0; … … 942 1022 943 1023 std::pair<SpeciesConstructResult, JSObject*> speciesResult = speciesConstructArray(exec, thisObj, actualDeleteCount); 1024 ASSERT(!!scope.exception() == (speciesResult.first == SpeciesConstructResult::Exception)); 944 1025 if (speciesResult.first == SpeciesConstructResult::Exception) 945 1026 return JSValue::encode(jsUndefined()); 946 1027 947 1028 JSObject* result = nullptr; 948 if (speciesResult.first == SpeciesConstructResult::FastPath && isJSArray(thisObj) && length == getLength(exec, thisObj)) 1029 bool okToDoFastPath = speciesResult.first == SpeciesConstructResult::FastPath && isJSArray(thisObj) && length == getLength(exec, thisObj); 1030 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 1031 if (LIKELY(okToDoFastPath)) 949 1032 result = asArray(thisObj)->fastSlice(*exec, actualStart, actualDeleteCount); 950 1033 … … 1001 1084 1002 1085 JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec); 1003 if (!thisObj) 1004 return JSValue::encode(JSValue()); 1086 ASSERT(!!scope.exception() == !thisObj); 1087 if (UNLIKELY(!thisObj)) 1088 return encodedJSValue(); 1005 1089 unsigned length = getLength(exec, thisObj); 1006 1090 RETURN_IF_EXCEPTION(scope, encodedJSValue()); … … 1016 1100 } 1017 1101 JSValue result = jsNumber(length + nrArgs); 1102 scope.release(); 1018 1103 putLength(exec, vm, thisObj, result); 1019 1104 return JSValue::encode(result); … … 1027 1112 // 15.4.4.14 1028 1113 JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec); 1029 if (!thisObj) 1030 return JSValue::encode(JSValue()); 1114 ASSERT(!!scope.exception() == !thisObj); 1115 if (UNLIKELY(!thisObj)) 1116 return encodedJSValue(); 1031 1117 unsigned length = getLength(exec, thisObj); 1032 1118 RETURN_IF_EXCEPTION(scope, encodedJSValue()); … … 1054 1140 // 15.4.4.15 1055 1141 JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec); 1056 if (!thisObj) 1057 return JSValue::encode(JSValue()); 1142 ASSERT(!!scope.exception() == !thisObj); 1143 if (UNLIKELY(!thisObj)) 1144 return encodedJSValue(); 1058 1145 unsigned length = getLength(exec, thisObj); 1059 if ( !length)1146 if (UNLIKELY(scope.exception()) || !length) 1060 1147 return JSValue::encode(jsNumber(-1)); 1061 1148 … … 1132 1219 return JSValue::encode(throwOutOfMemoryError(exec, scope)); 1133 1220 1134 if (!result->appendMemcpy(exec, vm, 0, first)) { 1135 if (!moveElements(exec, vm, result, 0, first, firstArraySize)) { 1136 ASSERT(scope.exception()); 1137 return JSValue::encode(JSValue()); 1138 } 1139 } 1140 1221 bool success = result->appendMemcpy(exec, vm, 0, first); 1222 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 1223 if (!success) { 1224 bool success = moveElements(exec, vm, result, 0, first, firstArraySize); 1225 ASSERT(!scope.exception() == success); 1226 if (UNLIKELY(!success)) 1227 return encodedJSValue(); 1228 } 1229 1230 scope.release(); 1141 1231 result->putDirectIndex(exec, firstArraySize, second); 1142 1232 return JSValue::encode(result); … … 1160 1250 1161 1251 // We need to check the species constructor here since checking it in the JS wrapper is too expensive for the non-optimizing tiers. 1162 if (UNLIKELY(!speciesWatchpointsValid(exec, firstArray))) 1252 bool isValid = speciesWatchpointsValid(exec, firstArray); 1253 ASSERT(!scope.exception() || !isValid); 1254 if (UNLIKELY(!isValid)) 1163 1255 return JSValue::encode(jsNull()); 1164 1256 1165 1257 JSValue second = exec->uncheckedArgument(1); 1166 if (!isJSArray(second)) 1258 if (!isJSArray(second)) { 1259 scope.release(); 1167 1260 return concatAppendOne(exec, vm, firstArray, second); 1261 } 1168 1262 1169 1263 JSArray* secondArray = jsCast<JSArray*>(second); … … 1181 1275 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 1182 1276 1183 if (!moveElements(exec, vm, result, 0, firstArray, firstArraySize) 1184 || !moveElements(exec, vm, result, firstArraySize, secondArray, secondArraySize)) { 1185 ASSERT(scope.exception()); 1186 return JSValue::encode(JSValue()); 1187 } 1277 bool success = moveElements(exec, vm, result, 0, firstArray, firstArraySize); 1278 ASSERT(!scope.exception() == success); 1279 if (UNLIKELY(!success)) 1280 return encodedJSValue(); 1281 success = moveElements(exec, vm, result, firstArraySize, secondArray, secondArraySize); 1282 ASSERT(!scope.exception() == success); 1283 if (UNLIKELY(!success)) 1284 return encodedJSValue(); 1188 1285 1189 1286 return JSValue::encode(result); … … 1251 1348 1252 1349 VM& vm = exec->vm(); 1350 auto scope = DECLARE_THROW_SCOPE(vm); 1253 1351 1254 1352 if (verbose) … … 1268 1366 PropertySlot constructorSlot(this, PropertySlot::InternalMethodType::VMInquiry); 1269 1367 JSValue(this).get(exec, vm.propertyNames->constructor, constructorSlot); 1270 if (constructorSlot.slotBase() != this 1368 if (UNLIKELY(scope.exception()) 1369 || constructorSlot.slotBase() != this 1271 1370 || !constructorSlot.isCacheableValue() 1272 1371 || constructorSlot.getValue(exec, vm.propertyNames->constructor) != arrayConstructor) … … 1279 1378 PropertySlot speciesSlot(arrayConstructor, PropertySlot::InternalMethodType::VMInquiry); 1280 1379 JSValue(arrayConstructor).get(exec, vm.propertyNames->speciesSymbol, speciesSlot); 1281 if (speciesSlot.slotBase() != arrayConstructor 1380 if (UNLIKELY(scope.exception()) 1381 || speciesSlot.slotBase() != arrayConstructor 1282 1382 || !speciesSlot.isCacheableGetter() 1283 1383 || speciesSlot.getterSetter() != globalObject->speciesGetterSetter())
Note: See TracChangeset
for help on using the changeset viewer.