Reland a37db4d95026
authorBrian Hackett <bhackett1024@gmail.com>
Fri, 08 Jul 2011 18:35:07 -0700
changeset 75194 7abfbaac06931b3c242934eafb0742646216382a
parent 75193 fd60ba97753ba9904c0f9344a8e212cf2384ab89
child 75195 90824c8852e69713dbbe1a409d4b4d9852cc86f7
child 76032 1d31362c86ce19d0f7c76a1b890b7b3a9601263b
child 76037 60b1a6a58531e9ce6c10445804b9a7f8fb4b4290
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
milestone8.0a1
Reland a37db4d95026
js/src/frontend/ParseMaps-inl.h
js/src/jsparse.cpp
--- a/js/src/frontend/ParseMaps-inl.h
+++ b/js/src/frontend/ParseMaps-inl.h
@@ -100,18 +100,17 @@ AtomDecls::lookupMulti(JSAtom *atom)
     JS_ASSERT(map);
     AtomDOHPtr p = map->lookup(atom);
     if (!p)
         return MultiDeclRange((JSDefinition *) NULL);
 
     DefnOrHeader &doh = p.value();
     if (doh.isHeader())
         return MultiDeclRange(doh.header());
-    else
-        return MultiDeclRange(doh.defn());
+    return MultiDeclRange(doh.defn());
 }
 
 inline bool
 AtomDecls::addUnique(JSAtom *atom, JSDefinition *defn)
 {
     JS_ASSERT(map);
     AtomDOHAddPtr p = map->lookupForAdd(atom);
     if (p) {
--- a/js/src/jsparse.cpp
+++ b/js/src/jsparse.cpp
@@ -1887,33 +1887,30 @@ struct BindData {
         struct {
             uintN   overflow;
         } let;
     };
     bool fresh;
 };
 
 static bool
-BindLocalVariable(JSContext *cx, JSTreeContext *tc, JSAtom *atom, BindingKind kind, bool isArg)
+BindLocalVariable(JSContext *cx, JSTreeContext *tc, JSParseNode *pn, BindingKind kind)
 {
     JS_ASSERT(kind == VARIABLE || kind == CONSTANT);
 
-    /*
-     * Don't bind a variable with the hidden name 'arguments', per ECMA-262.
-     * Instead 'var arguments' always restates the predefined property of the
-     * activation objects whose name is 'arguments'. Assignment to such a
-     * variable must be handled specially.
-     *
-     * Special case: an argument named 'arguments' *does* shadow the predefined
-     * arguments property.
-     */
-    if (atom == cx->runtime->atomState.argumentsAtom && !isArg)
-        return true;
-
-    return tc->bindings.add(cx, atom, kind);
+    /* 'arguments' can be bound as a local only via a destructuring formal parameter. */
+    JS_ASSERT_IF(pn->pn_atom == cx->runtime->atomState.argumentsAtom, kind == VARIABLE);
+
+    uintN index = tc->bindings.countVars();
+    if (!tc->bindings.add(cx, pn->pn_atom, kind))
+        return false;
+
+    pn->pn_cookie.set(tc->staticLevel, index);
+    pn->pn_dflags |= PND_BOUND;
+    return true;
 }
 
 #if JS_HAS_DESTRUCTURING
 static JSBool
 BindDestructuringArg(JSContext *cx, BindData *data, JSAtom *atom, JSTreeContext *tc)
 {
     /* Flag tc so we don't have to lookup arguments on every use. */
     if (atom == tc->parser->context->runtime->atomState.argumentsAtom)
@@ -3174,20 +3171,18 @@ Parser::functionDef(JSAtom *funAtom, Fun
     if (prelude) {
         AtomDeclsIter iter(&funtc.decls);
 
         while (JSDefinition *apn = iter()) {
             /* Filter based on pn_op -- see BindDestructuringArg, above. */
             if (apn->pn_op != JSOP_SETLOCAL)
                 continue;
 
-            uint16 index = funtc.bindings.countVars();
-            if (!BindLocalVariable(context, &funtc, apn->pn_atom, VARIABLE, true))
+            if (!BindLocalVariable(context, &funtc, apn, VARIABLE))
                 return NULL;
-            apn->pn_cookie.set(funtc.staticLevel, index);
         }
     }
 #endif
 
     if (type == Getter && fun->nargs > 0) {
         reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_ACCESSOR_WRONG_ARGS,
                           "getter", "no", "s");
         return NULL;
@@ -3763,17 +3758,17 @@ DefineGlobal(JSParseNode *pn, JSCodeGene
     }
 
     pn->pn_dflags |= PND_GVAR;
 
     return true;
 }
 
 static bool
-BindTopLevelVar(JSContext *cx, BindData *data, JSParseNode *pn, JSAtom *varname, JSTreeContext *tc)
+BindTopLevelVar(JSContext *cx, BindData *data, JSParseNode *pn, JSTreeContext *tc)
 {
     JS_ASSERT(pn->pn_op == JSOP_NAME);
     JS_ASSERT(!tc->inFunction());
 
     /* There's no need to optimize bindings if we're not compiling code. */
     if (!tc->compiling())
         return true;
 
@@ -3816,21 +3811,29 @@ BindTopLevelVar(JSContext *cx, BindData 
      * If this is a global variable, we're compile-and-go, and a global object
      * is present, try to bake in either an already available slot or a
      * predicted slot that will be defined after compiling is completed.
      */
     return DefineGlobal(pn, tc->asCodeGenerator(), pn->pn_atom);
 }
 
 static bool
-BindFunctionLocal(JSContext *cx, BindData *data, MultiDeclRange &mdl, JSParseNode *pn,
-                  JSAtom *name, JSTreeContext *tc)
+BindFunctionLocal(JSContext *cx, BindData *data, MultiDeclRange &mdl, JSTreeContext *tc)
 {
     JS_ASSERT(tc->inFunction());
 
+    JSParseNode *pn = data->pn;
+    JSAtom *name = pn->pn_atom;
+
+    /*
+     * Don't create a local variable with the name 'arguments', per ECMA-262.
+     * Instead, 'var arguments' always restates that predefined binding of the
+     * lexical environment for function activations. Assignments to arguments
+     * must be handled specially -- see NoteLValue.
+     */
     if (name == cx->runtime->atomState.argumentsAtom) {
         pn->pn_op = JSOP_ARGUMENTS;
         pn->pn_dflags |= PND_BOUND;
         return true;
     }
 
     BindingKind kind = tc->bindings.lookup(cx, name, NULL);
     if (kind == NONE) {
@@ -3838,22 +3841,19 @@ BindFunctionLocal(JSContext *cx, BindDat
          * Property not found in current variable scope: we have not seen this
          * variable before, so bind a new local variable for it. Any locals
          * declared in a with statement body are handled at runtime, by script
          * prolog JSOP_DEFVAR opcodes generated for global and heavyweight-
          * function-local vars.
          */
         kind = (data->op == JSOP_DEFCONST) ? CONSTANT : VARIABLE;
 
-        uintN index = tc->bindings.countVars();
-        if (!BindLocalVariable(cx, tc, name, kind, false))
+        if (!BindLocalVariable(cx, tc, pn, kind))
             return false;
         pn->pn_op = JSOP_GETLOCAL;
-        pn->pn_cookie.set(tc->staticLevel, index);
-        pn->pn_dflags |= PND_BOUND;
         return true;
     }
 
     if (kind == ARGUMENT) {
         JS_ASSERT(tc->inFunction());
         JS_ASSERT(!mdl.empty() && mdl.front()->kind() == JSDefinition::ARG);
     } else {
         JS_ASSERT(kind == VARIABLE || kind == CONSTANT);
@@ -4002,19 +4002,19 @@ BindVarOrConst(JSContext *cx, BindData *
         pn->pn_defn = true;
         pn->pn_dflags &= ~PND_PLACEHOLDER;
     }
 
     if (data->op == JSOP_DEFCONST)
         pn->pn_dflags |= PND_CONST;
 
     if (tc->inFunction())
-        return BindFunctionLocal(cx, data, mdl, pn, atom, tc);
-
-    return BindTopLevelVar(cx, data, pn, atom, tc);
+        return BindFunctionLocal(cx, data, mdl, tc);
+
+    return BindTopLevelVar(cx, data, pn, tc);
 }
 
 static bool
 MakeSetCall(JSContext *cx, JSParseNode *pn, JSTreeContext *tc, uintN msg)
 {
     JS_ASSERT(pn->pn_arity == PN_LIST);
     JS_ASSERT(pn->pn_op == JSOP_CALL || pn->pn_op == JSOP_EVAL ||
               pn->pn_op == JSOP_FUNCALL || pn->pn_op == JSOP_FUNAPPLY);
@@ -7092,18 +7092,19 @@ Parser::comprehensionTail(JSParseNode *k
             return NULL;
         MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_FOR_CTRL);
 
         guard.endBody();
 
         if (isGenexp) {
             if (!guard.checkValidBody(pn2))
                 return NULL;
-        } else if (!guard.maybeNoteGenerator()) {
-            return NULL;
+        } else {
+            if (!guard.maybeNoteGenerator())
+                return NULL;
         }
 
         switch (tt) {
 #if JS_HAS_DESTRUCTURING
           case TOK_LB:
           case TOK_LC:
             if (!CheckDestructuring(context, &data, pn3, tc))
                 return NULL;