⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jsparse.c

📁 java script test programing source code
💻 C
📖 第 1 页 / 共 5 页
字号:
            }        }    }    fun = js_NewFunction(cx, NULL, NULL, 0, lambda ? JSFUN_LAMBDA : 0, varobj,                         funAtom);    if (!fun)        return NULL;#if JS_HAS_GETTER_SETTER    if (op != JSOP_NOP)        fun->flags |= (op == JSOP_GETTER) ? JSPROP_GETTER : JSPROP_SETTER;#endif    /*     * Atomize fun->object early to protect against a last-ditch GC under     * js_LookupHiddenProperty.     *     * Absent use of the new scoped local GC roots API around compiler calls,     * we need to atomize here to protect against a GC activation.  Atoms are     * protected from GC during compilation by the JS_FRIEND_API entry points     * in this file.  There doesn't seem to be any gain in switching from the     * atom-keeping method to the bulkier, slower scoped local roots method.     */    objAtom = js_AtomizeObject(cx, fun->object, 0);    if (!objAtom)        return NULL;    /* Initialize early for possible flags mutation via DestructuringExpr. */    TREE_CONTEXT_INIT(&funtc);    /* 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)) {        BindData data;        data.pn = NULL;        data.ts = ts;        data.obj = fun->object;        data.op = JSOP_NOP;        data.binder = BindArg;        data.u.arg.fun = fun;        do {            tt = js_GetToken(cx, ts);            switch (tt) {#if JS_HAS_DESTRUCTURING              case TOK_LB:              case TOK_LC:              {                JSParseNode *lhs, *rhs;                jsint slot;                /*                 * A destructuring formal parameter turns into one or more                 * local variables initialized from properties of a single                 * anonymous positional parameter, so here we must tweak our                 * binder and its data.                 */                data.op = JSOP_DEFVAR;                data.binder = BindDestructuringArg;                data.u.var.clasp = &js_FunctionClass;                data.u.var.getter = js_GetLocalVariable;                data.u.var.setter = js_SetLocalVariable;                data.u.var.attrs = JSPROP_PERMANENT;                /*                 * Temporarily transfer the owneship of the recycle list to                 * funtc. See bug 313967.                 */                 funtc.nodeList = tc->nodeList;                tc->nodeList = NULL;                lhs = DestructuringExpr(cx, &data, &funtc, tt);                tc->nodeList = funtc.nodeList;                funtc.nodeList = NULL;                if (!lhs)                    return NULL;                /*                 * Restore the formal parameter binder in case there are more                 * non-destructuring formals in the parameter list.                 */                data.binder = BindArg;                /*                 * Adjust fun->nargs to count the single anonymous positional                 * parameter that is to be destructured.                 */                slot = fun->nargs;                if (!BumpFormalCount(cx, fun))                    return NULL;                /*                 * Synthesize a destructuring assignment from the single                 * anonymous positional parameter into the destructuring                 * left-hand-side expression and accumulate it in list.                 */                rhs = NewParseNode(cx, ts, PN_NAME, tc);                if (!rhs)                    return NULL;                rhs->pn_type = TOK_NAME;                rhs->pn_op = JSOP_GETARG;                rhs->pn_atom = cx->runtime->atomState.emptyAtom;                rhs->pn_expr = NULL;                rhs->pn_slot = slot;                rhs->pn_attrs = 0;                item = NewBinary(cx, TOK_ASSIGN, JSOP_NOP, lhs, rhs, tc);                if (!item)                    return NULL;                if (!list) {                    list = NewParseNode(cx, ts, PN_LIST, tc);                    if (!list)                        return NULL;                    list->pn_type = TOK_COMMA;                    PN_INIT_LIST(list);                }                PN_APPEND(list, item);                break;              }#endif /* JS_HAS_DESTRUCTURING */              case TOK_NAME:                if (!data.binder(cx, &data, CURRENT_TOKEN(ts).t_atom, tc))                    return NULL;                break;              default:                js_ReportCompileErrorNumber(cx, ts,                                            JSREPORT_TS | JSREPORT_ERROR,                                            JSMSG_MISSING_FORMAL);                return NULL;            }        } 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;    /*     * Temporarily transfer the owneship of the recycle list to funtc.     * See bug 313967.     */     funtc.nodeList = tc->nodeList;    tc->nodeList = NULL;    body = FunctionBody(cx, ts, fun, &funtc);    tc->nodeList = funtc.nodeList;    funtc.nodeList = NULL;        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_DESTRUCTURING    /*     * If there were destructuring formal parameters, prepend the initializing     * comma expression that we synthesized to body.  If the body is a lexical     * scope node, we must make a special TOK_BODY node, to prepend the formal     * parameter destructuring code without bracing the decompilation of the     * function body's lexical scope.     */    if (list) {        if (body->pn_arity != PN_LIST) {            JSParseNode *block;            JS_ASSERT(body->pn_type == TOK_LEXICALSCOPE);            JS_ASSERT(body->pn_arity == PN_NAME);            block = NewParseNode(cx, ts, PN_LIST, tc);            if (!block)                return NULL;            block->pn_type = TOK_BODY;            block->pn_pos = body->pn_pos;            PN_INIT_LIST_1(block, body);            body = block;        }        item = NewParseNode(cx, ts, PN_UNARY, tc);        if (!item)            return NULL;        item->pn_type = TOK_SEMI;        item->pn_pos.begin = item->pn_pos.end = body->pn_pos.begin;        item->pn_kid = list;        item->pn_next = body->pn_head;        body->pn_head = item;        if (body->pn_tail == &body->pn_head)            body->pn_tail = &item->pn_next;        ++body->pn_count;    }#endif    /*     * 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, not a function definiton or expression), then         * our enclosing function, if any, must be heavyweight.         *         * The TCF_FUN_USES_NONLOCALS flag is set only by the code generator,         * so it won't be set here.  Assert that it's not.  We have to check         * it later, in js_EmitTree, after js_EmitFunctionBody has traversed         * the function's body         */        JS_ASSERT(!(funtc.flags & TCF_FUN_USES_NONLOCALS));        if (!lambda && funAtom && !AT_TOP_LEVEL(tc))            tc->flags |= TCF_FUN_HEAVYWEIGHT;    }    result = pn;    if (lambda) {        /*         * ECMA ed. 3 standard: function expression, possibly anonymous.         */        op = funAtom ? JSOP_NAMEDFUNOBJ : JSOP_ANONFUNOBJ;    } else if (!funAtom) {        /*         * If this anonymous function definition is *not* embedded within a         * larger expression, we treat it as an expression statement, not as         * a function declaration -- and not as a syntax error (as ECMA-262         * Edition 3 would have it).  Backward compatibility trumps all.         */        result = NewParseNode(cx, ts, PN_UNARY, tc);        if (!result)            return NULL;        result->pn_type = TOK_SEMI;        result->pn_pos = pn->pn_pos;        result->pn_kid = pn;        op = JSOP_ANONFUNOBJ;    } else if (!AT_TOP_LEVEL(tc)) {        /*         * 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.         */        op = JSOP_CLOSURE;    } else {        op = JSOP_NOP;    }    pn->pn_funAtom = objAtom;    pn->pn_op = op;    pn->pn_body = body;    pn->pn_flags = funtc.flags & (TCF_FUN_FLAGS | TCF_HAS_DEFXMLNS);    pn->pn_tryCount = funtc.tryCount;    TREE_CONTEXT_FINISH(&funtc);    return result;}static JSParseNode *FunctionStmt(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc){    return FunctionDef(cx, ts, tc, JS_FALSE);}static JSParseNode *FunctionExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc){    return FunctionDef(cx, ts, tc, JS_TRUE);}/* * Parse the statements in a block, creating a TOK_LC node that lists the * statements' trees.  If called from block-parsing code, the caller must * match { before and } after. */static JSParseNode *Statements(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc){    JSParseNode *pn, *pn2, *saveBlock;    JSTokenType tt;    CHECK_RECURSION();    pn = NewParseNode(cx, ts, PN_LIST, tc);    if (!pn)        return NULL;    saveBlock = tc->blockNode;    tc->blockNode = pn;    PN_INIT_LIST(pn);    ts->flags |= TSF_OPERAND;    while ((tt = js_PeekToken(cx, ts)) > TOK_EOF && tt != TOK_RC) {        ts->flags &= ~TSF_OPERAND;        pn2 = Statement(cx, ts, tc);        if (!pn2) {            if (ts->flags & TSF_EOF)                ts->flags |= TSF_UNEXPECTED_EOF;            return NULL;        }        ts->flags |= TSF_OPERAND;        /* Detect a function statement for the TOK_LC case in Statement. */        if (pn2->pn_type == TOK_FUNCTION && !AT_TOP_LEVEL(tc))            tc->flags |= TCF_HAS_FUNCTION_STMT;        /* If compiling top-level statements, emit as we go to save space. */        if (!tc->topStmt && (tc->flags & TCF_COMPILING)) {            if (cx->fp->fun &&                JS_HAS_STRICT_OPTION(cx) &&                (tc->flags & TCF_RETURN_EXPR)) {                /*                 * Check pn2 for lack of a final return statement if it is the                 * last statement in the block.                 */                tt = js_PeekToken(cx, ts);                if ((tt == TOK_EOF || tt == TOK_RC) &&                    !CheckFinalReturn(cx, ts, pn2)) {                    tt = TOK_ERROR;                    break;                }                /*                 * Clear TCF_RETURN_EXPR so FunctionBody doesn't try to                 * CheckFinalReturn again.                 */                tc->flags &= ~TCF_RETURN_EXPR;            }            if (!js_FoldConstants(cx, pn2, tc) ||                !js_AllocTryNotes(cx, (JSCodeGenerator *)tc) ||                !js_EmitTree(cx, (JSCodeGenerator *)tc, pn2)) {                tt = TOK_ERROR;                break;            }            RecycleTree(pn2, tc);        } else {            PN_APPEND(pn, pn2);        }    }    /*     * Handle the case where there was a let declaration under this block.  If     * it replaced tc->blockNode with a new block node then we must refresh pn     * and then restore tc->blockNode.     */    if (tc->blockNode != pn)        pn = tc->blockNode;    tc->blockNode = saveBlock;    ts->flags &= ~TSF_OPERAND;    if (tt == TOK_ERROR)        return NULL;    pn->pn_pos.end = CURRENT_TOKEN(ts).pos.end;    return pn;}static JSParseNode *Condition(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc){    JSParseNode *pn, *pn2;    MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_COND);    pn = Expr(cx, ts, tc);    if (!pn)        return NULL;    MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_COND);    /*     * Check for (a = b) and "correct" it to (a == b) iff b's operator has     * greater precedence than ==.     * XXX not ECMA, but documented in several books -- now a strict warning.     */    if (pn->pn_type == TOK_ASSIGN &&        pn->pn_op == JSOP_NOP &&        pn->pn_right->pn_type > TOK_EQOP)    {        JSBool rewrite = !JS_VERSION_IS_ECMA(cx);        if (!js_ReportCompileErrorNumber(cx, ts,                                         JSREPORT_TS |                                         JSREPORT_WARNING |                                         JSREPORT_STRICT,                                         JSMSG_EQUAL_AS_ASSIGN,                                         rewrite

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -