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

📄 jsparse.c

📁 java script test programing source code
💻 C
📖 第 1 页 / 共 5 页
字号:
js_CompileFunctionBody(JSContext *cx, JSTokenStream *ts, JSFunction *fun){    JSArenaPool codePool, notePool;    JSCodeGenerator funcg;    JSStackFrame *fp, frame;    JSObject *funobj;    JSParseNode *pn;    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;    /*     * Farble the body so that it looks like a block statement to js_EmitTree,     * which is called beneath FunctionBody; see Statements, further below in     * this file.  FunctionBody pushes a STMT_BLOCK record around its call to     * Statements, so Statements will not compile each statement as it loops     * to save JSParseNode space -- it will not compile at all, only build a     * JSParseNode tree.     *     * Therefore we must fold constants, allocate try notes, and generate code     * for this function, including a stop opcode at the end.     */    CURRENT_TOKEN(ts).type = TOK_LC;    pn = FunctionBody(cx, ts, fun, &funcg.treeContext);    if (pn && !js_NewScriptFromCG(cx, &funcg, fun))        pn = NULL;    /* 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 pn != NULL;}/* * Parameter block types for the several Binder functions.  We use a common * helper function signature in order to share code among destructuring and * simple variable declaration parsers.  In the destructuring case, the binder * function is called indirectly from the variable declaration parser by way * of CheckDestructuring and its friends. */typedef struct BindData BindData;typedef JSBool(*Binder)(JSContext *cx, BindData *data, JSAtom *atom, JSTreeContext *tc);struct BindData {    JSParseNode             *pn;                /* error source coordinate */    JSTokenStream           *ts;                /* fallback if pn is null */    JSObject                *obj;               /* the variable object */    JSOp                    op;                 /* prolog bytecode or nop */    Binder                  binder;             /* binder, discriminates u */    union {        struct {            JSFunction      *fun;               /* must come first! see next */        } arg;        struct {            JSFunction      *fun;               /* this overlays u.arg.fun */            JSClass         *clasp;            JSPropertyOp    getter;            JSPropertyOp    setter;            uintN           attrs;        } var;        struct {            jsuint          index;            uintN           overflow;        } let;    } u;};/* * Given BindData *data and JSREPORT_* flags, expand to the second and third * actual parameters to js_ReportCompileErrorNumber.  Prefer reporting via pn * to reporting via ts, for better destructuring error pointers. */#define BIND_DATA_REPORT_ARGS(data, flags)                                    \    (data)->pn ? (void *)(data)->pn : (void *)(data)->ts,                     \    ((data)->pn ? JSREPORT_PN : JSREPORT_TS) | (flags)static JSBoolBumpFormalCount(JSContext *cx, JSFunction *fun){    if (fun->nargs == JS_BITMASK(16)) {        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,                             JSMSG_TOO_MANY_FUN_ARGS);        return JS_FALSE;    }    fun->nargs++;    return JS_TRUE;}static JSBoolBindArg(JSContext *cx, BindData *data, JSAtom *atom, JSTreeContext *tc){    JSObject *obj, *pobj;    JSProperty *prop;    JSBool ok;    uintN dupflag;    JSFunction *fun;    const char *name;    obj = data->obj;    ok = js_LookupHiddenProperty(cx, obj, ATOM_TO_JSID(atom), &pobj, &prop);    if (!ok)        return JS_FALSE;    dupflag = 0;    if (prop) {        JS_ASSERT(pobj == obj);        name = js_AtomToPrintableString(cx, atom);        /*         * A duplicate parameter name, a "feature" required by ECMA-262.         * 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,                                         BIND_DATA_REPORT_ARGS(data,                                             JSREPORT_WARNING |                                             JSREPORT_STRICT),                                         JSMSG_DUPLICATE_FORMAL,                                         name);        OBJ_DROP_PROPERTY(cx, pobj, prop);        if (!ok)            return JS_FALSE;        dupflag = SPROP_IS_DUPLICATE;    }    fun = data->u.arg.fun;    if (!js_AddHiddenProperty(cx, data->obj, ATOM_TO_JSID(atom),                              js_GetArgument, js_SetArgument,                              SPROP_INVALID_SLOT,                              JSPROP_PERMANENT | JSPROP_SHARED,                              dupflag | SPROP_HAS_SHORTID,                              fun->nargs)) {        return JS_FALSE;    }    return BumpFormalCount(cx, fun);}static JSBoolBindLocalVariable(JSContext *cx, BindData *data, JSAtom *atom){    JSFunction *fun;    /*     * Can't increase fun->nvars in an active frame, so insist that getter is     * js_GetLocalVariable, not js_GetCallVariable or anything else.     */    if (data->u.var.getter != js_GetLocalVariable)        return JS_TRUE;    /*     * Don't bind a variable with the hidden name 'arguments', per ECMA-262.     * Instead 'var arguments' always restates the predefined property of the     * activation objects with unhidden name 'arguments'.  Assignment to such     * a variable must be handled specially.     */    if (atom == cx->runtime->atomState.argumentsAtom)        return JS_TRUE;    fun = data->u.var.fun;    if (!js_AddHiddenProperty(cx, data->obj, ATOM_TO_JSID(atom),                              data->u.var.getter, data->u.var.setter,                              SPROP_INVALID_SLOT,                              data->u.var.attrs | JSPROP_SHARED,                              SPROP_HAS_SHORTID, fun->u.i.nvars)) {        return JS_FALSE;    }    if (fun->u.i.nvars == JS_BITMASK(16)) {        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,                             JSMSG_TOO_MANY_FUN_VARS);        return JS_FALSE;    }    fun->u.i.nvars++;    return JS_TRUE;}#if JS_HAS_DESTRUCTURING/* * Forward declaration to maintain top-down presentation. */static JSParseNode *DestructuringExpr(JSContext *cx, BindData *data, JSTreeContext *tc,                  JSTokenType tt);static JSBoolBindDestructuringArg(JSContext *cx, BindData *data, JSAtom *atom,                     JSTreeContext *tc){    JSAtomListElement *ale;    JSFunction *fun;    JSObject *obj, *pobj;    JSProperty *prop;    const char *name;    ATOM_LIST_SEARCH(ale, &tc->decls, atom);    if (!ale) {        ale = js_IndexAtom(cx, atom, &tc->decls);        if (!ale)            return JS_FALSE;        ALE_SET_JSOP(ale, data->op);    }    fun = data->u.var.fun;    obj = data->obj;    if (!js_LookupHiddenProperty(cx, obj, ATOM_TO_JSID(atom), &pobj, &prop))        return JS_FALSE;    if (prop) {        JS_ASSERT(pobj == obj && OBJ_IS_NATIVE(pobj));        name = js_AtomToPrintableString(cx, atom);        if (!name ||            !js_ReportCompileErrorNumber(cx,                                         BIND_DATA_REPORT_ARGS(data,                                             JSREPORT_WARNING |                                             JSREPORT_STRICT),                                         JSMSG_DUPLICATE_FORMAL,                                         name)) {            return JS_FALSE;        }        OBJ_DROP_PROPERTY(cx, pobj, prop);    } else {        if (!BindLocalVariable(cx, data, atom))            return JS_FALSE;    }    return JS_TRUE;}#endif /* JS_HAS_DESTRUCTURING */static JSParseNode *FunctionDef(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,            JSBool lambda){    JSOp op, prevop;    JSParseNode *pn, *body, *result;    JSTokenType tt;    JSAtom *funAtom, *objAtom;    JSStackFrame *fp;    JSObject *varobj, *pobj;    JSAtomListElement *ale;    JSProperty *prop;    JSFunction *fun;    JSTreeContext funtc;#if JS_HAS_DESTRUCTURING    JSParseNode *item, *list = NULL;#endif    /* Make a TOK_FUNCTION node. */#if JS_HAS_GETTER_SETTER    op = CURRENT_TOKEN(ts).t_op;#endif    pn = NewParseNode(cx, ts, PN_FUNC, tc);    if (!pn)        return NULL;    /* Scan the optional function name into funAtom. */    ts->flags |= TSF_KEYWORD_IS_NAME;    tt = js_GetToken(cx, ts);    ts->flags &= ~TSF_KEYWORD_IS_NAME;    if (tt == TOK_NAME) {        funAtom = CURRENT_TOKEN(ts).t_atom;    } else {        funAtom = NULL;        js_UngetToken(ts);    }    /* Find the nearest variable-declaring scope and use it as our parent. */    fp = cx->fp;    varobj = fp->varobj;    /*     * 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) {                const char *name = js_AtomToPrintableString(cx, funAtom);                if (!name ||                    !js_ReportCompileErrorNumber(cx, ts,                                                 (prevop != JSOP_DEFCONST)                                                 ? JSREPORT_TS |                                                   JSREPORT_WARNING |                                                   JSREPORT_STRICT                                                 : JSREPORT_TS | JSREPORT_ERROR,                                                 JSMSG_REDECLARED_VAR,                                                 (prevop == JSOP_DEFFUN ||                                                  prevop == JSOP_CLOSURE)                                                 ? js_function_str                                                 : (prevop == JSOP_DEFCONST)                                                 ? js_const_str                                                 : js_var_str,                                                 name)) {                    return NULL;                }            }            if (!AT_TOP_LEVEL(tc) && 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, AT_TOP_LEVEL(tc) ? JSOP_DEFFUN : JSOP_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 BindNameToSlot can optimize a JSOP_NAME into a         * JSOP_GETVAR bytecode).         */        if (AT_TOP_LEVEL(tc) && (tc->flags & TCF_IN_FUNCTION)) {            JSScopeProperty *sprop;            /*             * Define a property on the outer function so that BindNameToSlot             * can properly optimize accesses.             */            JS_ASSERT(OBJ_GET_CLASS(cx, varobj) == &js_FunctionClass);            JS_ASSERT(fp->fun == (JSFunction *) JS_GetPrivate(cx, varobj));            if (!js_LookupHiddenProperty(cx, varobj, ATOM_TO_JSID(funAtom),                                         &pobj, &prop)) {                return NULL;            }            if (prop)                OBJ_DROP_PROPERTY(cx, pobj, prop);            sprop = NULL;            if (!prop ||                pobj != varobj ||                (sprop = (JSScopeProperty *)prop,                 sprop->getter != js_GetLocalVariable)) {                uintN sflags;                /*                 * Use SPROP_IS_DUPLICATE if there is a formal argument of the                 * same name, so the decompiler can find the parameter name.                 */                sflags = (sprop && sprop->getter == js_GetArgument)                         ? SPROP_IS_DUPLICATE | SPROP_HAS_SHORTID                         : SPROP_HAS_SHORTID;                if (!js_AddHiddenProperty(cx, varobj, ATOM_TO_JSID(funAtom),                                          js_GetLocalVariable,                                          js_SetLocalVariable,                                          SPROP_INVALID_SLOT,                                          JSPROP_PERMANENT | JSPROP_SHARED,                                          sflags, fp->fun->u.i.nvars)) {                    return NULL;                }                if (fp->fun->u.i.nvars == JS_BITMASK(16)) {                    JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,                                         JSMSG_TOO_MANY_FUN_VARS);                    return NULL;                }                fp->fun->u.i.nvars++;

⌨️ 快捷键说明

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