зеркало из https://github.com/mozilla/pjs.git
Fix bug 433878: minor glitch when decompiling 'let' statements
Once I ran this through the regression tests, this ended up being more complicated unfortunately. There was a missing error check all along, but the previous bug caused us to pass a negative test, so I had to implement that to get everything to pass.
This commit is contained in:
Родитель
fd7d590887
Коммит
f463a7b1ac
|
@ -1412,7 +1412,7 @@ final class IRFactory
|
|||
createName(Token.NAME, tempName, right)));
|
||||
try {
|
||||
parser.pushScope(result);
|
||||
parser.defineSymbol(Token.LET, tempName);
|
||||
parser.defineSymbol(Token.LET, true, tempName);
|
||||
} finally {
|
||||
parser.popScope();
|
||||
}
|
||||
|
@ -1447,7 +1447,7 @@ final class IRFactory
|
|||
createName(Token.BINDNAME, name, null),
|
||||
rightElem));
|
||||
if (variableType != -1) {
|
||||
parser.defineSymbol(variableType, name);
|
||||
parser.defineSymbol(variableType, true, name);
|
||||
destructuringNames.add(name);
|
||||
}
|
||||
} else {
|
||||
|
@ -1480,7 +1480,7 @@ final class IRFactory
|
|||
createName(Token.BINDNAME, name, null),
|
||||
rightElem));
|
||||
if (variableType != -1) {
|
||||
parser.defineSymbol(variableType, name);
|
||||
parser.defineSymbol(variableType, true, name);
|
||||
destructuringNames.add(name);
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -518,7 +518,7 @@ public class Parser
|
|||
name.length() > 0)
|
||||
{
|
||||
// Function statements define a symbol in the enclosing scope
|
||||
defineSymbol(Token.FUNCTION, name);
|
||||
defineSymbol(Token.FUNCTION, false, name);
|
||||
}
|
||||
|
||||
boolean nested = insideFunction();
|
||||
|
@ -571,14 +571,14 @@ public class Parser
|
|||
destructuring = new Node(Token.COMMA);
|
||||
}
|
||||
String parmName = currentScriptOrFn.getNextTempName();
|
||||
defineSymbol(Token.LP, parmName);
|
||||
defineSymbol(Token.LP, false, parmName);
|
||||
destructuring.addChildToBack(
|
||||
nf.createDestructuringAssignment(Token.VAR,
|
||||
primaryExpr(), nf.createName(parmName)));
|
||||
} else {
|
||||
mustMatchToken(Token.NAME, "msg.no.parm");
|
||||
String s = ts.getString();
|
||||
defineSymbol(Token.LP, s);
|
||||
defineSymbol(Token.LP, false, s);
|
||||
decompiler.addName(s);
|
||||
}
|
||||
} while (matchToken(Token.COMMA));
|
||||
|
@ -608,7 +608,7 @@ public class Parser
|
|||
{
|
||||
// Function expressions define a name only in the body of the
|
||||
// function, and only if not hidden by a parameter name
|
||||
defineSymbol(Token.FUNCTION, name);
|
||||
defineSymbol(Token.FUNCTION, false, name);
|
||||
}
|
||||
|
||||
decompiler.addToken(Token.RC);
|
||||
|
@ -1113,11 +1113,13 @@ public class Parser
|
|||
consumeToken();
|
||||
decompiler.addToken(Token.LET);
|
||||
if (peekToken() == Token.LP) {
|
||||
pn = let(true);
|
||||
return let(true);
|
||||
} else {
|
||||
pn = variables(false, tt);
|
||||
if (peekToken() == Token.SEMI)
|
||||
break;
|
||||
return pn;
|
||||
}
|
||||
return pn;
|
||||
}
|
||||
|
||||
case Token.RETURN:
|
||||
|
@ -1383,7 +1385,7 @@ public class Parser
|
|||
first = false;
|
||||
|
||||
decompiler.addName(s);
|
||||
defineSymbol(declType, s);
|
||||
defineSymbol(declType, inFor, s);
|
||||
}
|
||||
|
||||
Node init = null;
|
||||
|
@ -1450,7 +1452,7 @@ public class Parser
|
|||
return result;
|
||||
}
|
||||
|
||||
void defineSymbol(int declType, String name) {
|
||||
void defineSymbol(int declType, boolean ignoreNotInBlock, String name) {
|
||||
Node.Scope definingScope = currentScope.getDefiningScope(name);
|
||||
Node.Scope.Symbol symbol = definingScope != null
|
||||
? definingScope.getSymbol(name)
|
||||
|
@ -1466,6 +1468,13 @@ public class Parser
|
|||
if (symbol != null && definingScope == currentScope) {
|
||||
error = symbol.declType == Token.LET;
|
||||
}
|
||||
int currentScopeType = currentScope.getType();
|
||||
if (!ignoreNotInBlock &&
|
||||
((currentScopeType == Token.LOOP) ||
|
||||
(currentScopeType == Token.IF)))
|
||||
{
|
||||
addError("msg.let.decl.not.in.block");
|
||||
}
|
||||
currentScope.putSymbol(name,
|
||||
new Node.Scope.Symbol(declType, name));
|
||||
break;
|
||||
|
@ -2158,7 +2167,7 @@ public class Parser
|
|||
if (tt == Token.LB || tt == Token.LC) {
|
||||
// handle destructuring assignment
|
||||
name = currentScriptOrFn.getNextTempName();
|
||||
defineSymbol(Token.LP, name);
|
||||
defineSymbol(Token.LP, false, name);
|
||||
expr = nf.createBinary(Token.COMMA,
|
||||
nf.createAssignment(Token.ASSIGN, primaryExpr(),
|
||||
nf.createName(name)),
|
||||
|
@ -2175,7 +2184,7 @@ public class Parser
|
|||
Node init = nf.createName(name);
|
||||
// Define as a let since we want the scope of the variable to
|
||||
// be restricted to the array comprehension
|
||||
defineSymbol(Token.LET, name);
|
||||
defineSymbol(Token.LET, false, name);
|
||||
|
||||
mustMatchToken(Token.IN, "msg.in.after.for.name");
|
||||
decompiler.addToken(Token.IN);
|
||||
|
@ -2263,7 +2272,7 @@ public class Parser
|
|||
String tempName = currentScriptOrFn.getNextTempName();
|
||||
pushScope(scopeNode);
|
||||
try {
|
||||
defineSymbol(Token.LET, tempName);
|
||||
defineSymbol(Token.LET, false, tempName);
|
||||
Node expr = (Node) elems.get(0);
|
||||
Node block = nf.createBlock(ts.getLineno());
|
||||
Node init = new Node(Token.EXPR_VOID,
|
||||
|
|
|
@ -272,13 +272,16 @@ msg.const.redecl =\
|
|||
|
||||
msg.let.redecl =\
|
||||
TypeError: redeclaration of variable {0}.
|
||||
|
||||
|
||||
msg.parm.redecl =\
|
||||
TypeError: redeclaration of formal parameter {0}.
|
||||
|
||||
msg.fn.redecl =\
|
||||
TypeError: redeclaration of function {0}.
|
||||
|
||||
msg.let.decl.not.in.block =\
|
||||
SyntaxError: let declaration not directly within block
|
||||
|
||||
# NodeTransformer
|
||||
msg.dup.label =\
|
||||
duplicated label
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
js> version(170)
|
||||
0
|
||||
js> function f(a,b,c) {
|
||||
> let sum = a + b + c;
|
||||
> return sum / 3;
|
||||
> }
|
||||
js> f.toString()
|
||||
|
||||
function f(a, b, c) {
|
||||
let sum = a + b + c;
|
||||
return sum / 3;
|
||||
}
|
||||
|
||||
js> try {
|
||||
> eval("function f() { for (;;) let a=3; return 3; }");
|
||||
> } catch (e) {
|
||||
> e;
|
||||
> }
|
||||
SyntaxError: SyntaxError: let declaration not directly within block
|
Загрузка…
Ссылка в новой задаче