tizen beta release
[framework/web/webkit-efl.git] / Source / JavaScriptCore / runtime / ArrayPrototype.cpp
1 /*
2  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3  *  Copyright (C) 2003, 2007, 2008, 2009, 2011 Apple Inc. All rights reserved.
4  *  Copyright (C) 2003 Peter Kelly (pmk@post.com)
5  *  Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
6  *
7  *  This library is free software; you can redistribute it and/or
8  *  modify it under the terms of the GNU Lesser General Public
9  *  License as published by the Free Software Foundation; either
10  *  version 2 of the License, or (at your option) any later version.
11  *
12  *  This library is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  *  Lesser General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Lesser General Public
18  *  License along with this library; if not, write to the Free Software
19  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
20  *  USA
21  *
22  */
23
24 #include "config.h"
25 #include "ArrayPrototype.h"
26
27 #include "CachedCall.h"
28 #include "CodeBlock.h"
29 #include "Interpreter.h"
30 #include "JIT.h"
31 #include "JSStringBuilder.h"
32 #include "Lookup.h"
33 #include "ObjectPrototype.h"
34 #include "Operations.h"
35 #include "StringRecursionChecker.h"
36 #include <algorithm>
37 #include <wtf/Assertions.h>
38 #include <wtf/HashSet.h>
39
40 namespace JSC {
41
42 ASSERT_CLASS_FITS_IN_CELL(ArrayPrototype);
43
44 static EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState*);
45 static EncodedJSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState*);
46 static EncodedJSValue JSC_HOST_CALL arrayProtoFuncConcat(ExecState*);
47 static EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState*);
48 static EncodedJSValue JSC_HOST_CALL arrayProtoFuncPop(ExecState*);
49 static EncodedJSValue JSC_HOST_CALL arrayProtoFuncPush(ExecState*);
50 static EncodedJSValue JSC_HOST_CALL arrayProtoFuncReverse(ExecState*);
51 static EncodedJSValue JSC_HOST_CALL arrayProtoFuncShift(ExecState*);
52 static EncodedJSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState*);
53 static EncodedJSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState*);
54 static EncodedJSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState*);
55 static EncodedJSValue JSC_HOST_CALL arrayProtoFuncUnShift(ExecState*);
56 static EncodedJSValue JSC_HOST_CALL arrayProtoFuncEvery(ExecState*);
57 static EncodedJSValue JSC_HOST_CALL arrayProtoFuncForEach(ExecState*);
58 static EncodedJSValue JSC_HOST_CALL arrayProtoFuncSome(ExecState*);
59 static EncodedJSValue JSC_HOST_CALL arrayProtoFuncIndexOf(ExecState*);
60 static EncodedJSValue JSC_HOST_CALL arrayProtoFuncFilter(ExecState*);
61 static EncodedJSValue JSC_HOST_CALL arrayProtoFuncMap(ExecState*);
62 static EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduce(ExecState*);
63 static EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduceRight(ExecState*);
64 static EncodedJSValue JSC_HOST_CALL arrayProtoFuncLastIndexOf(ExecState*);
65
66 }
67
68 #include "ArrayPrototype.lut.h"
69
70 namespace JSC {
71
72 static inline bool isNumericCompareFunction(ExecState* exec, CallType callType, const CallData& callData)
73 {
74     if (callType != CallTypeJS)
75         return false;
76
77     FunctionExecutable* executable = callData.js.functionExecutable;
78
79     JSObject* error = executable->compileForCall(exec, callData.js.scopeChain);
80     if (error)
81         return false;
82
83     return executable->generatedBytecodeForCall().isNumericCompareFunction();
84 }
85
86 // ------------------------------ ArrayPrototype ----------------------------
87
88 const ClassInfo ArrayPrototype::s_info = {"Array", &JSArray::s_info, 0, ExecState::arrayPrototypeTable, CREATE_METHOD_TABLE(ArrayPrototype)};
89
90 /* Source for ArrayPrototype.lut.h
91 @begin arrayPrototypeTable 16
92   toString       arrayProtoFuncToString       DontEnum|Function 0
93   toLocaleString arrayProtoFuncToLocaleString DontEnum|Function 0
94   concat         arrayProtoFuncConcat         DontEnum|Function 1
95   join           arrayProtoFuncJoin           DontEnum|Function 1
96   pop            arrayProtoFuncPop            DontEnum|Function 0
97   push           arrayProtoFuncPush           DontEnum|Function 1
98   reverse        arrayProtoFuncReverse        DontEnum|Function 0
99   shift          arrayProtoFuncShift          DontEnum|Function 0
100   slice          arrayProtoFuncSlice          DontEnum|Function 2
101   sort           arrayProtoFuncSort           DontEnum|Function 1
102   splice         arrayProtoFuncSplice         DontEnum|Function 2
103   unshift        arrayProtoFuncUnShift        DontEnum|Function 1
104   every          arrayProtoFuncEvery          DontEnum|Function 1
105   forEach        arrayProtoFuncForEach        DontEnum|Function 1
106   some           arrayProtoFuncSome           DontEnum|Function 1
107   indexOf        arrayProtoFuncIndexOf        DontEnum|Function 1
108   lastIndexOf    arrayProtoFuncLastIndexOf    DontEnum|Function 1
109   filter         arrayProtoFuncFilter         DontEnum|Function 1
110   reduce         arrayProtoFuncReduce         DontEnum|Function 1
111   reduceRight    arrayProtoFuncReduceRight    DontEnum|Function 1
112   map            arrayProtoFuncMap            DontEnum|Function 1
113 @end
114 */
115
116 // ECMA 15.4.4
117 ArrayPrototype::ArrayPrototype(JSGlobalObject* globalObject, Structure* structure)
118     : JSArray(globalObject->globalData(), structure)
119 {
120 }
121
122 void ArrayPrototype::finishCreation(JSGlobalObject* globalObject)
123 {
124     Base::finishCreation(globalObject->globalData());
125     ASSERT(inherits(&s_info));
126 }
127
128 bool ArrayPrototype::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
129 {
130     return getStaticFunctionSlot<JSArray>(exec, ExecState::arrayPrototypeTable(exec), jsCast<ArrayPrototype*>(cell), propertyName, slot);
131 }
132
133 bool ArrayPrototype::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
134 {
135     return getStaticFunctionDescriptor<JSArray>(exec, ExecState::arrayPrototypeTable(exec), jsCast<ArrayPrototype*>(object), propertyName, descriptor);
136 }
137
138 // ------------------------------ Array Functions ----------------------------
139
140 // Helper function
141 static JSValue getProperty(ExecState* exec, JSObject* obj, unsigned index)
142 {
143     PropertySlot slot(obj);
144     if (!obj->getPropertySlot(exec, index, slot))
145         return JSValue();
146     return slot.getValue(exec, index);
147 }
148
149 static void putProperty(ExecState* exec, JSObject* obj, const Identifier& propertyName, JSValue value)
150 {
151     PutPropertySlot slot;
152     obj->methodTable()->put(obj, exec, propertyName, value, slot);
153 }
154
155 static unsigned argumentClampedIndexFromStartOrEnd(ExecState* exec, int argument, unsigned length, unsigned undefinedValue = 0)
156 {
157     JSValue value = exec->argument(argument);
158     if (value.isUndefined())
159         return undefinedValue;
160
161     double indexDouble = value.toInteger(exec);
162     if (indexDouble < 0) {
163         indexDouble += length;
164         return indexDouble < 0 ? 0 : static_cast<unsigned>(indexDouble);
165     }
166     return indexDouble > length ? length : static_cast<unsigned>(indexDouble);
167 }
168
169 EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec)
170 {
171     JSValue thisValue = exec->hostThisValue();
172
173     bool isRealArray = isJSArray(&exec->globalData(), thisValue);
174     if (!isRealArray && !thisValue.inherits(&JSArray::s_info))
175         return throwVMTypeError(exec);
176     JSArray* thisObj = asArray(thisValue);
177     
178     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
179     if (exec->hadException())
180         return JSValue::encode(jsUndefined());
181
182     StringRecursionChecker checker(exec, thisObj);
183     if (JSValue earlyReturnValue = checker.earlyReturnValue())
184         return JSValue::encode(earlyReturnValue);
185
186     unsigned totalSize = length ? length - 1 : 0;
187     Vector<RefPtr<StringImpl>, 256> strBuffer(length);
188     bool allStrings8Bit = true;
189
190     for (unsigned k = 0; k < length; k++) {
191         JSValue element;
192         if (isRealArray && thisObj->canGetIndex(k))
193             element = thisObj->getIndex(k);
194         else
195             element = thisObj->get(exec, k);
196         
197         if (element.isUndefinedOrNull())
198             continue;
199         
200         UString str = element.toString(exec);
201         strBuffer[k] = str.impl();
202         totalSize += str.length();
203         allStrings8Bit = allStrings8Bit && str.is8Bit();
204         
205         if (!strBuffer.data()) {
206             throwOutOfMemoryError(exec);
207         }
208         
209         if (exec->hadException())
210             break;
211     }
212     if (!totalSize)
213         return JSValue::encode(jsEmptyString(exec));
214
215     if (allStrings8Bit) {
216         Vector<LChar> buffer;
217         buffer.reserveCapacity(totalSize);
218         if (!buffer.data())
219             return JSValue::encode(throwOutOfMemoryError(exec));
220         
221         for (unsigned i = 0; i < length; i++) {
222             if (i)
223                 buffer.append(',');
224             if (RefPtr<StringImpl> rep = strBuffer[i])
225                 buffer.append(rep->characters8(), rep->length());
226         }
227         ASSERT(buffer.size() == totalSize);
228         return JSValue::encode(jsString(exec, UString::adopt(buffer)));        
229     }
230
231     Vector<UChar> buffer;
232     buffer.reserveCapacity(totalSize);
233     if (!buffer.data())
234         return JSValue::encode(throwOutOfMemoryError(exec));
235         
236     for (unsigned i = 0; i < length; i++) {
237         if (i)
238             buffer.append(',');
239         if (RefPtr<StringImpl> rep = strBuffer[i])
240             buffer.append(rep->characters(), rep->length());
241     }
242     ASSERT(buffer.size() == totalSize);
243     return JSValue::encode(jsString(exec, UString::adopt(buffer)));
244 }
245
246 EncodedJSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState* exec)
247 {
248     JSValue thisValue = exec->hostThisValue();
249
250     if (!thisValue.inherits(&JSArray::s_info))
251         return throwVMTypeError(exec);
252     JSObject* thisObj = asArray(thisValue);
253
254     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
255     if (exec->hadException())
256         return JSValue::encode(jsUndefined());
257
258     StringRecursionChecker checker(exec, thisObj);
259     if (JSValue earlyReturnValue = checker.earlyReturnValue())
260         return JSValue::encode(earlyReturnValue);
261
262     JSStringBuilder strBuffer;
263     for (unsigned k = 0; k < length; k++) {
264         if (k >= 1)
265             strBuffer.append(',');
266
267         JSValue element = thisObj->get(exec, k);
268         if (!element.isUndefinedOrNull()) {
269             JSObject* o = element.toObject(exec);
270             JSValue conversionFunction = o->get(exec, exec->propertyNames().toLocaleString);
271             UString str;
272             CallData callData;
273             CallType callType = getCallData(conversionFunction, callData);
274             if (callType != CallTypeNone)
275                 str = call(exec, conversionFunction, callType, callData, element, exec->emptyList()).toString(exec);
276             else
277                 str = element.toString(exec);
278             strBuffer.append(str);
279         }
280     }
281
282     return JSValue::encode(strBuffer.build(exec));
283 }
284
285 EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec)
286 {
287     JSObject* thisObj = exec->hostThisValue().toObject(exec);
288     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
289     if (exec->hadException())
290         return JSValue::encode(jsUndefined());
291
292     StringRecursionChecker checker(exec, thisObj);
293     if (JSValue earlyReturnValue = checker.earlyReturnValue())
294         return JSValue::encode(earlyReturnValue);
295
296     JSStringBuilder strBuffer;
297
298     UString separator;
299     if (!exec->argument(0).isUndefined())
300         separator = exec->argument(0).toString(exec);
301
302     unsigned k = 0;
303     if (isJSArray(&exec->globalData(), thisObj)) {
304         JSArray* array = asArray(thisObj);
305
306         if (length) {
307             if (!array->canGetIndex(k)) 
308                 goto skipFirstLoop;
309             JSValue element = array->getIndex(k);
310             if (!element.isUndefinedOrNull())
311                 strBuffer.append(element.toString(exec));
312             k++;
313         }
314
315         if (separator.isNull()) {
316             for (; k < length; k++) {
317                 if (!array->canGetIndex(k))
318                     break;
319                 strBuffer.append(',');
320                 JSValue element = array->getIndex(k);
321                 if (!element.isUndefinedOrNull())
322                     strBuffer.append(element.toString(exec));
323             }
324         } else {
325             for (; k < length; k++) {
326                 if (!array->canGetIndex(k))
327                     break;
328                 strBuffer.append(separator);
329                 JSValue element = array->getIndex(k);
330                 if (!element.isUndefinedOrNull())
331                     strBuffer.append(element.toString(exec));
332             }
333         }
334     }
335  skipFirstLoop:
336     for (; k < length; k++) {
337         if (k >= 1) {
338             if (separator.isNull())
339                 strBuffer.append(',');
340             else
341                 strBuffer.append(separator);
342         }
343
344         JSValue element = thisObj->get(exec, k);
345         if (!element.isUndefinedOrNull())
346             strBuffer.append(element.toString(exec));
347     }
348
349     return JSValue::encode(strBuffer.build(exec));
350 }
351
352 EncodedJSValue JSC_HOST_CALL arrayProtoFuncConcat(ExecState* exec)
353 {
354     JSValue thisValue = exec->hostThisValue();
355     JSArray* arr = constructEmptyArray(exec);
356     unsigned n = 0;
357     JSValue curArg = thisValue.toObject(exec);
358     if (exec->hadException())
359         return JSValue::encode(jsUndefined());
360     size_t i = 0;
361     size_t argCount = exec->argumentCount();
362     while (1) {
363         if (curArg.inherits(&JSArray::s_info)) {
364             unsigned length = curArg.get(exec, exec->propertyNames().length).toUInt32(exec);
365             JSObject* curObject = curArg.toObject(exec);
366             for (unsigned k = 0; k < length; ++k) {
367                 JSValue v = getProperty(exec, curObject, k);
368                 if (exec->hadException())
369                     return JSValue::encode(jsUndefined());
370                 if (v)
371                     arr->methodTable()->putByIndex(arr, exec, n, v);
372                 n++;
373             }
374         } else {
375             arr->methodTable()->putByIndex(arr, exec, n, curArg);
376             n++;
377         }
378         if (i == argCount)
379             break;
380         curArg = (exec->argument(i));
381         ++i;
382     }
383     arr->setLength(n);
384     return JSValue::encode(arr);
385 }
386
387 EncodedJSValue JSC_HOST_CALL arrayProtoFuncPop(ExecState* exec)
388 {
389     JSValue thisValue = exec->hostThisValue();
390
391     if (isJSArray(&exec->globalData(), thisValue))
392         return JSValue::encode(asArray(thisValue)->pop());
393
394     JSObject* thisObj = thisValue.toObject(exec);
395     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
396     if (exec->hadException())
397         return JSValue::encode(jsUndefined());
398
399     JSValue result;
400     if (length == 0) {
401         putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(length));
402         result = jsUndefined();
403     } else {
404         result = thisObj->get(exec, length - 1);
405         thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, length - 1);
406         putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(length - 1));
407     }
408     return JSValue::encode(result);
409 }
410
411 EncodedJSValue JSC_HOST_CALL arrayProtoFuncPush(ExecState* exec)
412 {
413     JSValue thisValue = exec->hostThisValue();
414
415     if (isJSArray(&exec->globalData(), thisValue) && exec->argumentCount() == 1) {
416         JSArray* array = asArray(thisValue);
417         array->push(exec, exec->argument(0));
418         return JSValue::encode(jsNumber(array->length()));
419     }
420
421     JSObject* thisObj = thisValue.toObject(exec);
422     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
423     if (exec->hadException())
424         return JSValue::encode(jsUndefined());
425
426     for (unsigned n = 0; n < exec->argumentCount(); n++) {
427         // Check for integer overflow; where safe we can do a fast put by index.
428         if (length + n >= length)
429             thisObj->methodTable()->putByIndex(thisObj, exec, length + n, exec->argument(n));
430         else {
431             PutPropertySlot slot;
432             Identifier propertyName(exec, JSValue(static_cast<int64_t>(length) + static_cast<int64_t>(n)).toString(exec));
433             thisObj->methodTable()->put(thisObj, exec, propertyName, exec->argument(n), slot);
434         }
435     }
436     JSValue newLength(static_cast<int64_t>(length) + static_cast<int64_t>(exec->argumentCount()));
437     putProperty(exec, thisObj, exec->propertyNames().length, newLength);
438     return JSValue::encode(newLength);
439 }
440
441 EncodedJSValue JSC_HOST_CALL arrayProtoFuncReverse(ExecState* exec)
442 {
443     JSObject* thisObj = exec->hostThisValue().toObject(exec);
444     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
445     if (exec->hadException())
446         return JSValue::encode(jsUndefined());
447
448     unsigned middle = length / 2;
449     for (unsigned k = 0; k < middle; k++) {
450         unsigned lk1 = length - k - 1;
451         JSValue obj2 = getProperty(exec, thisObj, lk1);
452         if (exec->hadException())
453             return JSValue::encode(jsUndefined());
454         JSValue obj = getProperty(exec, thisObj, k);
455         if (exec->hadException())
456             return JSValue::encode(jsUndefined());
457
458         if (obj2)
459             thisObj->methodTable()->putByIndex(thisObj, exec, k, obj2);
460         else
461             thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, k);
462
463         if (obj)
464             thisObj->methodTable()->putByIndex(thisObj, exec, lk1, obj);
465         else
466             thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, lk1);
467     }
468     return JSValue::encode(thisObj);
469 }
470
471 EncodedJSValue JSC_HOST_CALL arrayProtoFuncShift(ExecState* exec)
472 {
473     JSObject* thisObj = exec->hostThisValue().toObject(exec);
474     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
475     if (exec->hadException())
476         return JSValue::encode(jsUndefined());
477
478     JSValue result;
479     if (length == 0) {
480         putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(length));
481         result = jsUndefined();
482     } else {
483         result = thisObj->get(exec, 0);
484         if (isJSArray(&exec->globalData(), thisObj))
485             ((JSArray *)thisObj)->shiftCount(exec, 1);
486         else {
487             for (unsigned k = 1; k < length; k++) {
488                 JSValue obj = getProperty(exec, thisObj, k);
489                 if (exec->hadException())
490                     return JSValue::encode(jsUndefined());
491                 if (obj)
492                     thisObj->methodTable()->putByIndex(thisObj, exec, k - 1, obj);
493                 else
494                     thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, k - 1);
495             }
496             thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, length - 1);
497         }
498         putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(length - 1));
499     }
500     return JSValue::encode(result);
501 }
502
503 EncodedJSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState* exec)
504 {
505     // http://developer.netscape.com/docs/manuals/js/client/jsref/array.htm#1193713 or 15.4.4.10
506     JSObject* thisObj = exec->hostThisValue().toObject(exec);
507     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
508     if (exec->hadException())
509         return JSValue::encode(jsUndefined());
510
511     // We return a new array
512     JSArray* resObj = constructEmptyArray(exec);
513     JSValue result = resObj;
514
515     unsigned begin = argumentClampedIndexFromStartOrEnd(exec, 0, length);
516     unsigned end = argumentClampedIndexFromStartOrEnd(exec, 1, length, length);
517
518     unsigned n = 0;
519     for (unsigned k = begin; k < end; k++, n++) {
520         JSValue v = getProperty(exec, thisObj, k);
521         if (exec->hadException())
522             return JSValue::encode(jsUndefined());
523         if (v)
524             resObj->methodTable()->putByIndex(resObj, exec, n, v);
525     }
526     resObj->setLength(n);
527     return JSValue::encode(result);
528 }
529
530 EncodedJSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec)
531 {
532     JSObject* thisObj = exec->hostThisValue().toObject(exec);
533     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
534     if (!length || exec->hadException())
535         return JSValue::encode(thisObj);
536
537     JSValue function = exec->argument(0);
538     CallData callData;
539     CallType callType = getCallData(function, callData);
540
541     if (thisObj->classInfo() == &JSArray::s_info) {
542         if (isNumericCompareFunction(exec, callType, callData))
543             asArray(thisObj)->sortNumeric(exec, function, callType, callData);
544         else if (callType != CallTypeNone)
545             asArray(thisObj)->sort(exec, function, callType, callData);
546         else
547             asArray(thisObj)->sort(exec);
548         return JSValue::encode(thisObj);
549     }
550
551     // "Min" sort. Not the fastest, but definitely less code than heapsort
552     // or quicksort, and much less swapping than bubblesort/insertionsort.
553     for (unsigned i = 0; i < length - 1; ++i) {
554         JSValue iObj = thisObj->get(exec, i);
555         if (exec->hadException())
556             return JSValue::encode(jsUndefined());
557         unsigned themin = i;
558         JSValue minObj = iObj;
559         for (unsigned j = i + 1; j < length; ++j) {
560             JSValue jObj = thisObj->get(exec, j);
561             if (exec->hadException())
562                 return JSValue::encode(jsUndefined());
563             double compareResult;
564             if (jObj.isUndefined())
565                 compareResult = 1; // don't check minObj because there's no need to differentiate == (0) from > (1)
566             else if (minObj.isUndefined())
567                 compareResult = -1;
568             else if (callType != CallTypeNone) {
569                 MarkedArgumentBuffer l;
570                 l.append(jObj);
571                 l.append(minObj);
572                 compareResult = call(exec, function, callType, callData, jsUndefined(), l).toNumber(exec);
573             } else
574                 compareResult = (jObj.toString(exec) < minObj.toString(exec)) ? -1 : 1;
575
576             if (compareResult < 0) {
577                 themin = j;
578                 minObj = jObj;
579             }
580         }
581         // Swap themin and i
582         if (themin > i) {
583             thisObj->methodTable()->putByIndex(thisObj, exec, i, minObj);
584             thisObj->methodTable()->putByIndex(thisObj, exec, themin, iObj);
585         }
586     }
587     return JSValue::encode(thisObj);
588 }
589
590 EncodedJSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec)
591 {
592     // 15.4.4.12
593
594     JSObject* thisObj = exec->hostThisValue().toObject(exec);
595     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
596     if (exec->hadException())
597         return JSValue::encode(jsUndefined());
598
599     if (!exec->argumentCount())
600         return JSValue::encode(constructEmptyArray(exec));
601
602     unsigned begin = argumentClampedIndexFromStartOrEnd(exec, 0, length);
603
604     unsigned deleteCount = length - begin;
605     if (exec->argumentCount() > 1) {
606         double deleteDouble = exec->argument(1).toInteger(exec);
607         if (deleteDouble < 0)
608             deleteCount = 0;
609         else if (deleteDouble > length - begin)
610             deleteCount = length - begin;
611         else
612             deleteCount = static_cast<unsigned>(deleteDouble);
613     }
614
615     JSArray* resObj = JSArray::create(exec->globalData(), exec->lexicalGlobalObject()->arrayStructure(), deleteCount, CreateCompact);
616     JSValue result = resObj;
617     JSGlobalData& globalData = exec->globalData();
618     for (unsigned k = 0; k < deleteCount; k++) {
619         JSValue v = getProperty(exec, thisObj, k + begin);
620         if (exec->hadException())
621             return JSValue::encode(jsUndefined());
622         resObj->uncheckedSetIndex(globalData, k, v);
623     }
624
625     resObj->setLength(deleteCount);
626
627     unsigned additionalArgs = std::max<int>(exec->argumentCount() - 2, 0);
628     if (additionalArgs != deleteCount) {
629         if (additionalArgs < deleteCount) {
630             if ((!begin) && (isJSArray(&exec->globalData(), thisObj)))
631                 ((JSArray *)thisObj)->shiftCount(exec, deleteCount - additionalArgs);
632             else {
633                 for (unsigned k = begin; k < length - deleteCount; ++k) {
634                     JSValue v = getProperty(exec, thisObj, k + deleteCount);
635                     if (exec->hadException())
636                         return JSValue::encode(jsUndefined());
637                     if (v)
638                         thisObj->methodTable()->putByIndex(thisObj, exec, k + additionalArgs, v);
639                     else
640                         thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, k + additionalArgs);
641                 }
642                 for (unsigned k = length; k > length - deleteCount + additionalArgs; --k)
643                     thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, k - 1);
644             }
645         } else {
646             if ((!begin) && (isJSArray(&exec->globalData(), thisObj)))
647                 ((JSArray *)thisObj)->unshiftCount(exec, additionalArgs - deleteCount);
648             else {
649                 for (unsigned k = length - deleteCount; k > begin; --k) {
650                     JSValue obj = getProperty(exec, thisObj, k + deleteCount - 1);
651                     if (exec->hadException())
652                         return JSValue::encode(jsUndefined());
653                     if (obj)
654                         thisObj->methodTable()->putByIndex(thisObj, exec, k + additionalArgs - 1, obj);
655                     else
656                         thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, k + additionalArgs - 1);
657                 }
658             }
659         }
660     }
661     for (unsigned k = 0; k < additionalArgs; ++k)
662         thisObj->methodTable()->putByIndex(thisObj, exec, k + begin, exec->argument(k + 2));
663
664     putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(length - deleteCount + additionalArgs));
665     return JSValue::encode(result);
666 }
667
668 EncodedJSValue JSC_HOST_CALL arrayProtoFuncUnShift(ExecState* exec)
669 {
670     // 15.4.4.13
671
672     JSObject* thisObj = exec->hostThisValue().toObject(exec);
673     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
674     if (exec->hadException())
675         return JSValue::encode(jsUndefined());
676
677     unsigned nrArgs = exec->argumentCount();
678     if ((nrArgs) && (length)) {
679         if (isJSArray(&exec->globalData(), thisObj))
680             ((JSArray *)thisObj)->unshiftCount(exec, nrArgs);
681         else {
682             for (unsigned k = length; k > 0; --k) {
683                 JSValue v = getProperty(exec, thisObj, k - 1);
684                 if (exec->hadException())
685                     return JSValue::encode(jsUndefined());
686                 if (v)
687                     thisObj->methodTable()->putByIndex(thisObj, exec, k + nrArgs - 1, v);
688                 else
689                     thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, k + nrArgs - 1);
690             }
691         }
692     }
693     for (unsigned k = 0; k < nrArgs; ++k)
694         thisObj->methodTable()->putByIndex(thisObj, exec, k, exec->argument(k));
695     JSValue result = jsNumber(length + nrArgs);
696     putProperty(exec, thisObj, exec->propertyNames().length, result);
697     return JSValue::encode(result);
698 }
699
700 EncodedJSValue JSC_HOST_CALL arrayProtoFuncFilter(ExecState* exec)
701 {
702     JSObject* thisObj = exec->hostThisValue().toObject(exec);
703     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
704     if (exec->hadException())
705         return JSValue::encode(jsUndefined());
706
707     JSValue function = exec->argument(0);
708     CallData callData;
709     CallType callType = getCallData(function, callData);
710     if (callType == CallTypeNone)
711         return throwVMTypeError(exec);
712
713     JSValue applyThis = exec->argument(1);
714     JSArray* resultArray = constructEmptyArray(exec);
715
716     unsigned filterIndex = 0;
717     unsigned k = 0;
718     if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) {
719         JSFunction* f = asFunction(function);
720         JSArray* array = asArray(thisObj);
721         CachedCall cachedCall(exec, f, 3);
722         for (; k < length && !exec->hadException(); ++k) {
723             if (!array->canGetIndex(k))
724                 break;
725             JSValue v = array->getIndex(k);
726             cachedCall.setThis(applyThis);
727             cachedCall.setArgument(0, v);
728             cachedCall.setArgument(1, jsNumber(k));
729             cachedCall.setArgument(2, thisObj);
730             
731             JSValue result = cachedCall.call();
732             if (result.toBoolean(exec))
733                 resultArray->methodTable()->putByIndex(resultArray, exec, filterIndex++, v);
734         }
735         if (k == length)
736             return JSValue::encode(resultArray);
737     }
738     for (; k < length && !exec->hadException(); ++k) {
739         PropertySlot slot(thisObj);
740         if (!thisObj->getPropertySlot(exec, k, slot))
741             continue;
742         JSValue v = slot.getValue(exec, k);
743
744         if (exec->hadException())
745             return JSValue::encode(jsUndefined());
746
747         MarkedArgumentBuffer eachArguments;
748         eachArguments.append(v);
749         eachArguments.append(jsNumber(k));
750         eachArguments.append(thisObj);
751
752         JSValue result = call(exec, function, callType, callData, applyThis, eachArguments);
753         if (result.toBoolean(exec))
754             resultArray->methodTable()->putByIndex(resultArray, exec, filterIndex++, v);
755     }
756     return JSValue::encode(resultArray);
757 }
758
759 EncodedJSValue JSC_HOST_CALL arrayProtoFuncMap(ExecState* exec)
760 {
761     JSObject* thisObj = exec->hostThisValue().toObject(exec);
762     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
763     if (exec->hadException())
764         return JSValue::encode(jsUndefined());
765
766     JSValue function = exec->argument(0);
767     CallData callData;
768     CallType callType = getCallData(function, callData);
769     if (callType == CallTypeNone)
770         return throwVMTypeError(exec);
771
772     JSValue applyThis = exec->argument(1);
773
774     JSArray* resultArray = constructEmptyArray(exec, length);
775     unsigned k = 0;
776     if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) {
777         JSFunction* f = asFunction(function);
778         JSArray* array = asArray(thisObj);
779         CachedCall cachedCall(exec, f, 3);
780         for (; k < length && !exec->hadException(); ++k) {
781             if (UNLIKELY(!array->canGetIndex(k)))
782                 break;
783
784             cachedCall.setThis(applyThis);
785             cachedCall.setArgument(0, array->getIndex(k));
786             cachedCall.setArgument(1, jsNumber(k));
787             cachedCall.setArgument(2, thisObj);
788
789             JSArray::putByIndex(resultArray, exec, k, cachedCall.call());
790         }
791     }
792     for (; k < length && !exec->hadException(); ++k) {
793         PropertySlot slot(thisObj);
794         if (!thisObj->getPropertySlot(exec, k, slot))
795             continue;
796         JSValue v = slot.getValue(exec, k);
797
798         if (exec->hadException())
799             return JSValue::encode(jsUndefined());
800
801         MarkedArgumentBuffer eachArguments;
802         eachArguments.append(v);
803         eachArguments.append(jsNumber(k));
804         eachArguments.append(thisObj);
805
806         if (exec->hadException())
807             return JSValue::encode(jsUndefined());
808
809         JSValue result = call(exec, function, callType, callData, applyThis, eachArguments);
810         resultArray->methodTable()->putByIndex(resultArray, exec, k, result);
811     }
812
813     return JSValue::encode(resultArray);
814 }
815
816 // Documentation for these three is available at:
817 // http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:every
818 // http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:forEach
819 // http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:some
820
821 EncodedJSValue JSC_HOST_CALL arrayProtoFuncEvery(ExecState* exec)
822 {
823     JSObject* thisObj = exec->hostThisValue().toObject(exec);
824     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
825     if (exec->hadException())
826         return JSValue::encode(jsUndefined());
827
828     JSValue function = exec->argument(0);
829     CallData callData;
830     CallType callType = getCallData(function, callData);
831     if (callType == CallTypeNone)
832         return throwVMTypeError(exec);
833
834     JSValue applyThis = exec->argument(1);
835
836     JSValue result = jsBoolean(true);
837
838     unsigned k = 0;
839     if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) {
840         JSFunction* f = asFunction(function);
841         JSArray* array = asArray(thisObj);
842         CachedCall cachedCall(exec, f, 3);
843         for (; k < length && !exec->hadException(); ++k) {
844             if (UNLIKELY(!array->canGetIndex(k)))
845                 break;
846             
847             cachedCall.setThis(applyThis);
848             cachedCall.setArgument(0, array->getIndex(k));
849             cachedCall.setArgument(1, jsNumber(k));
850             cachedCall.setArgument(2, thisObj);
851             JSValue result = cachedCall.call();
852             if (!result.toBoolean(cachedCall.newCallFrame(exec)))
853                 return JSValue::encode(jsBoolean(false));
854         }
855     }
856     for (; k < length && !exec->hadException(); ++k) {
857         PropertySlot slot(thisObj);
858         if (!thisObj->getPropertySlot(exec, k, slot))
859             continue;
860
861         MarkedArgumentBuffer eachArguments;
862         eachArguments.append(slot.getValue(exec, k));
863         eachArguments.append(jsNumber(k));
864         eachArguments.append(thisObj);
865
866         if (exec->hadException())
867             return JSValue::encode(jsUndefined());
868
869         bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments).toBoolean(exec);
870         if (!predicateResult) {
871             result = jsBoolean(false);
872             break;
873         }
874     }
875
876     return JSValue::encode(result);
877 }
878
879 EncodedJSValue JSC_HOST_CALL arrayProtoFuncForEach(ExecState* exec)
880 {
881     JSObject* thisObj = exec->hostThisValue().toObject(exec);
882     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
883     if (exec->hadException())
884         return JSValue::encode(jsUndefined());
885
886     JSValue function = exec->argument(0);
887     CallData callData;
888     CallType callType = getCallData(function, callData);
889     if (callType == CallTypeNone)
890         return throwVMTypeError(exec);
891
892     JSValue applyThis = exec->argument(1);
893
894     unsigned k = 0;
895     if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) {
896         JSFunction* f = asFunction(function);
897         JSArray* array = asArray(thisObj);
898         CachedCall cachedCall(exec, f, 3);
899         for (; k < length && !exec->hadException(); ++k) {
900             if (UNLIKELY(!array->canGetIndex(k)))
901                 break;
902
903             cachedCall.setThis(applyThis);
904             cachedCall.setArgument(0, array->getIndex(k));
905             cachedCall.setArgument(1, jsNumber(k));
906             cachedCall.setArgument(2, thisObj);
907
908             cachedCall.call();
909         }
910     }
911     for (; k < length && !exec->hadException(); ++k) {
912         PropertySlot slot(thisObj);
913         if (!thisObj->getPropertySlot(exec, k, slot))
914             continue;
915
916         MarkedArgumentBuffer eachArguments;
917         eachArguments.append(slot.getValue(exec, k));
918         eachArguments.append(jsNumber(k));
919         eachArguments.append(thisObj);
920
921         if (exec->hadException())
922             return JSValue::encode(jsUndefined());
923
924         call(exec, function, callType, callData, applyThis, eachArguments);
925     }
926     return JSValue::encode(jsUndefined());
927 }
928
929 EncodedJSValue JSC_HOST_CALL arrayProtoFuncSome(ExecState* exec)
930 {
931     JSObject* thisObj = exec->hostThisValue().toObject(exec);
932     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
933     if (exec->hadException())
934         return JSValue::encode(jsUndefined());
935
936     JSValue function = exec->argument(0);
937     CallData callData;
938     CallType callType = getCallData(function, callData);
939     if (callType == CallTypeNone)
940         return throwVMTypeError(exec);
941
942     JSValue applyThis = exec->argument(1);
943
944     JSValue result = jsBoolean(false);
945
946     unsigned k = 0;
947     if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) {
948         JSFunction* f = asFunction(function);
949         JSArray* array = asArray(thisObj);
950         CachedCall cachedCall(exec, f, 3);
951         for (; k < length && !exec->hadException(); ++k) {
952             if (UNLIKELY(!array->canGetIndex(k)))
953                 break;
954             
955             cachedCall.setThis(applyThis);
956             cachedCall.setArgument(0, array->getIndex(k));
957             cachedCall.setArgument(1, jsNumber(k));
958             cachedCall.setArgument(2, thisObj);
959             JSValue result = cachedCall.call();
960             if (result.toBoolean(cachedCall.newCallFrame(exec)))
961                 return JSValue::encode(jsBoolean(true));
962         }
963     }
964     for (; k < length && !exec->hadException(); ++k) {
965         PropertySlot slot(thisObj);
966         if (!thisObj->getPropertySlot(exec, k, slot))
967             continue;
968
969         MarkedArgumentBuffer eachArguments;
970         eachArguments.append(slot.getValue(exec, k));
971         eachArguments.append(jsNumber(k));
972         eachArguments.append(thisObj);
973
974         if (exec->hadException())
975             return JSValue::encode(jsUndefined());
976
977         bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments).toBoolean(exec);
978         if (predicateResult) {
979             result = jsBoolean(true);
980             break;
981         }
982     }
983     return JSValue::encode(result);
984 }
985
986 EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduce(ExecState* exec)
987 {
988     JSObject* thisObj = exec->hostThisValue().toObject(exec);
989     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
990     if (exec->hadException())
991         return JSValue::encode(jsUndefined());
992
993     JSValue function = exec->argument(0);
994     CallData callData;
995     CallType callType = getCallData(function, callData);
996     if (callType == CallTypeNone)
997         return throwVMTypeError(exec);
998
999     unsigned i = 0;
1000     JSValue rv;
1001     if (!length && exec->argumentCount() == 1)
1002         return throwVMTypeError(exec);
1003
1004     JSArray* array = 0;
1005     if (isJSArray(&exec->globalData(), thisObj))
1006         array = asArray(thisObj);
1007
1008     if (exec->argumentCount() >= 2)
1009         rv = exec->argument(1);
1010     else if (array && array->canGetIndex(0)){
1011         rv = array->getIndex(0);
1012         i = 1;
1013     } else {
1014         for (i = 0; i < length; i++) {
1015             rv = getProperty(exec, thisObj, i);
1016             if (exec->hadException())
1017                 return JSValue::encode(jsUndefined());
1018             if (rv)
1019                 break;
1020         }
1021         if (!rv)
1022             return throwVMTypeError(exec);
1023         i++;
1024     }
1025
1026     if (callType == CallTypeJS && array) {
1027         CachedCall cachedCall(exec, asFunction(function), 4);
1028         for (; i < length && !exec->hadException(); ++i) {
1029             cachedCall.setThis(jsUndefined());
1030             cachedCall.setArgument(0, rv);
1031             JSValue v;
1032             if (LIKELY(array->canGetIndex(i)))
1033                 v = array->getIndex(i);
1034             else
1035                 break; // length has been made unsafe while we enumerate fallback to slow path
1036             cachedCall.setArgument(1, v);
1037             cachedCall.setArgument(2, jsNumber(i));
1038             cachedCall.setArgument(3, array);
1039             rv = cachedCall.call();
1040         }
1041         if (i == length) // only return if we reached the end of the array
1042             return JSValue::encode(rv);
1043     }
1044
1045     for (; i < length && !exec->hadException(); ++i) {
1046         JSValue prop = getProperty(exec, thisObj, i);
1047         if (exec->hadException())
1048             return JSValue::encode(jsUndefined());
1049         if (!prop)
1050             continue;
1051         
1052         MarkedArgumentBuffer eachArguments;
1053         eachArguments.append(rv);
1054         eachArguments.append(prop);
1055         eachArguments.append(jsNumber(i));
1056         eachArguments.append(thisObj);
1057         
1058         rv = call(exec, function, callType, callData, jsUndefined(), eachArguments);
1059     }
1060     return JSValue::encode(rv);
1061 }
1062
1063 EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduceRight(ExecState* exec)
1064 {
1065     JSObject* thisObj = exec->hostThisValue().toObject(exec);
1066     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
1067     if (exec->hadException())
1068         return JSValue::encode(jsUndefined());
1069
1070     JSValue function = exec->argument(0);
1071     CallData callData;
1072     CallType callType = getCallData(function, callData);
1073     if (callType == CallTypeNone)
1074         return throwVMTypeError(exec);
1075     
1076     unsigned i = 0;
1077     JSValue rv;
1078     if (!length && exec->argumentCount() == 1)
1079         return throwVMTypeError(exec);
1080
1081     JSArray* array = 0;
1082     if (isJSArray(&exec->globalData(), thisObj))
1083         array = asArray(thisObj);
1084     
1085     if (exec->argumentCount() >= 2)
1086         rv = exec->argument(1);
1087     else if (array && array->canGetIndex(length - 1)){
1088         rv = array->getIndex(length - 1);
1089         i = 1;
1090     } else {
1091         for (i = 0; i < length; i++) {
1092             rv = getProperty(exec, thisObj, length - i - 1);
1093             if (exec->hadException())
1094                 return JSValue::encode(jsUndefined());
1095             if (rv)
1096                 break;
1097         }
1098         if (!rv)
1099             return throwVMTypeError(exec);
1100         i++;
1101     }
1102     
1103     if (callType == CallTypeJS && array) {
1104         CachedCall cachedCall(exec, asFunction(function), 4);
1105         for (; i < length && !exec->hadException(); ++i) {
1106             unsigned idx = length - i - 1;
1107             cachedCall.setThis(jsUndefined());
1108             cachedCall.setArgument(0, rv);
1109             if (UNLIKELY(!array->canGetIndex(idx)))
1110                 break; // length has been made unsafe while we enumerate fallback to slow path
1111             cachedCall.setArgument(1, array->getIndex(idx));
1112             cachedCall.setArgument(2, jsNumber(idx));
1113             cachedCall.setArgument(3, array);
1114             rv = cachedCall.call();
1115         }
1116         if (i == length) // only return if we reached the end of the array
1117             return JSValue::encode(rv);
1118     }
1119     
1120     for (; i < length && !exec->hadException(); ++i) {
1121         unsigned idx = length - i - 1;
1122         JSValue prop = getProperty(exec, thisObj, idx);
1123         if (exec->hadException())
1124             return JSValue::encode(jsUndefined());
1125         if (!prop)
1126             continue;
1127         
1128         MarkedArgumentBuffer eachArguments;
1129         eachArguments.append(rv);
1130         eachArguments.append(prop);
1131         eachArguments.append(jsNumber(idx));
1132         eachArguments.append(thisObj);
1133         
1134         rv = call(exec, function, callType, callData, jsUndefined(), eachArguments);
1135     }
1136     return JSValue::encode(rv);        
1137 }
1138
1139 EncodedJSValue JSC_HOST_CALL arrayProtoFuncIndexOf(ExecState* exec)
1140 {
1141     // 15.4.4.14
1142     JSObject* thisObj = exec->hostThisValue().toObject(exec);
1143     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
1144     if (exec->hadException())
1145         return JSValue::encode(jsUndefined());
1146
1147     unsigned index = argumentClampedIndexFromStartOrEnd(exec, 1, length);
1148     JSValue searchElement = exec->argument(0);
1149     for (; index < length; ++index) {
1150         JSValue e = getProperty(exec, thisObj, index);
1151         if (exec->hadException())
1152             return JSValue::encode(jsUndefined());
1153         if (!e)
1154             continue;
1155         if (JSValue::strictEqual(exec, searchElement, e))
1156             return JSValue::encode(jsNumber(index));
1157     }
1158
1159     return JSValue::encode(jsNumber(-1));
1160 }
1161
1162 EncodedJSValue JSC_HOST_CALL arrayProtoFuncLastIndexOf(ExecState* exec)
1163 {
1164     // 15.4.4.15
1165     JSObject* thisObj = exec->hostThisValue().toObject(exec);
1166     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
1167     if (!length)
1168         return JSValue::encode(jsNumber(-1));
1169
1170     unsigned index = length - 1;
1171     JSValue fromValue = exec->argument(1);
1172     if (!fromValue.isUndefined()) {
1173         double fromDouble = fromValue.toInteger(exec);
1174         if (fromDouble < 0) {
1175             fromDouble += length;
1176             if (fromDouble < 0)
1177                 return JSValue::encode(jsNumber(-1));
1178         }
1179         if (fromDouble < length)
1180             index = static_cast<unsigned>(fromDouble);
1181     }
1182
1183     JSValue searchElement = exec->argument(0);
1184     do {
1185         ASSERT(index < length);
1186         JSValue e = getProperty(exec, thisObj, index);
1187         if (exec->hadException())
1188             return JSValue::encode(jsUndefined());
1189         if (!e)
1190             continue;
1191         if (JSValue::strictEqual(exec, searchElement, e))
1192             return JSValue::encode(jsNumber(index));
1193     } while (index--);
1194
1195     return JSValue::encode(jsNumber(-1));
1196 }
1197
1198 } // namespace JSC