if (!js_ReportCompileErrorNumber(cx, ts, NULL,
if (!js_ReportCompileErrorNumber(cx, ts,
FunctionDef(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,            JSBool lambda){    JSParseNode *pn, *pn2, *body;    JSOp op;    JSAtom *funAtom, *argAtom;    JSFunction *fun;    JSObject *parent;    JSObject *pobj;    JSScopeProperty *sprop;    JSTreeContext funtc;    jsid oldArgId;    JSAtomListElement *ale;    /* Make a TOK_FUNCTION node. */    pn = NewParseNode(cx, &CURRENT_TOKEN(ts), PN_FUNC);    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, 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;            }            if (sprop && pobj == fun->object) {                if (SPROP_GETTER(sprop, pobj) == js_GetArgument) {                    if (JS_HAS_STRICT_OPTION(cx)) {                        OBJ_DROP_PROPERTY(cx, pobj, (JSProperty *)sprop);                        if (!js_ReportCompileErrorNumber(cx, ts, NULL,                                                         JSREPORT_WARNING |                                                         JSREPORT_STRICT,                                                         JSMSG_DUPLICATE_FORMAL,                                                         ATOM_BYTES(argAtom))) {                            return NULL;                        }                    }                    /*                     * A duplicate parameter name. We create a dummy symbol                     * entry with property id of the parameter number and set                     * the id to the name of the parameter.                     * The decompiler will know to treat this case specially.                     */                    oldArgId = (jsid) sprop->id;                    OBJ_DROP_PROPERTY(cx, pobj, (JSProperty *)sprop);                    sprop = NULL;                    if (!js_DefineProperty(cx, fun->object,                                           oldArgId, JSVAL_VOID,                                           js_GetArgument, js_SetArgument,                                           JSPROP_ENUMERATE | JSPROP_PERMANENT,                                           (JSProperty **)&sprop)) {                        return NULL;                    }                    sprop->id = (jsid) argAtom;                }            }            if (sprop) {                OBJ_DROP_PROPERTY(cx, pobj, (JSProperty *)sprop);                sprop = NULL;            }            if (!js_DefineProperty(cx, fun->object,                                   (jsid)argAtom, JSVAL_VOID,                                   js_GetArgument, js_SetArgument,                                   JSPROP_ENUMERATE | JSPROP_PERMANENT,                                   (JSProperty **)&sprop)) {                return NULL;            }            JS_ASSERT(sprop);            sprop->id = INT_TO_JSVAL(fun->nargs++);            OBJ_DROP_PROPERTY(cx, fun->object, (JSProperty *)sprop);        } 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 we collected flags that include nested functions or with statements     * while compiling our body, flag the function as heavyweight (requiring     * a call object per invocation).  Therefore, update tc->flags to reflect     * the fact that the outer context contains this function, and may also be     * heavy if it is a function body.     */    if (funtc.flags & TCF_FUN_HEAVYWEIGHT)        fun->flags |= JSFUN_HEAVYWEIGHT;    tc->flags |= TCF_FUN_HEAVYWEIGHT;    /*     * 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) {            pn2 = ALE_NODE(ale);            op = pn2->pn_op;            if ((JS_HAS_STRICT_OPTION(cx) || op == JSOP_DEFCONST) &&                !js_ReportCompileErrorNumber(cx, ts, NULL,                                             (op != JSOP_DEFCONST)                                             ? JSREPORT_WARNING|JSREPORT_STRICT                                             : JSREPORT_ERROR,                                             JSMSG_REDECLARED_VAR,                                             (pn2->pn_type == TOK_FUNCTION)                                             ? js_function_str                                             : (op == JSOP_DEFCONST)                                             ? js_const_str                                             : js_var_str,                                             ATOM_BYTES(funAtom))) {                return NULL;            }            if (op == JSOP_DEFVAR)                tc->flags |= TCF_FUN_VS_VAR;        } else {            ale = js_IndexAtom(cx, funAtom, &tc->decls);            if (!ale)                return NULL;        }        ALE_SET_NODE(ale, pn);    }#if JS_HAS_LEXICAL_CLOSURE    if (lambda || !fun->atom) {        /*         * ECMA ed. 3 standard: function expression, possibly anonymous (even         * if at top-level, an unnamed function is an expression statement, not         * a function declaration).         */        op = fun->atom ? JSOP_NAMEDFUNOBJ : JSOP_ANONFUNOBJ;    } else if (!(tc->flags & TCF_TOP_LEVEL) || cx->fp->scopeChain != parent) {        /*         * ECMA ed. 3 extension: a function expression statement not at the         * top level, e.g., in a compound statement such as the "then" part         * of an "if" statement, binds a closure only if control reaches that         * sub-statement.         *         * The scopeChain != parent test handles eval called from inside a         * with statement body.         */        op = JSOP_CLOSURE;    } else#endif        op = JSOP_NOP;    pn->pn_op = op;    pn->pn_fun = fun;    pn->pn_body = body;    pn->pn_flags = funtc.flags & TCF_FUN_FLAGS;    pn->pn_tryCount = funtc.tryCount;    TREE_CONTEXT_FREE(&funtc);    return pn;}