CodeGenUtils.java
package org.mozilla.javascript;
import org.mozilla.javascript.ast.AstNode;
import org.mozilla.javascript.ast.AstRoot;
import org.mozilla.javascript.ast.Block;
import org.mozilla.javascript.ast.FunctionNode;
import org.mozilla.javascript.ast.Scope;
import org.mozilla.javascript.ast.ScriptNode;
/**
* Common utilities usable by all the compilers for populating {@link JSDescriptor.Builder} entries
* from IR nodes.
*/
public class CodeGenUtils {
/** Populates builder data for a nested function. */
public static void fillInForNestedFunction(
JSDescriptor.Builder<JSFunction> builder,
JSDescriptor.Builder<?> parent,
FunctionNode fn) {
final AstNode fnParent = fn.getParent();
if (!(fnParent instanceof AstRoot
|| fnParent instanceof Scope
|| fnParent instanceof Block)) {
builder.declaredAsFunctionExpression = true;
boolean isArrow = fn.getFunctionType() == FunctionNode.ARROW_FUNCTION;
builder.hasLexicalThis = isArrow;
builder.hasPrototype = !isArrow;
if (!isArrow) {
builder.constructor = builder.code;
} else {
builder.constructor = new JSCode.NullBuilder<JSFunction>();
}
} else {
builder.hasLexicalThis = false;
builder.hasPrototype = true;
builder.constructor = builder.code;
}
fillInForFunction(builder, fn);
}
private static void fillInForFunction(JSDescriptor.Builder builder, FunctionNode fn) {
builder.functionType = fn.getFunctionType();
builder.requiresActivationFrame = fn.requiresActivation();
builder.requiresArgumentObject = fn.requiresArgumentObject();
if (fn.getFunctionName() != null) {
builder.name = fn.getName();
}
if (fn.isInStrictMode()) {
builder.isStrict = true;
}
if (fn.isES6Generator()) {
builder.isES6Generator = true;
}
if (fn.isShorthand()) {
builder.isShorthand = true;
}
fillInCommon(builder, fn);
}
/** Populate builder data for a top level function. */
public static void fillInForTopLevelFunction(
JSDescriptor.Builder builder,
FunctionNode fn,
String rawSource,
CompilerEnvirons compilerEnv) {
builder.hasPrototype = true;
fillInTopLevelCommon(builder, fn, rawSource, compilerEnv);
fillInForFunction(builder, fn);
}
/** Populate builder data for a top level script. */
public static void fillInForScript(
JSDescriptor.Builder builder,
ScriptNode scriptOrFn,
String rawSource,
CompilerEnvirons compilerEnv) {
builder.hasPrototype = false;
fillInTopLevelCommon(builder, scriptOrFn, rawSource, compilerEnv);
fillInCommon(builder, scriptOrFn);
}
private static void fillInTopLevelCommon(
JSDescriptor.Builder builder,
ScriptNode scriptOrFn,
String rawSource,
CompilerEnvirons compilerEnv) {
builder.sourceFile = scriptOrFn.getSourceName();
builder.rawSource = rawSource;
builder.isTopLevel = true;
builder.isScript = true;
builder.isEvalFunction = compilerEnv.isInEval();
builder.isStrict = scriptOrFn.isInStrictMode();
builder.hasLexicalThis = false;
builder.securityController = compilerEnv.securityController();
builder.securityDomain = compilerEnv.securityDomain();
}
private static void fillInCommon(JSDescriptor.Builder builder, ScriptNode scriptOrFn) {
builder.paramAndVarNames = scriptOrFn.getParamAndVarNames();
builder.paramCount = scriptOrFn.getParamCount();
builder.paramIsConst = scriptOrFn.getParamAndVarConst();
builder.paramAndVarCount = scriptOrFn.getParamAndVarCount();
builder.hasRestArg = scriptOrFn.hasRestParameter();
builder.hasDefaultParameters = scriptOrFn.getDefaultParams() != null;
builder.rawSourceStart = scriptOrFn.getRawSourceStart();
builder.rawSourceEnd = scriptOrFn.getRawSourceEnd();
}
/** Configure the constructor appropriately based on a function's type. */
public static <T extends ScriptOrFn<T>> void setConstructor(
JSDescriptor.Builder<T> builder, ScriptNode scriptOrFn) {
if (scriptOrFn instanceof FunctionNode) {
FunctionNode f = (FunctionNode) scriptOrFn;
boolean isArrow = f.getFunctionType() == FunctionNode.ARROW_FUNCTION;
if (isArrow || f.isMethodDefinition() || f.isGenerator()) {
builder.constructor = new JSCode.NullBuilder<T>();
} else {
builder.constructor = builder.code;
}
} else {
builder.constructor = new JSCode.NullBuilder<T>();
}
}
}