Commit 1052f503 authored by barraclough@apple.com's avatar barraclough@apple.com
Browse files

Array.prototype functions should throw if delete fails

https://bugs.webkit.org/show_bug.cgi?id=80467

Reviewed by Oliver Hunt.

Source/JavaScriptCore: 

All calls to [[Delete]] from Array.prototype are specified to pass 'true' as the value of Throw.
In the case of shift/unshift, these are also missing a throw from the 'put' in the implementations
in JSArray.cpp. There are effectively three copies of each of the generic shift/unshift routines,
one in splice, one in ArrayPrototype's shift/unshift methods, and one in JSArray's shift/unshift
routines, for handling arrays with holes. These three copies should be unified.

* runtime/ArrayPrototype.cpp:
(JSC::shift):
(JSC::unshift):
    - Added - shared copies of the shift/unshift functionality.
(JSC::arrayProtoFuncPop):
    - should throw if the delete fails.
(JSC::arrayProtoFuncReverse):
    - should throw if the delete fails.
(JSC::arrayProtoFuncShift):
(JSC::arrayProtoFuncSplice):
(JSC::arrayProtoFuncUnShift):
    - use shift/unshift.
* runtime/JSArray.cpp:
(JSC::JSArray::shiftCount):
(JSC::JSArray::unshiftCount):
    - Don't try to handle arrays with holes; return a value indicating
      the generic routine should be used instead.
* runtime/JSArray.h:
    - declaration for shiftCount/unshiftCount changed.
* tests/mozilla/js1_6/Array/regress-304828.js:
    - this was asserting incorrect behaviour.

LayoutTests: 

* fast/js/mozilla/strict/15.4.4.12-expected.txt:
* fast/js/mozilla/strict/15.4.4.13-expected.txt:
* fast/js/mozilla/strict/15.4.4.6-expected.txt:
* fast/js/mozilla/strict/15.4.4.8-expected.txt:
* fast/js/mozilla/strict/15.4.4.9-expected.txt:
    - check in passing test results.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@110026 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent dd5226ac
2012-03-06 Gavin Barraclough <barraclough@apple.com>
Array.prototype functions should throw if delete fails
https://bugs.webkit.org/show_bug.cgi?id=80467
Reviewed by Oliver Hunt.
* fast/js/mozilla/strict/15.4.4.12-expected.txt:
* fast/js/mozilla/strict/15.4.4.13-expected.txt:
* fast/js/mozilla/strict/15.4.4.6-expected.txt:
* fast/js/mozilla/strict/15.4.4.8-expected.txt:
* fast/js/mozilla/strict/15.4.4.9-expected.txt:
- check in passing test results.
2012-03-06 Philippe Normand <pnormand@igalia.com>
 
fullscreen/video-controls is too specific to the mac port
FAIL 'use strict'; var a = arr(); [a.splice(0, 1), a] should throw an instance of TypeError
FAIL var a = arr(); [a.splice(0, 1), a] should throw an instance of TypeError
PASS 'use strict'; var a = arr(); [a.splice(0, 1), a] threw exception of type TypeError.
PASS var a = arr(); [a.splice(0, 1), a] threw exception of type TypeError.
PASS true === true
PASS 'use strict'; var o = obj(); [Array.prototype.splice.call(o, 0, 1), o] threw exception of type TypeError.
PASS var o = obj(); [Array.prototype.splice.call(o, 0, 1), o] threw exception of type TypeError.
PASS true === true
FAIL 'use strict'; var a = agap(); [a.splice(0, 1), a] should throw an instance of TypeError
FAIL var a = agap(); [a.splice(0, 1), a] should throw an instance of TypeError
PASS 'use strict'; var a = agap(); [a.splice(0, 1), a] threw exception of type TypeError.
PASS var a = agap(); [a.splice(0, 1), a] threw exception of type TypeError.
PASS true === true
FAIL 'use strict'; var o = ogap(); [Array.prototype.splice.call(o, 0, 1), o] should throw an instance of TypeError
FAIL var o = ogap(); [Array.prototype.splice.call(o, 0, 1), o] should throw an instance of TypeError
PASS 'use strict'; var o = ogap(); [Array.prototype.splice.call(o, 0, 1), o] threw exception of type TypeError.
PASS var o = ogap(); [Array.prototype.splice.call(o, 0, 1), o] threw exception of type TypeError.
PASS true === true
PASSED!
PASS successfullyParsed is true
......
FAIL 'use strict'; var a = arr(); [a.unshift(40, 50), a] should throw an instance of TypeError
FAIL var a = arr(); [a.unshift(40, 50), a] should throw an instance of TypeError
PASS 'use strict'; var a = arr(); [a.unshift(40, 50), a] threw exception of type TypeError.
PASS var a = arr(); [a.unshift(40, 50), a] threw exception of type TypeError.
PASS true === true
PASS 'use strict'; var o = obj(); [Array.prototype.unshift.call(o, 40, 50), o] threw exception of type TypeError.
PASS var o = obj(); [Array.prototype.unshift.call(o, 40, 50), o] threw exception of type TypeError.
PASS true === true
FAIL 'use strict'; var a = agap(); [a.unshift(9), a] should throw an instance of TypeError
FAIL var a = agap(); [a.unshift(9), a] should throw an instance of TypeError
PASS 'use strict'; var a = agap(); [a.unshift(9), a] threw exception of type TypeError.
PASS var a = agap(); [a.unshift(9), a] threw exception of type TypeError.
PASS true === true
FAIL 'use strict'; var o = ogap(); [Array.prototype.unshift.call(o, 9), o] should throw an instance of TypeError
FAIL var o = ogap(); [Array.prototype.unshift.call(o, 9), o] should throw an instance of TypeError
PASS 'use strict'; var o = ogap(); [Array.prototype.unshift.call(o, 9), o] threw exception of type TypeError.
PASS var o = ogap(); [Array.prototype.unshift.call(o, 9), o] threw exception of type TypeError.
PASS true === true
PASSED!
PASS successfullyParsed is true
......
PASS 'use strict'; var a = arr(); [a.pop(), a] threw exception of type TypeError.
PASS var a = arr(); [a.pop(), a] threw exception of type TypeError.
PASS true === true
FAIL 'use strict'; var o = obj(); [Array.prototype.pop.call(o), o] should throw an instance of TypeError
FAIL var o = obj(); [Array.prototype.pop.call(o), o] should throw an instance of TypeError
PASS 'use strict'; var o = obj(); [Array.prototype.pop.call(o), o] threw exception of type TypeError.
PASS var o = obj(); [Array.prototype.pop.call(o), o] threw exception of type TypeError.
PASS true === true
PASSED!
PASS successfullyParsed is true
......
......@@ -4,11 +4,11 @@ PASS true === true
PASS 'use strict'; var o = obj(); Array.prototype.reverse.call(o) threw exception of type TypeError.
PASS var o = obj(); Array.prototype.reverse.call(o) threw exception of type TypeError.
PASS true === true
FAIL 'use strict'; var a = agap(); a.reverse() should throw an instance of TypeError
FAIL var a = agap(); a.reverse() should throw an instance of TypeError
PASS 'use strict'; var a = agap(); a.reverse() threw exception of type TypeError.
PASS var a = agap(); a.reverse() threw exception of type TypeError.
PASS true === true
FAIL 'use strict'; var o = ogap(); Array.prototype.reverse.call(o) should throw an instance of TypeError
FAIL var o = ogap(); Array.prototype.reverse.call(o) should throw an instance of TypeError
PASS 'use strict'; var o = ogap(); Array.prototype.reverse.call(o) threw exception of type TypeError.
PASS var o = ogap(); Array.prototype.reverse.call(o) threw exception of type TypeError.
PASS true === true
PASSED!
PASS successfullyParsed is true
......
FAIL 'use strict'; var a = arr(); [a.shift(), a] should throw an instance of TypeError
FAIL var a = arr(); [a.shift(), a] should throw an instance of TypeError
PASS 'use strict'; var a = arr(); [a.shift(), a] threw exception of type TypeError.
PASS var a = arr(); [a.shift(), a] threw exception of type TypeError.
PASS true === true
PASS 'use strict'; var o = obj(); [Array.prototype.shift.call(o), o] threw exception of type TypeError.
PASS var o = obj(); [Array.prototype.shift.call(o), o] threw exception of type TypeError.
PASS true === true
FAIL 'use strict'; var a = agap(); [a.shift(), a] should throw an instance of TypeError
FAIL var a = agap(); [a.shift(), a] should throw an instance of TypeError
PASS 'use strict'; var a = agap(); [a.shift(), a] threw exception of type TypeError.
PASS var a = agap(); [a.shift(), a] threw exception of type TypeError.
PASS true === true
FAIL 'use strict'; var o = ogap(); [Array.prototype.shift.call(o), o] should throw an instance of TypeError
FAIL var o = ogap(); [Array.prototype.shift.call(o), o] should throw an instance of TypeError
PASS 'use strict'; var o = ogap(); [Array.prototype.shift.call(o), o] threw exception of type TypeError.
PASS var o = ogap(); [Array.prototype.shift.call(o), o] threw exception of type TypeError.
PASS true === true
PASSED!
PASS successfullyParsed is true
......
2012-03-06 Gavin Barraclough <barraclough@apple.com>
Array.prototype functions should throw if delete fails
https://bugs.webkit.org/show_bug.cgi?id=80467
Reviewed by Oliver Hunt.
All calls to [[Delete]] from Array.prototype are specified to pass 'true' as the value of Throw.
In the case of shift/unshift, these are also missing a throw from the 'put' in the implementations
in JSArray.cpp. There are effectively three copies of each of the generic shift/unshift routines,
one in splice, one in ArrayPrototype's shift/unshift methods, and one in JSArray's shift/unshift
routines, for handling arrays with holes. These three copies should be unified.
* runtime/ArrayPrototype.cpp:
(JSC::shift):
(JSC::unshift):
- Added - shared copies of the shift/unshift functionality.
(JSC::arrayProtoFuncPop):
- should throw if the delete fails.
(JSC::arrayProtoFuncReverse):
- should throw if the delete fails.
(JSC::arrayProtoFuncShift):
(JSC::arrayProtoFuncSplice):
(JSC::arrayProtoFuncUnShift):
- use shift/unshift.
* runtime/JSArray.cpp:
(JSC::JSArray::shiftCount):
(JSC::JSArray::unshiftCount):
- Don't try to handle arrays with holes; return a value indicating
the generic routine should be used instead.
* runtime/JSArray.h:
- declaration for shiftCount/unshiftCount changed.
* tests/mozilla/js1_6/Array/regress-304828.js:
- this was asserting incorrect behaviour.
2012-03-06 Raphael Kubo da Costa <kubo@profusion.mobi>
 
[CMake] Make the removal of transitive library dependencies work with CMake < 2.8.7.
......@@ -166,6 +166,90 @@ static unsigned argumentClampedIndexFromStartOrEnd(ExecState* exec, int argument
return indexDouble > length ? length : static_cast<unsigned>(indexDouble);
}
// The shift/unshift function implement the shift/unshift behaviour required
// by the corresponding array prototype methods, and by splice. In both cases,
// the methods are operating an an array or array like object.
//
// header currentCount (remainder)
// [------][------------][-----------]
// header resultCount (remainder)
// [------][-----------][-----------]
//
// The set of properties in the range 'header' must be unchanged. The set of
// properties in the range 'remainder' (where remainder = length - header -
// currentCount) will be shifted to the left or right as appropriate; in the
// case of shift this must be removing values, in the case of unshift this
// must be introducing new values.
static inline void shift(ExecState* exec, JSObject* thisObj, unsigned header, unsigned currentCount, unsigned resultCount, unsigned length)
{
ASSERT(currentCount > resultCount);
unsigned count = currentCount - resultCount;
ASSERT(header <= length);
ASSERT(currentCount <= (length - header));
if (!header && isJSArray(thisObj) && asArray(thisObj)->shiftCount(exec, count))
return;
for (unsigned k = header; k < length - currentCount; ++k) {
unsigned from = k + currentCount;
unsigned to = k + resultCount;
PropertySlot slot(thisObj);
if (thisObj->getPropertySlot(exec, from, slot)) {
JSValue value = slot.getValue(exec, from);
if (exec->hadException())
return;
thisObj->methodTable()->putByIndex(thisObj, exec, to, value, true);
if (exec->hadException())
return;
} else if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, to)) {
throwTypeError(exec, "Unable to delete property.");
return;
}
}
for (unsigned k = length; k > length - count; --k) {
if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, k - 1)) {
throwTypeError(exec, "Unable to delete property.");
return;
}
}
}
static inline void unshift(ExecState* exec, JSObject* thisObj, unsigned header, unsigned currentCount, unsigned resultCount, unsigned length)
{
ASSERT(resultCount > currentCount);
unsigned count = resultCount - currentCount;
ASSERT(header <= length);
ASSERT(currentCount <= (length - header));
// Guard against overflow.
if (count > (UINT_MAX - length)) {
throwOutOfMemoryError(exec);
return;
}
if (!header && isJSArray(thisObj) && asArray(thisObj)->unshiftCount(exec, count))
return;
for (unsigned k = length - currentCount; k > header; --k) {
unsigned from = k + currentCount - 1;
unsigned to = k + resultCount - 1;
PropertySlot slot(thisObj);
if (thisObj->getPropertySlot(exec, from, slot)) {
JSValue value = slot.getValue(exec, from);
if (exec->hadException())
return;
thisObj->methodTable()->putByIndex(thisObj, exec, to, value, true);
} else if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, to)) {
throwTypeError(exec, "Unable to delete property.");
return;
}
if (exec->hadException())
return;
}
}
EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
......@@ -402,7 +486,12 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncPop(ExecState* exec)
result = jsUndefined();
} else {
result = thisObj->get(exec, length - 1);
thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, length - 1);
if (exec->hadException())
return JSValue::encode(jsUndefined());
if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, length - 1)) {
throwTypeError(exec, "Unable to delete property.");
return JSValue::encode(jsUndefined());
}
putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(length - 1));
}
return JSValue::encode(result);
......@@ -457,19 +546,23 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReverse(ExecState* exec)
if (exec->hadException())
return JSValue::encode(jsUndefined());
if (obj2)
if (obj2) {
thisObj->methodTable()->putByIndex(thisObj, exec, k, obj2, true);
else
thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, k);
if (exec->hadException())
if (exec->hadException())
return JSValue::encode(jsUndefined());
} else if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, k)) {
throwTypeError(exec, "Unable to delete property.");
return JSValue::encode(jsUndefined());
}
if (obj)
if (obj) {
thisObj->methodTable()->putByIndex(thisObj, exec, lk1, obj, true);
else
thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, lk1);
if (exec->hadException())
if (exec->hadException())
return JSValue::encode(jsUndefined());
} else if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, lk1)) {
throwTypeError(exec, "Unable to delete property.");
return JSValue::encode(jsUndefined());
}
}
return JSValue::encode(thisObj);
}
......@@ -487,22 +580,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncShift(ExecState* exec)
result = jsUndefined();
} else {
result = thisObj->get(exec, 0);
if (isJSArray(thisObj))
((JSArray *)thisObj)->shiftCount(exec, 1);
else {
for (unsigned k = 1; k < length; k++) {
JSValue obj = getProperty(exec, thisObj, k);
if (exec->hadException())
return JSValue::encode(jsUndefined());
if (obj)
thisObj->methodTable()->putByIndex(thisObj, exec, k - 1, obj, true);
else
thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, k - 1);
if (exec->hadException())
return JSValue::encode(jsUndefined());
}
thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, length - 1);
}
shift(exec, thisObj, 0, 1, 0, length);
if (exec->hadException())
return JSValue::encode(jsUndefined());
putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(length - 1));
}
return JSValue::encode(result);
......@@ -639,42 +719,14 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec)
resObj->completeInitialization(deleteCount);
unsigned additionalArgs = std::max<int>(exec->argumentCount() - 2, 0);
if (additionalArgs != deleteCount) {
if (additionalArgs < deleteCount) {
if ((!begin) && (isJSArray(thisObj)))
((JSArray *)thisObj)->shiftCount(exec, deleteCount - additionalArgs);
else {
for (unsigned k = begin; k < length - deleteCount; ++k) {
JSValue v = getProperty(exec, thisObj, k + deleteCount);
if (exec->hadException())
return JSValue::encode(jsUndefined());
if (v)
thisObj->methodTable()->putByIndex(thisObj, exec, k + additionalArgs, v, true);
else
thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, k + additionalArgs);
if (exec->hadException())
return JSValue::encode(jsUndefined());
}
for (unsigned k = length; k > length - deleteCount + additionalArgs; --k)
thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, k - 1);
}
} else {
if ((!begin) && (isJSArray(thisObj)))
((JSArray *)thisObj)->unshiftCount(exec, additionalArgs - deleteCount);
else {
for (unsigned k = length - deleteCount; k > begin; --k) {
JSValue obj = getProperty(exec, thisObj, k + deleteCount - 1);
if (exec->hadException())
return JSValue::encode(jsUndefined());
if (obj)
thisObj->methodTable()->putByIndex(thisObj, exec, k + additionalArgs - 1, obj, true);
else
thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, k + additionalArgs - 1);
if (exec->hadException())
return JSValue::encode(jsUndefined());
}
}
}
if (additionalArgs < deleteCount) {
shift(exec, thisObj, begin, deleteCount, additionalArgs, length);
if (exec->hadException())
return JSValue::encode(jsUndefined());
} else if (additionalArgs > deleteCount) {
unshift(exec, thisObj, begin, deleteCount, additionalArgs, length);
if (exec->hadException())
return JSValue::encode(jsUndefined());
}
for (unsigned k = 0; k < additionalArgs; ++k) {
thisObj->methodTable()->putByIndex(thisObj, exec, k + begin, exec->argument(k + 2), true);
......@@ -696,22 +748,10 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncUnShift(ExecState* exec)
return JSValue::encode(jsUndefined());
unsigned nrArgs = exec->argumentCount();
if ((nrArgs) && (length)) {
if (isJSArray(thisObj))
((JSArray *)thisObj)->unshiftCount(exec, nrArgs);
else {
for (unsigned k = length; k > 0; --k) {
JSValue v = getProperty(exec, thisObj, k - 1);
if (exec->hadException())
return JSValue::encode(jsUndefined());
if (v)
thisObj->methodTable()->putByIndex(thisObj, exec, k + nrArgs - 1, v, true);
else
thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, k + nrArgs - 1);
if (exec->hadException())
return JSValue::encode(jsUndefined());
}
}
if (nrArgs) {
unshift(exec, thisObj, 0, 0, nrArgs, length);
if (exec->hadException())
return JSValue::encode(jsUndefined());
}
for (unsigned k = 0; k < nrArgs; ++k) {
thisObj->methodTable()->putByIndex(thisObj, exec, k, exec->argument(k), true);
......
......@@ -1309,7 +1309,7 @@ void JSArray::push(ExecState* exec, JSValue value)
checkConsistency();
}
void JSArray::shiftCount(ExecState* exec, unsigned count)
bool JSArray::shiftCount(ExecState*, unsigned count)
{
ASSERT(count > 0);
......@@ -1317,32 +1317,15 @@ void JSArray::shiftCount(ExecState* exec, unsigned count)
unsigned oldLength = storage->m_length;
if (!oldLength)
return;
if (oldLength != storage->m_numValuesInVector) {
// If m_length and m_numValuesInVector aren't the same, we have a sparse vector
// which means we need to go through each entry looking for the the "empty"
// slots and then fill them with possible properties. See ECMA spec.
// 15.4.4.9 steps 11 through 13.
for (unsigned i = count; i < oldLength; ++i) {
if ((i >= m_vectorLength) || (!m_storage->m_vector[i])) {
PropertySlot slot(this);
JSValue p = prototype();
if ((!p.isNull()) && (asObject(p)->getPropertySlot(exec, i, slot)))
methodTable()->putByIndex(this, exec, i, slot.getValue(exec, i), false); // FIXME https://bugs.webkit.org/show_bug.cgi?id=80335
}
}
storage = m_storage; // The put() above could have grown the vector and realloc'ed storage.
// If the array contains holes or is otherwise in an abnormal state,
// use the generic algorithm in ArrayPrototype.
if (oldLength != storage->m_numValuesInVector || inSparseMode())
return false;
// Need to decrement numValuesInvector based on number of real entries
for (unsigned i = 0; i < (unsigned)count; ++i)
if ((i < m_vectorLength) && (storage->m_vector[i]))
--storage->m_numValuesInVector;
} else
storage->m_numValuesInVector -= count;
if (!oldLength)
return true;
storage->m_numValuesInVector -= count;
storage->m_length -= count;
if (m_vectorLength) {
......@@ -1358,30 +1341,20 @@ void JSArray::shiftCount(ExecState* exec, unsigned count)
m_indexBias += count;
}
}
return true;
}
void JSArray::unshiftCount(ExecState* exec, unsigned count)
// Returns true if the unshift can be handled, false to fallback.
bool JSArray::unshiftCount(ExecState* exec, unsigned count)
{
ArrayStorage* storage = m_storage;
unsigned length = storage->m_length;
if (length != storage->m_numValuesInVector) {
// If m_length and m_numValuesInVector aren't the same, we have a sparse vector
// which means we need to go through each entry looking for the the "empty"
// slots and then fill them with possible properties. See ECMA spec.
// 15.4.4.13 steps 8 through 10.
for (unsigned i = 0; i < length; ++i) {
if ((i >= m_vectorLength) || (!m_storage->m_vector[i])) {
PropertySlot slot(this);
JSValue p = prototype();
if ((!p.isNull()) && (asObject(p)->getPropertySlot(exec, i, slot)))
methodTable()->putByIndex(this, exec, i, slot.getValue(exec, i), false); // FIXME https://bugs.webkit.org/show_bug.cgi?id=80335
}
}
}
storage = m_storage; // The put() above could have grown the vector and realloc'ed storage.
// If the array contains holes or is otherwise in an abnormal state,
// use the generic algorithm in ArrayPrototype.
if (length != storage->m_numValuesInVector || inSparseMode())
return false;
if (m_indexBias >= count) {
m_indexBias -= count;
char* newBaseStorage = reinterpret_cast<char*>(storage) - count * sizeof(WriteBarrier<Unknown>);
......@@ -1390,12 +1363,13 @@ void JSArray::unshiftCount(ExecState* exec, unsigned count)
m_vectorLength += count;
} else if (!unshiftCountSlowCase(exec->globalData(), count)) {
throwOutOfMemoryError(exec);
return;
return true;
}
WriteBarrier<Unknown>* vector = m_storage->m_vector;
for (unsigned i = 0; i < count; i++)
vector[i].clear();
return true;
}
void JSArray::visitChildren(JSCell* cell, SlotVisitor& visitor)
......
......@@ -187,8 +187,8 @@ namespace JSC {
void push(ExecState*, JSValue);
JSValue pop(ExecState*);
void shiftCount(ExecState*, unsigned count);
void unshiftCount(ExecState*, unsigned count);
bool shiftCount(ExecState*, unsigned count);
bool unshiftCount(ExecState*, unsigned count);
bool canGetIndex(unsigned i) { return i < m_vectorLength && m_storage->m_vector[i]; }
JSValue getIndex(unsigned i)
......
......@@ -100,7 +100,7 @@ reportCompare('abc', value, summary + ': push');
// pop
value = 'abc';
expect = 'c';
expect = 'TypeError: Unable to delete property.';
try
{
actual = Array.prototype.pop.call(value);
......@@ -128,7 +128,7 @@ reportCompare('def', value, summary + ': unshift');
// shift
value = 'abc';
expect = 'a';
expect = 'TypeError: Unable to delete property.';
try
{
actual = Array.prototype.shift.call(value);
......@@ -142,7 +142,7 @@ reportCompare('abc', value, summary + ': shift');
// splice
value = 'abc';
expect = 'b';
expect = 'TypeError: Unable to delete property.';
try
{
actual = Array.prototype.splice.call(value, 1, 1) + '';
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment