use of org.mozilla.javascript.ast.ScriptNode in project hackpad by dropbox.
the class Context method compileImpl.
private Object compileImpl(Scriptable scope, Reader sourceReader, String sourceString, String sourceName, int lineno, Object securityDomain, boolean returnFunction, Evaluator compiler, ErrorReporter compilationErrorReporter) throws IOException {
if (sourceName == null) {
sourceName = "unnamed script";
}
if (securityDomain != null && getSecurityController() == null) {
throw new IllegalArgumentException("securityDomain should be null if setSecurityController() was never called");
}
// One of sourceReader or sourceString has to be null
if (!(sourceReader == null ^ sourceString == null))
Kit.codeBug();
// scope should be given if and only if compiling function
if (!(scope == null ^ returnFunction))
Kit.codeBug();
CompilerEnvirons compilerEnv = new CompilerEnvirons();
compilerEnv.initFromContext(this);
if (compilationErrorReporter == null) {
compilationErrorReporter = compilerEnv.getErrorReporter();
}
if (debugger != null) {
if (sourceReader != null) {
sourceString = Kit.readReader(sourceReader);
sourceReader = null;
}
}
Parser p = new Parser(compilerEnv, compilationErrorReporter);
if (returnFunction) {
p.calledByCompileFunction = true;
}
AstRoot ast;
if (sourceString != null) {
ast = p.parse(sourceString, sourceName, lineno);
} else {
ast = p.parse(sourceReader, sourceName, lineno);
}
if (returnFunction) {
// parser no longer adds function to script node
if (!(ast.getFirstChild() != null && ast.getFirstChild().getType() == Token.FUNCTION)) {
// with sources like function() {};;;
throw new IllegalArgumentException("compileFunction only accepts source with single JS function: " + sourceString);
}
}
IRFactory irf = new IRFactory(compilerEnv, compilationErrorReporter);
ScriptNode tree = irf.transformTree(ast);
// discard everything but the IR tree
p = null;
ast = null;
irf = null;
if (compiler == null) {
compiler = createCompiler();
}
Object bytecode = compiler.compile(compilerEnv, tree, tree.getEncodedSource(), returnFunction);
if (debugger != null) {
if (sourceString == null)
Kit.codeBug();
if (bytecode instanceof DebuggableScript) {
DebuggableScript dscript = (DebuggableScript) bytecode;
notifyDebugger_r(this, dscript, sourceString);
} else {
throw new RuntimeException("NOT SUPPORTED");
}
}
Object result;
if (returnFunction) {
result = compiler.createFunctionObject(this, scope, bytecode, securityDomain);
} else {
result = compiler.createScriptObject(bytecode, securityDomain);
}
return result;
}
use of org.mozilla.javascript.ast.ScriptNode in project hackpad by dropbox.
the class Node method toStringTreeHelper.
private static void toStringTreeHelper(ScriptNode treeTop, Node n, ObjToIntMap printIds, int level, StringBuffer sb) {
if (Token.printTrees) {
if (printIds == null) {
printIds = new ObjToIntMap();
generatePrintIds(treeTop, printIds);
}
for (int i = 0; i != level; ++i) {
sb.append(" ");
}
n.toString(printIds, sb);
sb.append('\n');
for (Node cursor = n.getFirstChild(); cursor != null; cursor = cursor.getNext()) {
if (cursor.getType() == Token.FUNCTION) {
int fnIndex = cursor.getExistingIntProp(Node.FUNCTION_PROP);
FunctionNode fn = treeTop.getFunctionNode(fnIndex);
toStringTreeHelper(fn, fn, null, level + 1, sb);
} else {
toStringTreeHelper(treeTop, cursor, printIds, level + 1, sb);
}
}
}
}
use of org.mozilla.javascript.ast.ScriptNode in project hackpad by dropbox.
the class ClassCompiler method compileToClassFiles.
/**
* Compile JavaScript source into one or more Java class files.
* The first compiled class will have name mainClassName.
* If the results of {@link #getTargetExtends()} or
* {@link #getTargetImplements()} are not null, then the first compiled
* class will extend the specified super class and implement
* specified interfaces.
*
* @return array where elements with even indexes specifies class name
* and the following odd index gives class file body as byte[]
* array. The initial element of the array always holds
* mainClassName and array[1] holds its byte code.
*/
public Object[] compileToClassFiles(String source, String sourceLocation, int lineno, String mainClassName) {
Parser p = new Parser(compilerEnv);
AstRoot ast = p.parse(source, sourceLocation, lineno);
IRFactory irf = new IRFactory(compilerEnv);
ScriptNode tree = irf.transformTree(ast);
// release reference to original parse tree & parser
irf = null;
ast = null;
p = null;
Class<?> superClass = getTargetExtends();
Class<?>[] interfaces = getTargetImplements();
String scriptClassName;
boolean isPrimary = (interfaces == null && superClass == null);
if (isPrimary) {
scriptClassName = mainClassName;
} else {
scriptClassName = makeAuxiliaryClassName(mainClassName, "1");
}
Codegen codegen = new Codegen();
codegen.setMainMethodClass(mainMethodClassName);
byte[] scriptClassBytes = codegen.compileToClassFile(compilerEnv, scriptClassName, tree, tree.getEncodedSource(), false);
if (isPrimary) {
return new Object[] { scriptClassName, scriptClassBytes };
}
int functionCount = tree.getFunctionCount();
ObjToIntMap functionNames = new ObjToIntMap(functionCount);
for (int i = 0; i != functionCount; ++i) {
FunctionNode ofn = tree.getFunctionNode(i);
String name = ofn.getName();
if (name != null && name.length() != 0) {
functionNames.put(name, ofn.getParamCount());
}
}
if (superClass == null) {
superClass = ScriptRuntime.ObjectClass;
}
byte[] mainClassBytes = JavaAdapter.createAdapterCode(functionNames, mainClassName, superClass, interfaces, scriptClassName);
return new Object[] { mainClassName, mainClassBytes, scriptClassName, scriptClassBytes };
}
use of org.mozilla.javascript.ast.ScriptNode in project hackpad by dropbox.
the class BodyCodegen method emitRegExpInit.
private void emitRegExpInit(ClassFileWriter cfw) {
// precompile all regexp literals
int totalRegCount = 0;
for (int i = 0; i != scriptOrFnNodes.length; ++i) {
totalRegCount += scriptOrFnNodes[i].getRegexpCount();
}
if (totalRegCount == 0) {
return;
}
cfw.startMethod(REGEXP_INIT_METHOD_NAME, REGEXP_INIT_METHOD_SIGNATURE, (short) (ClassFileWriter.ACC_STATIC | ClassFileWriter.ACC_PRIVATE | ClassFileWriter.ACC_SYNCHRONIZED));
cfw.addField("_reInitDone", "Z", (short) (ClassFileWriter.ACC_STATIC | ClassFileWriter.ACC_PRIVATE));
cfw.add(ByteCode.GETSTATIC, mainClassName, "_reInitDone", "Z");
int doInit = cfw.acquireLabel();
cfw.add(ByteCode.IFEQ, doInit);
cfw.add(ByteCode.RETURN);
cfw.markLabel(doInit);
for (int i = 0; i != scriptOrFnNodes.length; ++i) {
ScriptNode n = scriptOrFnNodes[i];
int regCount = n.getRegexpCount();
for (int j = 0; j != regCount; ++j) {
String reFieldName = getCompiledRegexpName(n, j);
String reFieldType = "Ljava/lang/Object;";
String reString = n.getRegexpString(j);
String reFlags = n.getRegexpFlags(j);
cfw.addField(reFieldName, reFieldType, (short) (ClassFileWriter.ACC_STATIC | ClassFileWriter.ACC_PRIVATE));
// proxy
cfw.addALoad(0);
// context
cfw.addALoad(1);
cfw.addPush(reString);
if (reFlags == null) {
cfw.add(ByteCode.ACONST_NULL);
} else {
cfw.addPush(reFlags);
}
cfw.addInvoke(ByteCode.INVOKEINTERFACE, "org/mozilla/javascript/RegExpProxy", "compileRegExp", "(Lorg/mozilla/javascript/Context;" + "Ljava/lang/String;Ljava/lang/String;" + ")Ljava/lang/Object;");
cfw.add(ByteCode.PUTSTATIC, mainClassName, reFieldName, reFieldType);
}
}
cfw.addPush(1);
cfw.add(ByteCode.PUTSTATIC, mainClassName, "_reInitDone", "Z");
cfw.add(ByteCode.RETURN);
cfw.stopMethod((short) 2);
}
use of org.mozilla.javascript.ast.ScriptNode in project HL4A by HL4A.
the class BodyCodegen method generateResumeGenerator.
// How dispatch to generators works:
// Two methods are generated corresponding to a user-written generator.
// One of these creates a generator object (NativeGenerator), which is
// returned to the user. The other method contains all of the body code
// of the generator.
// When a user calls a generator, the call() method dispatches control to
// to the method that creates the NativeGenerator object. Subsequently when
// the user invokes .next(), .send() or any such method on the generator
// object, the resumeGenerator() below dispatches the call to the
// method corresponding to the generator body. As a matter of convention
// the generator body is given the name of the generator activation function
// appended by "_gen".
private void generateResumeGenerator(ClassFileWriter cfw) {
boolean hasGenerators = false;
for (int i = 0; i < scriptOrFnNodes.length; i++) {
if (isGenerator(scriptOrFnNodes[i]))
hasGenerators = true;
}
// resumeGenerator(). The base class provides a default implementation.
if (!hasGenerators)
return;
cfw.startMethod("resumeGenerator", "(Lorg/mozilla/javascript/Context;" + "Lorg/mozilla/javascript/Scriptable;" + "ILjava/lang/Object;" + "Ljava/lang/Object;)Ljava/lang/Object;", (short) (ACC_PUBLIC | ACC_FINAL));
// load arguments for dispatch to the corresponding *_gen method
cfw.addALoad(0);
cfw.addALoad(1);
cfw.addALoad(2);
cfw.addALoad(4);
cfw.addALoad(5);
cfw.addILoad(3);
cfw.addLoadThis();
cfw.add(ByteCode.GETFIELD, cfw.getClassName(), ID_FIELD_NAME, "I");
int startSwitch = cfw.addTableSwitch(0, scriptOrFnNodes.length - 1);
cfw.markTableSwitchDefault(startSwitch);
int endlabel = cfw.acquireLabel();
for (int i = 0; i < scriptOrFnNodes.length; i++) {
ScriptNode n = scriptOrFnNodes[i];
cfw.markTableSwitchCase(startSwitch, i, (short) 6);
if (isGenerator(n)) {
String type = "(" + mainClassSignature + "Lorg/mozilla/javascript/Context;" + "Lorg/mozilla/javascript/Scriptable;" + "Ljava/lang/Object;" + "Ljava/lang/Object;I)Ljava/lang/Object;";
cfw.addInvoke(ByteCode.INVOKESTATIC, mainClassName, getBodyMethodName(n) + "_gen", type);
cfw.add(ByteCode.ARETURN);
} else {
cfw.add(ByteCode.GOTO, endlabel);
}
}
cfw.markLabel(endlabel);
pushUndefined(cfw);
cfw.add(ByteCode.ARETURN);
// this method uses as many locals as there are arguments (hence 6)
cfw.stopMethod((short) 6);
}
Aggregations