我目前正在查看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
。
因此,当执行上述代码时,NullPointerException
为空,我在CodeGenerator.visitExpression(Node, int)
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 );
}
}
我无法看到这段代码是如何工作的。但与此同时,它是一个核心功能,我无法想象人们如何能够错过它6年。
[编辑] 我设法创建了一个测试用例:
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)
如果我运行这个,我会遇到这个例外:
<?php namespace App;
use Artisaninweb\SoapWrapper\Facades\SoapWrapper;
use Illuminate\Http\RedirectResponse;
class SoapController {
private $auth_response;
private $cookie;
private $search_client;
private $search_response;
public function soapExchange() {
// create SOAP client and add service details
SoapWrapper::add(function ($service) {
$service
->name('WoSAuthenticate')
->wsdl('http://search.webofknowledge.com/esti/wokmws/ws/WOKMWSAuthenticate?wsdl')
->trace(true)
->cache(WSDL_CACHE_NONE);
});
SoapWrapper::service('WoSAuthenticate', function($service) {
// call authenticate() method to get SID cookie
$auth_response = $service->call('authenticate', []);
$cookie = $auth_response->return;
// test for cookie return
// print($cookie);
});
// create SOAP client and add service details
$search_client = new SoapWrapper;
$search_client::add(function ($service) {
$service
->name('WoSSearch')
->wsdl('http://search.webofknowledge.com/esti/wokmws/ws/WokSearch?wsdl')
->trace(true)
->cache(WSDL_CACHE_NONE);
});
if (isset($auth_response->return)) {
// if there is an SID returned then add it to the cookie attribute of the search client
$search_client->__setCookie('SID', $cookie);
} else {
// route to relevant view to display throttle error
return redirect('throttle');
}
}
}
答案 0 :(得分:1)
随着AST API的引入,代码生成需要一个额外的步骤来转换&#34; raw&#34;将树解析成适合codegen的东西。
要修复上面的测试用例,请更改以下行:
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);
中找到如何准备codegen的示例