Modified: trunk/Source/_javascript_Core/runtime/JSArray.cpp (209035 => 209036)
--- trunk/Source/_javascript_Core/runtime/JSArray.cpp 2016-11-28 23:42:25 UTC (rev 209035)
+++ trunk/Source/_javascript_Core/runtime/JSArray.cpp 2016-11-28 23:50:16 UTC (rev 209036)
@@ -186,7 +186,9 @@
// l.i. Set oldLen to oldLen – 1.
// l.ii. Let deleteSucceeded be the result of calling the [[Delete]] internal method of A passing ToString(oldLen) and false as arguments.
// l.iii. If deleteSucceeded is false, then
- if (!array->setLength(exec, newLen, throwException)) {
+ bool success = array->setLength(exec, newLen, throwException);
+ ASSERT(!scope.exception() || !success);
+ if (!success) {
// 1. Set newLenDesc.[[Value] to oldLen+1.
// 2. If newWritable is false, set newLenDesc.[[Writable] to false.
// 3. Call the default [[DefineOwnProperty]] internal method (8.12.9) on A passing "length", newLenDesc, and false as arguments.
@@ -220,9 +222,11 @@
// e.i. Set oldLenDesc.[[Value]] to index + 1.
// e.ii. Call the default [[DefineOwnProperty]] internal method (8.12.9) on A passing "length", oldLenDesc, and false as arguments. This call will always return true.
// f. Return true.
+ scope.release();
return array->defineOwnIndexedProperty(exec, index, descriptor, throwException);
}
+ scope.release();
return array->JSObject::defineOwnNonIndexProperty(exec, propertyName, descriptor, throwException);
}
@@ -246,18 +250,23 @@
JSArray* thisObject = jsCast<JSArray*>(cell);
- if (UNLIKELY(isThisValueAltered(slot, thisObject)))
+ if (UNLIKELY(isThisValueAltered(slot, thisObject))) {
+ scope.release();
return ordinarySetSlow(exec, thisObject, propertyName, value, slot.thisValue(), slot.isStrictMode());
+ }
if (propertyName == exec->propertyNames().length) {
unsigned newLength = value.toUInt32(exec);
+ RETURN_IF_EXCEPTION(scope, false);
if (value.toNumber(exec) != static_cast<double>(newLength)) {
throwException(exec, scope, createRangeError(exec, ASCIILiteral("Invalid array length")));
return false;
}
+ scope.release();
return thisObject->setLength(exec, newLength, slot.isStrictMode());
}
+ scope.release();
return JSObject::put(thisObject, exec, propertyName, value, slot);
}
@@ -517,6 +526,7 @@
if (!newLength)
return true;
if (newLength >= MIN_SPARSE_ARRAY_INDEX) {
+ scope.release();
return setLengthWithArrayStorage(
exec, newLength, throwException,
ensureArrayStorage(vm));
@@ -533,6 +543,7 @@
if (newLength >= MAX_ARRAY_INDEX // This case ensures that we can do fast push.
|| (newLength >= MIN_SPARSE_ARRAY_INDEX
&& !isDenseEnoughForVector(newLength, countElements()))) {
+ scope.release();
return setLengthWithArrayStorage(
exec, newLength, throwException,
ensureArrayStorage(vm));
@@ -565,6 +576,7 @@
case ArrayWithArrayStorage:
case ArrayWithSlowPutArrayStorage:
+ scope.release();
return setLengthWithArrayStorage(exec, newLength, throwException, arrayStorage());
default:
@@ -659,11 +671,14 @@
JSValue element = get(exec, index);
RETURN_IF_EXCEPTION(scope, JSValue());
// Call the [[Delete]] internal method of O with arguments indx and true.
- if (!deletePropertyByIndex(this, exec, index)) {
+ bool success = deletePropertyByIndex(this, exec, index);
+ RETURN_IF_EXCEPTION(scope, JSValue());
+ if (!success) {
throwTypeError(exec, scope, ASCIILiteral(UnableToDeletePropertyError));
return jsUndefined();
}
// Call the [[Put]] internal method of O with arguments "length", indx, and true.
+ scope.release();
setLength(exec, index, true);
// Return element.
return element;
@@ -687,6 +702,7 @@
case ArrayWithUndecided: {
convertUndecidedForValue(vm, value);
+ scope.release();
push(exec, value);
return;
}
@@ -694,6 +710,7 @@
case ArrayWithInt32: {
if (!value.isInt32()) {
convertInt32ForValue(vm, value);
+ scope.release();
push(exec, value);
return;
}
@@ -706,13 +723,14 @@
return;
}
- if (length > MAX_ARRAY_INDEX) {
+ if (UNLIKELY(length > MAX_ARRAY_INDEX)) {
methodTable(vm)->putByIndex(this, exec, length, value, true);
if (!scope.exception())
throwException(exec, scope, createRangeError(exec, ASCIILiteral("Invalid array length")));
return;
}
-
+
+ scope.release();
putByIndexBeyondVectorLengthWithoutAttributes<Int32Shape>(exec, length, value);
return;
}
@@ -726,13 +744,14 @@
return;
}
- if (length > MAX_ARRAY_INDEX) {
+ if (UNLIKELY(length > MAX_ARRAY_INDEX)) {
methodTable(vm)->putByIndex(this, exec, length, value, true);
if (!scope.exception())
throwException(exec, scope, createRangeError(exec, ASCIILiteral("Invalid array length")));
return;
}
-
+
+ scope.release();
putByIndexBeyondVectorLengthWithoutAttributes<ContiguousShape>(exec, length, value);
return;
}
@@ -740,6 +759,7 @@
case ArrayWithDouble: {
if (!value.isNumber()) {
convertDoubleToContiguous(vm);
+ scope.release();
push(exec, value);
return;
}
@@ -746,6 +766,7 @@
double valueAsDouble = value.asNumber();
if (valueAsDouble != valueAsDouble) {
convertDoubleToContiguous(vm);
+ scope.release();
push(exec, value);
return;
}
@@ -758,15 +779,16 @@
return;
}
- if (length > MAX_ARRAY_INDEX) {
+ if (UNLIKELY(length > MAX_ARRAY_INDEX)) {
methodTable(vm)->putByIndex(this, exec, length, value, true);
if (!scope.exception())
throwException(exec, scope, createRangeError(exec, ASCIILiteral("Invalid array length")));
return;
}
-
+
+ scope.release();
putByIndexBeyondVectorLengthWithoutAttributes<DoubleShape>(exec, length, value);
- break;
+ return;
}
case ArrayWithSlowPutArrayStorage: {
@@ -773,8 +795,10 @@
unsigned oldLength = length();
bool putResult = false;
if (attemptToInterceptPutByIndexOnHole(exec, oldLength, value, true, putResult)) {
- if (!scope.exception() && oldLength < 0xFFFFFFFFu)
+ if (!scope.exception() && oldLength < 0xFFFFFFFFu) {
+ scope.release();
setLength(exec, oldLength + 1, true);
+ }
return;
}
FALLTHROUGH;
@@ -793,7 +817,7 @@
}
// Pushing to an array of invalid length (2^31-1) stores the property, but throws a range error.
- if (storage->length() > MAX_ARRAY_INDEX) {
+ if (UNLIKELY(storage->length() > MAX_ARRAY_INDEX)) {
methodTable(vm)->putByIndex(this, exec, storage->length(), value, true);
// Per ES5.1 15.4.4.7 step 6 & 15.4.5.1 step 3.d.
if (!scope.exception())
@@ -802,8 +826,9 @@
}
// Handled the same as putIndex.
+ scope.release();
putByIndexBeyondVectorLengthWithArrayStorage(exec, storage->length(), value, true, storage);
- break;
+ return;
}
default:
@@ -1117,8 +1142,10 @@
// We may have to walk the entire array to do the unshift. We're willing to do so
// only if it's not horribly slow.
- if (oldLength - startIndex >= MIN_SPARSE_ARRAY_INDEX)
+ if (oldLength - startIndex >= MIN_SPARSE_ARRAY_INDEX) {
+ scope.release();
return unshiftCountWithArrayStorage(exec, startIndex, count, ensureArrayStorage(vm));
+ }
if (!ensureLength(vm, oldLength + count)) {
throwOutOfMemoryError(exec, scope);
@@ -1130,8 +1157,10 @@
// through shifting and then realize we should have been in ArrayStorage mode.
for (unsigned i = oldLength; i-- > startIndex;) {
JSValue v = butterfly->contiguous()[i].get();
- if (UNLIKELY(!v))
+ if (UNLIKELY(!v)) {
+ scope.release();
return unshiftCountWithArrayStorage(exec, startIndex, count, ensureArrayStorage(vm));
+ }
}
for (unsigned i = oldLength; i-- > startIndex;) {
@@ -1153,8 +1182,10 @@
// We may have to walk the entire array to do the unshift. We're willing to do so
// only if it's not horribly slow.
- if (oldLength - startIndex >= MIN_SPARSE_ARRAY_INDEX)
+ if (oldLength - startIndex >= MIN_SPARSE_ARRAY_INDEX) {
+ scope.release();
return unshiftCountWithArrayStorage(exec, startIndex, count, ensureArrayStorage(vm));
+ }
if (!ensureLength(vm, oldLength + count)) {
throwOutOfMemoryError(exec, scope);
@@ -1166,8 +1197,10 @@
// through shifting and then realize we should have been in ArrayStorage mode.
for (unsigned i = oldLength; i-- > startIndex;) {
double v = butterfly->contiguousDouble()[i];
- if (UNLIKELY(v != v))
+ if (UNLIKELY(v != v)) {
+ scope.release();
return unshiftCountWithArrayStorage(exec, startIndex, count, ensureArrayStorage(vm));
+ }
}
for (unsigned i = oldLength; i-- > startIndex;) {
@@ -1186,6 +1219,7 @@
case ArrayWithArrayStorage:
case ArrayWithSlowPutArrayStorage:
+ scope.release();
return unshiftCountWithArrayStorage(exec, startIndex, count, arrayStorage());
default: