📄 jsparse.c
字号:
? "\nAssuming equality test" : "")) { return NULL; } if (rewrite) { pn->pn_type = TOK_EQOP; pn->pn_op = (JSOp)cx->jsop_eq; pn2 = pn->pn_left; switch (pn2->pn_op) { case JSOP_SETNAME: pn2->pn_op = JSOP_NAME; break; case JSOP_SETPROP: pn2->pn_op = JSOP_GETPROP; break; case JSOP_SETELEM: pn2->pn_op = JSOP_GETELEM; break; default: JS_ASSERT(0); } } } return pn;}static JSBoolMatchLabel(JSContext *cx, JSTokenStream *ts, JSParseNode *pn){ JSAtom *label; JSTokenType tt; tt = js_PeekTokenSameLine(cx, ts); if (tt == TOK_ERROR) return JS_FALSE; if (tt == TOK_NAME) { (void) js_GetToken(cx, ts); label = CURRENT_TOKEN(ts).t_atom; } else { label = NULL; } pn->pn_atom = label; return JS_TRUE;}#if JS_HAS_EXPORT_IMPORTstatic JSParseNode *ImportExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc){ JSParseNode *pn, *pn2; JSTokenType tt; MUST_MATCH_TOKEN(TOK_NAME, JSMSG_NO_IMPORT_NAME); pn = NewParseNode(cx, ts, PN_NAME, tc); if (!pn) return NULL; pn->pn_op = JSOP_NAME; pn->pn_atom = CURRENT_TOKEN(ts).t_atom; pn->pn_expr = NULL; pn->pn_slot = -1; pn->pn_attrs = 0; ts->flags |= TSF_OPERAND; while ((tt = js_GetToken(cx, ts)) == TOK_DOT || tt == TOK_LB) { ts->flags &= ~TSF_OPERAND; if (pn->pn_op == JSOP_IMPORTALL) goto bad_import; if (tt == TOK_DOT) { pn2 = NewParseNode(cx, ts, PN_NAME, tc); if (!pn2) return NULL; ts->flags |= TSF_KEYWORD_IS_NAME; if (js_MatchToken(cx, ts, TOK_STAR)) { pn2->pn_op = JSOP_IMPORTALL; pn2->pn_atom = NULL; pn2->pn_slot = -1; pn2->pn_attrs = 0; } else { MUST_MATCH_TOKEN(TOK_NAME, JSMSG_NAME_AFTER_DOT); pn2->pn_op = JSOP_GETPROP; pn2->pn_atom = CURRENT_TOKEN(ts).t_atom; pn2->pn_slot = -1; pn2->pn_attrs = 0; } ts->flags &= ~TSF_KEYWORD_IS_NAME; pn2->pn_expr = pn; pn2->pn_pos.begin = pn->pn_pos.begin; pn2->pn_pos.end = CURRENT_TOKEN(ts).pos.end; } else { /* Make a TOK_LB binary node. */ pn2 = NewBinary(cx, tt, JSOP_GETELEM, pn, Expr(cx, ts, tc), tc); if (!pn2) return NULL; MUST_MATCH_TOKEN(TOK_RB, JSMSG_BRACKET_IN_INDEX); } pn = pn2; ts->flags |= TSF_OPERAND; } ts->flags &= ~TSF_OPERAND; if (tt == TOK_ERROR) return NULL; js_UngetToken(ts); switch (pn->pn_op) { case JSOP_GETPROP: pn->pn_op = JSOP_IMPORTPROP; break; case JSOP_GETELEM: pn->pn_op = JSOP_IMPORTELEM; break; case JSOP_IMPORTALL: break; default: goto bad_import; } return pn; bad_import: js_ReportCompileErrorNumber(cx, ts, JSREPORT_TS | JSREPORT_ERROR, JSMSG_BAD_IMPORT); return NULL;}#endif /* JS_HAS_EXPORT_IMPORT */static JSBoolBindLet(JSContext *cx, BindData *data, JSAtom *atom, JSTreeContext *tc){ JSObject *blockObj; JSScopeProperty *sprop; JSAtomListElement *ale; blockObj = data->obj; sprop = SCOPE_GET_PROPERTY(OBJ_SCOPE(blockObj), ATOM_TO_JSID(atom)); ATOM_LIST_SEARCH(ale, &tc->decls, atom); if (sprop || (ale && ALE_JSOP(ale) == JSOP_DEFCONST)) { const char *name; if (sprop) { JS_ASSERT(sprop->flags & SPROP_HAS_SHORTID); JS_ASSERT((uint16)sprop->shortid < data->u.let.index); } name = js_AtomToPrintableString(cx, atom); if (name) { js_ReportCompileErrorNumber(cx, BIND_DATA_REPORT_ARGS(data, JSREPORT_ERROR), JSMSG_REDECLARED_VAR, (ale && ALE_JSOP(ale) == JSOP_DEFCONST) ? js_const_str : "variable", name); } return JS_FALSE; } if (data->u.let.index == JS_BIT(16)) { js_ReportCompileErrorNumber(cx, BIND_DATA_REPORT_ARGS(data, JSREPORT_ERROR), data->u.let.overflow); return JS_FALSE; } /* Use JSPROP_ENUMERATE to aid the disassembler. */ return js_DefineNativeProperty(cx, blockObj, ATOM_TO_JSID(atom), JSVAL_VOID, NULL, NULL, JSPROP_ENUMERATE | JSPROP_PERMANENT, SPROP_HAS_SHORTID, (intN)data->u.let.index++, NULL);}static JSBoolBindVarOrConst(JSContext *cx, BindData *data, JSAtom *atom, JSTreeContext *tc){ JSStmtInfo *stmt; JSAtomListElement *ale; JSOp op, prevop; const char *name; JSFunction *fun; JSObject *obj, *pobj; JSProperty *prop; JSBool ok; JSPropertyOp getter, setter; JSScopeProperty *sprop; stmt = js_LexicalLookup(tc, atom, NULL, JS_FALSE); ATOM_LIST_SEARCH(ale, &tc->decls, atom); op = data->op; if ((stmt && stmt->type != STMT_WITH) || ale) { prevop = ale ? ALE_JSOP(ale) : JSOP_DEFVAR; if (JS_HAS_STRICT_OPTION(cx) ? op != JSOP_DEFVAR || prevop != JSOP_DEFVAR : op == JSOP_DEFCONST || prevop == JSOP_DEFCONST) { name = js_AtomToPrintableString(cx, atom); if (!name || !js_ReportCompileErrorNumber(cx, BIND_DATA_REPORT_ARGS(data, (op != JSOP_DEFCONST && prevop != JSOP_DEFCONST) ? JSREPORT_WARNING | JSREPORT_STRICT : 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 JS_FALSE; } } if (op == JSOP_DEFVAR && prevop == JSOP_CLOSURE) tc->flags |= TCF_FUN_CLOSURE_VS_VAR; } if (!ale) { ale = js_IndexAtom(cx, atom, &tc->decls); if (!ale) return JS_FALSE; } ALE_SET_JSOP(ale, op); fun = data->u.var.fun; obj = data->obj; if (!fun) { /* Don't lookup global variables at compile time. */ prop = NULL; } else { JS_ASSERT(OBJ_IS_NATIVE(obj)); if (!js_LookupHiddenProperty(cx, obj, ATOM_TO_JSID(atom), &pobj, &prop)) { return JS_FALSE; } } ok = JS_TRUE; getter = data->u.var.getter; setter = data->u.var.setter; if (prop && pobj == obj && OBJ_IS_NATIVE(pobj)) { sprop = (JSScopeProperty *)prop; if (sprop->getter == js_GetArgument) { name = js_AtomToPrintableString(cx, atom); if (!name) { ok = JS_FALSE; } else if (op == JSOP_DEFCONST) { js_ReportCompileErrorNumber(cx, BIND_DATA_REPORT_ARGS(data, JSREPORT_ERROR), JSMSG_REDECLARED_PARAM, name); ok = JS_FALSE; } else { getter = js_GetArgument; setter = js_SetArgument; ok = js_ReportCompileErrorNumber(cx, BIND_DATA_REPORT_ARGS(data, JSREPORT_WARNING | JSREPORT_STRICT), JSMSG_VAR_HIDES_ARG, name); } } else { JS_ASSERT(getter == js_GetLocalVariable); if (fun) { /* Not an argument, must be a redeclared local var. */ if (data->u.var.clasp == &js_FunctionClass) { JS_ASSERT(sprop->getter == js_GetLocalVariable); JS_ASSERT((sprop->flags & SPROP_HAS_SHORTID) && (uint16) sprop->shortid < fun->u.i.nvars); } else if (data->u.var.clasp == &js_CallClass) { if (sprop->getter == js_GetCallVariable) { /* * Referencing a name introduced by a var statement in * the enclosing function. Check that the slot number * we have is in range. */ JS_ASSERT((sprop->flags & SPROP_HAS_SHORTID) && (uint16) sprop->shortid < fun->u.i.nvars); } else { /* * A variable introduced through another eval: don't * use the special getters and setters since we can't * allocate a slot in the frame. */ getter = sprop->getter; setter = sprop->setter; } } /* Override the old getter and setter, to handle eval. */ sprop = js_ChangeNativePropertyAttrs(cx, obj, sprop, 0, sprop->attrs, getter, setter); if (!sprop) ok = JS_FALSE; } } if (prop) OBJ_DROP_PROPERTY(cx, pobj, prop); } else { /* * Property not found in current variable scope: we have not seen this * variable before. Define a new local variable by adding a property * to the function's scope, allocating one slot in the function's vars * frame. Global variables and any locals declared in with statement * bodies are handled at runtime, by script prolog JSOP_DEFVAR opcodes * generated for slot-less vars. */ sprop = NULL; if (prop) { OBJ_DROP_PROPERTY(cx, pobj, prop); prop = NULL; } if (cx->fp->scopeChain == obj && !js_InWithStatement(tc) && !BindLocalVariable(cx, data, atom)) { return JS_FALSE; } } return ok;}#if JS_HAS_DESTRUCTURINGstatic JSBoolBindDestructuringVar(JSContext *cx, BindData *data, JSParseNode *pn, JSTreeContext *tc){ JSAtom *atom; /* * Destructuring is a form of assignment, so just as for an initialized * simple variable, we must check for assignment to 'arguments' and flag * the enclosing function (if any) as heavyweight. */ JS_ASSERT(pn->pn_type == TOK_NAME); atom = pn->pn_atom; if (atom == cx->runtime->atomState.argumentsAtom) tc->flags |= TCF_FUN_HEAVYWEIGHT; data->pn = pn; if (!data->binder(cx, data, atom, tc)) return JS_FALSE; data->pn = NULL; /* * Select the appropriate name-setting opcode, which may be specialized * further for local variable and argument slot optimizations. At this * point, we can't select the optimal final opcode, yet we must preserve * the CONST bit and convey "set", not "get". */ pn->pn_op = (data->op == JSOP_DEFCONST) ? JSOP_SETCONST : JSOP_SETNAME; pn->pn_attrs = data->u.var.attrs; return JS_TRUE;}/* * Here, we are destructuring {... P: Q, ...} = R, where P is any id, Q is any * LHS expression except a destructuring initialiser, and R is on the stack. * Because R is already evaluated, the usual LHS-specialized bytecodes won't * work. After pushing R[P] we need to evaluate Q's "reference base" QB and * then push its property name QN. At this point the stack looks like * * [... R, R[P], QB, QN] * * We need to set QB[QN] = R[P]. This is a job for JSOP_ENUMELEM, which takes * its operands with left-hand side above right-hand side: * * [rval, lval, xval] * * and pops all three values, setting lval[xval] = rval. But we cannot select * JSOP_ENUMELEM yet, because the LHS may turn out to be an arg or local var, * which can be optimized further. So we select JSOP_SETNAME. */static JSBoolBindDestructuringLHS(JSContext *cx, JSParseNode *pn, JSTreeContext *tc){ while (pn->pn_t
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -