Commit 0a429dee authored by barraclough@apple.com's avatar barraclough@apple.com
Browse files

Sorting a non-array creates propreties (spec-violation)

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

Reviewed by Oliver Hunt.

Source/JavaScriptCore: 

We're just calling get() to get properties, which is converting missing properties to
undefined. Hole values should be retained, and moved to the end of the array.

* runtime/ArrayPrototype.cpp:
(JSC::getOrHole):
    - Helper function, returns JSValue() instead of undefined for missing properties.
(JSC::arrayProtoFuncSort):
    - Implemented per 15.4.4.11, see comments above.

LayoutTests: 

Added test cases.

* fast/js/array-sort-sparse-expected.txt: Added.
* fast/js/array-sort-sparse.html: Added.
* fast/js/script-tests/array-sort-sparse.js: Added.
(testSort):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@129317 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent ce086ca0
2012-09-23 Gavin Barraclough <barraclough@apple.com>
Sorting a non-array creates propreties (spec-violation)
https://bugs.webkit.org/show_bug.cgi?id=25477
Reviewed by Oliver Hunt.
Added test cases.
* fast/js/array-sort-sparse-expected.txt: Added.
* fast/js/array-sort-sparse.html: Added.
* fast/js/script-tests/array-sort-sparse.js: Added.
(testSort):
2012-09-22 Zan Dobersek <zandobersek@gmail.com>
 
Unreviewed GTK gardening.
This tests that arrays and array like objects containing holes are sorted correctly.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS testSort([,undefined,0,1]) is true
PASS testSort({length:4,1:undefined,2:0,3:1}) is true
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<script src="resources/js-test-pre.js"></script>
</head>
<body>
<script src="script-tests/array-sort-sparse.js"></script>
<script src="resources/js-test-post.js"></script>
</body>
</html>
description(
"This tests that arrays and array like objects containing holes are sorted correctly."
);
function testSort(x)
{
[].sort.call(x)
return x[0] < x[1] && x[2] === undefined && !(3 in x) && x.length == 4;
}
shouldBeTrue("testSort([,undefined,0,1])");
shouldBeTrue("testSort({length:4,1:undefined,2:0,3:1})");
2012-09-23 Gavin Barraclough <barraclough@apple.com>
Sorting a non-array creates propreties (spec-violation)
https://bugs.webkit.org/show_bug.cgi?id=25477
Reviewed by Oliver Hunt.
We're just calling get() to get properties, which is converting missing properties to
undefined. Hole values should be retained, and moved to the end of the array.
* runtime/ArrayPrototype.cpp:
(JSC::getOrHole):
- Helper function, returns JSValue() instead of undefined for missing properties.
(JSC::arrayProtoFuncSort):
- Implemented per 15.4.4.11, see comments above.
2012-09-23 Geoffrey Garen <ggaren@apple.com>
 
CSE for access to closure variables (get_/put_scoped_var)
......
......@@ -629,6 +629,15 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState* exec)
return JSValue::encode(result);
}
inline JSValue getOrHole(JSObject* obj, ExecState* exec, unsigned propertyName)
{
PropertySlot slot(obj);
if (obj->getPropertySlot(exec, propertyName, slot))
return slot.getValue(exec, propertyName);
return JSValue();
}
EncodedJSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec)
{
JSObject* thisObj = exec->hostThisValue().toObject(exec);
......@@ -653,17 +662,21 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec)
// "Min" sort. Not the fastest, but definitely less code than heapsort
// or quicksort, and much less swapping than bubblesort/insertionsort.
for (unsigned i = 0; i < length - 1; ++i) {
JSValue iObj = thisObj->get(exec, i);
JSValue iObj = getOrHole(thisObj, exec, i);
if (exec->hadException())
return JSValue::encode(jsUndefined());
unsigned themin = i;
JSValue minObj = iObj;
for (unsigned j = i + 1; j < length; ++j) {
JSValue jObj = thisObj->get(exec, j);
JSValue jObj = getOrHole(thisObj, exec, j);
if (exec->hadException())
return JSValue::encode(jsUndefined());
double compareResult;
if (jObj.isUndefined())
if (!jObj)
compareResult = 1;
else if (!minObj)
compareResult = -1;
else if (jObj.isUndefined())
compareResult = 1; // don't check minObj because there's no need to differentiate == (0) from > (1)
else if (minObj.isUndefined())
compareResult = -1;
......@@ -682,12 +695,22 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec)
}
// Swap themin and i
if (themin > i) {
thisObj->methodTable()->putByIndex(thisObj, exec, i, minObj, true);
if (exec->hadException())
if (minObj) {
thisObj->methodTable()->putByIndex(thisObj, exec, i, minObj, true);
if (exec->hadException())
return JSValue::encode(jsUndefined());
} else if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, i)) {
throwTypeError(exec, "Unable to delete property.");
return JSValue::encode(jsUndefined());
thisObj->methodTable()->putByIndex(thisObj, exec, themin, iObj, true);
if (exec->hadException())
}
if (iObj) {
thisObj->methodTable()->putByIndex(thisObj, exec, themin, iObj, true);
if (exec->hadException())
return JSValue::encode(jsUndefined());
} else if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, themin)) {
throwTypeError(exec, "Unable to delete property.");
return JSValue::encode(jsUndefined());
}
}
}
return JSValue::encode(thisObj);
......
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