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:
igor%mir2.org
2007-09-17 19:28:14 +00:00
parent dc8d3e4872
commit c419e325d6
10 changed files with 442 additions and 331 deletions

View File

@@ -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;
}