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

📄 jsparse.c

📁 java script test programing source code
💻 C
📖 第 1 页 / 共 5 页
字号:
        return;    }    memset(newfp, 0, sizeof *newfp);    /* Default to sharing the same variables object and scope chain. */    newfp->varobj = newfp->scopeChain = chain;    if (cx->options & JSOPTION_VAROBJFIX) {        while ((chain = JS_GetParent(cx, chain)) != NULL)            newfp->varobj = chain;    }    newfp->down = oldfp;    if (oldfp) {        /*         * In the case of eval and debugger frames, we need to dig down and find         * the real variables objects and function that our new stack frame is         * going to use.         */        newfp->flags = oldfp->flags & (JSFRAME_SPECIAL | JSFRAME_COMPILE_N_GO |                                       JSFRAME_SCRIPT_OBJECT);        while (oldfp->flags & JSFRAME_SPECIAL) {            oldfp = oldfp->down;            if (!oldfp)                break;        }        if (oldfp && (newfp->flags & JSFRAME_SPECIAL)) {            newfp->varobj = oldfp->varobj;            newfp->vars = oldfp->vars;            newfp->fun = oldfp->fun;        }    }    cx->fp = newfp;}/* * Parse a top-level JS script. */JS_FRIEND_API(JSParseNode *)js_ParseTokenStream(JSContext *cx, JSObject *chain, JSTokenStream *ts){    JSStackFrame *fp, frame;    JSTreeContext tc;    JSParseNode *pn;    /*     * Push a compiler frame if we have no frames, or if the top frame is a     * lightweight function activation, or if its scope chain doesn't match     * the one passed to us.     */    fp = cx->fp;    MaybeSetupFrame(cx, chain, fp, &frame);    /*     * Protect atoms from being collected by a GC activation, which might     * - nest on this thread due to out of memory (the so-called "last ditch"     *   GC attempted within js_NewGCThing), or     * - run for any reason on another thread if this thread is suspended on     *   an object lock before it finishes generating bytecode into a script     *   protected from the GC by a root or a stack frame reference.     */    JS_KEEP_ATOMS(cx->runtime);    TREE_CONTEXT_INIT(&tc);    pn = Statements(cx, ts, &tc);    if (pn) {        if (!js_MatchToken(cx, ts, TOK_EOF)) {            js_ReportCompileErrorNumber(cx, ts, JSREPORT_TS | JSREPORT_ERROR,                                        JSMSG_SYNTAX_ERROR);            pn = NULL;        } else {            pn->pn_type = TOK_LC;            if (!js_FoldConstants(cx, pn, &tc))                pn = NULL;        }    }    TREE_CONTEXT_FINISH(&tc);    JS_UNKEEP_ATOMS(cx->runtime);    cx->fp = fp;    return pn;}/* * Compile a top-level script. */JS_FRIEND_API(JSBool)js_CompileTokenStream(JSContext *cx, JSObject *chain, JSTokenStream *ts,                      JSCodeGenerator *cg){    JSStackFrame *fp, frame;    uint32 flags;    JSParseNode *pn;    JSBool ok;#ifdef METER_PARSENODES    void *sbrk(ptrdiff_t), *before = sbrk(0);#endif    /*     * Push a compiler frame if we have no frames, or if the top frame is a     * lightweight function activation, or if its scope chain doesn't match     * the one passed to us.     */    fp = cx->fp;    MaybeSetupFrame(cx, chain, fp, &frame);    flags = cx->fp->flags;    cx->fp->flags = flags |                    (JS_HAS_COMPILE_N_GO_OPTION(cx)                     ? JSFRAME_COMPILING | JSFRAME_COMPILE_N_GO                     : JSFRAME_COMPILING);    /* Prevent GC activation while compiling. */    JS_KEEP_ATOMS(cx->runtime);    pn = Statements(cx, ts, &cg->treeContext);    if (!pn) {        ok = JS_FALSE;    } else if (!js_MatchToken(cx, ts, TOK_EOF)) {        js_ReportCompileErrorNumber(cx, ts, JSREPORT_TS | JSREPORT_ERROR,                                    JSMSG_SYNTAX_ERROR);        ok = JS_FALSE;    } else {#ifdef METER_PARSENODES        printf("Parser growth: %d (%u nodes, %u max, %u unrecycled)\n",               (char *)sbrk(0) - (char *)before,               parsenodes,               maxparsenodes,               parsenodes - recyclednodes);        before = sbrk(0);#endif        /*         * No need to emit bytecode here -- Statements already has, for each         * statement in turn.  Search for TCF_COMPILING in Statements, below.         * That flag is set for every tc == &cg->treeContext, and it implies         * that the tc can be downcast to a cg and used to emit code during         * parsing, rather than at the end of the parse phase.         *         * Nowadays the threaded interpreter needs a stop instruction, so we         * do have to emit that here.         */        JS_ASSERT(cg->treeContext.flags & TCF_COMPILING);        ok = js_Emit1(cx, cg, JSOP_STOP) >= 0;    }#ifdef METER_PARSENODES    printf("Code-gen growth: %d (%u bytecodes, %u srcnotes)\n",           (char *)sbrk(0) - (char *)before, CG_OFFSET(cg), cg->noteCount);#endif#ifdef JS_ARENAMETER    JS_DumpArenaStats(stdout);#endif    JS_UNKEEP_ATOMS(cx->runtime);    cx->fp->flags = flags;    cx->fp = fp;    return ok;}/* * Insist on a final return before control flows out of pn.  Try to be a bit * smart about loops: do {...; return e2;} while(0) at the end of a function * that contains an early return e1 will get a strict warning.  Similarly for * iloops: while (true){...} is treated as though ... returns. */#define ENDS_IN_OTHER   0#define ENDS_IN_RETURN  1#define ENDS_IN_BREAK   2static intHasFinalReturn(JSParseNode *pn){    JSParseNode *pn2, *pn3;    uintN rv, rv2, hasDefault;    switch (pn->pn_type) {      case TOK_LC:        if (!pn->pn_head)            return ENDS_IN_OTHER;        return HasFinalReturn(PN_LAST(pn));      case TOK_IF:        if (!pn->pn_kid3)            return ENDS_IN_OTHER;        return HasFinalReturn(pn->pn_kid2) & HasFinalReturn(pn->pn_kid3);      case TOK_WHILE:        pn2 = pn->pn_left;        if (pn2->pn_type == TOK_PRIMARY && pn2->pn_op == JSOP_TRUE)            return ENDS_IN_RETURN;        if (pn2->pn_type == TOK_NUMBER && pn2->pn_dval)            return ENDS_IN_RETURN;        return ENDS_IN_OTHER;      case TOK_DO:        pn2 = pn->pn_right;        if (pn2->pn_type == TOK_PRIMARY) {            if (pn2->pn_op == JSOP_FALSE)                return HasFinalReturn(pn->pn_left);            if (pn2->pn_op == JSOP_TRUE)                return ENDS_IN_RETURN;        }        if (pn2->pn_type == TOK_NUMBER) {            if (pn2->pn_dval == 0)                return HasFinalReturn(pn->pn_left);            return ENDS_IN_RETURN;        }        return ENDS_IN_OTHER;      case TOK_FOR:        pn2 = pn->pn_left;        if (pn2->pn_arity == PN_TERNARY && !pn2->pn_kid2)            return ENDS_IN_RETURN;        return ENDS_IN_OTHER;      case TOK_SWITCH:        rv = ENDS_IN_RETURN;        hasDefault = ENDS_IN_OTHER;        pn2 = pn->pn_right;        if (pn2->pn_type == TOK_LEXICALSCOPE)            pn2 = pn2->pn_expr;        for (pn2 = pn2->pn_head; rv && pn2; pn2 = pn2->pn_next) {            if (pn2->pn_type == TOK_DEFAULT)                hasDefault = ENDS_IN_RETURN;            pn3 = pn2->pn_right;            JS_ASSERT(pn3->pn_type == TOK_LC);            if (pn3->pn_head) {                rv2 = HasFinalReturn(PN_LAST(pn3));                if (rv2 == ENDS_IN_OTHER && pn2->pn_next)                    /* Falling through to next case or default. */;                else                    rv &= rv2;            }        }        /* If a final switch has no default case, we judge it harshly. */        rv &= hasDefault;        return rv;      case TOK_BREAK:        return ENDS_IN_BREAK;      case TOK_WITH:        return HasFinalReturn(pn->pn_right);      case TOK_RETURN:        return ENDS_IN_RETURN;      case TOK_COLON:      case TOK_LEXICALSCOPE:        return HasFinalReturn(pn->pn_expr);      case TOK_THROW:        return ENDS_IN_RETURN;      case TOK_TRY:        /* If we have a finally block that returns, we are done. */        if (pn->pn_kid3) {            rv = HasFinalReturn(pn->pn_kid3);            if (rv == ENDS_IN_RETURN)                return rv;        }        /* Else check the try block and any and all catch statements. */        rv = HasFinalReturn(pn->pn_kid1);        if (pn->pn_kid2) {            JS_ASSERT(pn->pn_kid2->pn_arity == PN_LIST);            for (pn2 = pn->pn_kid2->pn_head; pn2; pn2 = pn2->pn_next)                rv &= HasFinalReturn(pn2);        }        return rv;      case TOK_CATCH:        /* Check this catch block's body. */        return HasFinalReturn(pn->pn_kid3);      case TOK_LET:        /* Non-binary let statements are let declarations. */        if (pn->pn_arity != PN_BINARY)            return ENDS_IN_OTHER;        return HasFinalReturn(pn->pn_right);      default:        return ENDS_IN_OTHER;    }}static JSBoolReportBadReturn(JSContext *cx, JSTokenStream *ts, uintN flags, uintN errnum,                uintN anonerrnum){    JSFunction *fun;    const char *name;    fun = cx->fp->fun;    if (fun->atom) {        name = js_AtomToPrintableString(cx, fun->atom);    } else {        errnum = anonerrnum;        name = NULL;    }    return js_ReportCompileErrorNumber(cx, ts, JSREPORT_TS | flags, errnum,                                       name);}static JSBoolCheckFinalReturn(JSContext *cx, JSTokenStream *ts, JSParseNode *pn){    return HasFinalReturn(pn) == ENDS_IN_RETURN ||           ReportBadReturn(cx, ts, JSREPORT_WARNING | JSREPORT_STRICT,                           JSMSG_NO_RETURN_VALUE, JSMSG_ANON_NO_RETURN_VALUE);}static JSParseNode *FunctionBody(JSContext *cx, JSTokenStream *ts, JSFunction *fun,             JSTreeContext *tc){    JSStackFrame *fp, frame;    JSObject *funobj;    JSStmtInfo stmtInfo;    uintN oldflags, firstLine;    JSParseNode *pn;    fp = cx->fp;    funobj = fun->object;    if (!fp || fp->fun != fun || fp->varobj != funobj ||        fp->scopeChain != funobj) {        memset(&frame, 0, sizeof frame);        frame.fun = fun;        frame.varobj = frame.scopeChain = funobj;        frame.down = fp;        if (fp)            frame.flags = fp->flags & JSFRAME_COMPILE_N_GO;        cx->fp = &frame;    }    /*     * Set interpreted early so js_EmitTree can test it to decide whether to     * eliminate useless expressions.     */    fun->flags |= JSFUN_INTERPRETED;    js_PushStatement(tc, &stmtInfo, STMT_BLOCK, -1);    stmtInfo.flags = SIF_BODY_BLOCK;    oldflags = tc->flags;    tc->flags &= ~(TCF_RETURN_EXPR | TCF_RETURN_VOID);    tc->flags |= TCF_IN_FUNCTION;    /*     * Save the body's first line, and store it in pn->pn_pos.begin.lineno     * later, because we may have not peeked in ts yet, so Statements won't     * acquire a valid pn->pn_pos.begin from the current token.     */    firstLine = ts->lineno;    pn = Statements(cx, ts, tc);    js_PopStatement(tc);    /* Check for falling off the end of a function that returns a value. */    if (pn && JS_HAS_STRICT_OPTION(cx) && (tc->flags & TCF_RETURN_EXPR)) {        if (!CheckFinalReturn(cx, ts, pn))            pn = NULL;    }    /*     * If we have a parse tree in pn and a code generator in tc, emit this     * function's code.  We must do this here, not in js_CompileFunctionBody,     * in order to detect TCF_IN_FUNCTION among tc->flags.     */    if (pn) {        pn->pn_pos.begin.lineno = firstLine;        if ((tc->flags & TCF_COMPILING)) {            JSCodeGenerator *cg = (JSCodeGenerator *) tc;            if (!js_FoldConstants(cx, pn, tc) ||                !js_EmitFunctionBytecode(cx, cg, pn)) {                pn = NULL;            }        }    }    cx->fp = fp;    tc->flags = oldflags | (tc->flags & (TCF_FUN_FLAGS | TCF_HAS_DEFXMLNS));    return pn;}/* * Compile a JS function body, which might appear as the value of an event * handler attribute in an HTML <INPUT> tag. */JSBool

⌨️ 快捷键说明

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