mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Fix closed-name analysis in with-statements (bug 593556, r=brendan).
--HG-- extra : rebase_source : 3ca35ee12087fe262ec147d571900fb94e809979
This commit is contained in:
parent
e9ec6c1765
commit
2804cac937
@ -2124,6 +2124,7 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
||||
*/
|
||||
if (cg->compileAndGo() &&
|
||||
cg->compiler()->globalScope->globalObj &&
|
||||
!pn->isDeoptimized() &&
|
||||
!(cg->flags & TCF_STRICT_MODE_CODE)) {
|
||||
switch (op) {
|
||||
case JSOP_NAME: op = JSOP_GETGNAME; break;
|
||||
|
@ -3601,6 +3601,7 @@ BindVarOrConst(JSContext *cx, BindData *data, JSAtom *atom, JSTreeContext *tc)
|
||||
|
||||
if (stmt && stmt->type == STMT_WITH) {
|
||||
data->fresh = false;
|
||||
pn->pn_dflags |= PND_DEOPTIMIZED;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -8503,78 +8504,79 @@ Parser::primaryExpr(TokenKind tt, JSBool afterDot)
|
||||
#endif
|
||||
) && !(tc->flags & TCF_DECL_DESTRUCTURING)) {
|
||||
JSStmtInfo *stmt = js_LexicalLookup(tc, pn->pn_atom, NULL);
|
||||
if (!stmt || stmt->type != STMT_WITH) {
|
||||
JSDefinition *dn;
|
||||
|
||||
JSAtomListElement *ale = tc->decls.lookup(pn->pn_atom);
|
||||
if (ale) {
|
||||
dn = ALE_DEFN(ale);
|
||||
JSDefinition *dn;
|
||||
|
||||
JSAtomListElement *ale = tc->decls.lookup(pn->pn_atom);
|
||||
if (ale) {
|
||||
dn = ALE_DEFN(ale);
|
||||
#if JS_HAS_BLOCK_SCOPE
|
||||
/*
|
||||
* Skip out-of-scope let bindings along an ALE list or hash
|
||||
* chain. These can happen due to |let (x = x) x| block and
|
||||
* expression bindings, where the x on the right of = comes
|
||||
* from an outer scope. See bug 496532.
|
||||
*/
|
||||
while (dn->isLet() && !BlockIdInScope(dn->pn_blockid, tc)) {
|
||||
do {
|
||||
ale = ALE_NEXT(ale);
|
||||
} while (ale && ALE_ATOM(ale) != pn->pn_atom);
|
||||
if (!ale)
|
||||
break;
|
||||
dn = ALE_DEFN(ale);
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* Skip out-of-scope let bindings along an ALE list or hash
|
||||
* chain. These can happen due to |let (x = x) x| block and
|
||||
* expression bindings, where the x on the right of = comes
|
||||
* from an outer scope. See bug 496532.
|
||||
*/
|
||||
while (dn->isLet() && !BlockIdInScope(dn->pn_blockid, tc)) {
|
||||
do {
|
||||
ale = ALE_NEXT(ale);
|
||||
} while (ale && ALE_ATOM(ale) != pn->pn_atom);
|
||||
if (!ale)
|
||||
break;
|
||||
dn = ALE_DEFN(ale);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (ale) {
|
||||
dn = ALE_DEFN(ale);
|
||||
} else {
|
||||
ale = tc->lexdeps.lookup(pn->pn_atom);
|
||||
if (ale) {
|
||||
dn = ALE_DEFN(ale);
|
||||
} else {
|
||||
ale = tc->lexdeps.lookup(pn->pn_atom);
|
||||
if (ale) {
|
||||
dn = ALE_DEFN(ale);
|
||||
} else {
|
||||
/*
|
||||
* No definition before this use in any lexical scope.
|
||||
* Add a mapping in tc->lexdeps from pn->pn_atom to a
|
||||
* new node for the forward-referenced definition. This
|
||||
* placeholder definition node will be adopted when we
|
||||
* parse the real defining declaration form, or left as
|
||||
* a free variable definition if we never see the real
|
||||
* definition.
|
||||
*/
|
||||
ale = MakePlaceholder(pn, tc);
|
||||
if (!ale)
|
||||
return NULL;
|
||||
dn = ALE_DEFN(ale);
|
||||
/*
|
||||
* No definition before this use in any lexical scope.
|
||||
* Add a mapping in tc->lexdeps from pn->pn_atom to a
|
||||
* new node for the forward-referenced definition. This
|
||||
* placeholder definition node will be adopted when we
|
||||
* parse the real defining declaration form, or left as
|
||||
* a free variable definition if we never see the real
|
||||
* definition.
|
||||
*/
|
||||
ale = MakePlaceholder(pn, tc);
|
||||
if (!ale)
|
||||
return NULL;
|
||||
dn = ALE_DEFN(ale);
|
||||
|
||||
/*
|
||||
* In case this is a forward reference to a function,
|
||||
* we pessimistically set PND_FUNARG if the next token
|
||||
* is not a left parenthesis.
|
||||
*
|
||||
* If the definition eventually parsed into dn is not a
|
||||
* function, this flag won't hurt, and if we do parse a
|
||||
* function with pn's name, then the PND_FUNARG flag is
|
||||
* necessary for safe context->display-based optimiza-
|
||||
* tion of the closure's static link.
|
||||
*/
|
||||
JS_ASSERT(PN_TYPE(dn) == TOK_NAME);
|
||||
JS_ASSERT(dn->pn_op == JSOP_NOP);
|
||||
if (tokenStream.peekToken() != TOK_LP)
|
||||
dn->pn_dflags |= PND_FUNARG;
|
||||
}
|
||||
/*
|
||||
* In case this is a forward reference to a function,
|
||||
* we pessimistically set PND_FUNARG if the next token
|
||||
* is not a left parenthesis.
|
||||
*
|
||||
* If the definition eventually parsed into dn is not a
|
||||
* function, this flag won't hurt, and if we do parse a
|
||||
* function with pn's name, then the PND_FUNARG flag is
|
||||
* necessary for safe context->display-based optimiza-
|
||||
* tion of the closure's static link.
|
||||
*/
|
||||
JS_ASSERT(PN_TYPE(dn) == TOK_NAME);
|
||||
JS_ASSERT(dn->pn_op == JSOP_NOP);
|
||||
if (tokenStream.peekToken() != TOK_LP)
|
||||
dn->pn_dflags |= PND_FUNARG;
|
||||
}
|
||||
|
||||
JS_ASSERT(dn->pn_defn);
|
||||
LinkUseToDef(pn, dn, tc);
|
||||
|
||||
/* Here we handle the backward function reference case. */
|
||||
if (tokenStream.peekToken() != TOK_LP)
|
||||
dn->pn_dflags |= PND_FUNARG;
|
||||
|
||||
pn->pn_dflags |= (dn->pn_dflags & PND_FUNARG);
|
||||
}
|
||||
|
||||
JS_ASSERT(dn->pn_defn);
|
||||
LinkUseToDef(pn, dn, tc);
|
||||
|
||||
/* Here we handle the backward function reference case. */
|
||||
if (tokenStream.peekToken() != TOK_LP)
|
||||
dn->pn_dflags |= PND_FUNARG;
|
||||
|
||||
pn->pn_dflags |= (dn->pn_dflags & PND_FUNARG);
|
||||
if (stmt && stmt->type == STMT_WITH)
|
||||
pn->pn_dflags |= PND_DEOPTIMIZED;
|
||||
}
|
||||
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
|
Loading…
Reference in New Issue
Block a user