Decouple JsProgram; this allows the JS AST to serialize in pieces.
1) A rethinking of how JsScope should work. Most notably, the JsRootScope is a singleton with special serialization. I also refactored bits and pieces of the JsScope hierarchy to get rid of fields and code that don't make sense for particular subclasses. And I broke serialization circular references (that pull in the whole world) by not having scopes serialize their children.
2) I got JsProgram out of the business of federating literals and singletons. This is much more like how the Java AST works now.
http://gwt-code-reviews.appspot.com/1342801/show
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@9683 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/javac/JsniCollector.java b/dev/core/src/com/google/gwt/dev/javac/JsniCollector.java
index 9decb5a..3888f9d 100644
--- a/dev/core/src/com/google/gwt/dev/javac/JsniCollector.java
+++ b/dev/core/src/com/google/gwt/dev/javac/JsniCollector.java
@@ -114,11 +114,6 @@
}
@Override
- public JsProgram program() {
- return func.getScope().getProgram();
- }
-
- @Override
public String toString() {
return func.toString();
}
@@ -251,8 +246,8 @@
int jsLine = info.getStartLine()
+ countLines(indexes, info.getStartPos(), absoluteJsStartPos);
- SourceInfo jsInfo = SourceOrigin.create(jsStartPos, jsEndPos, jsLine,
- info.getFileName());
+ SourceInfo jsInfo = jsProgram.createSourceInfo(jsStartPos, jsEndPos,
+ jsLine, info.getFileName());
try {
List<JsStatement> result = JsParser.parse(jsInfo, jsProgram.getScope(),
sr);
diff --git a/dev/core/src/com/google/gwt/dev/javac/JsniMethod.java b/dev/core/src/com/google/gwt/dev/javac/JsniMethod.java
index fd0c87b..616ff10 100644
--- a/dev/core/src/com/google/gwt/dev/javac/JsniMethod.java
+++ b/dev/core/src/com/google/gwt/dev/javac/JsniMethod.java
@@ -16,7 +16,6 @@
package com.google.gwt.dev.javac;
import com.google.gwt.dev.js.ast.JsFunction;
-import com.google.gwt.dev.js.ast.JsProgram;
/**
* Represents a single JsniMethod in a compiled class file.
@@ -53,9 +52,4 @@
* The parameter names.
*/
public abstract String[] paramNames();
-
- /**
- * Gets the JsProgram in which this method is located.
- */
- public abstract JsProgram program();
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/CorrelationFactory.java b/dev/core/src/com/google/gwt/dev/jjs/CorrelationFactory.java
index be0fbfb..b280c37 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/CorrelationFactory.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/CorrelationFactory.java
@@ -40,6 +40,16 @@
* A dummy factory that always returns <code>null</code>.
*/
public static final class DummyCorrelationFactory extends CorrelationFactory {
+ public static final CorrelationFactory INSTANCE = new DummyCorrelationFactory();
+
+ private DummyCorrelationFactory() {
+ }
+
+ @Override
+ public Correlation by(JDeclaredType type) {
+ return null;
+ }
+
@Override
public Correlation by(JField field) {
return null;
@@ -51,11 +61,6 @@
}
@Override
- public Correlation by(JDeclaredType type) {
- return null;
- }
-
- @Override
public Correlation by(JsFunction function) {
return null;
}
@@ -99,6 +104,8 @@
* public-API consumers of the Correlation.
*/
+ public static final CorrelationFactory INSTANCE = new RealCorrelationFactory();
+
/**
* Correlations based on Literals are all the same, so we'll just cook up a
* Map to make {@link #by(Literal)} fast.
@@ -108,8 +115,8 @@
static {
for (Literal l : Literal.values()) {
- LITERAL_CORRELATIONS.put(l, new Correlation(Axis.LITERAL,
- l.getDescription(), l));
+ LITERAL_CORRELATIONS.put(l,
+ new Correlation(Axis.LITERAL, l.getDescription(), l));
}
}
@@ -132,6 +139,19 @@
private final Map<Object, Correlation> canonicalMap = Collections.synchronizedMap(new ReferenceMap(
ReferenceMap.WEAK, ReferenceMap.WEAK));
+ private RealCorrelationFactory() {
+ }
+
+ @Override
+ public Correlation by(JDeclaredType type) {
+ Correlation toReturn = canonicalMap.get(type);
+ if (toReturn == null) {
+ toReturn = new Correlation(Axis.CLASS, type.getName(), type);
+ canonicalMap.put(type, toReturn);
+ }
+ return toReturn;
+ }
+
@Override
public Correlation by(JField field) {
Correlation toReturn = canonicalMap.get(field);
@@ -155,16 +175,6 @@
}
@Override
- public Correlation by(JDeclaredType type) {
- Correlation toReturn = canonicalMap.get(type);
- if (toReturn == null) {
- toReturn = new Correlation(Axis.CLASS, type.getName(), type);
- canonicalMap.put(type, toReturn);
- }
- return toReturn;
- }
-
- @Override
public Correlation by(JsFunction function) {
Correlation toReturn = canonicalMap.get(function);
if (toReturn == null) {
@@ -221,12 +231,12 @@
}
}
+ public abstract Correlation by(JDeclaredType type);
+
public abstract Correlation by(JField field);
public abstract Correlation by(JMethod method);
- public abstract Correlation by(JDeclaredType type);
-
public abstract Correlation by(JsFunction function);
public abstract Correlation by(JsName name);
diff --git a/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java b/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
index a50d4a1..13fce81 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
@@ -541,7 +541,7 @@
checkForErrors(logger, goldenCuds, false);
CorrelationFactory correlator = options.isSoycExtra()
- ? new RealCorrelationFactory() : new DummyCorrelationFactory();
+ ? RealCorrelationFactory.INSTANCE : DummyCorrelationFactory.INSTANCE;
JProgram jprogram = new JProgram(correlator);
JsProgram jsProgram = new JsProgram(correlator);
diff --git a/dev/core/src/com/google/gwt/dev/jjs/SourceInfo.java b/dev/core/src/com/google/gwt/dev/jjs/SourceInfo.java
index a34a2b0..ccaf1c4 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/SourceInfo.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/SourceInfo.java
@@ -49,6 +49,11 @@
*/
List<Correlation> getAllCorrelations(Axis axis);
+ /**
+ * Returns the correlation factory that created this node.
+ */
+ CorrelationFactory getCorrelationFactory();
+
int getEndPos();
String getFileName();
@@ -64,11 +69,11 @@
* has been set.
*/
Set<Correlation> getPrimaryCorrelations();
-
+
/**
* Returns the first Correlations added along each Axis on which a Correlation
- * has been set. Some entries may be null and should be ignored. The
- * returned array must not be modified.
+ * has been set. Some entries may be null and should be ignored. The returned
+ * array must not be modified.
*/
Correlation[] getPrimaryCorrelationsArray();
@@ -93,6 +98,13 @@
SourceInfo makeChild(Class<?> caller, String description, SourceInfo... merge);
/**
+ * Create a child node of the same type as this node, but with a new Origin.
+ * If data accumulation is enabled, the derived node will inherit its
+ * Correlations from this node.
+ */
+ SourceInfo makeChild(SourceOrigin origin);
+
+ /**
* Add additional ancestor SourceInfos. These SourceInfo objects indicate that
* a merge-type operation took place or that the additional ancestors have a
* containment relationship with the SourceInfo.
diff --git a/dev/core/src/com/google/gwt/dev/jjs/SourceInfoCorrelation.java b/dev/core/src/com/google/gwt/dev/jjs/SourceInfoCorrelation.java
index ab985f1..9176f89 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/SourceInfoCorrelation.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/SourceInfoCorrelation.java
@@ -16,6 +16,7 @@
package com.google.gwt.dev.jjs;
import com.google.gwt.dev.jjs.Correlation.Axis;
+import com.google.gwt.dev.jjs.CorrelationFactory.RealCorrelationFactory;
import java.io.Serializable;
import java.util.ArrayList;
@@ -36,7 +37,7 @@
* Micro-opt for {@link #makeChild(Class, String)}.
*/
private static final SourceInfo[] EMPTY_SOURCEINFO_ARRAY = new SourceInfo[0];
-
+
private static final int numCorrelationAxes = Axis.values().length;
private static int numCorrelationAxes() {
@@ -66,18 +67,17 @@
primaryCorrelations = new Correlation[numCorrelationAxes()];
}
+ private SourceInfoCorrelation(SourceInfoCorrelation parent,
+ SourceOrigin origin) {
+ this.origin = origin;
+ this.allCorrelations = new ArrayList<Correlation>(parent.allCorrelations);
+ primaryCorrelations = parent.primaryCorrelations.clone();
+ }
+
private SourceInfoCorrelation(SourceInfoCorrelation parent, String caller,
SourceInfo... additionalAncestors) {
- assert parent != null;
+ this(parent, parent.origin);
assert caller != null;
- this.origin = parent.origin;
-
- this.allCorrelations = new ArrayList<Correlation>(parent.allCorrelations);
- primaryCorrelations = new Correlation[numCorrelationAxes()];
- for (int i = 0; i < numCorrelationAxes(); i++) {
- primaryCorrelations[i] = parent.primaryCorrelations[i];
- }
-
merge(additionalAncestors);
}
@@ -134,6 +134,11 @@
return toReturn;
}
+ @Override
+ public CorrelationFactory getCorrelationFactory() {
+ return RealCorrelationFactory.INSTANCE;
+ }
+
public int getEndPos() {
return getOrigin().getEndPos();
}
@@ -167,7 +172,7 @@
}
return toReturn;
}
-
+
public Correlation[] getPrimaryCorrelationsArray() {
return primaryCorrelations;
}
@@ -202,6 +207,11 @@
return new SourceInfoCorrelation(this, callerName, merge);
}
+ @Override
+ public SourceInfo makeChild(SourceOrigin origin) {
+ return new SourceInfoCorrelation(this, origin);
+ }
+
/**
* Add additional ancestor SourceInfos. These SourceInfo objects indicate that
* a merge-type operation took place or that the additional ancestors have a
diff --git a/dev/core/src/com/google/gwt/dev/jjs/SourceOrigin.java b/dev/core/src/com/google/gwt/dev/jjs/SourceOrigin.java
index 5e666d7..555c503 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/SourceOrigin.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/SourceOrigin.java
@@ -16,6 +16,7 @@
package com.google.gwt.dev.jjs;
import com.google.gwt.dev.jjs.Correlation.Axis;
+import com.google.gwt.dev.jjs.CorrelationFactory.DummyCorrelationFactory;
import com.google.gwt.dev.util.StringInterner;
import java.util.Collections;
@@ -56,7 +57,7 @@
public int getStartPos() {
return startPos;
}
-
+
// super.equals and hashCode call getStartPos() and getEndPos(),
// so there is no need to implement them in this subclass
}
@@ -148,6 +149,11 @@
return Collections.emptyList();
}
+ @Override
+ public CorrelationFactory getCorrelationFactory() {
+ return DummyCorrelationFactory.INSTANCE;
+ }
+
public int getEndPos() {
return -1;
}
@@ -167,7 +173,7 @@
public Set<Correlation> getPrimaryCorrelations() {
return Collections.emptySet();
}
-
+
public Correlation[] getPrimaryCorrelationsArray() {
return new Correlation[0];
}
@@ -195,6 +201,11 @@
return this;
}
+ @Override
+ public SourceInfo makeChild(SourceOrigin origin) {
+ return origin;
+ }
+
public void merge(SourceInfo... sourceInfos) {
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java
index a4ca996..020c6d6 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java
@@ -15,11 +15,12 @@
*/
package com.google.gwt.dev.jjs.ast;
+import com.google.gwt.dev.jjs.Correlation.Literal;
import com.google.gwt.dev.jjs.CorrelationFactory;
+import com.google.gwt.dev.jjs.CorrelationFactory.DummyCorrelationFactory;
import com.google.gwt.dev.jjs.InternalCompilerException;
import com.google.gwt.dev.jjs.SourceInfo;
import com.google.gwt.dev.jjs.SourceOrigin;
-import com.google.gwt.dev.jjs.Correlation.Literal;
import com.google.gwt.dev.jjs.ast.JField.Disposition;
import com.google.gwt.dev.jjs.ast.js.JsniMethodBody;
import com.google.gwt.dev.jjs.ast.js.JsonObject;
@@ -107,7 +108,7 @@
private static final int IS_NULL = 0;
private static final Map<String, JPrimitiveType> primitiveTypes = new HashMap<String, JPrimitiveType>();
-
+
@Deprecated
private static final Map<String, JPrimitiveType> primitiveTypesDeprecated = new HashMap<String, JPrimitiveType>();
@@ -398,7 +399,7 @@
private JClassType typeString;
public JProgram() {
- this(new CorrelationFactory.DummyCorrelationFactory());
+ this(DummyCorrelationFactory.INSTANCE);
}
/**
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java b/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java
index 42bc89c..e2221ba 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java
@@ -1,12 +1,12 @@
/*
* Copyright 2008 Google Inc.
- *
+ *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -110,7 +110,7 @@
* corresponding JNode for each created method and variable. 4) Maps all
* synthetic arguments and fields for nested and local classes. 5) Slurps in
* JSNI code for native methods as an opaque string.
- *
+ *
* Note that methods and fields are not added to their classes here, that
* isn't done until {@link GenerateJavaAST}.
*/
@@ -292,13 +292,10 @@
private SourceInfo makeSourceInfo(AbstractMethodDeclaration methodDecl,
HasSourceInfo enclosing) {
- CompilationResult compResult = methodDecl.compilationResult;
- int[] indexes = compResult.lineSeparatorPositions;
- String fileName = String.valueOf(compResult.fileName);
- int startLine = Util.getLineNumber(methodDecl.sourceStart, indexes, 0,
- indexes.length - 1);
+ int startLine = Util.getLineNumber(methodDecl.sourceStart,
+ currentSeparatorPositions, 0, currentSeparatorPositions.length - 1);
SourceInfo toReturn = program.createSourceInfo(methodDecl.sourceStart,
- methodDecl.bodyEnd, startLine, fileName);
+ methodDecl.bodyEnd, startLine, currentFileName);
// The SourceInfo will inherit Correlations from its enclosing object
if (enclosing != null) {
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/FragmentExtractor.java b/dev/core/src/com/google/gwt/dev/jjs/impl/FragmentExtractor.java
index 88c152e..502aa35 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/FragmentExtractor.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/FragmentExtractor.java
@@ -538,7 +538,7 @@
* An empty JsVars seems possibly surprising; return a true empty
* statement instead.
*/
- return jsprogram.getEmptyStmt();
+ return new JsEmpty(stat.getSourceInfo());
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java
index 105d0f2..4c04e90 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java
@@ -2995,8 +2995,7 @@
JLiteral initializer = field.getConstInitializer();
JType type = initializer.getType();
if (type instanceof JPrimitiveType || program.isJavaLangString(type)) {
- GenerateJavaScriptLiterals generator = new GenerateJavaScriptLiterals(
- jsProgram);
+ GenerateJavaScriptLiterals generator = new GenerateJavaScriptLiterals();
generator.accept(initializer);
JsExpression result = generator.peek();
assert (result != null);
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
index c878a3b..84de28d 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
@@ -105,6 +105,7 @@
import com.google.gwt.dev.js.ast.JsContinue;
import com.google.gwt.dev.js.ast.JsDefault;
import com.google.gwt.dev.js.ast.JsDoWhile;
+import com.google.gwt.dev.js.ast.JsEmpty;
import com.google.gwt.dev.js.ast.JsExprStmt;
import com.google.gwt.dev.js.ast.JsExpression;
import com.google.gwt.dev.js.ast.JsFor;
@@ -118,6 +119,7 @@
import com.google.gwt.dev.js.ast.JsNameRef;
import com.google.gwt.dev.js.ast.JsNew;
import com.google.gwt.dev.js.ast.JsNode;
+import com.google.gwt.dev.js.ast.JsNormalScope;
import com.google.gwt.dev.js.ast.JsObjectLiteral;
import com.google.gwt.dev.js.ast.JsParameter;
import com.google.gwt.dev.js.ast.JsPostfixOperation;
@@ -125,6 +127,7 @@
import com.google.gwt.dev.js.ast.JsProgram;
import com.google.gwt.dev.js.ast.JsPropertyInitializer;
import com.google.gwt.dev.js.ast.JsReturn;
+import com.google.gwt.dev.js.ast.JsRootScope;
import com.google.gwt.dev.js.ast.JsScope;
import com.google.gwt.dev.js.ast.JsStatement;
import com.google.gwt.dev.js.ast.JsSwitch;
@@ -295,7 +298,7 @@
if (parentScope == objectScope) {
parentScope = interfaceScope;
}
- myScope = new JsScope(parentScope, "class " + x.getShortName());
+ myScope = new JsNormalScope(parentScope, "class " + x.getShortName());
}
classScopes.put(x, myScope);
@@ -532,10 +535,6 @@
arrayLength.setObfuscatable(false);
}
- public GenerateJavaScriptVisitor() {
- super(jsProgram);
- }
-
@Override
public void endVisit(JAbsentArrayDimension x, Context ctx) {
throw new InternalCompilerException("Should not get here.");
@@ -594,7 +593,7 @@
Iterator<JsStatement> iterator = stmts.iterator();
while (iterator.hasNext()) {
JsStatement stmt = iterator.next();
- if (stmt == jsProgram.getEmptyStmt()) {
+ if (stmt instanceof JsEmpty) {
iterator.remove();
}
}
@@ -755,7 +754,7 @@
if (x.getBody() != null) {
stmt.setBody((JsStatement) pop()); // body
} else {
- stmt.setBody(jsProgram.getEmptyStmt());
+ stmt.setBody(new JsEmpty(x.getSourceInfo()));
}
stmt.setCondition((JsExpression) pop()); // testExpr
push(stmt);
@@ -843,7 +842,7 @@
if (x.getBody() != null) {
jsFor.setBody((JsStatement) pop());
} else {
- jsFor.setBody(jsProgram.getEmptyStmt());
+ jsFor.setBody(new JsEmpty(x.getSourceInfo()));
}
// increments
@@ -892,7 +891,7 @@
if (x.getThenStmt() != null) {
stmt.setThenStmt((JsStatement) pop()); // thenStmt
} else {
- stmt.setThenStmt(jsProgram.getEmptyStmt());
+ stmt.setThenStmt(new JsEmpty(x.getSourceInfo()));
}
stmt.setIfExpr((JsExpression) pop()); // ifExpr
@@ -1092,7 +1091,8 @@
}
if (cur == null) {
// the multi-expression was empty; use undefined
- cur = jsProgram.getUndefinedLiteral();
+ cur = new JsNameRef(x.getSourceInfo(),
+ JsRootScope.INSTANCE.getUndefined());
}
push(cur);
}
@@ -1284,7 +1284,7 @@
if (x.getBody() != null) {
stmt.setBody((JsStatement) pop()); // body
} else {
- stmt.setBody(jsProgram.getEmptyStmt());
+ stmt.setBody(new JsEmpty(x.getSourceInfo()));
}
stmt.setCondition((JsExpression) pop()); // testExpr
push(stmt);
@@ -1593,8 +1593,7 @@
SourceInfo sourceInfo = program.createSourceInfoSynthetic(
GenerateJavaScriptAST.class, "gwtOnLoad");
- JsName entryName = topScope.findExistingName("$entry");
- entryName.setObfuscatable(true);
+ JsName entryName = topScope.declareName("$entry");
JsVar entryVar = new JsVar(sourceInfo, entryName);
JsInvocation registerEntryCall = new JsInvocation(sourceInfo);
JsFunction registerEntryFunction = indexedFunctions.get("Impl.registerEntry");
@@ -1746,8 +1745,8 @@
* primitive with a modified prototype.
*/
JsNameRef rhs = prototype.makeRef(sourceInfo);
- rhs.setQualifier(jsProgram.getRootScope().declareName("String").makeRef(
- sourceInfo));
+ rhs.setQualifier(JsRootScope.INSTANCE.findExistingUnobfuscatableName(
+ "String").makeRef(sourceInfo));
JsExpression tmpAsg = createAssignment(globalTemp.makeRef(sourceInfo),
rhs);
JsExprStmt tmpAsgStmt = tmpAsg.makeStmt();
@@ -2114,7 +2113,7 @@
this.jsProgram = jsProgram;
topScope = jsProgram.getScope();
objectScope = jsProgram.getObjectScope();
- interfaceScope = new JsScope(objectScope, "Interfaces");
+ interfaceScope = new JsNormalScope(objectScope, "Interfaces");
this.output = output;
this.symbolTable = symbolTable;
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptLiterals.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptLiterals.java
index e9c55c2..fb50d79 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptLiterals.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptLiterals.java
@@ -26,11 +26,14 @@
import com.google.gwt.dev.jjs.ast.JNullLiteral;
import com.google.gwt.dev.jjs.ast.JStringLiteral;
import com.google.gwt.dev.jjs.ast.JVisitor;
+import com.google.gwt.dev.js.ast.JsBooleanLiteral;
import com.google.gwt.dev.js.ast.JsExpression;
import com.google.gwt.dev.js.ast.JsNameRef;
+import com.google.gwt.dev.js.ast.JsNullLiteral;
+import com.google.gwt.dev.js.ast.JsNumberLiteral;
import com.google.gwt.dev.js.ast.JsObjectLiteral;
-import com.google.gwt.dev.js.ast.JsProgram;
import com.google.gwt.dev.js.ast.JsPropertyInitializer;
+import com.google.gwt.dev.js.ast.JsStringLiteral;
import com.google.gwt.dev.js.ast.JsVisitable;
import com.google.gwt.lang.LongLib;
@@ -44,36 +47,31 @@
*/
public class GenerateJavaScriptLiterals extends JVisitor {
- private final JsProgram program;
private final Stack<JsVisitable> nodeStack = new Stack<JsVisitable>();
- public GenerateJavaScriptLiterals(JsProgram program) {
- this.program = program;
- }
-
@Override
public final void endVisit(JBooleanLiteral x, Context ctx) {
- push(x.getValue() ? program.getTrueLiteral() : program.getFalseLiteral());
+ push(JsBooleanLiteral.get(x.getValue()));
}
@Override
public final void endVisit(JCharLiteral x, Context ctx) {
- push(program.getNumberLiteral(x.getSourceInfo(), x.getValue()));
+ push(new JsNumberLiteral(x.getSourceInfo(), x.getValue()));
}
@Override
public final void endVisit(JDoubleLiteral x, Context ctx) {
- push(program.getNumberLiteral(x.getSourceInfo(), x.getValue()));
+ push(new JsNumberLiteral(x.getSourceInfo(), x.getValue()));
}
@Override
public final void endVisit(JFloatLiteral x, Context ctx) {
- push(program.getNumberLiteral(x.getSourceInfo(), x.getValue()));
+ push(new JsNumberLiteral(x.getSourceInfo(), x.getValue()));
}
@Override
public final void endVisit(JIntLiteral x, Context ctx) {
- push(program.getNumberLiteral(x.getSourceInfo(), x.getValue()));
+ push(new JsNumberLiteral(x.getSourceInfo(), x.getValue()));
}
@Override
@@ -85,9 +83,9 @@
JsExpression label0 = new JsNameRef(sourceInfo, "l");
JsExpression label1 = new JsNameRef(sourceInfo, "m");
JsExpression label2 = new JsNameRef(sourceInfo, "h");
- JsExpression value0 = program.getNumberLiteral(sourceInfo, intArray[0]);
- JsExpression value1 = program.getNumberLiteral(sourceInfo, intArray[1]);
- JsExpression value2 = program.getNumberLiteral(sourceInfo, intArray[2]);
+ JsExpression value0 = new JsNumberLiteral(sourceInfo, intArray[0]);
+ JsExpression value1 = new JsNumberLiteral(sourceInfo, intArray[1]);
+ JsExpression value2 = new JsNumberLiteral(sourceInfo, intArray[2]);
inits.add(new JsPropertyInitializer(sourceInfo, label0, value0));
inits.add(new JsPropertyInitializer(sourceInfo, label1, value1));
inits.add(new JsPropertyInitializer(sourceInfo, label2, value2));
@@ -96,12 +94,12 @@
@Override
public final void endVisit(JNullLiteral x, Context ctx) {
- push(program.getNullLiteral());
+ push(JsNullLiteral.INSTANCE);
}
@Override
public final void endVisit(JStringLiteral x, Context ctx) {
- push(program.getStringLiteral(x.getSourceInfo(), x.getValue()));
+ push(new JsStringLiteral(x.getSourceInfo(), x.getValue()));
}
@SuppressWarnings("unchecked")
diff --git a/dev/core/src/com/google/gwt/dev/js/JsInliner.java b/dev/core/src/com/google/gwt/dev/js/JsInliner.java
index 5b56c97..aa97813 100644
--- a/dev/core/src/com/google/gwt/dev/js/JsInliner.java
+++ b/dev/core/src/com/google/gwt/dev/js/JsInliner.java
@@ -26,9 +26,11 @@
import com.google.gwt.dev.js.ast.JsBlock;
import com.google.gwt.dev.js.ast.JsBooleanLiteral;
import com.google.gwt.dev.js.ast.JsCase;
+import com.google.gwt.dev.js.ast.JsCatchScope;
import com.google.gwt.dev.js.ast.JsConditional;
import com.google.gwt.dev.js.ast.JsContext;
import com.google.gwt.dev.js.ast.JsDefault;
+import com.google.gwt.dev.js.ast.JsEmpty;
import com.google.gwt.dev.js.ast.JsExprStmt;
import com.google.gwt.dev.js.ast.JsExpression;
import com.google.gwt.dev.js.ast.JsFor;
@@ -48,9 +50,9 @@
import com.google.gwt.dev.js.ast.JsPostfixOperation;
import com.google.gwt.dev.js.ast.JsPrefixOperation;
import com.google.gwt.dev.js.ast.JsProgram;
-import com.google.gwt.dev.js.ast.JsProgramFragment;
import com.google.gwt.dev.js.ast.JsRegExp;
import com.google.gwt.dev.js.ast.JsReturn;
+import com.google.gwt.dev.js.ast.JsRootScope;
import com.google.gwt.dev.js.ast.JsScope;
import com.google.gwt.dev.js.ast.JsStatement;
import com.google.gwt.dev.js.ast.JsStringLiteral;
@@ -89,11 +91,9 @@
*/
private static class AffectedBySideEffectsVisitor extends JsVisitor {
private boolean affectedBySideEffects;
- private final JsProgram program;
private final JsScope safeScope;
- public AffectedBySideEffectsVisitor(JsProgram program, JsScope safeScope) {
- this.program = program;
+ public AffectedBySideEffectsVisitor(JsScope safeScope) {
this.safeScope = safeScope;
}
@@ -125,7 +125,7 @@
public void endVisit(JsNameRef x, JsContext ctx) {
if (x.getQualifier() == null && x.getName() != null) {
// Special case the undefined literal.
- if (x.getName() == program.getUndefinedLiteral().getName()) {
+ if (x.getName() == JsRootScope.INSTANCE.getUndefined()) {
return;
}
// Locals in a safe scope are unaffected.
@@ -423,7 +423,7 @@
return false;
} else {
// The return value from an XO function is never used
- ctx.replaceMe(program.getNullLiteral());
+ ctx.replaceMe(JsNullLiteral.INSTANCE);
return false;
}
@@ -489,7 +489,7 @@
if (ctx.canRemove()) {
ctx.removeMe();
} else {
- ctx.replaceMe(program.getEmptyStmt());
+ ctx.replaceMe(new JsEmpty(x.getSourceInfo()));
}
return false;
@@ -604,8 +604,11 @@
* invocations occur.
*/
private static class EvaluationOrderVisitor extends JsVisitor {
- public static final JsName THIS_NAME = (new JsScope("fake scope") {
- }).declareName("this");
+ /**
+ * A dummy name to represent 'this' refs.
+ */
+ public static final JsName THIS_NAME = new JsCatchScope(
+ JsRootScope.INSTANCE, "this").getAllNames().next();
private boolean maintainsOrder = true;
private final List<JsName> toEvaluate;
@@ -777,7 +780,6 @@
private final Stack<JsFunction> functionStack = new Stack<JsFunction>();
private final InvocationCountingVisitor invocationCountingVisitor = new InvocationCountingVisitor();
private final Stack<List<JsName>> newLocalVariableStack = new Stack<List<JsName>>();
- private final JsProgram program;
/**
* A map containing the next integer to try as an identifier suffix for a
@@ -791,7 +793,6 @@
private JsFunction programFunction;
public InliningVisitor(JsProgram program) {
- this.program = program;
invocationCountingVisitor.accept(program);
}
@@ -856,7 +857,7 @@
if (ctx.canRemove()) {
ctx.removeMe();
} else {
- ctx.replaceMe(program.getEmptyStmt());
+ ctx.replaceMe(new JsEmpty(x.getSourceInfo()));
}
} else if (x.getExpression() != statements.get(0).getExpression()) {
@@ -969,7 +970,7 @@
}
@Override
- public void endVisit(JsProgramFragment x, JsContext ctx) {
+ public void endVisit(JsProgram x, JsContext ctx) {
if (!functionStack.pop().equals(programFunction)) {
throw new InternalCompilerException("Unexpected function popped");
}
@@ -1003,9 +1004,8 @@
* top-level of the program.
*/
@Override
- public boolean visit(JsProgramFragment x, JsContext ctx) {
- programFunction = new JsFunction(program.getSourceInfo(),
- program.getScope());
+ public boolean visit(JsProgram x, JsContext ctx) {
+ programFunction = new JsFunction(x.getSourceInfo(), x.getScope());
programFunction.setBody(new JsBlock(x.getSourceInfo()));
functionStack.push(programFunction);
newLocalVariableStack.push(new ArrayList<JsName>());
@@ -1097,8 +1097,7 @@
* distinct objects, it would not be possible to substitute different
* JsNameRefs at different call sites.
*/
- JsExpression h = hoistedExpression(program, statement,
- localVariableNames);
+ JsExpression h = hoistedExpression(statement, localVariableNames);
if (h == null) {
return x;
}
@@ -1117,7 +1116,8 @@
* JsExprStmt.
*/
if (!sawReturnStatement) {
- hoisted.add(program.getUndefinedLiteral());
+ hoisted.add(new JsNameRef(x.getSourceInfo(),
+ JsRootScope.INSTANCE.getUndefined()));
}
assert (hoisted.size() > 0);
@@ -1141,7 +1141,7 @@
}
// Confirm that the expression conforms to the desired heuristics
- if (!isInlinable(program, callerFunction, invokedFunction, thisExpr,
+ if (!isInlinable(callerFunction, invokedFunction, thisExpr,
x.getArguments(), op)) {
return x;
}
@@ -1618,8 +1618,8 @@
* the generated output. Increasing this number will allow larger sections of
* code to be inlined, but at a cost of larger JS output.
*/
- private static final double MAX_COMPLEXITY_INCREASE =
- Double.parseDouble(System.getProperty("gwt.jsinlinerRatio", "5.0"));
+ private static final double MAX_COMPLEXITY_INCREASE = Double.parseDouble(System.getProperty(
+ "gwt.jsinlinerRatio", "5.0"));
/**
* Static entry point used by JavaToJavaScriptCompiler.
@@ -1637,8 +1637,8 @@
* The context parameter provides a scope in which local (and therefore
* immutable) variables are defined.
*/
- private static boolean affectedBySideEffects(JsProgram program,
- List<JsExpression> list, JsFunction context) {
+ private static boolean affectedBySideEffects(List<JsExpression> list,
+ JsFunction context) {
/*
* If the caller contains no nested functions, none of its locals can
* possibly be affected by side effects.
@@ -1647,8 +1647,7 @@
if (context != null && !containsNestedFunctions(context)) {
safeScope = context.getScope();
}
- AffectedBySideEffectsVisitor v = new AffectedBySideEffectsVisitor(program,
- safeScope);
+ AffectedBySideEffectsVisitor v = new AffectedBySideEffectsVisitor(safeScope);
v.acceptList(list);
return v.affectedBySideEffects();
}
@@ -1762,8 +1761,8 @@
* @return a JsExpression representing all expressions that would have been
* evaluated by the statement
*/
- private static JsExpression hoistedExpression(JsProgram program,
- JsStatement statement, List<JsName> localVariableNames) {
+ private static JsExpression hoistedExpression(JsStatement statement,
+ List<JsName> localVariableNames) {
JsExpression expression;
if (statement instanceof JsExprStmt) {
// Extract the expression
@@ -1775,7 +1774,8 @@
JsReturn ret = (JsReturn) statement;
expression = ret.getExpr();
if (expression == null) {
- expression = program.getUndefinedLiteral();
+ expression = new JsNameRef(ret.getSourceInfo(),
+ JsRootScope.INSTANCE.getUndefined());
}
} else if (statement instanceof JsVars) {
@@ -1783,7 +1783,7 @@
JsVars vars = (JsVars) statement;
// Rely on comma expression cleanup to remove this later.
- expression = program.getNullLiteral();
+ expression = JsNullLiteral.INSTANCE;
for (JsVar var : vars) {
// Record the locally-defined variable
@@ -1854,9 +1854,8 @@
/**
* Determine if a statement can be inlined into a call site.
*/
- private static boolean isInlinable(JsProgram program, JsFunction caller,
- JsFunction callee, JsExpression thisExpr, List<JsExpression> arguments,
- JsNode toInline) {
+ private static boolean isInlinable(JsFunction caller, JsFunction callee,
+ JsExpression thisExpr, List<JsExpression> arguments, JsNode toInline) {
/*
* This will happen with varargs-style JavaScript functions that rely on the
@@ -1913,21 +1912,21 @@
* effects. This will determine how aggressively the parameters may be
* reordered.
*/
- if (isVolatile(program, evalArgs, caller)) {
+ if (isVolatile(evalArgs, caller)) {
/*
* Determine the order in which the parameters must be evaluated. This
* will vary between call sites, based on whether or not the invocation's
* arguments can be repeated without ill effect.
*/
List<JsName> requiredOrder = new ArrayList<JsName>();
- if (thisExpr != null && isVolatile(program, thisExpr, callee)) {
+ if (thisExpr != null && isVolatile(thisExpr, callee)) {
requiredOrder.add(EvaluationOrderVisitor.THIS_NAME);
}
for (int i = 0; i < arguments.size(); i++) {
JsExpression e = arguments.get(i);
JsParameter p = callee.getParameters().get(i);
- if (isVolatile(program, e, callee)) {
+ if (isVolatile(e, callee)) {
requiredOrder.add(p.getName());
}
}
@@ -1974,9 +1973,8 @@
* affected by side effects when evaluated within a particular function
* context.
*/
- private static boolean isVolatile(JsProgram program, JsExpression e,
- JsFunction context) {
- return isVolatile(program, Collections.singletonList(e), context);
+ private static boolean isVolatile(JsExpression e, JsFunction context) {
+ return isVolatile(Collections.singletonList(e), context);
}
/**
@@ -1984,10 +1982,8 @@
* affected by side effects when evaluated within a particular function
* context.
*/
- private static boolean isVolatile(JsProgram program, List<JsExpression> list,
- JsFunction context) {
- return hasSideEffects(list)
- || affectedBySideEffects(program, list, context);
+ private static boolean isVolatile(List<JsExpression> list, JsFunction context) {
+ return hasSideEffects(list) || affectedBySideEffects(list, context);
}
/**
diff --git a/dev/core/src/com/google/gwt/dev/js/JsParser.java b/dev/core/src/com/google/gwt/dev/js/JsParser.java
index f1bdb2d..d3d81de 100644
--- a/dev/core/src/com/google/gwt/dev/js/JsParser.java
+++ b/dev/core/src/com/google/gwt/dev/js/JsParser.java
@@ -15,7 +15,9 @@
*/
package com.google.gwt.dev.js;
+import com.google.gwt.dev.jjs.Correlation.Literal;
import com.google.gwt.dev.jjs.SourceInfo;
+import com.google.gwt.dev.jjs.SourceOrigin;
import com.google.gwt.dev.js.ast.JsArrayAccess;
import com.google.gwt.dev.js.ast.JsArrayLiteral;
import com.google.gwt.dev.js.ast.JsBinaryOperation;
@@ -27,8 +29,10 @@
import com.google.gwt.dev.js.ast.JsCatch;
import com.google.gwt.dev.js.ast.JsConditional;
import com.google.gwt.dev.js.ast.JsContinue;
+import com.google.gwt.dev.js.ast.JsDebugger;
import com.google.gwt.dev.js.ast.JsDefault;
import com.google.gwt.dev.js.ast.JsDoWhile;
+import com.google.gwt.dev.js.ast.JsEmpty;
import com.google.gwt.dev.js.ast.JsExprStmt;
import com.google.gwt.dev.js.ast.JsExpression;
import com.google.gwt.dev.js.ast.JsFor;
@@ -41,14 +45,16 @@
import com.google.gwt.dev.js.ast.JsNameRef;
import com.google.gwt.dev.js.ast.JsNew;
import com.google.gwt.dev.js.ast.JsNode;
+import com.google.gwt.dev.js.ast.JsNullLiteral;
+import com.google.gwt.dev.js.ast.JsNumberLiteral;
import com.google.gwt.dev.js.ast.JsObjectLiteral;
import com.google.gwt.dev.js.ast.JsParameter;
import com.google.gwt.dev.js.ast.JsPostfixOperation;
import com.google.gwt.dev.js.ast.JsPrefixOperation;
-import com.google.gwt.dev.js.ast.JsProgram;
import com.google.gwt.dev.js.ast.JsPropertyInitializer;
import com.google.gwt.dev.js.ast.JsRegExp;
import com.google.gwt.dev.js.ast.JsReturn;
+import com.google.gwt.dev.js.ast.JsRootScope;
import com.google.gwt.dev.js.ast.JsScope;
import com.google.gwt.dev.js.ast.JsStatement;
import com.google.gwt.dev.js.ast.JsStringLiteral;
@@ -80,7 +86,7 @@
public static List<JsStatement> parse(SourceInfo rootSourceInfo,
JsScope scope, Reader r) throws IOException, JsParserException {
- return new JsParser(scope.getProgram()).parseImpl(rootSourceInfo, scope, r);
+ return new JsParser().parseImpl(rootSourceInfo, scope, r);
}
public static void parseInto(SourceInfo rootSourceInfo, JsScope scope,
@@ -90,13 +96,10 @@
parentStmts.addAll(childStmts);
}
- private JsProgram program;
-
private final Stack<JsScope> scopeStack = new Stack<JsScope>();
private final Stack<SourceInfo> sourceInfoStack = new Stack<SourceInfo>();
- private JsParser(JsProgram program) {
- this.program = program;
+ private JsParser() {
}
List<JsStatement> parseImpl(final SourceInfo rootSourceInfo, JsScope scope,
@@ -155,9 +158,20 @@
// Rhino only reports line numbers for statement nodes, not expressions
return parent;
}
- SourceInfo toReturn = program.createSourceInfo(lineno, parent.getFileName());
- toReturn.copyMissingCorrelationsFrom(parent);
- return toReturn;
+ return parent.makeChild(SourceOrigin.create(lineno, parent.getFileName()));
+ }
+
+ /**
+ * Force a distinct child to be created, so correlations can be added.
+ */
+ private SourceInfo makeSourceInfoDistinct(Node node) {
+ SourceInfo parent = sourceInfoStack.peek();
+ int lineno = node.getLineno();
+ if (lineno == -1) {
+ // Rhino only reports line numbers for statement nodes, not expressions
+ lineno = parent.getStartLine();
+ }
+ return parent.makeChild(SourceOrigin.create(lineno, parent.getFileName()));
}
private JsNode map(Node node) throws JsParserException {
@@ -170,7 +184,7 @@
}
case TokenStream.DEBUGGER:
- return mapDebuggerStatement();
+ return mapDebuggerStatement(node);
case TokenStream.VOID:
// VOID = nothing was parsed for this node
@@ -236,10 +250,11 @@
case TokenStream.HOOK:
return mapConditional(node);
- case TokenStream.STRING:
- return program.getStringLiteral(
- sourceInfoStack.peek().makeChild(JsParser.class,
- "JS String literal"), node.getString());
+ case TokenStream.STRING: {
+ SourceInfo info = makeSourceInfoDistinct(node);
+ info.addCorrelation(info.getCorrelationFactory().by(Literal.JS_STRING));
+ return new JsStringLiteral(info, node.getString());
+ }
case TokenStream.NUMBER:
return mapNumber(node);
@@ -484,10 +499,10 @@
}
}
- private JsStatement mapDebuggerStatement() {
+ private JsStatement mapDebuggerStatement(Node node) {
// Calls an optional method to invoke the debugger.
//
- return program.getDebuggerStmt();
+ return new JsDebugger(makeSourceInfo(node));
}
private JsExpression mapDeleteProp(Node node) throws JsParserException {
@@ -597,6 +612,7 @@
Node fromIncr = fromTest.getNext();
Node fromBody = fromIncr.getNext();
+ SourceInfo info = makeSourceInfo(forNode);
if (fromBody == null) {
// This could be a "for...in" structure.
// We could based on the different child layout.
@@ -612,7 +628,7 @@
Node fromIterVarName = fromIter.getFirstChild();
String fromName = fromIterVarName.getString();
JsName toName = getScope().declareName(fromName);
- toForIn = new JsForIn(makeSourceInfo(forNode), toName);
+ toForIn = new JsForIn(info, toName);
Node fromIterInit = fromIterVarName.getFirstChild();
if (fromIterInit != null) {
// That has an initializer expression (useful only for side effects).
@@ -622,7 +638,7 @@
} else {
// An unnamed iterator var.
//
- toForIn = new JsForIn(makeSourceInfo(forNode));
+ toForIn = new JsForIn(info);
toForIn.setIterExpr(mapExpression(fromIter));
}
toForIn.setObjExpr(mapExpression(fromObjExpr));
@@ -633,14 +649,14 @@
if (bodyStmt != null) {
toForIn.setBody(bodyStmt);
} else {
- toForIn.setBody(program.getEmptyStmt());
+ toForIn.setBody(new JsEmpty(info));
}
return toForIn;
} else {
// Regular ol' for loop.
//
- JsFor toFor = new JsFor(makeSourceInfo(forNode));
+ JsFor toFor = new JsFor(info);
// The first item is either an expression or a JsVars.
JsNode initThingy = map(fromInit);
@@ -659,7 +675,7 @@
if (bodyStmt != null) {
toFor.setBody(bodyStmt);
} else {
- toFor.setBody(program.getEmptyStmt());
+ toFor.setBody(new JsEmpty(info));
}
return toFor;
}
@@ -821,7 +837,8 @@
}
private JsExpression mapNumber(Node numberNode) {
- return program.getNumberLiteral(numberNode.getDouble());
+ return new JsNumberLiteral(makeSourceInfo(numberNode),
+ numberNode.getDouble());
}
private JsExpression mapObjectLit(Node objLitNode) throws JsParserException {
@@ -887,16 +904,20 @@
return new JsThisRef(makeSourceInfo(node));
case TokenStream.TRUE:
- return program.getTrueLiteral();
+ return JsBooleanLiteral.TRUE;
case TokenStream.FALSE:
- return program.getFalseLiteral();
+ return JsBooleanLiteral.FALSE;
case TokenStream.NULL:
- return program.getNullLiteral();
+ return JsNullLiteral.INSTANCE;
- case TokenStream.UNDEFINED:
- return program.getUndefinedLiteral();
+ case TokenStream.UNDEFINED: {
+ SourceInfo info = makeSourceInfoDistinct(node);
+ info.addCorrelation(info.getCorrelationFactory().by(
+ Literal.JS_UNDEFINED));
+ return new JsNameRef(info, JsRootScope.INSTANCE.getUndefined());
+ }
default:
throw createParserException("Unknown primary: " + node.getIntDatum(),
@@ -1017,7 +1038,7 @@
} else {
// When map() returns null, we return an empty statement.
//
- return program.getEmptyStmt();
+ return new JsEmpty(makeSourceInfo(nodeStmt));
}
}
diff --git a/dev/core/src/com/google/gwt/dev/js/JsStackEmulator.java b/dev/core/src/com/google/gwt/dev/js/JsStackEmulator.java
index 26bcfbc..35633c3 100644
--- a/dev/core/src/com/google/gwt/dev/js/JsStackEmulator.java
+++ b/dev/core/src/com/google/gwt/dev/js/JsStackEmulator.java
@@ -27,6 +27,7 @@
import com.google.gwt.dev.js.ast.JsBinaryOperation;
import com.google.gwt.dev.js.ast.JsBinaryOperator;
import com.google.gwt.dev.js.ast.JsBlock;
+import com.google.gwt.dev.js.ast.JsBooleanLiteral;
import com.google.gwt.dev.js.ast.JsCatch;
import com.google.gwt.dev.js.ast.JsContext;
import com.google.gwt.dev.js.ast.JsExprStmt;
@@ -39,10 +40,13 @@
import com.google.gwt.dev.js.ast.JsNameRef;
import com.google.gwt.dev.js.ast.JsNew;
import com.google.gwt.dev.js.ast.JsNode;
+import com.google.gwt.dev.js.ast.JsNullLiteral;
+import com.google.gwt.dev.js.ast.JsNumberLiteral;
import com.google.gwt.dev.js.ast.JsPostfixOperation;
import com.google.gwt.dev.js.ast.JsPrefixOperation;
import com.google.gwt.dev.js.ast.JsProgram;
import com.google.gwt.dev.js.ast.JsReturn;
+import com.google.gwt.dev.js.ast.JsRootScope;
import com.google.gwt.dev.js.ast.JsStatement;
import com.google.gwt.dev.js.ast.JsStringLiteral;
import com.google.gwt.dev.js.ast.JsThrow;
@@ -50,9 +54,9 @@
import com.google.gwt.dev.js.ast.JsUnaryOperation;
import com.google.gwt.dev.js.ast.JsUnaryOperator;
import com.google.gwt.dev.js.ast.JsVars;
+import com.google.gwt.dev.js.ast.JsVars.JsVar;
import com.google.gwt.dev.js.ast.JsVisitor;
import com.google.gwt.dev.js.ast.JsWhile;
-import com.google.gwt.dev.js.ast.JsVars.JsVar;
import com.google.gwt.dev.util.collect.Lists;
import com.google.gwt.dev.util.collect.Maps;
@@ -278,7 +282,7 @@
// There is a finally block, so we need to set the early-exit flag
JsBinaryOperation asg = new JsBinaryOperation(x.getSourceInfo(),
JsBinaryOperator.ASG, earlyExitRef(outerFinallyBlock),
- program.getBooleanLiteral(true));
+ JsBooleanLiteral.get(true));
if (x.getExpr() == null) {
if (ctx.canInsert()) {
// exitingEarly = true; return;
@@ -507,7 +511,7 @@
*/
private JsExpression pop(SourceInfo info) {
JsBinaryOperation sub = new JsBinaryOperation(info, JsBinaryOperator.SUB,
- stackIndexRef(info), program.getNumberLiteral(1));
+ stackIndexRef(info), new JsNumberLiteral(info, 1));
JsBinaryOperation op = new JsBinaryOperation(info, JsBinaryOperator.ASG,
stackDepth.makeRef(info), sub);
return op;
@@ -525,7 +529,7 @@
JsExpression currentFunctionRef;
if (currentFunction.getName() == null) {
// Anonymous
- currentFunctionRef = program.getNullLiteral();
+ currentFunctionRef = JsNullLiteral.INSTANCE;
} else {
currentFunctionRef = currentFunction.getName().makeRef(info);
}
@@ -737,11 +741,11 @@
"Synthetic location data");
// ($locations[stackIndex] = fileName + lineNumber, x)
- JsExpression location = program.getStringLiteral(info,
+ JsExpression location = new JsStringLiteral(info,
String.valueOf(lastLine = info.getStartLine()));
if (recordFileNames) {
// 'fileName:' + lineNumber
- JsStringLiteral stringLit = program.getStringLiteral(info,
+ JsStringLiteral stringLit = new JsStringLiteral(info,
baseName(lastFile = info.getFileName()) + ":");
location = new JsBinaryOperation(info, JsBinaryOperator.ADD, stringLit,
location);
@@ -770,13 +774,10 @@
* with references to our locally-defined, obfuscatable names.
*/
private class ReplaceUnobfuscatableNames extends JsModVisitor {
- private final JsName rootLineNumbers = program.getRootScope().findExistingUnobfuscatableName(
- "$location");
// See JsRootScope for the definition of these names
- private final JsName rootStack = program.getRootScope().findExistingUnobfuscatableName(
- "$stack");
- private final JsName rootStackDepth = program.getRootScope().findExistingUnobfuscatableName(
- "$stackDepth");
+ private final JsName rootLineNumbers = JsRootScope.INSTANCE.findExistingUnobfuscatableName("$location");
+ private final JsName rootStack = JsRootScope.INSTANCE.findExistingUnobfuscatableName("$stack");
+ private final JsName rootStackDepth = JsRootScope.INSTANCE.findExistingUnobfuscatableName("$stackDepth");
@Override
public void endVisit(JsNameRef x, JsContext ctx) {
@@ -896,7 +897,7 @@
JsVar stackVar = new JsVar(info, stack);
stackVar.setInitExpr(new JsArrayLiteral(info));
JsVar stackDepthVar = new JsVar(info, stackDepth);
- stackDepthVar.setInitExpr(program.getNumberLiteral(info, -1));
+ stackDepthVar.setInitExpr(new JsNumberLiteral(info, (-1)));
JsVar lineNumbersVar = new JsVar(info, lineNumbers);
lineNumbersVar.setInitExpr(new JsArrayLiteral(info));
diff --git a/dev/core/src/com/google/gwt/dev/js/JsStaticEval.java b/dev/core/src/com/google/gwt/dev/js/JsStaticEval.java
index aaa9db5..f44b733 100644
--- a/dev/core/src/com/google/gwt/dev/js/JsStaticEval.java
+++ b/dev/core/src/com/google/gwt/dev/js/JsStaticEval.java
@@ -28,6 +28,7 @@
import com.google.gwt.dev.js.ast.JsContext;
import com.google.gwt.dev.js.ast.JsContinue;
import com.google.gwt.dev.js.ast.JsDoWhile;
+import com.google.gwt.dev.js.ast.JsEmpty;
import com.google.gwt.dev.js.ast.JsExprStmt;
import com.google.gwt.dev.js.ast.JsExpression;
import com.google.gwt.dev.js.ast.JsFor;
@@ -291,7 +292,7 @@
if (ctx.canRemove()) {
ctx.removeMe();
} else {
- ctx.replaceMe(program.getEmptyStmt());
+ ctx.replaceMe(new JsEmpty(x.getSourceInfo()));
}
}
}
@@ -623,7 +624,7 @@
// "undefined" is not a JsValueLiteral, so the only way
// the result can be true is if exp is itself a JsNullLiteral
boolean result = exp instanceof JsNullLiteral;
- return program.getBooleanLiteral(result);
+ return JsBooleanLiteral.get(result);
}
// no simplification made
@@ -640,7 +641,7 @@
// "undefined" is not a JsValueLiteral, so the only way
// the result can be false is if exp is itself a JsNullLiteral
boolean result = !(exp instanceof JsNullLiteral);
- return program.getBooleanLiteral(result);
+ return JsBooleanLiteral.get(result);
}
// no simplification made
@@ -653,18 +654,19 @@
private void trySimplifyAdd(JsExpression original, JsExpression arg1,
JsExpression arg2, JsContext ctx) {
if (arg1 instanceof JsValueLiteral && arg2 instanceof JsValueLiteral) {
+ SourceInfo info = original.getSourceInfo();
// case: number + number
if (arg1 instanceof JsNumberLiteral && arg2 instanceof JsNumberLiteral) {
double value = ((JsNumberLiteral) arg1).getValue()
+ ((JsNumberLiteral) arg2).getValue();
- ctx.replaceMe(program.getNumberLiteral(value));
+ ctx.replaceMe(new JsNumberLiteral(info, value));
} else {
// cases: number + string or string + number
StringBuilder result = new StringBuilder();
if (appendLiteral(result, (JsValueLiteral) arg1)
&& appendLiteral(result, (JsValueLiteral) arg2)) {
- ctx.replaceMe(program.getStringLiteral(original.getSourceInfo(),
- result.toString()));
+ info.merge(arg1.getSourceInfo(), arg2.getSourceInfo());
+ ctx.replaceMe(new JsStringLiteral(info, result.toString()));
}
}
}
diff --git a/dev/core/src/com/google/gwt/dev/js/JsSymbolResolver.java b/dev/core/src/com/google/gwt/dev/js/JsSymbolResolver.java
index 1f0c050..3ae0308 100644
--- a/dev/core/src/com/google/gwt/dev/js/JsSymbolResolver.java
+++ b/dev/core/src/com/google/gwt/dev/js/JsSymbolResolver.java
@@ -37,7 +37,7 @@
name = getScope().findExistingName(ident);
if (name == null) {
// No clue what this is; create a new unobfuscatable name
- name = program.getRootScope().declareName(ident);
+ name = program.getScope().declareName(ident);
name.setObfuscatable(false);
}
} else {
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsBooleanLiteral.java b/dev/core/src/com/google/gwt/dev/js/ast/JsBooleanLiteral.java
index e254270..24fc9c1 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsBooleanLiteral.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsBooleanLiteral.java
@@ -16,16 +16,26 @@
package com.google.gwt.dev.js.ast;
import com.google.gwt.dev.jjs.SourceInfo;
+import com.google.gwt.dev.jjs.SourceOrigin;
/**
* Represents a JavaScript literal boolean expression.
*/
public final class JsBooleanLiteral extends JsValueLiteral {
+ public static final JsBooleanLiteral FALSE = new JsBooleanLiteral(
+ SourceOrigin.UNKNOWN, false);
+
+ public static final JsBooleanLiteral TRUE = new JsBooleanLiteral(
+ SourceOrigin.UNKNOWN, true);
+
+ public static JsBooleanLiteral get(boolean value) {
+ return value ? TRUE : FALSE;
+ }
+
private final boolean value;
- // Should be interned by JsProgram
- JsBooleanLiteral(SourceInfo sourceInfo, boolean value) {
+ private JsBooleanLiteral(SourceInfo sourceInfo, boolean value) {
super(sourceInfo);
this.value = value;
}
@@ -56,4 +66,8 @@
v.visit(this, ctx);
v.endVisit(this, ctx);
}
+
+ private Object readResolve() {
+ return get(value);
+ }
}
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsCatchScope.java b/dev/core/src/com/google/gwt/dev/js/ast/JsCatchScope.java
index 1791fc5..542d398 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsCatchScope.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsCatchScope.java
@@ -15,14 +15,14 @@
*/
package com.google.gwt.dev.js.ast;
+import java.util.Collections;
import java.util.Iterator;
-import java.util.NoSuchElementException;
/**
* A special scope used only for catch blocks. It only holds a single symbol:
* the catch argument's name.
*/
-public class JsCatchScope extends JsScope {
+public class JsCatchScope extends JsNestingScope {
private final JsName name;
@@ -32,45 +32,14 @@
}
@Override
- public JsName declareName(String ident) {
- // Declare into parent scope!
- return getParent().declareName(ident);
- }
-
- @Override
- public JsName declareName(String ident, String shortIdent) {
- // Declare into parent scope!
- return getParent().declareName(ident, shortIdent);
- }
-
- @Override
public Iterator<JsName> getAllNames() {
- return new Iterator<JsName>() {
- private boolean didIterate = false;
-
- public boolean hasNext() {
- return !didIterate;
- }
-
- public JsName next() {
- if (didIterate) {
- throw new NoSuchElementException();
- }
- didIterate = true;
- return name;
- }
-
- public void remove() {
- throw new UnsupportedOperationException();
- }
-
- };
+ return Collections.singleton(name).iterator();
}
@Override
protected JsName doCreateName(String ident, String shortIdent) {
- throw new UnsupportedOperationException(
- "Cannot create a name in a catch scope");
+ // Declare into parent scope!
+ return getParent().declareName(ident, shortIdent);
}
@Override
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsEmpty.java b/dev/core/src/com/google/gwt/dev/js/ast/JsEmpty.java
index 00a5b6f..4727008 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsEmpty.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsEmpty.java
@@ -22,8 +22,7 @@
*/
public class JsEmpty extends JsStatement {
- // Interned by JsProgram
- JsEmpty(SourceInfo sourceInfo) {
+ public JsEmpty(SourceInfo sourceInfo) {
super(sourceInfo);
}
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsFunction.java b/dev/core/src/com/google/gwt/dev/js/ast/JsFunction.java
index 959470c..74f211f 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsFunction.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsFunction.java
@@ -68,7 +68,7 @@
setName(name);
String scopeName = (name == null) ? "<anonymous>" : name.getIdent();
scopeName = "function " + scopeName;
- this.scope = new JsScope(parent, scopeName);
+ this.scope = new JsNormalScope(parent, scopeName);
}
public JsBlock getBody() {
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsNameRef.java b/dev/core/src/com/google/gwt/dev/js/ast/JsNameRef.java
index 58a7a8c..4bde74d 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsNameRef.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsNameRef.java
@@ -89,10 +89,7 @@
@Override
public boolean isDefinitelyNull() {
- if (name != null) {
- return (name.getEnclosing().getProgram().getUndefinedLiteral().getName() == name);
- }
- return false;
+ return name == JsRootScope.INSTANCE.getUndefined();
}
@Override
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsNestingScope.java b/dev/core/src/com/google/gwt/dev/js/ast/JsNestingScope.java
new file mode 100644
index 0000000..36b83e7
--- /dev/null
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsNestingScope.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.dev.js.ast;
+
+import com.google.gwt.dev.util.collect.Lists;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * A normal scope that has a parent and children.
+ */
+public abstract class JsNestingScope extends JsScope implements Serializable {
+
+ /**
+ * Transient because children will add themselves to the parent after
+ * deserialization.
+ */
+ private transient List<JsScope> children = Lists.create();
+
+ private final JsScope parent;
+
+ /**
+ * Create a scope with parent.
+ */
+ public JsNestingScope(JsScope parent, String description) {
+ super(description);
+ assert (parent != null);
+ this.parent = parent;
+ parent.addChild(this);
+ }
+
+ /**
+ * Returns a list of this scope's child scopes.
+ */
+ @Override
+ public final List<JsScope> getChildren() {
+ return children;
+ }
+
+ /**
+ * Returns the parent scope of this scope, or <code>null</code> if this is the
+ * root scope.
+ */
+ @Override
+ public final JsScope getParent() {
+ return parent;
+ }
+
+ @Override
+ protected final void addChild(JsScope child) {
+ children = Lists.add(children, child);
+ }
+
+ protected Object readResolve() {
+ children = Lists.create();
+ parent.addChild(this);
+ return this;
+ }
+
+}
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsNormalScope.java b/dev/core/src/com/google/gwt/dev/js/ast/JsNormalScope.java
new file mode 100644
index 0000000..ce4dcf6
--- /dev/null
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsNormalScope.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.dev.js.ast;
+
+import com.google.gwt.dev.util.StringInterner;
+import com.google.gwt.dev.util.collect.Maps;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * A normal scope that has a parent and children.
+ */
+public class JsNormalScope extends JsNestingScope implements Serializable {
+
+ private Map<String, JsName> names = Collections.emptyMap();
+
+ /**
+ * Create a scope with parent.
+ */
+ public JsNormalScope(JsScope parent, String description) {
+ super(parent, description);
+ }
+
+ /**
+ * Returns an iterator for all the names defined by this scope.
+ */
+ @Override
+ public Iterator<JsName> getAllNames() {
+ return names.values().iterator();
+ }
+
+ /**
+ * Creates a new name in this scope.
+ */
+ @Override
+ protected JsName doCreateName(String ident, String shortIdent) {
+ ident = StringInterner.get().intern(ident);
+ shortIdent = StringInterner.get().intern(shortIdent);
+ JsName name = new JsName(this, ident, shortIdent);
+ names = Maps.putOrdered(names, ident, name);
+ return name;
+ }
+
+ /**
+ * Attempts to find the name object for the specified ident, searching in this
+ * scope only.
+ *
+ * @return <code>null</code> if the identifier has no associated name
+ */
+ @Override
+ protected JsName findExistingNameNoRecurse(String ident) {
+ return names.get(ident);
+ }
+}
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsNullLiteral.java b/dev/core/src/com/google/gwt/dev/js/ast/JsNullLiteral.java
index dba3966..2774635 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsNullLiteral.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsNullLiteral.java
@@ -16,14 +16,17 @@
package com.google.gwt.dev.js.ast;
import com.google.gwt.dev.jjs.SourceInfo;
+import com.google.gwt.dev.jjs.SourceOrigin;
/**
* A JavaScript null literal.
*/
public final class JsNullLiteral extends JsValueLiteral {
- // Should only be instantiated in JsProgram
- JsNullLiteral(SourceInfo sourceInfo) {
+ public static final JsNullLiteral INSTANCE = new JsNullLiteral(
+ SourceOrigin.UNKNOWN);
+
+ private JsNullLiteral(SourceInfo sourceInfo) {
super(sourceInfo);
}
@@ -49,4 +52,12 @@
v.visit(this, ctx);
v.endVisit(this, ctx);
}
+
+ /**
+ * Note, if this ever becomes not-a-singleton, we'll need to check the
+ * SourceInfo == SourceOrigin.UNKNOWN.
+ */
+ private Object readResolve() {
+ return INSTANCE;
+ }
}
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsNumberLiteral.java b/dev/core/src/com/google/gwt/dev/js/ast/JsNumberLiteral.java
index 90026ac..df3508c 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsNumberLiteral.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsNumberLiteral.java
@@ -24,8 +24,7 @@
private final double value;
- // Should be interned by JsProgram
- JsNumberLiteral(SourceInfo sourceInfo, double value) {
+ public JsNumberLiteral(SourceInfo sourceInfo, double value) {
super(sourceInfo);
this.value = value;
}
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsProgram.java b/dev/core/src/com/google/gwt/dev/js/ast/JsProgram.java
index 9ab9e27..a05967b 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsProgram.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsProgram.java
@@ -16,10 +16,9 @@
package com.google.gwt.dev.js.ast;
import com.google.gwt.dev.jjs.CorrelationFactory;
+import com.google.gwt.dev.jjs.CorrelationFactory.DummyCorrelationFactory;
import com.google.gwt.dev.jjs.SourceInfo;
import com.google.gwt.dev.jjs.SourceOrigin;
-import com.google.gwt.dev.jjs.Correlation.Axis;
-import com.google.gwt.dev.jjs.Correlation.Literal;
import java.util.HashMap;
import java.util.Map;
@@ -31,39 +30,16 @@
private final CorrelationFactory correlator;
- private final JsStatement debuggerStmt;
-
- private final JsEmpty emptyStmt;
-
- private final JsBooleanLiteral falseLiteral;
-
private JsProgramFragment[] fragments;
- /**
- * The root intrinsic source info.
- */
- private final SourceInfo intrinsic;
-
private final Map<String, JsFunction> indexedFunctions = new HashMap<String, JsFunction>();
- private final JsNullLiteral nullLiteral;
-
- private final Map<Double, JsNumberLiteral> numberLiteralMap = new HashMap<Double, JsNumberLiteral>();
-
private final JsScope objectScope;
- private final JsRootScope rootScope;
-
- private final Map<String, JsStringLiteral> stringLiteralMap = new HashMap<String, JsStringLiteral>();
-
- private final SourceInfo stringPoolSourceInfo;
-
private final JsScope topScope;
- private final JsBooleanLiteral trueLiteral;
-
public JsProgram() {
- this(new CorrelationFactory.DummyCorrelationFactory());
+ this(DummyCorrelationFactory.INSTANCE);
}
/**
@@ -79,26 +55,16 @@
JsProgram.class.getName())));
this.correlator = correlator;
- intrinsic = createSourceInfo(0, getClass().getName());
- rootScope = new JsRootScope(this);
- topScope = new JsScope(rootScope, "Global");
- objectScope = new JsScope(rootScope, "Object");
+ topScope = new JsNormalScope(JsRootScope.INSTANCE, "Global");
+ objectScope = new JsNormalScope(JsRootScope.INSTANCE, "Object");
setFragmentCount(1);
+ }
- debuggerStmt = new JsDebugger(createLiteralSourceInfo("debugger statement"));
- emptyStmt = new JsEmpty(createLiteralSourceInfo("Empty statement"));
- falseLiteral = new JsBooleanLiteral(createLiteralSourceInfo(
- "false literal", Literal.JS_BOOLEAN), false);
- nullLiteral = new JsNullLiteral(createLiteralSourceInfo("null literal",
- Literal.JS_NULL));
- trueLiteral = new JsBooleanLiteral(createLiteralSourceInfo("true literal",
- Literal.JS_BOOLEAN), true);
-
- trueLiteral.getSourceInfo().addCorrelation(
- correlator.by(Literal.JS_BOOLEAN));
- stringPoolSourceInfo = createLiteralSourceInfo("String pool",
- Literal.JS_STRING);
+ public SourceInfo createSourceInfo(int startPos, int endPos, int startLine,
+ String fileName) {
+ return correlator.makeSourceInfo(SourceOrigin.create(startPos, endPos,
+ startLine, fileName));
}
public SourceInfo createSourceInfo(int lineNumber, String location) {
@@ -110,31 +76,6 @@
return createSourceInfo(0, caller.getName()).makeChild(caller, description);
}
- public JsBooleanLiteral getBooleanLiteral(boolean truth) {
- if (truth) {
- return getTrueLiteral();
- }
- return getFalseLiteral();
- }
-
- /**
- * Gets the {@link JsStatement} to use whenever parsed source include a
- * <code>debugger</code> statement.
- *
- * @see #setDebuggerStmt(JsStatement)
- */
- public JsStatement getDebuggerStmt() {
- return debuggerStmt;
- }
-
- public JsEmpty getEmptyStmt() {
- return emptyStmt;
- }
-
- public JsBooleanLiteral getFalseLiteral() {
- return falseLiteral;
- }
-
public JsBlock getFragmentBlock(int fragment) {
if (fragment < 0 || fragment >= fragments.length) {
throw new IllegalArgumentException("Invalid fragment: " + fragment);
@@ -157,56 +98,11 @@
return indexedFunctions.get(name);
}
- public JsNullLiteral getNullLiteral() {
- return nullLiteral;
- }
-
- public JsNumberLiteral getNumberLiteral(double value) {
- return getNumberLiteral(null, value);
- }
-
- public JsNumberLiteral getNumberLiteral(SourceInfo info, double value) {
- /*
- * This method only canonicalizes number literals when we don't have an
- * incoming SourceInfo so that we can distinguish int-0 from double-0 in the
- * analysis.
- */
- if (info == null) {
- JsNumberLiteral lit = numberLiteralMap.get(value);
- if (lit == null) {
- info = createSourceInfoSynthetic(JsProgram.class, "Number literal "
- + value);
- info.addCorrelation(correlator.by(Literal.JS_NUMBER));
- lit = new JsNumberLiteral(info, value);
- numberLiteralMap.put(value, lit);
- }
-
- return lit;
- } else {
- // Only add a JS_NUMBER if no literal correlation present: e.g. Java int
- if (info.getPrimaryCorrelation(Axis.LITERAL) == null) {
- // Don't mutate incoming SourceInfo
- info = info.makeChild(JsProgram.class, "Number literal " + value);
- info.addCorrelation(correlator.by(Literal.JS_NUMBER));
- }
- return new JsNumberLiteral(info, value);
- }
- }
-
public JsScope getObjectScope() {
return objectScope;
}
/**
- * Gets the quasi-mythical root scope. This is not the same as the top scope;
- * all unresolvable identifiers wind up here, because they are considered
- * external to the program.
- */
- public JsRootScope getRootScope() {
- return rootScope;
- }
-
- /**
* Gets the top level scope. This is the scope of all the statements in the
* main program.
*/
@@ -214,31 +110,6 @@
return topScope;
}
- /**
- * Creates or retrieves a JsStringLiteral from an interned object pool.
- */
- public JsStringLiteral getStringLiteral(SourceInfo sourceInfo, String value) {
- JsStringLiteral lit = stringLiteralMap.get(value);
- if (lit == null) {
- lit = new JsStringLiteral(stringPoolSourceInfo.makeChild(JsProgram.class,
- "String literal: " + value), value);
- stringLiteralMap.put(value, lit);
- }
- lit.getSourceInfo().merge(sourceInfo);
- return lit;
- }
-
- public JsBooleanLiteral getTrueLiteral() {
- return trueLiteral;
- }
-
- public JsNameRef getUndefinedLiteral() {
- SourceInfo info = createSourceInfoSynthetic(JsProgram.class,
- "undefined reference");
- info.addCorrelation(correlator.by(Literal.JS_UNDEFINED));
- return rootScope.findExistingName("undefined").makeRef(info);
- }
-
public void setFragmentCount(int fragments) {
this.fragments = new JsProgramFragment[fragments];
for (int i = 0; i < fragments; i++) {
@@ -260,14 +131,4 @@
}
v.endVisit(this, ctx);
}
-
- private SourceInfo createLiteralSourceInfo(String description) {
- return intrinsic.makeChild(getClass(), description);
- }
-
- private SourceInfo createLiteralSourceInfo(String description, Literal literal) {
- SourceInfo child = createLiteralSourceInfo(description);
- child.addCorrelation(correlator.by(literal));
- return child;
- }
}
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsRootName.java b/dev/core/src/com/google/gwt/dev/js/ast/JsRootName.java
new file mode 100644
index 0000000..d32582a
--- /dev/null
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsRootName.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.dev.js.ast;
+
+import java.io.Serializable;
+
+/**
+ * A well-known name in the root scope.
+ */
+public class JsRootName extends JsName {
+
+ private static class SerializedForm implements Serializable {
+ private final String ident;
+
+ public SerializedForm(String ident) {
+ this.ident = ident;
+ }
+
+ private Object readResolve() {
+ return JsRootScope.INSTANCE.findExistingName(ident);
+ }
+ }
+
+ JsRootName(JsRootScope rootScope, String ident) {
+ super(rootScope, ident, ident);
+ super.setObfuscatable(false);
+ }
+
+ @Override
+ public void setObfuscatable(boolean isObfuscatable) {
+ throw new UnsupportedOperationException("Root names are immutable");
+ }
+
+ @Override
+ public void setShortIdent(String shortIdent) {
+ throw new UnsupportedOperationException("Root names are immutable");
+ }
+
+ @Override
+ public void setStaticRef(JsNode node) {
+ throw new UnsupportedOperationException("Root names are immutable");
+ }
+
+ private Object writeReplace() {
+ return new SerializedForm(getIdent());
+ }
+
+}
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsRootScope.java b/dev/core/src/com/google/gwt/dev/js/ast/JsRootScope.java
index 325f62e..6f1dfc1 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsRootScope.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsRootScope.java
@@ -15,336 +15,383 @@
*/
package com.google.gwt.dev.js.ast;
+import com.google.gwt.dev.util.collect.Lists;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
/**
- * The root scope is the parent of every scope. All identifiers in this scope
- * are not obfuscatable.
+ * The root scope is the parent of every scope, it contains a list of browser
+ * built-in identifiers that we should recognize and never obfuscate into.
*/
public final class JsRootScope extends JsScope {
+ /*
+ * NOTE: the startup sequence for this class is a bit tricky.
+ */
- private final JsProgram program;
+ private static class SerializedForm implements Serializable {
+ private Object readResolve() {
+ return JsRootScope.INSTANCE;
+ }
+ }
- public JsRootScope(JsProgram program) {
+ public static final JsRootScope INSTANCE;
+
+ private static final String[] COMMON_BUILTINS = new String[]{
+ // 15.1.1 Value Properties of the Global Object
+ "NaN",
+ "Infinity",
+ "undefined",
+
+ // 15.1.2 Function Properties of the Global Object
+ "eval",
+ "parseInt",
+ "parseFloat",
+ "isNan",
+ "isFinite",
+
+ // 15.1.3 URI Handling Function Properties
+ "decodeURI",
+ "decodeURIComponent",
+ "encodeURI",
+ "encodeURIComponent",
+
+ // 15.1.4 Constructor Properties of the Global Object
+ "Object",
+ "Function",
+ "Array",
+ "String",
+ "Boolean",
+ "Number",
+ "Date",
+ "RegExp",
+ "Error",
+ "EvalError",
+ "RangeError",
+ "ReferenceError",
+ "SyntaxError",
+ "TypeError",
+ "URIError",
+
+ // 15.1.5 Other Properties of the Global Object
+ "Math",
+
+ // 10.1.6 Activation Object
+ "arguments",
+
+ // B.2 Additional Properties (non-normative)
+ "escape",
+ "unescape",
+
+ // Window props (https://developer.mozilla.org/en/DOM/window)
+ "applicationCache",
+ "closed",
+ "Components",
+ "content",
+ "controllers",
+ "crypto",
+ "defaultStatus",
+ "dialogArguments",
+ "directories",
+ "document",
+ "frameElement",
+ "frames",
+ "fullScreen",
+ "globalStorage",
+ "history",
+ "innerHeight",
+ "innerWidth",
+ "length",
+ "location",
+ "locationbar",
+ "localStorage",
+ "menubar",
+ "mozInnerScreenX",
+ "mozInnerScreenY",
+ "mozScreenPixelsPerCssPixel",
+ "name",
+ "navigator",
+ "opener",
+ "outerHeight",
+ "outerWidth",
+ "pageXOffset",
+ "pageYOffset",
+ "parent",
+ "personalbar",
+ "pkcs11",
+ "returnValue",
+ "screen",
+ "scrollbars",
+ "scrollMaxX",
+ "scrollMaxY",
+ "self",
+ "sessionStorage",
+ "sidebar",
+ "status",
+ "statusbar",
+ "toolbar",
+ "top",
+ "window",
+
+ // Window methods (https://developer.mozilla.org/en/DOM/window)
+ "alert",
+ "addEventListener",
+ "atob",
+ "back",
+ "blur",
+ "btoa",
+ "captureEvents",
+ "clearInterval",
+ "clearTimeout",
+ "close",
+ "confirm",
+ "disableExternalCapture",
+ "dispatchEvent",
+ "dump",
+ "enableExternalCapture",
+ "escape",
+ "find",
+ "focus",
+ "forward",
+ "GeckoActiveXObject",
+ "getAttention",
+ "getAttentionWithCycleCount",
+ "getComputedStyle",
+ "getSelection",
+ "home",
+ "maximize",
+ "minimize",
+ "moveBy",
+ "moveTo",
+ "open",
+ "openDialog",
+ "postMessage",
+ "print",
+ "prompt",
+ "QueryInterface",
+ "releaseEvents",
+ "removeEventListener",
+ "resizeBy",
+ "resizeTo",
+ "restore",
+ "routeEvent",
+ "scroll",
+ "scrollBy",
+ "scrollByLines",
+ "scrollByPages",
+ "scrollTo",
+ "setInterval",
+ "setResizeable",
+ "setTimeout",
+ "showModalDialog",
+ "sizeToContent",
+ "stop",
+ "uuescape",
+ "updateCommands",
+ "XPCNativeWrapper",
+ "XPCSafeJSOjbectWrapper",
+
+ // Mozilla Window event handlers, same cite
+ "onabort",
+ "onbeforeunload",
+ "onchange",
+ "onclick",
+ "onclose",
+ "oncontextmenu",
+ "ondragdrop",
+ "onerror",
+ "onfocus",
+ "onhashchange",
+ "onkeydown",
+ "onkeypress",
+ "onkeyup",
+ "onload",
+ "onmousedown",
+ "onmousemove",
+ "onmouseout",
+ "onmouseover",
+ "onmouseup",
+ "onmozorientation",
+ "onpaint",
+ "onreset",
+ "onresize",
+ "onscroll",
+ "onselect",
+ "onsubmit",
+ "onunload",
+
+ // Safari Web Content Guide
+ // http://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariWebContent/SafariWebContent.pdf
+ // WebKit Window member data, from WebKit DOM Reference
+ // (http://developer.apple.com/safari/library/documentation/AppleApplications/Reference/WebKitDOMRef/DOMWindow_idl/Classes/DOMWindow/index.html)
+ // TODO(fredsa) Many, many more functions and member data to add
+ "ontouchcancel",
+ "ontouchend",
+ "ontouchmove",
+ "ontouchstart",
+ "ongesturestart",
+ "ongesturechange",
+ "ongestureend",
+
+ // extra window methods
+ "uneval",
+
+ // keywords https://developer.mozilla.org/en/New_in_JavaScript_1.7,
+ // https://developer.mozilla.org/en/New_in_JavaScript_1.8.1
+ "getPrototypeOf",
+ "let",
+
+ // "future reserved words"
+ "abstract",
+ "int",
+ "short",
+ "boolean",
+ "interface",
+ "static",
+ "byte",
+ "long",
+ "char",
+ "final",
+ "native",
+ "synchronized",
+ "float",
+ "package",
+ "throws",
+ "goto",
+ "private",
+ "transient",
+ "implements",
+ "protected",
+ "volatile",
+ "double",
+ "public",
+
+ // IE methods
+ // (http://msdn.microsoft.com/en-us/library/ms535873(VS.85).aspx#)
+ "attachEvent",
+ "clientInformation",
+ "clipboardData",
+ "createPopup",
+ "dialogHeight",
+ "dialogLeft",
+ "dialogTop",
+ "dialogWidth",
+ "onafterprint",
+ "onbeforedeactivate",
+ "onbeforeprint",
+ "oncontrolselect",
+ "ondeactivate",
+ "onhelp",
+ "onresizeend",
+
+ // Common browser-defined identifiers not defined in ECMAScript
+ "event",
+ "external",
+ "Debug",
+ "Enumerator",
+ "Global",
+ "Image",
+ "ActiveXObject",
+ "VBArray",
+ "Components",
+
+ // Functions commonly defined on Object
+ "toString",
+ "getClass",
+ "constructor",
+ "prototype",
+
+ // Client-side JavaScript identifiers, which are needed for linkers
+ // that don't ensure GWT's window != $wnd, document != $doc, etc.
+ // Taken from the Rhino book, pg 715
+ "Anchor", "Applet", "Attr", "Canvas", "CanvasGradient", "CanvasPattern",
+ "CanvasRenderingContext2D", "CDATASection", "CharacterData", "Comment",
+ "CSS2Properties", "CSSRule", "CSSStyleSheet", "Document",
+ "DocumentFragment", "DocumentType", "DOMException", "DOMImplementation",
+ "DOMParser", "Element", "Event", "ExternalInterface", "FlashPlayer",
+ "Form", "Frame", "History", "HTMLCollection", "HTMLDocument",
+ "HTMLElement", "IFrame", "Image", "Input", "JSObject", "KeyEvent",
+ "Link", "Location", "MimeType", "MouseEvent", "Navigator", "Node",
+ "NodeList", "Option", "Plugin", "ProcessingInstruction", "Range",
+ "RangeException", "Screen", "Select", "Table", "TableCell", "TableRow",
+ "TableSelection", "Text", "TextArea", "UIEvent", "Window",
+ "XMLHttpRequest", "XMLSerializer", "XPathException", "XPathResult",
+ "XSLTProcessor",
+
+ /*
+ * These keywords trigger the loading of the java-plugin. For the
+ * next-generation plugin, this results in starting a new Java process.
+ */
+ "java", "Packages", "netscape", "sun", "JavaObject", "JavaClass",
+ "JavaArray", "JavaMember",
+
+ // GWT-defined identifiers
+ "$wnd", "$doc", "$moduleName", "$moduleBase", "$gwt_version",
+ "$sessionId",
+
+ // Identifiers used by JsStackEmulator; later set to obfuscatable
+ "$stack", "$stackDepth", "$location",
+
+ // TODO: prove why this is necessary or remove it
+ "call",};
+
+ static {
+ INSTANCE = new JsRootScope();
+ }
+
+ private final Map<String, JsName> names = new LinkedHashMap<String, JsName>();
+
+ private final JsName undefined;
+
+ private JsRootScope() {
super("Root");
- this.program = program;
- ctorAddKnownGlobalSymbols();
+ for (String ident : COMMON_BUILTINS) {
+ names.put(ident, new JsRootName(this, ident));
+ }
+ undefined = names.get("undefined");
+ assert undefined != null;
}
@Override
- public JsProgram getProgram() {
- return program;
+ public Iterator<JsName> getAllNames() {
+ return Collections.unmodifiableCollection(names.values()).iterator();
+ }
+
+ @Override
+ public List<JsScope> getChildren() {
+ return Lists.create();
+ }
+
+ @Override
+ public JsScope getParent() {
+ return null;
+ }
+
+ public JsName getUndefined() {
+ return undefined;
+ }
+
+ @Override
+ protected void addChild(JsScope child) {
+ // Don't record children.
}
@Override
protected JsName doCreateName(String ident, String shortIdent) {
- JsName name = super.doCreateName(ident, shortIdent);
- name.setObfuscatable(false);
- return name;
+ throw new UnsupportedOperationException(
+ "Cannot create new names in the root scope");
}
- private void ctorAddKnownGlobalSymbols() {
- // Section references are from Ecma-262
- // (http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf)
- String[] commonBuiltins = new String[]{
- // 15.1.1 Value Properties of the Global Object
- "NaN",
- "Infinity",
- "undefined",
+ @Override
+ protected JsName findExistingNameNoRecurse(String ident) {
+ return names.get(ident);
+ }
- // 15.1.2 Function Properties of the Global Object
- "eval",
- "parseInt",
- "parseFloat",
- "isNan",
- "isFinite",
-
- // 15.1.3 URI Handling Function Properties
- "decodeURI",
- "decodeURIComponent",
- "encodeURI",
- "encodeURIComponent",
-
- // 15.1.4 Constructor Properties of the Global Object
- "Object",
- "Function",
- "Array",
- "String",
- "Boolean",
- "Number",
- "Date",
- "RegExp",
- "Error",
- "EvalError",
- "RangeError",
- "ReferenceError",
- "SyntaxError",
- "TypeError",
- "URIError",
-
- // 15.1.5 Other Properties of the Global Object
- "Math",
-
- // 10.1.6 Activation Object
- "arguments",
-
- // B.2 Additional Properties (non-normative)
- "escape",
- "unescape",
-
- // Window props (https://developer.mozilla.org/en/DOM/window)
- "applicationCache",
- "closed",
- "Components",
- "content",
- "controllers",
- "crypto",
- "defaultStatus",
- "dialogArguments",
- "directories",
- "document",
- "frameElement",
- "frames",
- "fullScreen",
- "globalStorage",
- "history",
- "innerHeight",
- "innerWidth",
- "length",
- "location",
- "locationbar",
- "localStorage",
- "menubar",
- "mozInnerScreenX",
- "mozInnerScreenY",
- "mozScreenPixelsPerCssPixel",
- "name",
- "navigator",
- "opener",
- "outerHeight",
- "outerWidth",
- "pageXOffset",
- "pageYOffset",
- "parent",
- "personalbar",
- "pkcs11",
- "returnValue",
- "screen",
- "scrollbars",
- "scrollMaxX",
- "scrollMaxY",
- "self",
- "sessionStorage",
- "sidebar",
- "status",
- "statusbar",
- "toolbar",
- "top",
- "window",
-
- // Window methods (https://developer.mozilla.org/en/DOM/window)
- "alert",
- "addEventListener",
- "atob",
- "back",
- "blur",
- "btoa",
- "captureEvents",
- "clearInterval",
- "clearTimeout",
- "close",
- "confirm",
- "disableExternalCapture",
- "dispatchEvent",
- "dump",
- "enableExternalCapture",
- "escape",
- "find",
- "focus",
- "forward",
- "GeckoActiveXObject",
- "getAttention",
- "getAttentionWithCycleCount",
- "getComputedStyle",
- "getSelection",
- "home",
- "maximize",
- "minimize",
- "moveBy",
- "moveTo",
- "open",
- "openDialog",
- "postMessage",
- "print",
- "prompt",
- "QueryInterface",
- "releaseEvents",
- "removeEventListener",
- "resizeBy",
- "resizeTo",
- "restore",
- "routeEvent",
- "scroll",
- "scrollBy",
- "scrollByLines",
- "scrollByPages",
- "scrollTo",
- "setInterval",
- "setResizeable",
- "setTimeout",
- "showModalDialog",
- "sizeToContent",
- "stop",
- "uuescape",
- "updateCommands",
- "XPCNativeWrapper",
- "XPCSafeJSOjbectWrapper",
-
- // Mozilla Window event handlers, same cite
- "onabort",
- "onbeforeunload",
- "onchange",
- "onclick",
- "onclose",
- "oncontextmenu",
- "ondragdrop",
- "onerror",
- "onfocus",
- "onhashchange",
- "onkeydown",
- "onkeypress",
- "onkeyup",
- "onload",
- "onmousedown",
- "onmousemove",
- "onmouseout",
- "onmouseover",
- "onmouseup",
- "onmozorientation",
- "onpaint",
- "onreset",
- "onresize",
- "onscroll",
- "onselect",
- "onsubmit",
- "onunload",
-
- // Safari Web Content Guide
- // http://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariWebContent/SafariWebContent.pdf
- // WebKit Window member data, from WebKit DOM Reference
- // (http://developer.apple.com/safari/library/documentation/AppleApplications/Reference/WebKitDOMRef/DOMWindow_idl/Classes/DOMWindow/index.html)
- // TODO(fredsa) Many, many more functions and member data to add
- "ontouchcancel",
- "ontouchend",
- "ontouchmove",
- "ontouchstart",
- "ongesturestart",
- "ongesturechange",
- "ongestureend",
-
- // extra window methods
- "uneval",
-
- // keywords https://developer.mozilla.org/en/New_in_JavaScript_1.7,
- // https://developer.mozilla.org/en/New_in_JavaScript_1.8.1
- "getPrototypeOf",
- "let",
-
- // "future reserved words"
- "abstract",
- "int",
- "short",
- "boolean",
- "interface",
- "static",
- "byte",
- "long",
- "char",
- "final",
- "native",
- "synchronized",
- "float",
- "package",
- "throws",
- "goto",
- "private",
- "transient",
- "implements",
- "protected",
- "volatile",
- "double",
- "public",
-
- // IE methods
- // (http://msdn.microsoft.com/en-us/library/ms535873(VS.85).aspx#)
- "attachEvent",
- "clientInformation",
- "clipboardData",
- "createPopup",
- "dialogHeight",
- "dialogLeft",
- "dialogTop",
- "dialogWidth",
- "onafterprint",
- "onbeforedeactivate",
- "onbeforeprint",
- "oncontrolselect",
- "ondeactivate",
- "onhelp",
- "onresizeend",
-
- // Common browser-defined identifiers not defined in ECMAScript
- "event",
- "external",
- "Debug",
- "Enumerator",
- "Global",
- "Image",
- "ActiveXObject",
- "VBArray",
- "Components",
-
- // Functions commonly defined on Object
- "toString",
- "getClass",
- "constructor",
- "prototype",
-
- // Client-side JavaScript identifiers, which are needed for linkers
- // that don't ensure GWT's window != $wnd, document != $doc, etc.
- // Taken from the Rhino book, pg 715
- "Anchor", "Applet", "Attr", "Canvas", "CanvasGradient",
- "CanvasPattern", "CanvasRenderingContext2D", "CDATASection",
- "CharacterData", "Comment", "CSS2Properties", "CSSRule",
- "CSSStyleSheet", "Document", "DocumentFragment", "DocumentType",
- "DOMException", "DOMImplementation", "DOMParser", "Element", "Event",
- "ExternalInterface", "FlashPlayer", "Form", "Frame", "History",
- "HTMLCollection", "HTMLDocument", "HTMLElement", "IFrame", "Image",
- "Input", "JSObject", "KeyEvent", "Link", "Location", "MimeType",
- "MouseEvent", "Navigator", "Node", "NodeList", "Option", "Plugin",
- "ProcessingInstruction", "Range", "RangeException", "Screen", "Select",
- "Table", "TableCell", "TableRow", "TableSelection", "Text", "TextArea",
- "UIEvent", "Window", "XMLHttpRequest", "XMLSerializer",
- "XPathException", "XPathResult", "XSLTProcessor",
-
- /*
- * These keywords trigger the loading of the java-plugin. For the
- * next-generation plugin, this results in starting a new Java process.
- */
- "java", "Packages", "netscape", "sun", "JavaObject", "JavaClass",
- "JavaArray", "JavaMember",
-
- // GWT-defined identifiers
- "$wnd", "$doc", "$entry", "$moduleName", "$moduleBase", "$gwt_version",
- "$sessionId",
-
- // Identifiers used by JsStackEmulator; later set to obfuscatable
- "$stack", "$stackDepth", "$location",
-
- // TODO: prove why this is necessary or remove it
- "call",};
-
- for (int i = 0; i < commonBuiltins.length; i++) {
- String ident = commonBuiltins[i];
- this.doCreateName(ident, ident);
- }
+ private Object writeReplace() {
+ return new SerializedForm();
}
}
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsScope.java b/dev/core/src/com/google/gwt/dev/js/ast/JsScope.java
index 5dc5ed9..a1ff03c 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsScope.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsScope.java
@@ -17,14 +17,10 @@
import com.google.gwt.dev.js.JsKeywords;
import com.google.gwt.dev.util.StringInterner;
-import com.google.gwt.dev.util.collect.Lists;
-import com.google.gwt.dev.util.collect.Maps;
import java.io.Serializable;
-import java.util.Collections;
import java.util.Iterator;
import java.util.List;
-import java.util.Map;
/**
* A scope is a factory for creating and allocating
@@ -51,7 +47,7 @@
* qualifier and could therefore never be confused with the global scope
* hierarchy.
*/
-public class JsScope implements Serializable {
+public abstract class JsScope implements Serializable {
/**
* Prevents the client from programmatically creating an illegal ident.
@@ -63,27 +59,10 @@
return StringInterner.get().intern(ident);
}
- private List<JsScope> children = Collections.emptyList();
private final String description;
- private Map<String, JsName> names = Collections.emptyMap();
- private final JsScope parent;
- /**
- * Create a scope with parent.
- */
- public JsScope(JsScope parent, String description) {
- assert (parent != null);
- this.description = StringInterner.get().intern(description);
- this.parent = parent;
- parent.children = Lists.add(parent.children, this);
- }
-
- /**
- * Subclasses can be parentless.
- */
protected JsScope(String description) {
this.description = StringInterner.get().intern(description);
- this.parent = null;
}
/**
@@ -92,7 +71,7 @@
*
* @param ident An identifier that is unique within this scope.
*/
- public JsName declareName(String ident) {
+ public final JsName declareName(String ident) {
ident = maybeMangleKeyword(ident);
JsName name = findExistingNameNoRecurse(ident);
if (name != null) {
@@ -110,7 +89,7 @@
* @throws IllegalArgumentException if ident already exists in this scope but
* the requested short name does not match the existing short name.
*/
- public JsName declareName(String ident, String shortIdent) {
+ public final JsName declareName(String ident, String shortIdent) {
ident = maybeMangleKeyword(ident);
shortIdent = maybeMangleKeyword(shortIdent);
JsName name = findExistingNameNoRecurse(ident);
@@ -134,8 +113,8 @@
public final JsName findExistingName(String ident) {
ident = maybeMangleKeyword(ident);
JsName name = findExistingNameNoRecurse(ident);
- if (name == null && parent != null) {
- return parent.findExistingName(ident);
+ if (name == null && getParent() != null) {
+ return getParent().findExistingName(ident);
}
return name;
}
@@ -152,8 +131,8 @@
if (name != null && name.isObfuscatable()) {
name = null;
}
- if (name == null && parent != null) {
- return parent.findExistingUnobfuscatableName(ident);
+ if (name == null && getParent() != null) {
+ return getParent().findExistingUnobfuscatableName(ident);
}
return name;
}
@@ -161,52 +140,34 @@
/**
* Returns an iterator for all the names defined by this scope.
*/
- public Iterator<JsName> getAllNames() {
- return names.values().iterator();
- }
+ public abstract Iterator<JsName> getAllNames();
/**
* Returns a list of this scope's child scopes.
*/
- public final List<JsScope> getChildren() {
- return children;
- }
+ public abstract List<JsScope> getChildren();
/**
* Returns the parent scope of this scope, or <code>null</code> if this is the
* root scope.
*/
- public final JsScope getParent() {
- return parent;
- }
-
- /**
- * Returns the associated program.
- */
- public JsProgram getProgram() {
- assert (parent != null) : "Subclasses must override getProgram() if they do not set a parent";
- return parent.getProgram();
- }
+ public abstract JsScope getParent();
@Override
public final String toString() {
- if (parent != null) {
- return description + "->" + parent;
+ if (getParent() != null) {
+ return description + "->" + getParent();
} else {
return description;
}
}
+ protected abstract void addChild(JsScope child);
+
/**
* Creates a new name in this scope.
*/
- protected JsName doCreateName(String ident, String shortIdent) {
- ident = StringInterner.get().intern(ident);
- shortIdent = StringInterner.get().intern(shortIdent);
- JsName name = new JsName(this, ident, shortIdent);
- names = Maps.putOrdered(names, ident, name);
- return name;
- }
+ protected abstract JsName doCreateName(String ident, String shortIdent);
/**
* Attempts to find the name object for the specified ident, searching in this
@@ -214,8 +175,5 @@
*
* @return <code>null</code> if the identifier has no associated name
*/
- protected JsName findExistingNameNoRecurse(String ident) {
- return names.get(ident);
- }
-
+ protected abstract JsName findExistingNameNoRecurse(String ident);
}
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsStringLiteral.java b/dev/core/src/com/google/gwt/dev/js/ast/JsStringLiteral.java
index 6691d80..7eba50f 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsStringLiteral.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsStringLiteral.java
@@ -25,8 +25,7 @@
private final String value;
- // These only get created by JsProgram so that they can be interned.
- JsStringLiteral(SourceInfo sourceInfo, String value) {
+ public JsStringLiteral(SourceInfo sourceInfo, String value) {
super(sourceInfo);
this.value = StringInterner.get().intern(value);
}
diff --git a/dev/core/src/com/google/gwt/dev/shell/Jsni.java b/dev/core/src/com/google/gwt/dev/shell/Jsni.java
index a5a2d45..5c2b519 100644
--- a/dev/core/src/com/google/gwt/dev/shell/Jsni.java
+++ b/dev/core/src/com/google/gwt/dev/shell/Jsni.java
@@ -15,7 +15,6 @@
*/
package com.google.gwt.dev.shell;
-import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.dev.javac.JsniMethod;
import com.google.gwt.dev.jjs.SourceInfo;
import com.google.gwt.dev.js.JsSourceGenerationVisitor;
@@ -25,7 +24,8 @@
import com.google.gwt.dev.js.ast.JsInvocation;
import com.google.gwt.dev.js.ast.JsNameRef;
import com.google.gwt.dev.js.ast.JsNode;
-import com.google.gwt.dev.js.ast.JsProgram;
+import com.google.gwt.dev.js.ast.JsNullLiteral;
+import com.google.gwt.dev.js.ast.JsNumberLiteral;
import com.google.gwt.dev.util.DefaultTextOutput;
import com.google.gwt.dev.util.TextOutput;
@@ -85,14 +85,11 @@
JsSourceGenerationVisitor {
private final DispatchIdOracle dispatchInfo;
private final TextOutput out;
- private final JsProgram program;
- public JsSourceGenWithJsniIdentFixup(TextOutput out, DispatchIdOracle ccl,
- JsProgram program) {
+ public JsSourceGenWithJsniIdentFixup(TextOutput out, DispatchIdOracle ccl) {
super(out);
this.dispatchInfo = ccl;
this.out = out;
- this.program = program;
}
/**
@@ -149,11 +146,11 @@
List<JsExpression> arguments = rewritten.getArguments();
if (q == null) {
- q = program.getNullLiteral();
+ q = JsNullLiteral.INSTANCE;
}
arguments.add(q);
- arguments.add(program.getNumberLiteral(dispId));
- arguments.add(program.getNumberLiteral(paramCount));
+ arguments.add(new JsNumberLiteral(newSourceInfo, dispId));
+ arguments.add(new JsNumberLiteral(newSourceInfo, paramCount));
accept(rewritten);
return false;
@@ -210,17 +207,18 @@
JsInvocation inner = new JsInvocation(newSourceInfo);
inner.setQualifier(new JsNameRef(newSourceInfo,
"__gwt_makeJavaInvoke"));
- inner.getArguments().add(program.getNumberLiteral(paramCount));
+ inner.getArguments().add(
+ new JsNumberLiteral(newSourceInfo, paramCount));
JsInvocation outer = new JsInvocation(newSourceInfo);
outer.setQualifier(inner);
JsExpression q = ref.getQualifier();
if (q == null) {
- q = program.getNullLiteral();
+ q = JsNullLiteral.INSTANCE;
}
List<JsExpression> arguments = outer.getArguments();
arguments.add(q);
- arguments.add(program.getNumberLiteral(dispId));
+ arguments.add(new JsNumberLiteral(newSourceInfo, dispId));
arguments.addAll(x.getArguments());
accept(outer);
@@ -240,14 +238,13 @@
*
* @param logger a TreeLogger
*/
- public static String getJavaScriptForHostedMode(TreeLogger logger,
+ public static String getJavaScriptForHostedMode(
DispatchIdOracle dispatchInfo, JsniMethod jsniMethod) {
JsFunction func = jsniMethod.function();
if (func == null) {
return null;
}
- return generateJavaScriptForHostedMode(dispatchInfo, jsniMethod.program(),
- func.getBody());
+ return generateJavaScriptForHostedMode(dispatchInfo, func.getBody());
}
/**
@@ -255,10 +252,10 @@
* JSNI idents have been replaced with legal JavaScript for hosted mode.
*/
private static String generateJavaScriptForHostedMode(
- DispatchIdOracle dispatchInfo, JsProgram program, JsNode node) {
+ DispatchIdOracle dispatchInfo, JsNode node) {
DefaultTextOutput out = new DefaultTextOutput(false);
JsSourceGenWithJsniIdentFixup vi = new JsSourceGenWithJsniIdentFixup(out,
- dispatchInfo, program);
+ dispatchInfo);
vi.accept(node);
return out.toString();
}
diff --git a/dev/core/src/com/google/gwt/dev/shell/ModuleSpaceOOPHM.java b/dev/core/src/com/google/gwt/dev/shell/ModuleSpaceOOPHM.java
index 97b2f05..8ef7931 100644
--- a/dev/core/src/com/google/gwt/dev/shell/ModuleSpaceOOPHM.java
+++ b/dev/core/src/com/google/gwt/dev/shell/ModuleSpaceOOPHM.java
@@ -49,7 +49,7 @@
if (jsniMethod.isScriptOnly()) {
continue;
}
- String body = Jsni.getJavaScriptForHostedMode(logger, dispatchIdOracle,
+ String body = Jsni.getJavaScriptForHostedMode(dispatchIdOracle,
jsniMethod);
if (body == null) {
// The error has been logged; just ignore it for now.
diff --git a/dev/core/test/com/google/gwt/dev/jjs/JavaAstConstructor.java b/dev/core/test/com/google/gwt/dev/jjs/JavaAstConstructor.java
index 133e356..6a015b0 100644
--- a/dev/core/test/com/google/gwt/dev/jjs/JavaAstConstructor.java
+++ b/dev/core/test/com/google/gwt/dev/jjs/JavaAstConstructor.java
@@ -152,7 +152,7 @@
code.append(" private final String name;\n");
code.append(" private final int ordinal;\n");
code.append(" public final String name() { return name; }\n");
- code.append(" public final int ordinal() { return ordinal; }\n");
+ code.append(" public final int ordinal() { return ordinal; }\n");
code.append("}\n");
return code;
}
@@ -231,7 +231,7 @@
JavaToJavaScriptCompiler.checkForErrors(logger, goldenCuds, true);
- CorrelationFactory correlator = new DummyCorrelationFactory();
+ CorrelationFactory correlator = DummyCorrelationFactory.INSTANCE;
JProgram jprogram = new JProgram(correlator);
JsProgram jsProgram = new JsProgram(correlator);
diff --git a/dev/core/test/com/google/gwt/dev/js/JsToStringGenerationVisitorAccuracyTest.java b/dev/core/test/com/google/gwt/dev/js/JsToStringGenerationVisitorAccuracyTest.java
index 590ffe4..5a99ddd 100644
--- a/dev/core/test/com/google/gwt/dev/js/JsToStringGenerationVisitorAccuracyTest.java
+++ b/dev/core/test/com/google/gwt/dev/js/JsToStringGenerationVisitorAccuracyTest.java
@@ -18,6 +18,7 @@
import com.google.gwt.dev.jjs.SourceOrigin;
import com.google.gwt.dev.js.ast.JsProgram;
import com.google.gwt.dev.js.ast.JsStatement;
+import com.google.gwt.dev.js.ast.JsStringLiteral;
import com.google.gwt.dev.js.ast.JsVisitor;
import com.google.gwt.dev.util.DefaultTextOutput;
import com.google.gwt.dev.util.TextOutput;
@@ -192,8 +193,7 @@
}
private void doTestEscapes(String value, String expected) {
- String actual = new JsProgram().getStringLiteral(SourceOrigin.UNKNOWN,
- value).toString();
+ String actual = new JsStringLiteral(SourceOrigin.UNKNOWN, value).toString();
assertEquals(expected, actual);
}