EncodedJSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec)
{
JSObject* thisObj = exec->hostThisValue().toObject(exec);
unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
if (!length || exec->hadException())
return JSValue::encode(thisObj);
JSValue function = exec->argument(0);
CallData callData;
CallType callType = getCallData(function, callData);
if (thisObj->classInfo() == &JSArray::s_info && !asArray(thisObj)->inSparseMode()) {
if (isNumericCompareFunction(exec, callType, callData))
asArray(thisObj)->sortNumeric(exec, function, callType, callData);
else if (callType != CallTypeNone)
asArray(thisObj)->sort(exec, function, callType, callData);
else
asArray(thisObj)->sort(exec);
return JSValue::encode(thisObj);
}
// "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);
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);
if (exec->hadException())
return JSValue::encode(jsUndefined());
double compareResult;
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;
else if (callType != CallTypeNone) {
MarkedArgumentBuffer l;
l.append(jObj);
l.append(minObj);
compareResult = call(exec, function, callType, callData, jsUndefined(), l).toNumber(exec);
} else
compareResult = (jObj.toUStringInline(exec) < minObj.toUStringInline(exec)) ? -1 : 1;
if (compareResult < 0) {
themin = j;
minObj = jObj;
}
}
// Swap themin and i
if (themin > i) {
thisObj->methodTable()->putByIndex(thisObj, exec, i, minObj, true);
if (exec->hadException())
return JSValue::encode(jsUndefined());
thisObj->methodTable()->putByIndex(thisObj, exec, themin, iObj, true);
if (exec->hadException())
return JSValue::encode(jsUndefined());
}
}
return JSValue::encode(thisObj);
} |