mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-03-02 06:22:20 +00:00
Bug 463997: JS regression test bug with 'with (window) ...', r=mrbkap
This commit is contained in:
parent
be93713678
commit
5f391095f0
@ -6449,7 +6449,8 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
// defined on our prototype chain. This way we can access this
|
||||
// expando w/o ever getting back into XPConnect.
|
||||
JSStackFrame *fp = NULL;
|
||||
if ((flags & (JSRESOLVE_ASSIGNING)) &&
|
||||
if ((flags & JSRESOLVE_ASSIGNING) &&
|
||||
!(flags & JSRESOLVE_WITH) &&
|
||||
!(JS_FrameIterator(cx, &fp) && fp->regs && (JSOp)*fp->regs->pc == JSOP_BINDNAME) &&
|
||||
win->IsInnerWindow()) {
|
||||
JSObject *realObj;
|
||||
|
@ -1409,6 +1409,7 @@ JS_IdToValue(JSContext *cx, jsid id, jsval *vp);
|
||||
#define JSRESOLVE_DETECTING 0x04 /* 'if (o.p)...' or '(o.p) ?...:...' */
|
||||
#define JSRESOLVE_DECLARING 0x08 /* var, const, or function prolog op */
|
||||
#define JSRESOLVE_CLASSNAME 0x10 /* class name used when constructing */
|
||||
#define JSRESOLVE_WITH 0x20 /* resolve inside a with statement */
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_PropertyStub(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
|
||||
|
191
js/src/jsobj.cpp
191
js/src/jsobj.cpp
@ -1892,6 +1892,104 @@ js_Object(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given pc pointing after a property accessing bytecode, return true if the
|
||||
* access is "object-detecting" in the sense used by web scripts, e.g., when
|
||||
* checking whether document.all is defined.
|
||||
*/
|
||||
static JS_REQUIRES_STACK JSBool
|
||||
Detecting(JSContext *cx, jsbytecode *pc)
|
||||
{
|
||||
JSScript *script;
|
||||
jsbytecode *endpc;
|
||||
JSOp op;
|
||||
JSAtom *atom;
|
||||
|
||||
if (!cx->fp)
|
||||
return JS_FALSE;
|
||||
script = cx->fp->script;
|
||||
for (endpc = script->code + script->length;
|
||||
pc < endpc;
|
||||
pc += js_CodeSpec[op].length) {
|
||||
/* General case: a branch or equality op follows the access. */
|
||||
op = (JSOp) *pc;
|
||||
if (js_CodeSpec[op].format & JOF_DETECTING)
|
||||
return JS_TRUE;
|
||||
|
||||
switch (op) {
|
||||
case JSOP_NULL:
|
||||
/*
|
||||
* Special case #1: handle (document.all == null). Don't sweat
|
||||
* about JS1.2's revision of the equality operators here.
|
||||
*/
|
||||
if (++pc < endpc)
|
||||
return *pc == JSOP_EQ || *pc == JSOP_NE;
|
||||
return JS_FALSE;
|
||||
|
||||
case JSOP_NAME:
|
||||
/*
|
||||
* Special case #2: handle (document.all == undefined). Don't
|
||||
* worry about someone redefining undefined, which was added by
|
||||
* Edition 3, so is read/write for backward compatibility.
|
||||
*/
|
||||
GET_ATOM_FROM_BYTECODE(script, pc, 0, atom);
|
||||
if (atom == cx->runtime->atomState.typeAtoms[JSTYPE_VOID] &&
|
||||
(pc += js_CodeSpec[op].length) < endpc) {
|
||||
op = (JSOp) *pc;
|
||||
return op == JSOP_EQ || op == JSOP_NE ||
|
||||
op == JSOP_STRICTEQ || op == JSOP_STRICTNE;
|
||||
}
|
||||
return JS_FALSE;
|
||||
|
||||
default:
|
||||
/*
|
||||
* At this point, anything but an extended atom index prefix means
|
||||
* we're not detecting.
|
||||
*/
|
||||
if (!(js_CodeSpec[op].format & JOF_INDEXBASE))
|
||||
return JS_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Infer lookup flags from the currently executing bytecode. This does
|
||||
* not attempt to infer JSRESOLVE_WITH, because the current bytecode
|
||||
* does not indicate whether we are in a with statement. Return defaultFlags
|
||||
* if a currently executing bytecode cannot be determined.
|
||||
*/
|
||||
static uintN
|
||||
InferFlags(JSContext *cx, uintN defaultFlags)
|
||||
{
|
||||
JSStackFrame *fp;
|
||||
jsbytecode *pc;
|
||||
const JSCodeSpec *cs;
|
||||
uint32 format;
|
||||
uintN flags = 0;
|
||||
|
||||
fp = js_GetTopStackFrame(cx);
|
||||
if (!fp || !fp->regs)
|
||||
return defaultFlags;
|
||||
pc = fp->regs->pc;
|
||||
cs = &js_CodeSpec[*pc];
|
||||
format = cs->format;
|
||||
if (JOF_MODE(format) != JOF_NAME)
|
||||
flags |= JSRESOLVE_QUALIFIED;
|
||||
if ((format & (JOF_SET | JOF_FOR)) ||
|
||||
(fp->flags & JSFRAME_ASSIGNING)) {
|
||||
flags |= JSRESOLVE_ASSIGNING;
|
||||
} else {
|
||||
pc += cs->length;
|
||||
if (Detecting(cx, pc))
|
||||
flags |= JSRESOLVE_DETECTING;
|
||||
}
|
||||
if (format & JOF_DECLARING)
|
||||
flags |= JSRESOLVE_DECLARING;
|
||||
return flags;
|
||||
}
|
||||
|
||||
/*
|
||||
* ObjectOps and Class for with-statement stack objects.
|
||||
*/
|
||||
@ -1899,6 +1997,12 @@ static JSBool
|
||||
with_LookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
|
||||
JSProperty **propp)
|
||||
{
|
||||
/* Fixes bug 463997 */
|
||||
uintN flags = cx->resolveFlags;
|
||||
if (flags == JSRESOLVE_INFER)
|
||||
flags = InferFlags(cx, flags);
|
||||
flags |= JSRESOLVE_WITH;
|
||||
JSAutoResolveFlags rf(cx, flags);
|
||||
JSObject *proto = OBJ_GET_PROTO(cx, obj);
|
||||
if (!proto)
|
||||
return js_LookupProperty(cx, obj, id, objp, propp);
|
||||
@ -3310,68 +3414,6 @@ bad:
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given pc pointing after a property accessing bytecode, return true if the
|
||||
* access is "object-detecting" in the sense used by web scripts, e.g., when
|
||||
* checking whether document.all is defined.
|
||||
*/
|
||||
static JS_REQUIRES_STACK JSBool
|
||||
Detecting(JSContext *cx, jsbytecode *pc)
|
||||
{
|
||||
JSScript *script;
|
||||
jsbytecode *endpc;
|
||||
JSOp op;
|
||||
JSAtom *atom;
|
||||
|
||||
if (!cx->fp)
|
||||
return JS_FALSE;
|
||||
script = cx->fp->script;
|
||||
for (endpc = script->code + script->length;
|
||||
pc < endpc;
|
||||
pc += js_CodeSpec[op].length) {
|
||||
/* General case: a branch or equality op follows the access. */
|
||||
op = (JSOp) *pc;
|
||||
if (js_CodeSpec[op].format & JOF_DETECTING)
|
||||
return JS_TRUE;
|
||||
|
||||
switch (op) {
|
||||
case JSOP_NULL:
|
||||
/*
|
||||
* Special case #1: handle (document.all == null). Don't sweat
|
||||
* about JS1.2's revision of the equality operators here.
|
||||
*/
|
||||
if (++pc < endpc)
|
||||
return *pc == JSOP_EQ || *pc == JSOP_NE;
|
||||
return JS_FALSE;
|
||||
|
||||
case JSOP_NAME:
|
||||
/*
|
||||
* Special case #2: handle (document.all == undefined). Don't
|
||||
* worry about someone redefining undefined, which was added by
|
||||
* Edition 3, so is read/write for backward compatibility.
|
||||
*/
|
||||
GET_ATOM_FROM_BYTECODE(script, pc, 0, atom);
|
||||
if (atom == cx->runtime->atomState.typeAtoms[JSTYPE_VOID] &&
|
||||
(pc += js_CodeSpec[op].length) < endpc) {
|
||||
op = (JSOp) *pc;
|
||||
return op == JSOP_EQ || op == JSOP_NE ||
|
||||
op == JSOP_STRICTEQ || op == JSOP_STRICTNE;
|
||||
}
|
||||
return JS_FALSE;
|
||||
|
||||
default:
|
||||
/*
|
||||
* At this point, anything but an extended atom index prefix means
|
||||
* we're not detecting.
|
||||
*/
|
||||
if (!(js_CodeSpec[op].format & JOF_INDEXBASE))
|
||||
return JS_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSBool)
|
||||
js_LookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
|
||||
JSProperty **propp)
|
||||
@ -3397,9 +3439,6 @@ js_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, jsid id, uintN flags,
|
||||
JSResolvingEntry *entry;
|
||||
uint32 generation;
|
||||
JSNewResolveOp newresolve;
|
||||
jsbytecode *pc;
|
||||
const JSCodeSpec *cs;
|
||||
uint32 format;
|
||||
JSBool ok;
|
||||
|
||||
/* Convert string indices to integers if appropriate. */
|
||||
@ -3448,27 +3487,9 @@ js_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, jsid id, uintN flags,
|
||||
*propp = NULL;
|
||||
|
||||
if (clasp->flags & JSCLASS_NEW_RESOLVE) {
|
||||
JSStackFrame *fp = js_GetTopStackFrame(cx);
|
||||
|
||||
newresolve = (JSNewResolveOp)resolve;
|
||||
if (flags == JSRESOLVE_INFER && fp && fp->regs) {
|
||||
flags = 0;
|
||||
pc = fp->regs->pc;
|
||||
cs = &js_CodeSpec[*pc];
|
||||
format = cs->format;
|
||||
if (JOF_MODE(format) != JOF_NAME)
|
||||
flags |= JSRESOLVE_QUALIFIED;
|
||||
if ((format & (JOF_SET | JOF_FOR)) ||
|
||||
(fp->flags & JSFRAME_ASSIGNING)) {
|
||||
flags |= JSRESOLVE_ASSIGNING;
|
||||
} else {
|
||||
pc += cs->length;
|
||||
if (Detecting(cx, pc))
|
||||
flags |= JSRESOLVE_DETECTING;
|
||||
}
|
||||
if (format & JOF_DECLARING)
|
||||
flags |= JSRESOLVE_DECLARING;
|
||||
}
|
||||
if (flags == JSRESOLVE_INFER)
|
||||
flags = InferFlags(cx, flags);
|
||||
obj2 = (clasp->flags & JSCLASS_NEW_RESOLVE_GETS_START)
|
||||
? start
|
||||
: NULL;
|
||||
|
Loading…
x
Reference in New Issue
Block a user