rhino CodeGenerator Token.EXPR_RESULT 中的错误?
Bug in rhino CodeGenerator Token.EXPR_RESULT?
我目前正在查看 Rhino 1.7.5 和 1.7.6 的代码。
在 CodeGenerator.java
中是这个代码 (line 380+):
case Token.EXPR_VOID:
case Token.EXPR_RESULT:
updateLineNumber(node);
visitExpression(child, 0);
addIcode((type == Token.EXPR_VOID) ? Icode_POP : Icode_POP_RESULT);
stackChange(-1);
break;
child
是 (line 232):
Node child = node.getFirstChild();
ExpressionStatement
是触发上面case
的节点
但它从不调用 addChildToBack()
将 first
设置为任何值。
所以当上面的代码执行时,child
为 null,我在 CodeGenerator.visitExpression(Node, int)
中得到一个 NullPointerException
我看不出这段代码是如何工作的。但与此同时,它是如此核心的功能,我无法想象人们怎么会错过它 6 年。
[编辑] 我设法创建了一个测试用例:
import static org.junit.Assert.*;
import org.junit.Test;
import org.mozilla.javascript.CompilerEnvirons;
import org.mozilla.javascript.Interpreter;
import org.mozilla.javascript.Parser;
import org.mozilla.javascript.ast.ScriptNode;
public class RhinoTest {
@Test
public void testCompileExpression() throws Exception {
String expression = "row[\"COL_Col1\"]";
CompilerEnvirons compilerEnv = new CompilerEnvirons();
Parser p = new Parser( compilerEnv, compilerEnv.getErrorReporter() );
ScriptNode script = p.parse( expression, null, 0 );
Interpreter compiler = new Interpreter( );
Object compiledOb = compiler.compile( compilerEnv, script, null, false );
assertNotNull( compiledOb );
}
}
如果我运行这个,我得到这个异常:
java.lang.NullPointerException
at org.mozilla.javascript.CodeGenerator.visitExpression(CodeGenerator.java:497)
at org.mozilla.javascript.CodeGenerator.visitStatement(CodeGenerator.java:383)
at org.mozilla.javascript.CodeGenerator.visitStatement(CodeGenerator.java:276)
at org.mozilla.javascript.CodeGenerator.generateICodeFromTree(CodeGenerator.java:113)
at org.mozilla.javascript.CodeGenerator.compile(CodeGenerator.java:83)
at org.mozilla.javascript.Interpreter.compile(Interpreter.java:194)
at com.avanon.basic.birt.RhinoTest.testCompileExpression(RhinoTest.java:21)
随着 AST API 的引入,代码生成需要一个额外的步骤来将 "raw" 解析树转换为适合代码生成的东西。
要修复上面的测试用例,请更改行:
ScriptNode script = p.parse( expression, null, 0 );
进入:
ScriptNode ast = p.parse( expression, null, 0 );
IRFactory irf = new IRFactory(compilerEnv, compilerEnv.getErrorReporter());
ScriptNode tree = irf.transformTree(ast);
您还可以在 Context.compileImpl()
中找到如何准备 codegen 的示例
我目前正在查看 Rhino 1.7.5 和 1.7.6 的代码。
在 CodeGenerator.java
中是这个代码 (line 380+):
case Token.EXPR_VOID:
case Token.EXPR_RESULT:
updateLineNumber(node);
visitExpression(child, 0);
addIcode((type == Token.EXPR_VOID) ? Icode_POP : Icode_POP_RESULT);
stackChange(-1);
break;
child
是 (line 232):
Node child = node.getFirstChild();
ExpressionStatement
是触发上面case
的节点
但它从不调用 addChildToBack()
将 first
设置为任何值。
所以当上面的代码执行时,child
为 null,我在 CodeGenerator.visitExpression(Node, int)
NullPointerException
我看不出这段代码是如何工作的。但与此同时,它是如此核心的功能,我无法想象人们怎么会错过它 6 年。
[编辑] 我设法创建了一个测试用例:
import static org.junit.Assert.*;
import org.junit.Test;
import org.mozilla.javascript.CompilerEnvirons;
import org.mozilla.javascript.Interpreter;
import org.mozilla.javascript.Parser;
import org.mozilla.javascript.ast.ScriptNode;
public class RhinoTest {
@Test
public void testCompileExpression() throws Exception {
String expression = "row[\"COL_Col1\"]";
CompilerEnvirons compilerEnv = new CompilerEnvirons();
Parser p = new Parser( compilerEnv, compilerEnv.getErrorReporter() );
ScriptNode script = p.parse( expression, null, 0 );
Interpreter compiler = new Interpreter( );
Object compiledOb = compiler.compile( compilerEnv, script, null, false );
assertNotNull( compiledOb );
}
}
如果我运行这个,我得到这个异常:
java.lang.NullPointerException
at org.mozilla.javascript.CodeGenerator.visitExpression(CodeGenerator.java:497)
at org.mozilla.javascript.CodeGenerator.visitStatement(CodeGenerator.java:383)
at org.mozilla.javascript.CodeGenerator.visitStatement(CodeGenerator.java:276)
at org.mozilla.javascript.CodeGenerator.generateICodeFromTree(CodeGenerator.java:113)
at org.mozilla.javascript.CodeGenerator.compile(CodeGenerator.java:83)
at org.mozilla.javascript.Interpreter.compile(Interpreter.java:194)
at com.avanon.basic.birt.RhinoTest.testCompileExpression(RhinoTest.java:21)
随着 AST API 的引入,代码生成需要一个额外的步骤来将 "raw" 解析树转换为适合代码生成的东西。
要修复上面的测试用例,请更改行:
ScriptNode script = p.parse( expression, null, 0 );
进入:
ScriptNode ast = p.parse( expression, null, 0 );
IRFactory irf = new IRFactory(compilerEnv, compilerEnv.getErrorReporter());
ScriptNode tree = irf.transformTree(ast);
您还可以在 Context.compileImpl()