Comply with weird ECMA nit: call (o.f)() (note parens around the function expression) must bind 'this' to the global object, not to o\! (41864, r=shaver).

This commit is contained in:
brendan%mozilla.org 2000-06-08 06:46:18 +00:00
parent 88a5018252
commit d8f3cd1921
5 changed files with 29 additions and 34 deletions

View File

@ -2392,20 +2392,11 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
* The node for (e) has e as its kid, enabling users who want to nest
* assignment expressions in conditions to avoid the error correction
* done by Condition (from x = y to x == y) by double-parenthesizing.
*
* We also emit an annotated NOP so we can decompile user parentheses,
* but that's just a nicety (the decompiler does not preserve comments
* or white space, and it parenthesizes for correct precedence anyway,
* so this nop nicety should be considered with a cold eye, especially
* if another srcnote type is needed).
*/
if (!js_EmitTree(cx, cg, pn->pn_kid))
return JS_FALSE;
if (js_NewSrcNote(cx, cg, SRC_PAREN) < 0 ||
js_Emit1(cx, cg, JSOP_NOP) < 0) {
if (js_Emit1(cx, cg, JSOP_GROUP) < 0)
return JS_FALSE;
}
break;
case TOK_NAME:
@ -2467,7 +2458,7 @@ JS_FRIEND_DATA(const char *) js_SrcNoteName[] = {
"pcdelta",
"assignop",
"cond",
"paren",
"reserved0",
"hidden",
"pcbase",
"label",
@ -2499,7 +2490,7 @@ uint8 js_SrcNoteArity[] = {
1, /* SRC_PCDELTA */
0, /* SRC_ASSIGNOP */
0, /* SRC_COND */
0, /* SRC_PAREN */
0, /* SRC_RESERVED0 */
0, /* SRC_HIDDEN */
1, /* SRC_PCBASE */
1, /* SRC_LABEL */

View File

@ -300,7 +300,7 @@ typedef enum JSSrcNoteType {
or from CONDSWITCH to first CASE opcode */
SRC_ASSIGNOP = 8, /* += or another assign-op follows */
SRC_COND = 9, /* JSOP_IFEQ is from conditional ?: operator */
SRC_PAREN = 10, /* JSOP_NOP generated to mark user parens */
SRC_RESERVED0 = 10, /* reserved for future use */
SRC_HIDDEN = 11, /* opcode shouldn't be decompiled */
SRC_PCBASE = 12, /* offset of first obj.prop.subprop bytecode */
SRC_LABEL = 13, /* JSOP_NOP for label: with atomid immediate */

View File

@ -1207,6 +1207,10 @@ js_Interpret(JSContext *cx, jsval *result)
case JSOP_NOP:
break;
case JSOP_GROUP:
obj = NULL;
break;
case JSOP_PUSH:
PUSH_OPND(JSVAL_VOID);
break;
@ -1347,12 +1351,11 @@ js_Interpret(JSContext *cx, jsval *result)
#endif
case JSOP_TOOBJECT:
rval = POP();
SAVE_SP(fp);
ok = js_ValueToObject(cx, rval, &obj);
ok = js_ValueToObject(cx, sp[-1], &obj);
if (!ok)
goto out;
PUSH(OBJECT_TO_JSVAL(obj));
sp[-1] = OBJECT_TO_JSVAL(obj);
break;
#define POP_ELEMENT_ID(id) { \
@ -1373,7 +1376,7 @@ js_Interpret(JSContext *cx, jsval *result)
#if JS_HAS_IN_OPERATOR
case JSOP_IN:
rval = POP();
if (!JSVAL_IS_OBJECT(rval) || rval == JSVAL_NULL) {
if (JSVAL_IS_PRIMITIVE(rval)) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_IN_NOT_OBJECT);
ok = JS_FALSE;
@ -2507,7 +2510,7 @@ js_Interpret(JSContext *cx, jsval *result)
PUSH_OPND(JSVAL_VOID);
goto advance_pc;
}
if (op2 != JSOP_NOP)
if (op2 != JSOP_GROUP)
break;
}
js_ReportIsNotDefined(cx, ATOM_BYTES(atom));

View File

@ -888,26 +888,13 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
switch (op) {
case JSOP_NOP:
/*
* Check for extra user parenthesization, a do-while loop,
* a for-loop with an empty initializer part, a labeled
* statement, a function definition, or try/finally.
* Check for a do-while loop, a for-loop with an empty
* initializer part, a labeled statement, a function
* definition, or try/finally.
*/
sn = js_GetSrcNote(jp->script, pc);
todo = -2;
switch (sn ? SN_TYPE(sn) : SRC_NULL) {
case SRC_PAREN:
/* Use last real op so PopOff adds parens if needed. */
todo = PopOff(ss, lastop);
/* Now add user-supplied parens only if PopOff did not. */
cs = &js_CodeSpec[lastop];
topcs = &js_CodeSpec[ss->opcodes[ss->top]];
if (topcs->prec >= cs->prec) {
todo = Sprint(&ss->sprinter, "(%s)",
OFF2STR(&ss->sprinter, todo));
}
break;
#if JS_HAS_DO_WHILE_LOOP
case SRC_WHILE:
js_printf(jp, "\tdo {\n"); /* balance} */
@ -1033,6 +1020,19 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
}
break;
case JSOP_GROUP:
/* Use last real op so PopOff adds parens if needed. */
todo = PopOff(ss, lastop);
/* Now add user-supplied parens only if PopOff did not. */
cs = &js_CodeSpec[lastop];
topcs = &js_CodeSpec[ss->opcodes[ss->top]];
if (topcs->prec >= cs->prec) {
todo = Sprint(&ss->sprinter, "(%s)",
OFF2STR(&ss->sprinter, todo));
}
break;
case JSOP_PUSH:
case JSOP_PUSHOBJ:
case JSOP_BINDNAME:

View File

@ -268,3 +268,4 @@ OPDEF(JSOP_NAMEDFUNOBJ, 129, "namedfunobj", NULL, 3, 0, 1, 12, JOF_CONST)
/* Like JSOP_INITPROP, but specialized to make a DontDelete property for ECMA ed. 3 catch variables. */
OPDEF(JSOP_INITCATCHVAR,130, "initcatchvar",NULL, 3, 1, 0, 0, JOF_CONST|JOF_PROP)
OPDEF(JSOP_GROUP, 131, "group", NULL, 1, 0, 0, 0, JOF_BYTE)