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

📄 jsparse.c

📁 Swfdec still is development software, but has also followed a rigid no-crashes-allowed policy. I b
💻 C
📖 第 1 页 / 共 5 页
字号:
                                        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;    if (!fp || !fp->varobj || fp->scopeChain != chain) {        memset(&frame, 0, sizeof frame);        frame.varobj = frame.scopeChain = chain;        if (cx->options & JSOPTION_VAROBJFIX) {            while ((chain = JS_GetParent(cx, chain)) != NULL)                frame.varobj = chain;        }        frame.down = fp;        cx->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, NULL, 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 code 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.         */        JS_ASSERT(cg->treeContext.flags & TCF_COMPILING);        ok = JS_TRUE;    }#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, but don't be too * smart about loops (do {...; return e2;} while(0) at the end of a function * that contains an early return e1 will get a strict-option-only warning). */#define ENDS_IN_OTHER   0#define ENDS_IN_RETURN  1#define ENDS_IN_BREAK   2static intHasFinalReturn(JSParseNode *pn){    uintN rv, rv2, hasDefault;    JSParseNode *pn2, *pn3;    switch (pn->pn_type) {      case TOK_LC:        if (!pn->pn_head)            return ENDS_IN_OTHER;        return HasFinalReturn(PN_LAST(pn));      case TOK_IF:        rv = HasFinalReturn(pn->pn_kid2);        if (pn->pn_kid3)            rv &= HasFinalReturn(pn->pn_kid3);        return rv;#if JS_HAS_SWITCH_STATEMENT      case TOK_SWITCH:        rv = ENDS_IN_RETURN;        hasDefault = ENDS_IN_OTHER;        for (pn2 = pn->pn_kid2->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;#endif /* JS_HAS_SWITCH_STATEMENT */      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:        return HasFinalReturn(pn->pn_expr);#if JS_HAS_EXCEPTIONS      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)            rv &= HasFinalReturn(pn->pn_kid2);        return rv;      case TOK_CATCH:        /* Check this block's code and iterate over further catch blocks. */        rv = HasFinalReturn(pn->pn_kid3);        for (pn2 = pn->pn_kid2; pn2; pn2 = pn2->pn_kid2)            rv &= HasFinalReturn(pn2->pn_kid3);        return rv;#endif      default:        return ENDS_IN_OTHER;    }}static JSBoolReportNoReturnValue(JSContext *cx, JSTokenStream *ts){    JSFunction *fun;    JSBool ok;    fun = cx->fp->fun;    if (fun->atom) {        char *name = js_GetStringBytes(ATOM_TO_STRING(fun->atom));        ok = js_ReportCompileErrorNumber(cx, ts, NULL,                                         JSREPORT_WARNING |                                         JSREPORT_STRICT,                                         JSMSG_NO_RETURN_VALUE, name);    } else {        ok = js_ReportCompileErrorNumber(cx, ts, NULL,                                         JSREPORT_WARNING |                                         JSREPORT_STRICT,                                         JSMSG_ANON_NO_RETURN_VALUE);    }    return ok;}static JSBoolCheckFinalReturn(JSContext *cx, JSTokenStream *ts, JSParseNode *pn){    return HasFinalReturn(pn) == ENDS_IN_RETURN || ReportNoReturnValue(cx, ts);}static JSParseNode *FunctionBody(JSContext *cx, JSTokenStream *ts, JSFunction *fun,             JSTreeContext *tc){    JSStackFrame *fp, frame;    JSObject *funobj;    uintN oldflags;    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;        cx->fp = &frame;    }    oldflags = tc->flags;    tc->flags &= ~(TCF_RETURN_EXPR | TCF_RETURN_VOID);    tc->flags |= TCF_IN_FUNCTION;    pn = Statements(cx, ts, 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;    }    cx->fp = fp;    tc->flags = oldflags | (tc->flags & TCF_FUN_FLAGS);    return pn;}/* * Compile a JS function body, which might appear as the value of an event * handler attribute in an HTML <INPUT> tag. */JSBooljs_CompileFunctionBody(JSContext *cx, JSTokenStream *ts, JSFunction *fun){    JSArenaPool codePool, notePool;    JSCodeGenerator funcg;    JSStackFrame *fp, frame;    JSObject *funobj;    JSParseNode *pn;    JSBool ok;    JS_InitArenaPool(&codePool, "code", 1024, sizeof(jsbytecode));    JS_InitArenaPool(&notePool, "note", 1024, sizeof(jssrcnote));    if (!js_InitCodeGenerator(cx, &funcg, &codePool, &notePool,                              ts->filename, ts->lineno,                              ts->principals)) {        return JS_FALSE;    }    /* Prevent GC activation while compiling. */    JS_KEEP_ATOMS(cx->runtime);    /* Push a JSStackFrame for use by FunctionBody. */    fp = cx->fp;    funobj = fun->object;    JS_ASSERT(!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;    frame.flags = JS_HAS_COMPILE_N_GO_OPTION(cx)                  ? JSFRAME_COMPILING | JSFRAME_COMPILE_N_GO                  : JSFRAME_COMPILING;    cx->fp = &frame;    /* Ensure that the body looks like a block statement to js_EmitTree. */    CURRENT_TOKEN(ts).type = TOK_LC;    pn = FunctionBody(cx, ts, fun, &funcg.treeContext);    if (!pn) {        ok = JS_FALSE;    } else {        /*         * No need to emit code here -- Statements (via FunctionBody) already         * has.  See similar comment in js_CompileTokenStream, and bug 108257.         */        fun->script = js_NewScriptFromCG(cx, &funcg, fun);        if (!fun->script) {            ok = JS_FALSE;        } else {            if (funcg.treeContext.flags & TCF_FUN_HEAVYWEIGHT)                fun->flags |= JSFUN_HEAVYWEIGHT;            ok = JS_TRUE;        }    }    /* Restore saved state and release code generation arenas. */    cx->fp = fp;    JS_UNKEEP_ATOMS(cx->runtime);    js_FinishCodeGenerator(cx, &funcg);    JS_FinishArenaPool(&codePool);    JS_FinishArenaPool(&notePool);    return ok;}static JSParseNode *FunctionDef(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,            JSBool lambda){    JSParseNode *pn, *body;    JSOp op, prevop;    JSAtom *funAtom, *argAtom;    JSFunction *fun;    JSObject *parent;    JSObject *pobj;    JSProperty *prop;    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;#if JS_HAS_GETTER_SETTER    op = CURRENT_TOKEN(ts).t_op;#endif    /* 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,                                   &prop)) {                return NULL;            }            dupflag = 0;            if (prop) {                ok = JS_TRUE;                if (pobj == fun->object &&                    ((JSScopeProperty *) prop)->getter == js_GetArgument) {                    const char *name = js_AtomToPrintableString(cx, argAtom);                    /*                     * 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 = name &&                         js_ReportCompileErrorNumber(cx, ts, NULL,                                                     JSREPORT_WARNING |                                                     JSREPORT_STRICT,                                                     JSMSG_DUPLICATE_FORMAL,                                                     name);                    dupflag = SPROP_IS_DUPLICATE;                }

⌨️ 快捷键说明

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