if (!js_MatchToken(cx, ts, TOK_RP)) { do { MUST_MATCH_TOKEN(TOK_NAME, JSMSG_MISSING_FORMAL); argAtom = CURRENT_TOKEN(ts).t_atom; pobj = NULL; if (!js_LookupProperty(cx, fun->object, (jsid)argAtom, &pobj, (JSProperty **)&sprop)) { return NULL; } dupflag = 0; if (sprop) { ok = JS_TRUE; if (pobj == fun->object && sprop->getter == js_GetArgument) {  ok = js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_WARNING | JSREPORT_STRICT, JSMSG_DUPLICATE_FORMAL, ATOM_BYTES(argAtom));  dupflag = SPROP_IS_DUPLICATE; } OBJ_DROP_PROPERTY(cx, pobj, (JSProperty *)sprop); if (!ok) return NULL; sprop = NULL; } if (!js_AddNativeProperty(cx, fun->object, (jsid)argAtom, js_GetArgument, js_SetArgument, SPROP_INVALID_SLOT, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, SPROP_HAS_SHORTID | dupflag, fun->nargs)) { return NULL; } fun->nargs++; } while (js_MatchToken(cx, ts, TOK_COMMA));  MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_FORMAL); }  MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_BODY); pn->pn_pos.begin = CURRENT_TOKEN(ts).pos.begin;  TREE_CONTEXT_INIT(&funtc); body = FunctionBody(cx, ts, fun, &funtc); if (!body) return NULL;  MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_BODY); pn->pn_pos.end = CURRENT_TOKEN(ts).pos.end;  #if JS_HAS_LEXICAL_CLOSURE  if (funtc.flags & TCF_FUN_HEAVYWEIGHT) { fun->flags |= JSFUN_HEAVYWEIGHT; tc->flags |= TCF_FUN_HEAVYWEIGHT; } else {  if ((!lambda && funAtom && tc->topStmt) || (funtc.flags & TCF_FUN_USES_NONLOCALS)) { tc->flags |= TCF_FUN_HEAVYWEIGHT; } } #endif   if (!lambda && funAtom) { ATOM_LIST_SEARCH(ale, &tc->decls, funAtom); if (ale) { prevop = ALE_JSOP(ale); if ((JS_HAS_STRICT_OPTION(cx) || prevop == JSOP_DEFCONST) && !js_ReportCompileErrorNumber(cx, ts, NULL, (prevop != JSOP_DEFCONST) ? JSREPORT_WARNING|JSREPORT_STRICT : JSREPORT_ERROR, JSMSG_REDECLARED_VAR, (prevop == JSOP_DEFFUN || prevop == JSOP_CLOSURE) ? js_function_str : (prevop == JSOP_DEFCONST) ? js_const_str : js_var_str, ATOM_BYTES(funAtom))) { return NULL; } if (tc->topStmt && prevop == JSOP_DEFVAR) tc->flags |= TCF_FUN_CLOSURE_VS_VAR; } else { ale = js_IndexAtom(cx, funAtom, &tc->decls); if (!ale) return NULL; } ALE_SET_JSOP(ale, tc->topStmt ? JSOP_CLOSURE : JSOP_DEFFUN);  #if JS_HAS_LEXICAL_CLOSURE  if (!tc->topStmt && (tc->flags & TCF_IN_FUNCTION)) { JSStackFrame *fp; JSObject *varobj;   fp = cx->fp; varobj = fp->varobj; JS_ASSERT(OBJ_GET_CLASS(cx, varobj) == &js_FunctionClass); JS_ASSERT(fp->fun == (JSFunction *) JS_GetPrivate(cx, varobj)); if (!js_DefineNativeProperty(cx, varobj, (jsid)funAtom, OBJECT_TO_JSVAL(fun->object), js_GetLocalVariable, js_SetLocalVariable, JSPROP_ENUMERATE, SPROP_HAS_SHORTID, fp->fun->nvars, NULL)) { return NULL; } fp->fun->nvars++; } #endif }
FunctionDef(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,            JSBool lambda){    JSParseNode *pn, *body;    JSOp op, prevop;    JSAtom *funAtom, *argAtom;    JSFunction *fun;    JSObject *parent;    JSObject *pobj;    JSScopeProperty *sprop;    uintN dupflag;    JSBool ok;    JSTreeContext funtc;    JSAtomListElement *ale;    /* Make a TOK_FUNCTION node. */    pn = NewParseNode(cx, &CURRENT_TOKEN(ts), PN_FUNC, tc);    if (!pn)        return NULL;    op = CURRENT_TOKEN(ts).t_op;    /* Scan the optional function name into funAtom. */    if (js_MatchToken(cx, ts, TOK_NAME))        funAtom = CURRENT_TOKEN(ts).t_atom;    else        funAtom = NULL;    /* Find the nearest variable-declaring scope and use it as our parent. */    parent = cx->fp->varobj;    fun = js_NewFunction(cx, NULL, NULL, 0, lambda ? JSFUN_LAMBDA : 0, parent,                         funAtom);    if (!fun)        return NULL;#if JS_HAS_GETTER_SETTER    if (op != JSOP_NOP)        fun->flags |= (op == JSOP_GETTER) ? JSPROP_GETTER : JSPROP_SETTER;#endif    /* Now parse formal argument list and compute fun->nargs. */    MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_FORMAL);    if (!js_MatchToken(cx, ts, TOK_RP)) {        do {            MUST_MATCH_TOKEN(TOK_NAME, JSMSG_MISSING_FORMAL);            argAtom = CURRENT_TOKEN(ts).t_atom;            pobj = NULL;            if (!js_LookupProperty(cx, fun->object, (jsid)argAtom, &pobj,                                   (JSProperty **)&sprop)) {                return NULL;            }            dupflag = 0;            if (sprop) {                ok = JS_TRUE;                if (pobj == fun->object &&                    sprop->getter == js_GetArgument) {                    /*                     * A duplicate parameter name. We force a duplicate node                     * on the SCOPE_LAST_PROP(scope) list with the same id,                     * distinguished by the SPROP_IS_DUPLICATE flag, and not                     * mapped by an entry in scope.                     */                    ok = js_ReportCompileErrorNumber(cx, ts, NULL,                                                     JSREPORT_WARNING |                                                     JSREPORT_STRICT,                                                     JSMSG_DUPLICATE_FORMAL,                                                     ATOM_BYTES(argAtom));                    dupflag = SPROP_IS_DUPLICATE;                }                OBJ_DROP_PROPERTY(cx, pobj, (JSProperty *)sprop);                if (!ok)                    return NULL;                sprop = NULL;            }            if (!js_AddNativeProperty(cx, fun->object, (jsid)argAtom,                                      js_GetArgument, js_SetArgument,                                      SPROP_INVALID_SLOT,                                      JSPROP_ENUMERATE | JSPROP_PERMANENT |                                      JSPROP_SHARED,                                      SPROP_HAS_SHORTID | dupflag,                                      fun->nargs)) {                return NULL;            }            fun->nargs++;        } while (js_MatchToken(cx, ts, TOK_COMMA));        MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_FORMAL);    }    MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_BODY);    pn->pn_pos.begin = CURRENT_TOKEN(ts).pos.begin;    TREE_CONTEXT_INIT(&funtc);    body = FunctionBody(cx, ts, fun, &funtc);    if (!body)        return NULL;    MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_BODY);    pn->pn_pos.end = CURRENT_TOKEN(ts).pos.end;#if JS_HAS_LEXICAL_CLOSURE    /*     * If we collected flags that indicate nested heavyweight functions, or     * this function contains heavyweight-making statements (references to     * __parent__ or __proto__; use of with, eval, import, or export; and     * assignment to arguments), flag the function as heavyweight (requiring     * a call object per invocation).     */    if (funtc.flags & TCF_FUN_HEAVYWEIGHT) {        fun->flags |= JSFUN_HEAVYWEIGHT;        tc->flags |= TCF_FUN_HEAVYWEIGHT;    } else {        /*         * If this function is a named statement function not at top-level         * (i.e. a JSOP_CLOSURE), or if it refers to unqualified names that         * are not local args or vars (TCF_FUN_USES_NONLOCALS), then our         * enclosing function, if any, must be heavyweight.         */        if ((!lambda && funAtom && tc->topStmt) ||            (funtc.flags & TCF_FUN_USES_NONLOCALS)) {            tc->flags |= TCF_FUN_HEAVYWEIGHT;        }    }#endif    /*     * Record names for function statements in tc->decls so we know when to     * avoid optimizing variable references that might name a function.     */    if (!lambda && funAtom) {        ATOM_LIST_SEARCH(ale, &tc->decls, funAtom);        if (ale) {            prevop = ALE_JSOP(ale);            if ((JS_HAS_STRICT_OPTION(cx) || prevop == JSOP_DEFCONST) &&                !js_ReportCompileErrorNumber(cx, ts, NULL,                                             (prevop != JSOP_DEFCONST)                                             ? JSREPORT_WARNING|JSREPORT_STRICT                                             : JSREPORT_ERROR,                                             JSMSG_REDECLARED_VAR,                                             (prevop == JSOP_DEFFUN ||                                              prevop == JSOP_CLOSURE)                                             ? js_function_str                                             : (prevop == JSOP_DEFCONST)                                             ? js_const_str                                             : js_var_str,                                             ATOM_BYTES(funAtom))) {                return NULL;            }            if (tc->topStmt && prevop == JSOP_DEFVAR)                tc->flags |= TCF_FUN_CLOSURE_VS_VAR;        } else {            ale = js_IndexAtom(cx, funAtom, &tc->decls);            if (!ale)                return NULL;        }        ALE_SET_JSOP(ale, tc->topStmt ? JSOP_CLOSURE : JSOP_DEFFUN);#if JS_HAS_LEXICAL_CLOSURE        /*         * A function nested at top level inside another's body needs only a         * local variable to bind its name to its value, and not an activation         * object property (it might also need the activation property, if the         * outer function contains with statements, e.g., but the stack slot         * wins when jsemit.c's LookupArgOrVar can optimize a JSOP_NAME into a         * JSOP_GETVAR bytecode).         */        if (!tc->topStmt && (tc->flags & TCF_IN_FUNCTION)) {            JSStackFrame *fp;            JSObject *varobj;            /*             * Define a property on the outer function so that LookupArgOrVar             * can properly optimize accesses.             *             * XXX Here and in Variables, we use the function object's scope,             * XXX arguably polluting it, when we could use a compiler-private             * XXX scope structure.  Tradition!             */            fp = cx->fp;            varobj = fp->varobj;            JS_ASSERT(OBJ_GET_CLASS(cx, varobj) == &js_FunctionClass);            JS_ASSERT(fp->fun == (JSFunction *) JS_GetPrivate(cx, varobj));            if (!js_DefineNativeProperty(cx, varobj, (jsid)funAtom,                                         OBJECT_TO_JSVAL(fun->object),                                         js_GetLocalVariable,                                         js_SetLocalVariable,                                         JSPROP_ENUMERATE,                                         SPROP_HAS_SHORTID, fp->fun->nvars,                                         NULL)) {                return NULL;            }            fp->fun->nvars++;        }#endif    }