mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 549617 - JS_EvaluateUCInStackFrame doesn't see variables in flat closure (r=mrbkap).
This commit is contained in:
parent
23f47cabac
commit
9c8234d49b
175
js/src/jsfun.cpp
175
js/src/jsfun.cpp
@ -1007,113 +1007,135 @@ call_enumerate(JSContext *cx, JSObject *obj)
|
||||
return ok;
|
||||
}
|
||||
|
||||
typedef enum JSCallPropertyKind {
|
||||
enum JSCallPropertyKind {
|
||||
JSCPK_ARGUMENTS,
|
||||
JSCPK_ARG,
|
||||
JSCPK_VAR
|
||||
} JSCallPropertyKind;
|
||||
JSCPK_VAR,
|
||||
JSCPK_UPVAR
|
||||
};
|
||||
|
||||
static JSBool
|
||||
CallPropertyOp(JSContext *cx, JSObject *obj, jsid id, jsval *vp,
|
||||
JSCallPropertyKind kind, JSBool setter)
|
||||
JSCallPropertyKind kind, JSBool setter = false)
|
||||
{
|
||||
JSFunction *fun;
|
||||
JSStackFrame *fp;
|
||||
uintN i;
|
||||
jsval *array;
|
||||
|
||||
if (STOBJ_GET_CLASS(obj) != &js_CallClass)
|
||||
return JS_TRUE;
|
||||
|
||||
fun = js_GetCallObjectFunction(obj);
|
||||
fp = (JSStackFrame *) obj->getPrivate();
|
||||
|
||||
if (kind == JSCPK_ARGUMENTS) {
|
||||
if (setter) {
|
||||
if (fp)
|
||||
fp->flags |= JSFRAME_OVERRIDE_ARGS;
|
||||
STOBJ_SET_SLOT(obj, JSSLOT_CALL_ARGUMENTS, *vp);
|
||||
} else {
|
||||
if (fp && !(fp->flags & JSFRAME_OVERRIDE_ARGS)) {
|
||||
JSObject *argsobj;
|
||||
|
||||
argsobj = js_GetArgsObject(cx, fp);
|
||||
if (!argsobj)
|
||||
return JS_FALSE;
|
||||
*vp = OBJECT_TO_JSVAL(argsobj);
|
||||
} else {
|
||||
*vp = STOBJ_GET_SLOT(obj, JSSLOT_CALL_ARGUMENTS);
|
||||
}
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_ASSERT(obj->getClass() == &js_CallClass);
|
||||
JS_ASSERT((int16) JSVAL_TO_INT(id) == JSVAL_TO_INT(id));
|
||||
i = (uint16) JSVAL_TO_INT(id);
|
||||
JS_ASSERT_IF(kind == JSCPK_ARG, i < fun->nargs);
|
||||
JS_ASSERT_IF(kind == JSCPK_VAR, i < fun->u.i.nvars);
|
||||
|
||||
if (!fp) {
|
||||
i += CALL_CLASS_FIXED_RESERVED_SLOTS;
|
||||
if (kind == JSCPK_VAR)
|
||||
i += fun->nargs;
|
||||
else
|
||||
JS_ASSERT(kind == JSCPK_ARG);
|
||||
return setter
|
||||
? JS_SetReservedSlot(cx, obj, i, *vp)
|
||||
: JS_GetReservedSlot(cx, obj, i, vp);
|
||||
}
|
||||
uintN i = (uint16) JSVAL_TO_INT(id);
|
||||
|
||||
if (kind == JSCPK_ARG) {
|
||||
array = fp->argv;
|
||||
jsval *array;
|
||||
if (kind == JSCPK_UPVAR) {
|
||||
JSObject *callee = JSVAL_TO_OBJECT(STOBJ_GET_SLOT(obj, JSSLOT_CALLEE));
|
||||
|
||||
#ifdef DEBUG
|
||||
JSFunction *callee_fun = (JSFunction *) callee->getPrivate();
|
||||
JS_ASSERT(FUN_FLAT_CLOSURE(callee_fun));
|
||||
JS_ASSERT(i < callee_fun->u.i.nupvars);
|
||||
#endif
|
||||
|
||||
array = callee->dslots;
|
||||
} else {
|
||||
JS_ASSERT(kind == JSCPK_VAR);
|
||||
array = fp->slots;
|
||||
JSFunction *fun = js_GetCallObjectFunction(obj);
|
||||
JS_ASSERT_IF(kind == JSCPK_ARG, i < fun->nargs);
|
||||
JS_ASSERT_IF(kind == JSCPK_VAR, i < fun->u.i.nvars);
|
||||
|
||||
JSStackFrame *fp = (JSStackFrame *) obj->getPrivate();
|
||||
|
||||
if (kind == JSCPK_ARGUMENTS) {
|
||||
if (setter) {
|
||||
if (fp)
|
||||
fp->flags |= JSFRAME_OVERRIDE_ARGS;
|
||||
STOBJ_SET_SLOT(obj, JSSLOT_CALL_ARGUMENTS, *vp);
|
||||
} else {
|
||||
if (fp && !(fp->flags & JSFRAME_OVERRIDE_ARGS)) {
|
||||
JSObject *argsobj;
|
||||
|
||||
argsobj = js_GetArgsObject(cx, fp);
|
||||
if (!argsobj)
|
||||
return false;
|
||||
*vp = OBJECT_TO_JSVAL(argsobj);
|
||||
} else {
|
||||
*vp = STOBJ_GET_SLOT(obj, JSSLOT_CALL_ARGUMENTS);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!fp) {
|
||||
i += CALL_CLASS_FIXED_RESERVED_SLOTS;
|
||||
if (kind == JSCPK_VAR)
|
||||
i += fun->nargs;
|
||||
else
|
||||
JS_ASSERT(kind == JSCPK_ARG);
|
||||
return setter
|
||||
? JS_SetReservedSlot(cx, obj, i, *vp)
|
||||
: JS_GetReservedSlot(cx, obj, i, vp);
|
||||
}
|
||||
|
||||
if (kind == JSCPK_ARG) {
|
||||
array = fp->argv;
|
||||
} else {
|
||||
JS_ASSERT(kind == JSCPK_VAR);
|
||||
array = fp->slots;
|
||||
}
|
||||
}
|
||||
|
||||
if (setter) {
|
||||
GC_POKE(cx, array[i]);
|
||||
array[i] = *vp;
|
||||
} else {
|
||||
*vp = array[i];
|
||||
}
|
||||
return JS_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
GetCallArguments(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||
{
|
||||
return CallPropertyOp(cx, obj, id, vp, JSCPK_ARGUMENTS, JS_FALSE);
|
||||
return CallPropertyOp(cx, obj, id, vp, JSCPK_ARGUMENTS);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
SetCallArguments(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||
{
|
||||
return CallPropertyOp(cx, obj, id, vp, JSCPK_ARGUMENTS, JS_TRUE);
|
||||
return CallPropertyOp(cx, obj, id, vp, JSCPK_ARGUMENTS, true);
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_GetCallArg(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||
{
|
||||
return CallPropertyOp(cx, obj, id, vp, JSCPK_ARG, JS_FALSE);
|
||||
return CallPropertyOp(cx, obj, id, vp, JSCPK_ARG);
|
||||
}
|
||||
|
||||
JSBool
|
||||
SetCallArg(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||
{
|
||||
return CallPropertyOp(cx, obj, id, vp, JSCPK_ARG, JS_TRUE);
|
||||
return CallPropertyOp(cx, obj, id, vp, JSCPK_ARG, true);
|
||||
}
|
||||
|
||||
JSBool
|
||||
GetFlatUpvar(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||
{
|
||||
return CallPropertyOp(cx, obj, id, vp, JSCPK_UPVAR);
|
||||
}
|
||||
|
||||
JSBool
|
||||
SetFlatUpvar(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||
{
|
||||
return CallPropertyOp(cx, obj, id, vp, JSCPK_UPVAR, true);
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_GetCallVar(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||
{
|
||||
return CallPropertyOp(cx, obj, id, vp, JSCPK_VAR, JS_FALSE);
|
||||
return CallPropertyOp(cx, obj, id, vp, JSCPK_VAR);
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_GetCallVarChecked(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||
{
|
||||
if (!CallPropertyOp(cx, obj, id, vp, JSCPK_VAR, JS_FALSE))
|
||||
return JS_FALSE;
|
||||
if (!CallPropertyOp(cx, obj, id, vp, JSCPK_VAR))
|
||||
return false;
|
||||
|
||||
return CheckForEscapingClosure(cx, obj, vp);
|
||||
}
|
||||
@ -1121,19 +1143,19 @@ js_GetCallVarChecked(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||
JSBool
|
||||
SetCallVar(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||
{
|
||||
return CallPropertyOp(cx, obj, id, vp, JSCPK_VAR, JS_TRUE);
|
||||
return CallPropertyOp(cx, obj, id, vp, JSCPK_VAR, true);
|
||||
}
|
||||
|
||||
JSBool JS_FASTCALL
|
||||
js_SetCallArg(JSContext *cx, JSObject *obj, jsid id, jsval v)
|
||||
{
|
||||
return CallPropertyOp(cx, obj, id, &v, JSCPK_ARG, JS_TRUE);
|
||||
return CallPropertyOp(cx, obj, id, &v, JSCPK_ARG, true);
|
||||
}
|
||||
|
||||
JSBool JS_FASTCALL
|
||||
js_SetCallVar(JSContext *cx, JSObject *obj, jsid id, jsval v)
|
||||
{
|
||||
return CallPropertyOp(cx, obj, id, &v, JSCPK_VAR, JS_TRUE);
|
||||
return CallPropertyOp(cx, obj, id, &v, JSCPK_VAR, true);
|
||||
}
|
||||
|
||||
JS_DEFINE_CALLINFO_4(extern, BOOL, js_SetCallArg, CONTEXT, OBJECT, JSID, JSVAL, 0,
|
||||
@ -1178,7 +1200,7 @@ call_resolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags,
|
||||
* comments in js_PurgeScopeChainHelper from jsobj.cpp.
|
||||
*/
|
||||
localKind = js_LookupLocal(cx, fun, JSID_TO_ATOM(id), &slot);
|
||||
if (localKind != JSLOCAL_NONE && localKind != JSLOCAL_UPVAR) {
|
||||
if (localKind != JSLOCAL_NONE) {
|
||||
JS_ASSERT((uint16) slot == slot);
|
||||
|
||||
/*
|
||||
@ -1191,12 +1213,22 @@ call_resolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags,
|
||||
getter = js_GetCallArg;
|
||||
setter = SetCallArg;
|
||||
} else {
|
||||
JS_ASSERT(localKind == JSLOCAL_VAR || localKind == JSLOCAL_CONST);
|
||||
JS_ASSERT(slot < fun->u.i.nvars);
|
||||
getter = js_GetCallVar;
|
||||
setter = SetCallVar;
|
||||
if (localKind == JSLOCAL_CONST)
|
||||
attrs |= JSPROP_READONLY;
|
||||
JSCallPropertyKind cpkind;
|
||||
if (localKind == JSLOCAL_UPVAR) {
|
||||
if (!FUN_FLAT_CLOSURE(fun))
|
||||
return JS_TRUE;
|
||||
getter = GetFlatUpvar;
|
||||
setter = SetFlatUpvar;
|
||||
cpkind = JSCPK_UPVAR;
|
||||
} else {
|
||||
JS_ASSERT(localKind == JSLOCAL_VAR || localKind == JSLOCAL_CONST);
|
||||
JS_ASSERT(slot < fun->u.i.nvars);
|
||||
getter = js_GetCallVar;
|
||||
setter = SetCallVar;
|
||||
cpkind = JSCPK_VAR;
|
||||
if (localKind == JSLOCAL_CONST)
|
||||
attrs |= JSPROP_READONLY;
|
||||
}
|
||||
|
||||
/*
|
||||
* Use js_GetCallVarChecked if the local's value is a null closure.
|
||||
@ -1204,7 +1236,7 @@ call_resolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags,
|
||||
* null closure, not on every use.
|
||||
*/
|
||||
jsval v;
|
||||
if (!CallPropertyOp(cx, obj, INT_TO_JSID((int16)slot), &v, JSCPK_VAR, JS_FALSE))
|
||||
if (!CallPropertyOp(cx, obj, INT_TO_JSID((int16)slot), &v, cpkind))
|
||||
return JS_FALSE;
|
||||
if (VALUE_IS_FUNCTION(cx, v) &&
|
||||
GET_FUNCTION_PRIVATE(cx, JSVAL_TO_OBJECT(v))->needsWrapper()) {
|
||||
@ -2535,6 +2567,7 @@ js_NewDebuggableFlatClosure(JSContext *cx, JSFunction *fun)
|
||||
{
|
||||
JS_ASSERT(cx->fp->fun->flags & JSFUN_HEAVYWEIGHT);
|
||||
JS_ASSERT(!cx->fp->fun->optimizedClosure());
|
||||
JS_ASSERT(FUN_FLAT_CLOSURE(fun));
|
||||
|
||||
return WrapEscapingClosure(cx, cx->fp, FUN_OBJECT(fun), fun);
|
||||
}
|
||||
|
@ -1457,10 +1457,10 @@ TrapHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
|
||||
|
||||
str = (JSString *) closure;
|
||||
caller = JS_GetScriptedCaller(cx, NULL);
|
||||
if (!JS_EvaluateScript(cx, caller->scopeChain,
|
||||
JS_GetStringBytes(str), JS_GetStringLength(str),
|
||||
caller->script->filename, caller->script->lineno,
|
||||
rval)) {
|
||||
if (!JS_EvaluateUCInStackFrame(cx, caller,
|
||||
JS_GetStringChars(str), JS_GetStringLength(str),
|
||||
caller->script->filename, caller->script->lineno,
|
||||
rval)) {
|
||||
return JSTRAP_ERROR;
|
||||
}
|
||||
if (!JSVAL_IS_VOID(*rval))
|
||||
|
@ -32,3 +32,4 @@ script 15.8-1.js
|
||||
script 15.9.5.js
|
||||
script 8.6.2.1-1.js
|
||||
script 9.9-1.js
|
||||
script testflatclosure.js
|
||||
|
24
js/src/tests/ecma/extensions/trapflatclosure.js
Normal file
24
js/src/tests/ecma/extensions/trapflatclosure.js
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/licenses/publicdomain/
|
||||
*/
|
||||
|
||||
var gTestfile = 'trapflatclosure.js';
|
||||
var BUGNUMBER = 549617;
|
||||
var summary = 'flat closure debugged via trap while still active';
|
||||
|
||||
var expect = "abc";
|
||||
var actual = expect;
|
||||
|
||||
function a(x, y) {
|
||||
return function () { return x; };
|
||||
}
|
||||
|
||||
var f = a("abc", 123);
|
||||
if (this.trap)
|
||||
trap(f, "try {actual = x} catch (e) {actual = e}");
|
||||
f();
|
||||
|
||||
reportCompare(expect, actual, summary);
|
||||
|
||||
printStatus("All tests passed!");
|
Loading…
Reference in New Issue
Block a user