Bug 394551: taking out the last patch as broke Windows build.
git-svn-id: svn://10.0.0.236/trunk@236126 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -1762,23 +1762,29 @@ typedef enum ArrayExtraMode {
|
||||
static JSBool
|
||||
array_extra(JSContext *cx, ArrayExtraMode mode, uintN argc, jsval *vp)
|
||||
{
|
||||
enum { ELEM, TEMP, RVAL, NROOTS };
|
||||
jsval *argv, roots[NROOTS], *sp, *origsp, *oldsp;
|
||||
JSObject *obj;
|
||||
jsuint length, newlen;
|
||||
jsval *argv, *elemroot, *invokevp, *sp;
|
||||
JSBool ok, cond, hole;
|
||||
jsuint length, newlen;
|
||||
JSObject *callable, *thisp, *newarr;
|
||||
jsint start, end, step, i;
|
||||
JSTempValueRooter tvr;
|
||||
void *mark;
|
||||
JSStackFrame *fp;
|
||||
|
||||
/* Hoist the explicit local root address computation. */
|
||||
argv = vp + 2;
|
||||
|
||||
obj = JSVAL_TO_OBJECT(vp[1]);
|
||||
if (!js_GetLengthProperty(cx, obj, &length))
|
||||
ok = js_GetLengthProperty(cx, obj, &length);
|
||||
if (!ok)
|
||||
return JS_FALSE;
|
||||
|
||||
/*
|
||||
* First, get or compute our callee, so that we error out consistently
|
||||
* when passed a non-callable object.
|
||||
*/
|
||||
argv = vp + 2;
|
||||
callable = js_ValueToCallableObject(cx, &argv[0], JSV2F_SEARCH_STACK);
|
||||
if (!callable)
|
||||
return JS_FALSE;
|
||||
@@ -1792,6 +1798,8 @@ array_extra(JSContext *cx, ArrayExtraMode mode, uintN argc, jsval *vp)
|
||||
newarr = NULL;
|
||||
#endif
|
||||
start = 0, end = length, step = 1;
|
||||
memset(roots, 0, sizeof roots);
|
||||
JS_PUSH_TEMP_ROOT(cx, NROOTS, roots, &tvr);
|
||||
|
||||
switch (mode) {
|
||||
case REDUCE_RIGHT:
|
||||
@@ -1801,21 +1809,24 @@ array_extra(JSContext *cx, ArrayExtraMode mode, uintN argc, jsval *vp)
|
||||
if (length == 0 && argc == 1) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_EMPTY_ARRAY_REDUCE);
|
||||
return JS_FALSE;
|
||||
ok = JS_FALSE;
|
||||
goto early_out;
|
||||
}
|
||||
if (argc >= 2) {
|
||||
*vp = argv[1];
|
||||
roots[RVAL] = argv[1];
|
||||
} else {
|
||||
do {
|
||||
if (!GetArrayElement(cx, obj, start, &hole, vp))
|
||||
return JS_FALSE;
|
||||
ok = GetArrayElement(cx, obj, start, &hole, &roots[RVAL]);
|
||||
if (!ok)
|
||||
goto early_out;
|
||||
start += step;
|
||||
} while (hole && start != end);
|
||||
|
||||
if (hole && start == end) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_EMPTY_ARRAY_REDUCE);
|
||||
return JS_FALSE;
|
||||
ok = JS_FALSE;
|
||||
goto early_out;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1823,80 +1834,87 @@ array_extra(JSContext *cx, ArrayExtraMode mode, uintN argc, jsval *vp)
|
||||
case FILTER:
|
||||
newlen = (mode == MAP) ? length : 0;
|
||||
newarr = js_NewArrayObject(cx, newlen, NULL);
|
||||
if (!newarr)
|
||||
return JS_FALSE;
|
||||
*vp = OBJECT_TO_JSVAL(newarr);
|
||||
if (!newarr) {
|
||||
ok = JS_FALSE;
|
||||
goto early_out;
|
||||
}
|
||||
roots[RVAL] = OBJECT_TO_JSVAL(newarr);
|
||||
break;
|
||||
case SOME:
|
||||
*vp = JSVAL_FALSE;
|
||||
roots[RVAL] = JSVAL_FALSE;
|
||||
break;
|
||||
case EVERY:
|
||||
*vp = JSVAL_TRUE;
|
||||
roots[RVAL] = JSVAL_TRUE;
|
||||
break;
|
||||
case FOREACH:
|
||||
*vp = JSVAL_VOID;
|
||||
break;
|
||||
}
|
||||
|
||||
if (length == 0)
|
||||
return JS_TRUE;
|
||||
goto early_out;
|
||||
|
||||
if (argc > 1 && !REDUCE_MODE(mode)) {
|
||||
if (!js_ValueToObject(cx, argv[1], &thisp))
|
||||
return JS_FALSE;
|
||||
ok = js_ValueToObject(cx, argv[1], &thisp);
|
||||
if (!ok)
|
||||
goto early_out;
|
||||
argv[1] = OBJECT_TO_JSVAL(thisp);
|
||||
} else {
|
||||
thisp = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* For all but REDUCE, we call with 3 args (value, index, array). REDUCE
|
||||
* requires 4 args (accum, value, index, array).
|
||||
* For all but REDUCE, we call with 3 args (value, index, array), plus
|
||||
* room for rval. REDUCE requires 4 args (accum, value, index, array).
|
||||
*/
|
||||
argc = 3 + REDUCE_MODE(mode);
|
||||
elemroot = js_AllocStack(cx, 1 + 2 + argc, &mark);
|
||||
if (!elemroot)
|
||||
return JS_FALSE;
|
||||
origsp = js_AllocStack(cx, 2 + argc + 1, &mark);
|
||||
if (!origsp) {
|
||||
ok = JS_FALSE;
|
||||
goto early_out;
|
||||
}
|
||||
|
||||
/* From this point the control must flow through out:. */
|
||||
ok = JS_TRUE;
|
||||
invokevp = elemroot + 1;
|
||||
/* Lift current frame to include our args. */
|
||||
fp = cx->fp;
|
||||
oldsp = fp->sp;
|
||||
|
||||
for (i = start; i != end; i += step) {
|
||||
ok = JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP) &&
|
||||
GetArrayElement(cx, obj, i, &hole, elemroot);
|
||||
ok = (JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP) &&
|
||||
GetArrayElement(cx, obj, i, &hole, &roots[ELEM]));
|
||||
if (!ok)
|
||||
goto out;
|
||||
break;
|
||||
if (hole)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Push callable and 'this', then args. We must do this for every
|
||||
* iteration around the loop since js_Invoke uses spbase[0] for return
|
||||
* value storage, while some native functions use spbase[1] for local
|
||||
* iteration around the loop since js_Invoke uses origsp[0] for return
|
||||
* value storage, while some native functions use origsp[1] for local
|
||||
* rooting.
|
||||
*/
|
||||
sp = invokevp;
|
||||
sp = origsp;
|
||||
*sp++ = OBJECT_TO_JSVAL(callable);
|
||||
*sp++ = OBJECT_TO_JSVAL(thisp);
|
||||
if (REDUCE_MODE(mode))
|
||||
*sp++ = *vp;
|
||||
*sp++ = *elemroot;
|
||||
*sp++ = roots[RVAL];
|
||||
*sp++ = roots[ELEM];
|
||||
*sp++ = INT_TO_JSVAL(i);
|
||||
*sp++ = OBJECT_TO_JSVAL(obj);
|
||||
|
||||
/* Do the call. */
|
||||
ok = js_Invoke(cx, argc, invokevp, JSINVOKE_INTERNAL);
|
||||
fp->sp = sp;
|
||||
ok = js_Invoke(cx, argc, JSINVOKE_INTERNAL);
|
||||
roots[TEMP] = fp->sp[-1];
|
||||
fp->sp = oldsp;
|
||||
if (!ok)
|
||||
break;
|
||||
|
||||
if (mode > MAP) {
|
||||
if (*invokevp == JSVAL_NULL) {
|
||||
if (roots[TEMP] == JSVAL_NULL) {
|
||||
cond = JS_FALSE;
|
||||
} else if (JSVAL_IS_BOOLEAN(*invokevp)) {
|
||||
cond = JSVAL_TO_BOOLEAN(*invokevp);
|
||||
} else if (JSVAL_IS_BOOLEAN(roots[TEMP])) {
|
||||
cond = JSVAL_TO_BOOLEAN(roots[TEMP]);
|
||||
} else {
|
||||
ok = js_ValueToBoolean(cx, *invokevp, &cond);
|
||||
ok = js_ValueToBoolean(cx, roots[TEMP], &cond);
|
||||
if (!ok)
|
||||
goto out;
|
||||
}
|
||||
@@ -1907,30 +1925,30 @@ array_extra(JSContext *cx, ArrayExtraMode mode, uintN argc, jsval *vp)
|
||||
break;
|
||||
case REDUCE:
|
||||
case REDUCE_RIGHT:
|
||||
*vp = *invokevp;
|
||||
roots[RVAL] = roots[TEMP];
|
||||
break;
|
||||
case MAP:
|
||||
ok = SetArrayElement(cx, newarr, i, *invokevp);
|
||||
ok = SetArrayElement(cx, newarr, i, roots[TEMP]);
|
||||
if (!ok)
|
||||
goto out;
|
||||
break;
|
||||
case FILTER:
|
||||
if (!cond)
|
||||
break;
|
||||
/* The filter passed *elemroot, so push it onto our result. */
|
||||
ok = SetArrayElement(cx, newarr, newlen++, *elemroot);
|
||||
/* The filter passed roots[ELEM], so push it onto our result. */
|
||||
ok = SetArrayElement(cx, newarr, newlen++, roots[ELEM]);
|
||||
if (!ok)
|
||||
goto out;
|
||||
break;
|
||||
case SOME:
|
||||
if (cond) {
|
||||
*vp = JSVAL_TRUE;
|
||||
roots[RVAL] = JSVAL_TRUE;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
case EVERY:
|
||||
if (!cond) {
|
||||
*vp = JSVAL_FALSE;
|
||||
roots[RVAL] = JSVAL_FALSE;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
@@ -1941,6 +1959,9 @@ array_extra(JSContext *cx, ArrayExtraMode mode, uintN argc, jsval *vp)
|
||||
js_FreeStack(cx, mark);
|
||||
if (ok && mode == FILTER)
|
||||
ok = js_SetLengthProperty(cx, newarr, newlen);
|
||||
early_out:
|
||||
*vp = roots[RVAL];
|
||||
JS_POP_TEMP_ROOT(cx, &tvr);
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user