Improve JSRESOLVE_DETECTING to handle typeof, ==, !=, etc.; don't give undefined property strict warning for detecting cases (253150, r=shaver).

This commit is contained in:
brendan%mozilla.org 2004-07-29 20:44:20 +00:00
Родитель d585c6199a
Коммит 652a45f1d5
2 изменённых файлов: 62 добавлений и 17 удалений

Просмотреть файл

@ -2380,6 +2380,59 @@ bad:
return JS_FALSE;
}
/*
* Given pc pointing after a property accessing bytecode, return true if the
* access is a "object-detecting" in the sense used by web pages, e.g., when
* checking whether document.all is defined.
*/
static JSBool
Detecting(JSContext *cx, jsbytecode *pc)
{
JSScript *script;
jsbytecode *endpc;
JSOp op;
JSAtom *atom;
script = cx->fp->script;
for (endpc = script->code + script->length; pc < endpc; pc++) {
/* General case: a branch or equality op follows the access. */
op = (JSOp) *pc;
if (js_CodeSpec[op].format & JOF_DETECTING)
return JS_TRUE;
/*
* Special case #1: handle (document.all == null). Don't sweat about
* JS1.2's revision of the equality operators here.
*/
if (op == JSOP_NULL) {
if (++pc < endpc)
return *pc == JSOP_EQ || *pc == JSOP_NE;
break;
}
/*
* Special case #2: handle (document.all == undefined). Don't worry
* about someone redefining undefined, which was added by Edition 3,
* so was read/write for backward compatibility.
*/
if (op == JSOP_NAME) {
atom = GET_ATOM(cx, script, pc);
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_NEW_EQ || op == JSOP_NEW_NE;
}
break;
}
/* At this point, anything but grouping means we're not detecting. */
if (op != JSOP_GROUP)
break;
}
return JS_FALSE;
}
#if defined JS_THREADSAFE && defined DEBUG
JS_FRIEND_API(JSBool)
_js_LookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
@ -2466,9 +2519,7 @@ js_LookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
flags |= JSRESOLVE_ASSIGNING;
} else {
pc += cs->length;
while (*pc == JSOP_GROUP)
pc++;
if (js_CodeSpec[*pc].format & JOF_DETECTING)
if (Detecting(cx, pc))
flags |= JSRESOLVE_DETECTING;
}
}
@ -2695,21 +2746,15 @@ js_GetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
cx->fp && cx->fp->pc &&
(*cx->fp->pc == JSOP_GETPROP || *cx->fp->pc == JSOP_GETELEM))
{
jsbytecode *pc, *endpc;
jsbytecode *pc;
JSString *str;
/* Kludge to allow (typeof foo == "undefined") tests. */
JS_ASSERT(cx->fp->script);
pc = cx->fp->pc;
pc += js_CodeSpec[*pc].length;
endpc = cx->fp->script->code + cx->fp->script->length;
while (pc < endpc) {
if (*pc == JSOP_TYPEOF)
return JS_TRUE;
if (*pc != JSOP_GROUP)
break;
pc++;
}
if (Detecting(cx, pc))
return JS_TRUE;
/* Ok, bad undefined property reference: whine about it. */
str = js_DecompileValueGenerator(cx, JSDVG_IGNORE_STACK,

Просмотреть файл

@ -93,8 +93,8 @@ OPDEF(JSOP_SETCONST, 14, "setconst", NULL, 3, 1, 1, 1, JOF_CONST|
OPDEF(JSOP_BITOR, 15, "bitor", "|", 1, 2, 1, 2, JOF_BYTE|JOF_LEFTASSOC)
OPDEF(JSOP_BITXOR, 16, "bitxor", "^", 1, 2, 1, 3, JOF_BYTE|JOF_LEFTASSOC)
OPDEF(JSOP_BITAND, 17, "bitand", "&", 1, 2, 1, 4, JOF_BYTE|JOF_LEFTASSOC)
OPDEF(JSOP_EQ, 18, "eq", "==", 1, 2, 1, 5, JOF_BYTE|JOF_LEFTASSOC)
OPDEF(JSOP_NE, 19, "ne", "!=", 1, 2, 1, 5, JOF_BYTE|JOF_LEFTASSOC)
OPDEF(JSOP_EQ, 18, "eq", "==", 1, 2, 1, 5, JOF_BYTE|JOF_LEFTASSOC|JOF_DETECTING)
OPDEF(JSOP_NE, 19, "ne", "!=", 1, 2, 1, 5, JOF_BYTE|JOF_LEFTASSOC|JOF_DETECTING)
OPDEF(JSOP_LT, 20, "lt", "<", 1, 2, 1, 6, JOF_BYTE|JOF_LEFTASSOC)
OPDEF(JSOP_LE, 21, "le", "<=", 1, 2, 1, 6, JOF_BYTE|JOF_LEFTASSOC)
OPDEF(JSOP_GT, 22, "gt", ">", 1, 2, 1, 6, JOF_BYTE|JOF_LEFTASSOC)
@ -114,7 +114,7 @@ OPDEF(JSOP_NEW, 35, js_new_str, NULL, 3, -1, 1, 10, JOF_UINT16
OPDEF(JSOP_DELNAME, 36, "delname", NULL, 3, 0, 1, 10, JOF_CONST|JOF_NAME|JOF_DEL)
OPDEF(JSOP_DELPROP, 37, "delprop", NULL, 3, 1, 1, 10, JOF_CONST|JOF_PROP|JOF_DEL)
OPDEF(JSOP_DELELEM, 38, "delelem", NULL, 1, 2, 1, 10, JOF_BYTE |JOF_ELEM|JOF_DEL)
OPDEF(JSOP_TYPEOF, 39, js_typeof_str,NULL, 1, 1, 1, 10, JOF_BYTE)
OPDEF(JSOP_TYPEOF, 39, js_typeof_str,NULL, 1, 1, 1, 10, JOF_BYTE|JOF_DETECTING)
OPDEF(JSOP_VOID, 40, js_void_str, NULL, 1, 1, 1, 10, JOF_BYTE)
OPDEF(JSOP_INCNAME, 41, "incname", NULL, 3, 0, 1, 10, JOF_CONST|JOF_NAME|JOF_INC)
OPDEF(JSOP_INCPROP, 42, "incprop", NULL, 3, 1, 1, 10, JOF_CONST|JOF_PROP|JOF_INC)
@ -151,8 +151,8 @@ OPDEF(JSOP_TABLESWITCH, 70, "tableswitch", NULL, -1, 1, 0, 0, JOF_TABLES
OPDEF(JSOP_LOOKUPSWITCH, 71, "lookupswitch", NULL, -1, 1, 0, 0, JOF_LOOKUPSWITCH)
/* New, infallible/transitive identity ops. */
OPDEF(JSOP_NEW_EQ, 72, "eq", NULL, 1, 2, 1, 5, JOF_BYTE)
OPDEF(JSOP_NEW_NE, 73, "ne", NULL, 1, 2, 1, 5, JOF_BYTE)
OPDEF(JSOP_NEW_EQ, 72, "eq", NULL, 1, 2, 1, 5, JOF_BYTE|JOF_DETECTING)
OPDEF(JSOP_NEW_NE, 73, "ne", NULL, 1, 2, 1, 5, JOF_BYTE|JOF_DETECTING)
/* Lexical closure constructor. */
OPDEF(JSOP_CLOSURE, 74, "closure", NULL, 3, 0, 0, 0, JOF_CONST)