You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@royale.apache.org by gr...@apache.org on 2019/06/11 03:46:06 UTC
[royale-compiler] branch develop updated: Squashed commit of the
following:
This is an automated email from the ASF dual-hosted git repository.
gregdove pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/royale-compiler.git
The following commit(s) were added to refs/heads/develop by this push:
new 6224c1a Squashed commit of the following:
6224c1a is described below
commit 6224c1ad785a9e2d0dda444d5a2add69c21cdf5f
Author: greg-dove <gr...@gmail.com>
AuthorDate: Tue Jun 11 15:21:08 2019 +1200
Squashed commit of the following:
commit 628d09e862fc3ff6edc9df6b0689b3634d157684
Merge: 29f4ba04 806603c8
Author: greg-dove <gr...@gmail.com>
Date: Tue Jun 11 14:51:58 2019 +1200
Merge branch 'develop' into improvements/Language
commit 29f4ba04b6eae4d294586803133e14ce0486cf6b
Author: greg-dove <gr...@gmail.com>
Date: Tue Jun 11 14:38:33 2019 +1200
Fix synthVector output for file-private element types.
Also add Class as a synthType
commit 378c07814db83d4e0af5343de8288d6c23583c4a
Merge: e461980d 905517ef
Author: greg-dove <gr...@gmail.com>
Date: Sun Jun 9 14:04:15 2019 +1200
Merge branch 'develop' into improvements/Language
commit e461980d384b71bc85a7c5014b9da5c7f26dfd4b
Author: greg-dove <gr...@gmail.com>
Date: Sun Jun 9 11:23:34 2019 +1200
Support for legacy Vector-as-Array via vectorEmulationClass setting, including fixes for insertAt/removeAt
commit 7dd36596e73f122ddb0af76db2abeb3d0a7b4231
Merge: b7cb250c de4bdad6
Author: greg-dove <gr...@gmail.com>
Date: Sat May 25 13:47:42 2019 +1200
Merge branch 'develop' into improvements/Language
commit b7cb250cbdc98218c69a83293603179f0fe297a4
Merge: b3080422 f1e68b92
Author: greg-dove <gr...@gmail.com>
Date: Thu May 23 18:37:54 2019 +1200
Merge branch 'develop' into improvements/Language
commit b30804227ad9bb8b5763fb56517649749e433a54
Author: greg-dove <gr...@gmail.com>
Date: Thu May 23 18:20:28 2019 +1200
Fixes for Issue #424
commit 164d1a1a37c15e83dc1142f9f628c4e7a4e6ee78
Author: greg-dove <gr...@gmail.com>
Date: Thu May 23 11:36:07 2019 +1200
support @royalesuppressexport on public fields
commit cea3363e6b0c7220015ff423c14b708f320dd83a
Author: greg-dove <gr...@gmail.com>
Date: Wed May 22 13:35:20 2019 +1200
Added 2 new doc directives for tuning js output: royalesuppressclosure and royalesuppressexport
commit 68293a747ff8e49f9c6a9152cca82f3a656ec0a4
Author: greg-dove <gr...@gmail.com>
Date: Sun May 19 18:07:49 2019 +1200
Avoid some Language warnings
Avoid some java language warnings in this code
commit e59fbf8152c09b65dbf7bb2dc74913a06b10c69d
Author: greg-dove <gr...@gmail.com>
Date: Sun May 19 17:32:23 2019 +1200
Allow line-based separation of individual additionalCompilerOptions entries in pom.xml
commit 54b062bce8a75d4de52c2b2a9d25a4ba92b431b0
Author: greg-dove <gr...@gmail.com>
Date: Wed May 15 10:51:57 2019 +1200
Fix for an XML bug identified in testing.
commit 4dade1a0500767a35b051829ebf2908254f22438
Author: greg-dove <gr...@gmail.com>
Date: Tue May 7 17:57:32 2019 +1200
remove 'no' from new config settings and toggle defaults accordingly (group review decision)
commit f11f18215f5d4c127b9715bc2f1e19c5a7a88d51
Author: greg-dove <gr...@gmail.com>
Date: Sun May 5 07:39:10 2019 +1200
code tidy
commit 88b2c1f52e7b15d2573d1d40e6963de4aa15b24f
Author: greg-dove <gr...@gmail.com>
Date: Sat May 4 18:21:57 2019 +1200
Squashed commit of cumulative work on Language improvements
---
.../royale/compiler/asdoc/royale/ASDocComment.java | 2 +-
.../royale/compiler/clients/JSConfiguration.java | 121 +++++-
.../codegen/js/goog/IJSGoogDocEmitter.java | 2 +-
.../compiler/internal/codegen/js/JSEmitter.java | 207 +++++++++-
.../internal/codegen/js/goog/JSGoogDocEmitter.java | 48 ++-
.../internal/codegen/js/jx/AccessorEmitter.java | 8 +-
.../internal/codegen/js/jx/AsIsEmitter.java | 31 +-
.../codegen/js/jx/BinaryOperatorEmitter.java | 44 ++-
.../internal/codegen/js/jx/ClassEmitter.java | 4 +-
.../codegen/js/jx/DynamicAccessEmitter.java | 54 +++
.../codegen/js/jx/FunctionCallEmitter.java | 429 ++++++++++++++++-----
.../internal/codegen/js/jx/IdentifierEmitter.java | 42 +-
.../internal/codegen/js/jx/InterfaceEmitter.java | 10 +
.../codegen/js/jx/MemberAccessEmitter.java | 41 +-
.../internal/codegen/js/jx/MethodEmitter.java | 8 +-
.../codegen/js/jx/PackageFooterEmitter.java | 2 +-
.../codegen/js/jx/UnaryOperatorEmitter.java | 29 ++
.../codegen/js/royale/JSRoyaleDocEmitter.java | 129 ++++++-
.../codegen/js/royale/JSRoyaleEmitter.java | 47 ++-
.../codegen/js/royale/JSRoyaleEmitterTokens.java | 11 +-
.../internal/codegen/js/utils/DocEmitterUtils.java | 9 +
.../internal/projects/RoyaleJSProject.java | 20 +-
.../compiler/utils/JSClosureCompilerWrapper.java | 2 +
.../apache/royale/compiler/utils/NativeUtils.java | 43 ++-
.../codegen/js/goog/TestGoogFieldMembers.java | 4 +-
.../codegen/js/goog/TestGoogGlobalClasses.java | 2 +-
.../codegen/js/goog/TestGoogGlobalFunctions.java | 2 +-
.../codegen/js/royale/TestRoyaleExpressions.java | 10 +-
.../codegen/js/royale/TestRoyaleFieldMembers.java | 4 +-
.../codegen/js/royale/TestRoyaleGlobalClasses.java | 251 +++++++++++-
.../js/royale/TestRoyaleGlobalFunctions.java | 50 ++-
.../internal/tree/as/DynamicAccessNode.java | 7 +-
.../org/apache/royale/compiler/ant/FlexTask.java | 10 +-
.../java/org/apache/royale/maven/BaseMojo.java | 12 +-
34 files changed, 1447 insertions(+), 248 deletions(-)
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/asdoc/royale/ASDocComment.java b/compiler-jx/src/main/java/org/apache/royale/compiler/asdoc/royale/ASDocComment.java
index a1006dc..21bdc95 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/asdoc/royale/ASDocComment.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/asdoc/royale/ASDocComment.java
@@ -134,7 +134,7 @@ public class ASDocComment implements IASDocComment
tags = new ArrayList<IASDocTag>();
tagMap.put(tagName, tags);
}
- tags.add(new ASDocTag(tagName, line.substring(after + 1)));
+ tags.add(new ASDocTag(tagName, line.substring(after + 1).trim()));
}
}
}
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/clients/JSConfiguration.java b/compiler-jx/src/main/java/org/apache/royale/compiler/clients/JSConfiguration.java
index 357a838..eda4012 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/clients/JSConfiguration.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/clients/JSConfiguration.java
@@ -457,13 +457,128 @@ public class JSConfiguration extends Configuration
}
/**
- * The class to use instead of Array for handling Vector.
+ * The class to use instead of default Vector implementation for handling Vector.
*/
@Config(advanced = true)
public void setJsVectorEmulationClass(ConfigurationValue cv, String b)
{
jsVectorEmulationClass = b;
}
-
-
+
+
+ //
+ // 'js-complex-implicit-coercions'
+ //
+
+ private boolean jsComplexImplicitCoercions = true;
+
+ public boolean getJsComplexImplicitCoercions()
+ {
+ return jsComplexImplicitCoercions;
+ }
+
+ /**
+ * Support for including/avoiding more complex implicit assignment coercions
+ * example
+ * var array:Array = [new MyClass()];
+ * var myOtherClass:MyOtherClass = array[0];
+ *
+ * In the above example, the compiler will (by default) output an implicit coercion
+ * that is equivalent in actionscript to:
+ * var myOtherClass:MyOtherClass = MyOtherClass(array[0]);
+ *
+ * By setting this configuration option to false, the implicit coercion code in situations similar to the above
+ * is not generated (other primitive implicit coercions, such as int/uint/Number/String and Boolean coercions remain)
+ * This is a global setting for the current source code being compiled, it is possible to leave it on and specifically avoid it via doc
+ * settings. The doc comment compiler directive for that is: @royalesuppresscompleximplicitcoercion
+ * Another option is to add the explicit coercions in code and then avoid their output
+ * via specific @royaleignorecoercion doc comment directives. Doing so however may add extra unwanted output
+ * in other compiler targets (for example, swf bytecode) if the same source code is shared between targets.
+ */
+ @Config(advanced = true)
+ @Mapping("js-complex-implicit-coercions")
+ public void setJsComplexImplicitCoercions(ConfigurationValue cv, boolean value)
+ throws ConfigurationException
+ {
+ jsComplexImplicitCoercions = value;
+ }
+
+ //
+ // 'js-resolve-uncertain'
+ //
+
+ private boolean jsResolveUncertain = true;
+
+ public boolean getJsResolveUncertain()
+ {
+ return jsResolveUncertain;
+ }
+
+ /**
+ * Support for avoiding more overhead of resolving instantiations from
+ * unknown constructors
+ * example
+ * var myClass:Class = String;
+ * var myString:* = new myClass("test");
+ *
+ * In the above example, the compiler will (by default) output
+ * a call to a Language.resolveUncertain method which wraps the 'new myClass("test")'
+ *
+ *
+ * This normalizes the return value for some primitive constructors, so that (for example)
+ * strict equality and inequality operators provide the same results between compiler
+ * targets.
+ * In situations where it is certain that the resolveUncertain method is not needed,
+ * this option provides a way to switch it off 'globally' for the current source code being compiled.
+ * It can also be switched off or on locally using the '@royalesuppressresolveuncertain'
+ * doc comment compiler directive.
+ */
+ @Config(advanced = true)
+ @Mapping("js-resolve-uncertain")
+ public void setJsResolveUncertain(ConfigurationValue cv, boolean value)
+ throws ConfigurationException
+ {
+ jsResolveUncertain = value;
+ }
+
+ //
+ // 'js-vector-index-checks'
+ //
+
+ private boolean jsVectorIndexChecks = true;
+
+ public boolean getJsVectorIndexChecks()
+ {
+ return jsVectorIndexChecks;
+ }
+
+ /**
+ * Support for avoiding more overhead of adding checks into
+ * assignments via Vector index access
+ * example
+ * var myVector:Vector.<int> = new Vector.<int>();
+ * myVector[0] = 42;
+ *
+ * In the above example, the compiler will (by default) wrap
+ * the '0' inside myVector[0] with a method call on the vector instance
+ * that checks to see if the index is valid for the Vector it is being used against
+ *
+ * This check will throw an error if the index is out of range, and the
+ * range checking differs if the Vector is 'fixed' or non-'fixed'
+ *
+ * In situations where it is certain that the index will always be valid for Vector instance
+ * being targeted, or where all cases in a given codebase are certain to be valid, it is possible
+ * to avoid the overhead of this check. This is especially important in loops.
+ * This config setting affects the global setting for the current source code being compiled.
+ * It can be adjusted locally within code, using the '@royalesuppressvectorindexcheck'
+ * doc comment compiler directive.
+ */
+ @Config(advanced = true)
+ @Mapping("js-vector-index-checks")
+ public void setJsVectorIndexChecks(ConfigurationValue cv, boolean value)
+ throws ConfigurationException
+ {
+ jsVectorIndexChecks = value;
+ }
+
}
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/codegen/js/goog/IJSGoogDocEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/codegen/js/goog/IJSGoogDocEmitter.java
index 112f3a0..6c99459 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/codegen/js/goog/IJSGoogDocEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/codegen/js/goog/IJSGoogDocEmitter.java
@@ -134,7 +134,7 @@ public interface IJSGoogDocEmitter extends IJSDocEmitter
void emitThis(ITypeDefinition node, String packageName);
- void emitType(IASNode node, String packageName);
+ void emitType(IASNode node, String packageName, ICompilerProject project);
void emitType(String type, String packageName);
}
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/JSEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/JSEmitter.java
index 45baa5a..a60ffbc 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/JSEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/JSEmitter.java
@@ -23,6 +23,7 @@ import java.io.FilterWriter;
import java.util.ArrayList;
import java.util.List;
+import org.apache.royale.compiler.codegen.IASGlobalFunctionConstants;
import org.apache.royale.compiler.codegen.IDocEmitter;
import org.apache.royale.compiler.codegen.IEmitter;
import org.apache.royale.compiler.codegen.ISubEmitter;
@@ -32,6 +33,8 @@ import org.apache.royale.compiler.common.ISourceLocation;
import org.apache.royale.compiler.constants.IASLanguageConstants;
import org.apache.royale.compiler.constants.IMetaAttributeConstants;
import org.apache.royale.compiler.constants.IASLanguageConstants.BuiltinType;
+import org.apache.royale.compiler.definitions.IAppliedVectorDefinition;
+import org.apache.royale.compiler.definitions.IClassDefinition;
import org.apache.royale.compiler.definitions.IDefinition;
import org.apache.royale.compiler.definitions.metadata.IMetaTag;
import org.apache.royale.compiler.definitions.metadata.IMetaTagAttribute;
@@ -64,8 +67,10 @@ import org.apache.royale.compiler.internal.codegen.js.jx.UnaryOperatorEmitter;
import org.apache.royale.compiler.internal.codegen.js.jx.WhileLoopEmitter;
import org.apache.royale.compiler.internal.codegen.js.jx.WithEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleDocEmitter;
+import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitterTokens;
+import org.apache.royale.compiler.internal.projects.RoyaleJSProject;
import org.apache.royale.compiler.internal.semantics.SemanticUtils;
-import org.apache.royale.compiler.internal.tree.as.FunctionNode;
+import org.apache.royale.compiler.internal.tree.as.*;
import org.apache.royale.compiler.projects.ICompilerProject;
import org.apache.royale.compiler.tree.as.IASNode;
import org.apache.royale.compiler.tree.as.ICatchNode;
@@ -97,6 +102,9 @@ import org.apache.royale.compiler.tree.as.IWithNode;
import com.google.debugging.sourcemap.FilePosition;
+import org.apache.royale.compiler.internal.codegen.as.ASEmitterTokens;
+import org.apache.royale.compiler.utils.NativeUtils;
+
/**
* @author Michael Schmalle
*/
@@ -220,12 +228,12 @@ public class JSEmitter extends ASEmitter implements IJSEmitter
public void emitClosureStart()
{
-
+
}
public void emitClosureEnd(IASNode node, IDefinition nodeDef)
{
-
+
}
public void emitSourceMapDirective(ITypeNode node)
@@ -502,7 +510,7 @@ public class JSEmitter extends ASEmitter implements IJSEmitter
/**
* Adjusts the line numbers saved in the source map when a line should be
* removed during post processing.
- *
+ *
* @param lineIndex
*/
protected void removeLineFromMappings(int lineIndex)
@@ -547,6 +555,7 @@ public class JSEmitter extends ASEmitter implements IJSEmitter
}
String coercionStart = null;
String coercionEnd = null;
+ boolean avoidCoercion = false;
if (project.getBuiltinType(BuiltinType.INT).equals(definition))
{
boolean needsCoercion = false;
@@ -567,6 +576,10 @@ public class JSEmitter extends ASEmitter implements IJSEmitter
endMapping(assignedNode);
return;
}
+ else if(assignedNode instanceof BinaryOperatorAsNode)
+ {
+ needsCoercion = true;
+ }
else if(!project.getBuiltinType(BuiltinType.INT).equals(assignedTypeDef))
{
needsCoercion = true;
@@ -597,6 +610,10 @@ public class JSEmitter extends ASEmitter implements IJSEmitter
endMapping(assignedNode);
return;
}
+ else if(assignedNode instanceof BinaryOperatorAsNode)
+ {
+ needsCoercion = true;
+ }
else if(!project.getBuiltinType(BuiltinType.UINT).equals(assignedTypeDef))
{
needsCoercion = true;
@@ -632,6 +649,8 @@ public class JSEmitter extends ASEmitter implements IJSEmitter
if (t.equals(IASLanguageConstants.Number))
{
needsCoercion = false;
+ //explicitly prevent other coercion detection rules from picking this up
+ avoidCoercion = true;
}
}
}
@@ -696,6 +715,186 @@ public class JSEmitter extends ASEmitter implements IJSEmitter
coercionStart = "org.apache.royale.utils.Language.string(";
}
}
+ if ( assignedDef != null
+ && assignedDef instanceof IAppliedVectorDefinition
+ && assignedNode instanceof TypedExpressionNode) {
+ //assign a Vector class as the assigned value, e.g. var c:Class = Vector.<int>
+ if (project instanceof RoyaleJSProject
+ && ((RoyaleJSProject)project).config.getJsVectorEmulationClass() != null) {
+ startMapping(assignedNode);
+ write(((RoyaleJSProject)project).config.getJsVectorEmulationClass());
+ endMapping(assignedNode);
+ } else {
+ startMapping(assignedNode);
+ write(JSRoyaleEmitterTokens.SYNTH_VECTOR);
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ //the element type of the Vector:
+ write(formatQualifiedName(((TypedExpressionNode)assignedNode).getTypeNode().resolve(project).getQualifiedName()));
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ endMapping(assignedNode);
+ if (project instanceof RoyaleJSProject)
+ ((RoyaleJSProject)project).needLanguage = true;
+ getModel().needLanguage = true;
+ }
+ return;
+ }
+ if (assignedDef instanceof IClassDefinition
+ && assignedNode instanceof IdentifierNode
+ && ((IdentifierNode)assignedNode).getName().equals(IASGlobalFunctionConstants.Vector)
+ && project instanceof RoyaleJSProject
+ && ((RoyaleJSProject)project).config.getJsVectorEmulationClass() == null ){
+ startMapping(assignedNode);
+ write(JSRoyaleEmitterTokens.SYNTH_VECTOR);
+ write(ASEmitterTokens.PAREN_OPEN);
+ //null to signify not a valid constructor
+ write(ASEmitterTokens.NULL);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ endMapping(assignedNode);
+ if (project instanceof RoyaleJSProject)
+ ((RoyaleJSProject)project).needLanguage = true;
+ getModel().needLanguage = true;
+ return;
+ }
+ if (coercionStart == null
+ && !avoidCoercion
+ && assignedTypeDef !=null
+ && definition !=null
+ && (project.getBuiltinType(BuiltinType.ANY_TYPE).equals(assignedTypeDef)
+ || project.getBuiltinType(BuiltinType.OBJECT).equals(assignedTypeDef))
+ && !(project.getBuiltinType(BuiltinType.ANY_TYPE).equals(definition)
+ || project.getBuiltinType(BuiltinType.OBJECT).equals(definition))) {
+ //catch leftovers: remaining implicit coercion of loosely typed assigned values to strongly typed context
+ //assignment to Class definitions is excluded because there is no 'Class' type in JS
+ //Possibility: 'Class' could be implemented as a synthType
+ boolean needsCoercion = ((RoyaleJSProject)project).config.getJsComplexImplicitCoercions();
+
+ IDocEmitter docEmitter = getDocEmitter();
+ if (docEmitter instanceof JSRoyaleDocEmitter)
+ {
+ JSRoyaleDocEmitter royaleDocEmitter = (JSRoyaleDocEmitter) docEmitter;
+ //check for local toggle
+ needsCoercion = royaleDocEmitter.getLocalSettingAsBoolean(
+ JSRoyaleEmitterTokens.SUPPRESS_COMPLEX_IMPLICIT_COERCION, needsCoercion);
+ if (needsCoercion) {
+ //check for individual specified suppression
+
+ String definitionName = definition.getQualifiedName();
+ //for Vectors, use the unqualified name to match the source code
+ if (NativeUtils.isVector(definitionName)) {
+ definitionName = definition.getBaseName();
+ }
+
+ if (royaleDocEmitter.getLocalSettingIncludesString(
+ JSRoyaleEmitterTokens.SUPPRESS_COMPLEX_IMPLICIT_COERCION,
+ definitionName))
+ {
+ needsCoercion = false;
+ }
+
+ }
+ }
+
+ //Avoid specific compile-time 'fake' class(es)
+ if (needsCoercion && definition.getQualifiedName().equals("org.apache.royale.core.WrappedHTMLElement")) {
+ //*actual* coercion fails here, because this is not actually instantiated, it is
+ //simply a type definition representing the 'wrapped' (or tagged) HTMLElement
+ needsCoercion = false;
+ }
+
+ //Avoid XML/XMLList:
+ if (needsCoercion && project.getBuiltinType(BuiltinType.XML) != null) {
+ if (project.getBuiltinType(BuiltinType.XML).equals(definition)
+ || project.getBuiltinType(BuiltinType.XMLLIST).equals(definition)) {
+ //XML/XMLList has complex output and would need more work
+ needsCoercion = false;
+ }
+ }
+
+ //avoid scenario with ArrayElementType specified as metadata definition type - assume it is 'typed'
+ if (needsCoercion && assignedNode instanceof IDynamicAccessNode)
+ {
+ IDynamicAccessNode dynamicAccess = (IDynamicAccessNode) assignedNode;
+ IDefinition dynamicAccessIndexDef = dynamicAccess.getRightOperandNode().resolveType(project);
+ if (project.getBuiltinType(BuiltinType.NUMBER).equals(dynamicAccessIndexDef))
+ {
+ IDefinition leftDef = dynamicAccess.getLeftOperandNode().resolveType(project);
+ if (leftDef != null) {
+ IMetaTag[] metas = leftDef.getAllMetaTags();
+ for (IMetaTag meta : metas)
+ {
+ if (meta.getTagName().equals(IMetaAttributeConstants.ATTRIBUTE_ARRAYELEMENTTYPE))
+ {
+ IMetaTagAttribute[] attrs = meta.getAllAttributes();
+ for (IMetaTagAttribute attr : attrs)
+ {
+ String t = attr.getValue();
+ if (t.equals(definition.getQualifiedName()))
+ {
+ needsCoercion = false;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (needsCoercion && project.getBuiltinType(BuiltinType.STRING).equals(definition)) {
+ //explicit suppression of String coercion
+ if (docEmitter instanceof JSRoyaleDocEmitter)
+ {
+ JSRoyaleDocEmitter royaleDocEmitter = (JSRoyaleDocEmitter) docEmitter;
+ needsCoercion = royaleDocEmitter.emitStringConversions;
+ }
+ if (needsCoercion
+ && assignedNode instanceof FunctionCallNode
+ && ((FunctionCallNode) assignedNode).getNameNode() instanceof MemberAccessExpressionNode
+ && ((MemberAccessExpressionNode)((FunctionCallNode) assignedNode).getNameNode()).getRightOperandNode() instanceof IdentifierNode
+ && ((IdentifierNode)(((MemberAccessExpressionNode)((FunctionCallNode) assignedNode).getNameNode()).getRightOperandNode())).getName().equals("toString")) {
+ //even if toString() is called in an untyped way, assume a call to a method named 'toString' is actually providing a String
+ needsCoercion = false;
+ }
+ }
+
+ if (needsCoercion) {
+ //add a comment tag leader, so implicit casts are identifiable in the output
+ coercionStart = "/* implicit cast */ "
+ + JSRoyaleEmitterTokens.LANGUAGE_QNAME.getToken()
+ + ASEmitterTokens.MEMBER_ACCESS.getToken()
+ + ASEmitterTokens.AS.getToken()
+ + ASEmitterTokens.PAREN_OPEN.getToken();
+ String coercionTypeString = formatQualifiedName(definition.getQualifiedName());
+ if (NativeUtils.isSyntheticJSType(coercionTypeString)) {
+ String synthCall;
+ String synthethicType;
+ if (NativeUtils.isVector(coercionTypeString)) {
+ synthCall = JSRoyaleEmitterTokens.SYNTH_VECTOR.getToken();
+ synthethicType = formatQualifiedName(coercionTypeString.substring(8, coercionTypeString.length() -1));
+ } else {
+ synthCall = JSRoyaleEmitterTokens.SYNTH_TYPE.getToken();
+ synthethicType = coercionTypeString;
+ }
+ coercionTypeString = synthCall
+ + ASEmitterTokens.PAREN_OPEN.getToken()
+ + ASEmitterTokens.SINGLE_QUOTE.getToken()
+ + synthethicType
+ + ASEmitterTokens.SINGLE_QUOTE.getToken()
+ + ASEmitterTokens.PAREN_CLOSE.getToken();
+ }
+
+ coercionEnd = ASEmitterTokens.COMMA.getToken()
+ + ASEmitterTokens.SPACE.getToken()
+ + coercionTypeString
+ + ASEmitterTokens.COMMA.getToken()
+ + ASEmitterTokens.SPACE.getToken()
+ + ASEmitterTokens.TRUE.getToken()
+ + ASEmitterTokens.PAREN_CLOSE.getToken();
+ if (project instanceof RoyaleJSProject)
+ ((RoyaleJSProject)project).needLanguage = true;
+ getModel().needLanguage = true;
+ }
+ }
if (coercionStart != null)
{
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/goog/JSGoogDocEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/goog/JSGoogDocEmitter.java
index 6c94259..c64823a 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/goog/JSGoogDocEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/goog/JSGoogDocEmitter.java
@@ -39,6 +39,7 @@ import org.apache.royale.compiler.internal.codegen.js.JSSharedData;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitter;
import org.apache.royale.compiler.internal.scopes.ASScope;
import org.apache.royale.compiler.internal.semantics.SemanticUtils;
+import org.apache.royale.compiler.internal.tree.as.TypedExpressionNode;
import org.apache.royale.compiler.projects.ICompilerProject;
import org.apache.royale.compiler.tree.as.IASNode;
import org.apache.royale.compiler.tree.as.IClassNode;
@@ -128,7 +129,7 @@ public class JSGoogDocEmitter extends JSDocEmitter implements IJSGoogDocEmitter
if (def != null)
packageName = def.getPackageName();
- emitType(node, packageName);
+ emitType(node, packageName, project);
end();
}
@@ -257,15 +258,14 @@ public class JSGoogDocEmitter extends JSDocEmitter implements IJSGoogDocEmitter
packageName = ((ITypeDefinition) type).getPackageName();
}
}
-
- emitTypeShort(node, project.getActualPackageName(packageName));
+ emitTypeShort(node, project.getActualPackageName(packageName), project);
}
else
{
writeNewline();
begin();
emitConst(node);
- emitType(node, project.getActualPackageName(packageName));
+ emitType(node, project.getActualPackageName(packageName), project);
end();
}
}
@@ -361,9 +361,18 @@ public class JSGoogDocEmitter extends JSDocEmitter implements IJSGoogDocEmitter
}
@Override
- public void emitType(IASNode node, String packageName)
+ public void emitType(IASNode node, String packageName, ICompilerProject project)
{
String type = ((IVariableNode) node).getVariableType();
+ if (((IVariableNode) node).getVariableTypeNode() instanceof TypedExpressionNode) {
+ ITypeDefinition elemenTypeDef = ((TypedExpressionNode)(((IVariableNode) node).getVariableTypeNode())).getTypeNode().resolveType(project);
+ if (elemenTypeDef != null) {
+ type = "Vector.<" +
+ convertASTypeToJS(elemenTypeDef.getQualifiedName(),"")
+ +">";
+ packageName = "";
+ }
+ }
emitJSDocLine(JSGoogDocEmitterTokens.TYPE.getToken(),
convertASTypeToJS(type, packageName));
}
@@ -375,9 +384,18 @@ public class JSGoogDocEmitter extends JSDocEmitter implements IJSGoogDocEmitter
convertASTypeToJS(type, packageName));
}
- public void emitTypeShort(IASNode node, String packageName)
+ public void emitTypeShort(IASNode node, String packageName, ICompilerProject project)
{
String type = ((IVariableNode) node).getVariableType();
+ if (((IVariableNode) node).getVariableTypeNode() instanceof TypedExpressionNode) {
+ ITypeDefinition elemenTypeDef = ((TypedExpressionNode)(((IVariableNode) node).getVariableTypeNode())).getTypeNode().resolveType(project);
+ if (elemenTypeDef != null) {
+ type = "Vector.<" +
+ convertASTypeToJS(elemenTypeDef.getQualifiedName(),"")
+ +">";
+ packageName = "";
+ }
+ }
writeToken(JSDocEmitterTokens.JSDOC_OPEN);
write(ASEmitterTokens.ATSIGN);
writeToken(JSGoogDocEmitterTokens.TYPE);
@@ -494,16 +512,18 @@ public class JSGoogDocEmitter extends JSDocEmitter implements IJSGoogDocEmitter
// is a vector so convert the element type
String elementType = name.substring(8, name.length() - 1);
elementType = convertASTypeToJSType(elementType, pname);
- name = "Vector.<" + elementType + ">";
+ name = "Array.<" + elementType + ">";
}
- IASGlobalFunctionConstants.BuiltinType[] builtinTypes = IASGlobalFunctionConstants.BuiltinType
- .values();
- for (IASGlobalFunctionConstants.BuiltinType builtinType : builtinTypes)
- {
- if (name.equalsIgnoreCase(builtinType.getName()))
+ else {
+ IASGlobalFunctionConstants.BuiltinType[] builtinTypes = IASGlobalFunctionConstants.BuiltinType
+ .values();
+ for (IASGlobalFunctionConstants.BuiltinType builtinType : builtinTypes)
{
- isBuiltinFunction = true;
- break;
+ if (name.equalsIgnoreCase(builtinType.getName()))
+ {
+ isBuiltinFunction = true;
+ break;
+ }
}
}
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/AccessorEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/AccessorEmitter.java
index 428f542..e3bd834 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/AccessorEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/AccessorEmitter.java
@@ -105,7 +105,7 @@ public class AccessorEmitter extends JSSubEmitter implements
if (emitExports)
writeNewline(" * @export");
if (p.type != null)
- writeNewline(" * @type {"+JSGoogDocEmitter.convertASTypeToJSType(p.type.getBaseName(), p.type.getPackageName()) + "} */");
+ writeNewline(" * @type {"+ JSGoogDocEmitter.convertASTypeToJSType(p.type.getBaseName(), p.type.getPackageName()) + "} */");
else
writeNewline(" */");
write(getEmitter().formatQualifiedName(qname));
@@ -321,7 +321,7 @@ public class AccessorEmitter extends JSSubEmitter implements
if (emitExports)
writeNewline(" * @export");
if (p.type != null)
- writeNewline(" * @type {"+JSGoogDocEmitter.convertASTypeToJSType(p.type.getBaseName(), p.type.getPackageName()) + "} */");
+ writeNewline(" * @type {" + JSGoogDocEmitter.convertASTypeToJSType(p.type.getBaseName(), p.type.getPackageName()) + "} */");
else
writeNewline(" */");
FunctionNode fnNode = getterNode != null ? (FunctionNode) getterNode : (FunctionNode) setterNode;
@@ -483,7 +483,7 @@ public class AccessorEmitter extends JSSubEmitter implements
if (emitExports)
writeNewline(" * @export");
if (p.type != null)
- writeNewline(" * @type {"+JSGoogDocEmitter.convertASTypeToJSType(p.type.getBaseName(), p.type.getPackageName()) + "} */");
+ writeNewline(" * @type {" + JSGoogDocEmitter.convertASTypeToJSType(p.type.getBaseName(), p.type.getPackageName()) + "} */");
else
writeNewline(" */");
write(getEmitter().formatQualifiedName(qname));
@@ -602,7 +602,7 @@ public class AccessorEmitter extends JSSubEmitter implements
if (emitExports)
writeNewline(" * @export");
if (p.type != null)
- writeNewline(" * @type {"+JSGoogDocEmitter.convertASTypeToJSType(p.type.getBaseName(), p.type.getPackageName()) + "} */");
+ writeNewline(" * @type {" + JSGoogDocEmitter.convertASTypeToJSType(p.type.getBaseName(), p.type.getPackageName()) + "} */");
else
writeNewline(" */");
write(propName);
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/AsIsEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/AsIsEmitter.java
index e8ffe98..9ddea56 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/AsIsEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/AsIsEmitter.java
@@ -22,6 +22,7 @@ package org.apache.royale.compiler.internal.codegen.js.jx;
import org.apache.royale.compiler.asdoc.royale.ASDocComment;
import org.apache.royale.compiler.codegen.js.IJSEmitter;
import org.apache.royale.compiler.constants.IASLanguageConstants;
+import org.apache.royale.compiler.definitions.IAppliedVectorDefinition;
import org.apache.royale.compiler.definitions.IClassDefinition;
import org.apache.royale.compiler.definitions.IDefinition;
import org.apache.royale.compiler.internal.codegen.as.ASEmitterTokens;
@@ -29,12 +30,14 @@ import org.apache.royale.compiler.internal.codegen.js.JSSubEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitterTokens;
import org.apache.royale.compiler.internal.projects.RoyaleJSProject;
+import org.apache.royale.compiler.parsing.IASToken;
import org.apache.royale.compiler.projects.ICompilerProject;
import org.apache.royale.compiler.tree.ASTNodeID;
import org.apache.royale.compiler.tree.as.IASNode;
import org.apache.royale.compiler.tree.as.IBinaryOperatorNode;
import org.apache.royale.compiler.tree.as.IExpressionNode;
import org.apache.royale.compiler.tree.as.IFunctionNode;
+import org.apache.royale.compiler.utils.NativeUtils;
public class AsIsEmitter extends JSSubEmitter
{
@@ -53,7 +56,7 @@ public class AsIsEmitter extends JSSubEmitter
.resolve(getProject()) : null;
if (id != ASTNodeID.Op_IsID && dnode != null)
{
- boolean emit = coercion ?
+ boolean emit = coercion ?
!((RoyaleJSProject)getProject()).config.getJSOutputOptimizations().contains(JSRoyaleEmitterTokens.SKIP_FUNCTION_COERCIONS.getToken()) :
!((RoyaleJSProject)getProject()).config.getJSOutputOptimizations().contains(JSRoyaleEmitterTokens.SKIP_AS_COERCIONS.getToken());
@@ -147,7 +150,7 @@ public class AsIsEmitter extends JSSubEmitter
getEmitter().getModel().needLanguage = true;
if (node instanceof IBinaryOperatorNode)
{
- IBinaryOperatorNode binaryOperatorNode = (IBinaryOperatorNode) node;
+ IBinaryOperatorNode binaryOperatorNode = (IBinaryOperatorNode) node;
startMapping(node, binaryOperatorNode.getLeftOperandNode());
}
else
@@ -181,7 +184,29 @@ public class AsIsEmitter extends JSSubEmitter
if (dnode instanceof IClassDefinition)
{
startMapping(right);
- write(getEmitter().formatQualifiedName(((JSRoyaleEmitter)getEmitter()).convertASTypeToJS(dnode.getQualifiedName())));
+ if (NativeUtils.isSyntheticJSType(dnode.getQualifiedName())) {
+ JSRoyaleEmitterTokens langMethod;
+ String synthName;
+ if (NativeUtils.isVector(dnode.getQualifiedName()) && dnode instanceof IAppliedVectorDefinition) {
+ langMethod = JSRoyaleEmitterTokens.SYNTH_VECTOR;
+ synthName = getEmitter().formatQualifiedName(((IAppliedVectorDefinition) dnode).resolveElementType(project).getQualifiedName());
+ } else {
+ //non-vector, e.g. int/uint
+ langMethod = JSRoyaleEmitterTokens.SYNTH_TYPE;
+ synthName = getEmitter().formatQualifiedName(dnode.getQualifiedName());
+ }
+ write(langMethod);
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(synthName);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ if (project instanceof RoyaleJSProject)
+ ((RoyaleJSProject)project).needLanguage = true;
+ getEmitter().getModel().needLanguage = true;
+ } else {
+ write(getEmitter().formatQualifiedName(((JSRoyaleEmitter)getEmitter()).convertASTypeToJS(dnode.getQualifiedName())));
+ }
endMapping(right);
}
else
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java
index 1533bf4..8d6c103 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java
@@ -21,6 +21,7 @@ package org.apache.royale.compiler.internal.codegen.js.jx;
import org.apache.royale.compiler.codegen.ISubEmitter;
import org.apache.royale.compiler.codegen.js.IJSEmitter;
+import org.apache.royale.compiler.constants.IASLanguageConstants;
import org.apache.royale.compiler.definitions.IDefinition;
import org.apache.royale.compiler.definitions.ITypeDefinition;
import org.apache.royale.compiler.internal.codegen.as.ASEmitterTokens;
@@ -30,10 +31,10 @@ import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.goog.JSGoogEmitterTokens;
import org.apache.royale.compiler.internal.definitions.AccessorDefinition;
+import org.apache.royale.compiler.internal.definitions.AppliedVectorDefinition;
+import org.apache.royale.compiler.internal.projects.RoyaleJSProject;
import org.apache.royale.compiler.internal.semantics.SemanticUtils;
-import org.apache.royale.compiler.internal.tree.as.DynamicAccessNode;
-import org.apache.royale.compiler.internal.tree.as.MemberAccessExpressionNode;
-import org.apache.royale.compiler.internal.tree.as.UnaryOperatorAtNode;
+import org.apache.royale.compiler.internal.tree.as.*;
import org.apache.royale.compiler.tree.ASTNodeID;
import org.apache.royale.compiler.tree.as.IASNode;
import org.apache.royale.compiler.tree.as.IBinaryOperatorNode;
@@ -100,7 +101,7 @@ public class BinaryOperatorEmitter extends JSSubEmitter implements
{
IASNode lnode = leftSide.getChild(0);
IASNode rnode = leftSide.getChild(1);
- IDefinition rnodeDef = (rnode instanceof IIdentifierNode) ?
+ IDefinition rnodeDef = (rnode instanceof IIdentifierNode) ?
((IIdentifierNode) rnode).resolve(getWalker().getProject()) :
null;
boolean isDynamicAccess = rnode instanceof DynamicAccessNode;
@@ -117,7 +118,7 @@ public class BinaryOperatorEmitter extends JSSubEmitter implements
else
write(getEmitter().formatQualifiedName(
getModel().getCurrentClass().getQualifiedName()));
-
+
write(ASEmitterTokens.MEMBER_ACCESS);
write(JSGoogEmitterTokens.SUPERCLASS);
write(ASEmitterTokens.MEMBER_ACCESS);
@@ -391,10 +392,11 @@ public class BinaryOperatorEmitter extends JSSubEmitter implements
}
}
-
- super_emitBinaryOperator(node, isAssignment);
+
+ super_emitBinaryOperator(node, isAssignment);
}
}
+
private void super_emitBinaryOperator(IBinaryOperatorNode node, boolean isAssignment)
{
@@ -431,8 +433,28 @@ public class BinaryOperatorEmitter extends JSSubEmitter implements
}
else
{
- getWalker().walk(node.getLeftOperandNode());
-
+ if (isAssignment
+ && (getProject() instanceof RoyaleJSProject && ((RoyaleJSProject) getProject()).config != null && ((RoyaleJSProject) getProject()).config.getJsVectorEmulationClass() == null)
+ && node.getLeftOperandNode() instanceof MemberAccessExpressionNode
+ && ((MemberAccessExpressionNode) node.getLeftOperandNode()).getRightOperandNode() instanceof IdentifierNode
+ && ((IdentifierNode) ((MemberAccessExpressionNode) node.getLeftOperandNode()).getRightOperandNode()).getName().equals("length")
+ && ((MemberAccessExpressionNode) node.getLeftOperandNode()).getLeftOperandNode().resolveType(getProject()) instanceof AppliedVectorDefinition)
+ {
+ //for default Vector implementation, when setting length, we need to set it on the associated 'synthType' instance which tags the native
+ //Array representation of the Vector. This allows running 'setter' code because it is not possible to override the native length setter on Array
+ //unless using a different approach, like es6 Proxy.
+ //this code inserts the extra access name for setting length, e.g. myVectInstance['_synthType'].length = assignedValue
+ //the dynamic access field name is a constant on Language, so it can be different/shorter in release build
+ getWalker().walk(((MemberAccessExpressionNode) node.getLeftOperandNode()).getLeftOperandNode());
+ write(ASEmitterTokens.SQUARE_OPEN);
+ write(JSRoyaleEmitterTokens.LANGUAGE_QNAME.getToken());
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write(JSRoyaleEmitterTokens.ROYALE_SYNTH_TAG_FIELD_NAME);
+ write(ASEmitterTokens.SQUARE_CLOSE);
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ getWalker().walk(((MemberAccessExpressionNode) node.getLeftOperandNode()).getRightOperandNode());
+ }
+ else getWalker().walk(node.getLeftOperandNode());
startMapping(node, node.getLeftOperandNode());
if (id != ASTNodeID.Op_CommaID)
@@ -469,12 +491,14 @@ public class BinaryOperatorEmitter extends JSSubEmitter implements
}
else
{
+
getWalker().walk(node.getRightOperandNode());
+
if (node.getNodeID() == ASTNodeID.Op_InID &&
((JSRoyaleEmitter)getEmitter()).isXML(node.getRightOperandNode()))
{
write(".elementNames()");
- }
+ }
else if (node.getNodeID() == ASTNodeID.Op_InID &&
((JSRoyaleEmitter)getEmitter()).isProxy(node.getRightOperandNode()))
{
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/ClassEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/ClassEmitter.java
index 807e7ae..3f6e13e 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/ClassEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/ClassEmitter.java
@@ -67,6 +67,8 @@ public class ClassEmitter extends JSSubEmitter implements
ASDocComment asDoc = (ASDocComment) node.getASDocComment();
if (asDoc != null && keepASDoc)
DocEmitterUtils.loadImportIgnores(fjs, asDoc.commentNoEnd());
+
+ boolean suppressExport = (asDoc != null && DocEmitterUtils.hasSuppressExport(fjs, asDoc.commentNoEnd()));
IClassDefinition definition = node.getDefinition();
@@ -131,7 +133,7 @@ public class ClassEmitter extends JSSubEmitter implements
}
}
- if (!getEmitter().getModel().isExterns)
+ if (!getEmitter().getModel().isExterns && !suppressExport)
{
JSRoyaleDocEmitter doc = (JSRoyaleDocEmitter) getEmitter()
.getDocEmitter();
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/DynamicAccessEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/DynamicAccessEmitter.java
index 2fd5085..5b78317 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/DynamicAccessEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/DynamicAccessEmitter.java
@@ -19,20 +19,30 @@
package org.apache.royale.compiler.internal.codegen.js.jx;
+import org.apache.royale.compiler.codegen.IDocEmitter;
import org.apache.royale.compiler.codegen.ISubEmitter;
import org.apache.royale.compiler.codegen.js.IJSEmitter;
import org.apache.royale.compiler.constants.IASLanguageConstants;
import org.apache.royale.compiler.definitions.ITypeDefinition;
import org.apache.royale.compiler.internal.codegen.as.ASEmitterTokens;
+import org.apache.royale.compiler.internal.codegen.js.JSEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.JSSubEmitter;
+import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleDocEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitter;
+import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitterTokens;
+import org.apache.royale.compiler.internal.definitions.AppliedVectorDefinition;
+import org.apache.royale.compiler.internal.projects.RoyaleJSProject;
+import org.apache.royale.compiler.internal.tree.as.BinaryOperatorAssignmentNode;
import org.apache.royale.compiler.internal.tree.as.FunctionCallNode;
+import org.apache.royale.compiler.internal.tree.as.IdentifierNode;
import org.apache.royale.compiler.internal.tree.as.MemberAccessExpressionNode;
+import org.apache.royale.compiler.parsing.IASToken;
import org.apache.royale.compiler.tree.ASTNodeID;
import org.apache.royale.compiler.tree.as.IDynamicAccessNode;
import org.apache.royale.compiler.tree.as.IExpressionNode;
import org.apache.royale.compiler.tree.as.ILiteralNode;
import org.apache.royale.compiler.tree.as.IOperatorNode.OperatorType;
+import org.apache.royale.compiler.utils.NativeUtils;
public class DynamicAccessEmitter extends JSSubEmitter implements
ISubEmitter<IDynamicAccessNode>
@@ -98,8 +108,52 @@ public class DynamicAccessEmitter extends JSSubEmitter implements
startMapping(node, leftOperandNode);
write(ASEmitterTokens.SQUARE_OPEN);
endMapping(node);
+ boolean wrapVectorIndex = false;
+ if (getProject() instanceof RoyaleJSProject) {
+ if (node.getNodeID().equals(ASTNodeID.ArrayIndexExpressionID)){
+ if (node.getParent() instanceof BinaryOperatorAssignmentNode) {
+ if (node.getLeftOperandNode().resolveType(getProject()) instanceof AppliedVectorDefinition) {
+ boolean suppressVectorIndexCheck = !(((RoyaleJSProject)getProject()).config.getJsVectorIndexChecks());
+
+ IDocEmitter docEmitter = getEmitter().getDocEmitter();
+ if (docEmitter instanceof JSRoyaleDocEmitter)
+ {
+ JSRoyaleDocEmitter royaleDocEmitter = (JSRoyaleDocEmitter) docEmitter;
+ //check for local toggle
+ suppressVectorIndexCheck = royaleDocEmitter.getLocalSettingAsBoolean(
+ JSRoyaleEmitterTokens.SUPPRESS_VECTOR_INDEX_CHECK, suppressVectorIndexCheck);
+
+ if (!suppressVectorIndexCheck) {
+ //check for individual specified suppression, based on variable name
+ if (leftOperandNode instanceof IdentifierNode) {
+ if (royaleDocEmitter.getLocalSettingIncludesString(
+ JSRoyaleEmitterTokens.SUPPRESS_VECTOR_INDEX_CHECK,
+ ((IdentifierNode) leftOperandNode).getName()
+ )){
+ suppressVectorIndexCheck = true;
+ }
+ }
+ }
+ }
+ if (!suppressVectorIndexCheck) {
+ getModel().needLanguage = true;
+ ((RoyaleJSProject) getProject()).needLanguage = true;
+ getWalker().walk(leftOperandNode);
+ write(ASEmitterTokens.SQUARE_OPEN);
+ write(JSRoyaleEmitterTokens.VECTOR_INDEX_CHECK_METHOD_NAME);
+ write(ASEmitterTokens.SQUARE_CLOSE);
+ write(ASEmitterTokens.PAREN_OPEN);
+ wrapVectorIndex = true;
+ }
+ }
+ }
+ }
+ }
getWalker().walk(rightOperandNode);
+ if (wrapVectorIndex) {
+ write(ASEmitterTokens.PAREN_CLOSE);
+ }
if (type != null && type.getQualifiedName().contentEquals(IASLanguageConstants.QName))
write(".objectAccessFormat()");
startMapping(node, rightOperandNode);
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/FunctionCallEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/FunctionCallEmitter.java
index 1e0bae0..855dd76 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/FunctionCallEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/FunctionCallEmitter.java
@@ -20,8 +20,10 @@
package org.apache.royale.compiler.internal.codegen.js.jx;
import org.apache.royale.compiler.codegen.IASGlobalFunctionConstants;
+import org.apache.royale.compiler.codegen.IDocEmitter;
import org.apache.royale.compiler.codegen.ISubEmitter;
import org.apache.royale.compiler.codegen.js.IJSEmitter;
+import org.apache.royale.compiler.common.SourceLocation;
import org.apache.royale.compiler.constants.IASLanguageConstants;
import org.apache.royale.compiler.constants.IASLanguageConstants.BuiltinType;
import org.apache.royale.compiler.definitions.IDefinition;
@@ -29,28 +31,18 @@ import org.apache.royale.compiler.definitions.ITypeDefinition;
import org.apache.royale.compiler.internal.codegen.as.ASEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.JSSessionModel;
import org.apache.royale.compiler.internal.codegen.js.JSSubEmitter;
+import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleDocEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.utils.EmitterUtils;
-import org.apache.royale.compiler.internal.definitions.AppliedVectorDefinition;
-import org.apache.royale.compiler.internal.definitions.ClassDefinition;
-import org.apache.royale.compiler.internal.definitions.FunctionDefinition;
-import org.apache.royale.compiler.internal.definitions.InterfaceDefinition;
-import org.apache.royale.compiler.internal.definitions.NamespaceDefinition;
+import org.apache.royale.compiler.internal.definitions.*;
import org.apache.royale.compiler.internal.projects.RoyaleJSProject;
-import org.apache.royale.compiler.internal.tree.as.ContainerNode;
-import org.apache.royale.compiler.internal.tree.as.IdentifierNode;
-import org.apache.royale.compiler.internal.tree.as.MemberAccessExpressionNode;
-import org.apache.royale.compiler.internal.tree.as.NamespaceIdentifierNode;
-import org.apache.royale.compiler.internal.tree.as.VectorLiteralNode;
+import org.apache.royale.compiler.internal.tree.as.*;
import org.apache.royale.compiler.problems.TooFewFunctionParametersProblem;
import org.apache.royale.compiler.problems.TooManyFunctionParametersProblem;
import org.apache.royale.compiler.projects.ICompilerProject;
import org.apache.royale.compiler.tree.ASTNodeID;
-import org.apache.royale.compiler.tree.as.IASNode;
-import org.apache.royale.compiler.tree.as.IContainerNode;
-import org.apache.royale.compiler.tree.as.IExpressionNode;
-import org.apache.royale.compiler.tree.as.IFunctionCallNode;
+import org.apache.royale.compiler.tree.as.*;
import org.apache.royale.compiler.utils.NativeUtils;
public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFunctionCallNode>
@@ -66,7 +58,6 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
{
// TODO (mschmalle) will remove this cast as more things get abstracted
JSRoyaleEmitter fjs = (JSRoyaleEmitter) getEmitter();
-
IASNode cnode = node.getChild(0);
if (cnode.getNodeID() == ASTNodeID.MemberAccessExpressionID)
@@ -80,16 +71,45 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
def = nameNode.resolve(getProject());
boolean isClassCast = false;
-
+ boolean wrapResolve = false;
if (node.isNewExpression())
{
- if (!(node.getChild(1) instanceof VectorLiteralNode))
+ boolean omitNew = false;
+ if (nameNode instanceof IdentifierNode
+ && (((IdentifierNode) nameNode).getName().equals(IASLanguageConstants.String)
+ || ((IdentifierNode) nameNode).getName().equals(IASLanguageConstants.Boolean)
+ || ((IdentifierNode) nameNode).getName().equals(IASLanguageConstants.Number)))
+ {
+ omitNew = true;
+ }
+
+ if (!((node.getChild(1) instanceof VectorLiteralNode)))
{
- if (def == null || !(def.getBaseName().equals(IASGlobalFunctionConstants._int) ||
- def.getBaseName().equals(IASGlobalFunctionConstants.uint) ||
- def instanceof AppliedVectorDefinition))
+ if (!omitNew
+ && ((def == null
+ || !(def.getBaseName().equals(IASGlobalFunctionConstants._int) || def.getBaseName().equals(IASGlobalFunctionConstants.uint)))
+ && !(def instanceof AppliedVectorDefinition && (
+ ((RoyaleJSProject) getProject()).config.getJsVectorEmulationClass()!= null
+ && ((RoyaleJSProject) getProject()).config.getJsVectorEmulationClass().equals("Array"))
+ ))
+ )
{
- startMapping(node.getNewKeywordNode());
+ if (getProject() instanceof RoyaleJSProject
+ && nameNode.resolveType(getProject()) != null
+ && nameNode.resolveType(getProject()).getQualifiedName().equals("Class")) {
+
+ wrapResolve = shouldResolveUncertain(nameNode, false);
+
+ if (wrapResolve) {
+ ((RoyaleJSProject) getProject()).needLanguage = true;
+ getModel().needLanguage = true;
+ write(JSRoyaleEmitterTokens.LANGUAGE_QNAME);
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write("resolveUncertain");
+ write(ASEmitterTokens.PAREN_OPEN);
+ }
+ }
+ startMapping(node.getNewKeywordNode());
writeToken(ASEmitterTokens.NEW);
endMapping(node.getNewKeywordNode());
}
@@ -97,14 +117,52 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
else
{
VectorLiteralNode vectorLiteralNode = (VectorLiteralNode) node.getChild(1);
- String vectorClassName = (((RoyaleJSProject)fjs.getWalker().getProject()).config.getJsVectorEmulationClass());
- if (vectorClassName != null)
+ String vectorEmulationClass = (((RoyaleJSProject)fjs.getWalker().getProject()).config.getJsVectorEmulationClass());
+ SourceLocation mappingLocation;
+ String elementClassName;
+ IDefinition elementClass = (((AppliedVectorDefinition)def).resolveElementType(getWalker().getProject()));
+ elementClassName = getEmitter().formatQualifiedName(elementClass.getQualifiedName());
+ if (vectorEmulationClass != null)
{
- writeToken(ASEmitterTokens.NEW);
- write(vectorClassName);
- write(ASEmitterTokens.PAREN_OPEN);
+ if (!vectorEmulationClass.equals("Array")) {
+ //Explanation:
+ //this was how it was originally set up, but it assumes the constructor of the emulation
+ //class can handle first argument being an Array or numeric value...
+ writeToken(ASEmitterTokens.NEW);
+ write(vectorEmulationClass);
+ write(ASEmitterTokens.PAREN_OPEN);
+ }// otherwise.... if 'Array' is the emulation class, then just use the literal content
+ } else {
+ //no 'new' output in this case, just coercion, so map from the start of 'new'
+ startMapping(node);
+ write(JSRoyaleEmitterTokens.SYNTH_VECTOR);
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ //the element type of the Vector:
+ write(elementClassName);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ write(ASEmitterTokens.SQUARE_OPEN);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write("coerce");
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.SQUARE_CLOSE);
+ mappingLocation = new SourceLocation(vectorLiteralNode.getCollectionTypeNode());
+ mappingLocation.setEndColumn(mappingLocation.getEndColumn() + 1);
+ endMapping(mappingLocation);
+ write(ASEmitterTokens.PAREN_OPEN);
+ if (getProject() instanceof RoyaleJSProject)
+ ((RoyaleJSProject)getProject()).needLanguage = true;
+ getEmitter().getModel().needLanguage = true;
+
}
+ mappingLocation = new SourceLocation(vectorLiteralNode.getContentsNode());
+ if (mappingLocation.getColumn()>0) mappingLocation.setColumn(mappingLocation.getColumn() -1);
+ mappingLocation.setEndColumn(mappingLocation.getColumn()+1);
+ startMapping(mappingLocation);
write("[");
+
+ endMapping(mappingLocation);
ContainerNode contentsNode = vectorLiteralNode.getContentsNode();
int len = contentsNode.getChildCount();
for (int i = 0; i < len; i++)
@@ -115,14 +173,24 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
writeToken(ASEmitterTokens.COMMA);
}
}
+ mappingLocation = new SourceLocation(vectorLiteralNode.getContentsNode());
+ mappingLocation.setLine(vectorLiteralNode.getContentsNode().getEndLine());
+ mappingLocation.setColumn(vectorLiteralNode.getContentsNode().getEndColumn());
+ mappingLocation.setEndColumn(mappingLocation.getColumn() + 1);
+ startMapping(mappingLocation);
write("]");
- if (vectorClassName != null)
+ endMapping(mappingLocation);
+ if (vectorEmulationClass != null)
{
- writeToken(ASEmitterTokens.COMMA);
- write(ASEmitterTokens.SINGLE_QUOTE);
- write(((AppliedVectorDefinition)def).resolveElementType(getWalker().getProject()).getBaseName());
- write(ASEmitterTokens.SINGLE_QUOTE);
- write(ASEmitterTokens.PAREN_CLOSE);
+ if (!vectorEmulationClass.equals("Array")) {
+ writeToken(ASEmitterTokens.COMMA);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(elementClassName);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ }
+ } else {
+ write(ASEmitterTokens.PAREN_CLOSE);
}
return;
}
@@ -131,12 +199,15 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
{
def = node.getNameNode().resolve(getProject());
- isClassCast = (def instanceof ClassDefinition || def instanceof InterfaceDefinition)
+ isClassCast = def != null && (def instanceof ClassDefinition
+ || def instanceof InterfaceDefinition
+ || ( def instanceof VariableDefinition && ((VariableDefinition) def).resolveType(getProject()).getBaseName().equals("Class")))
&& !(NativeUtils.isJSNative(def.getBaseName()))
&& !def.getBaseName().equals(IASLanguageConstants.XML)
&& !def.getBaseName().equals(IASLanguageConstants.XMLList);
+
}
-
+
if (node.isNewExpression())
{
def = node.resolveCalledExpression(getProject());
@@ -177,30 +248,39 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
if (nameNode.hasParenthesis())
write(ASEmitterTokens.PAREN_CLOSE);
}
-
- if (def instanceof AppliedVectorDefinition)
+ if ( def instanceof AppliedVectorDefinition
+ && (fjs.getWalker().getProject() instanceof RoyaleJSProject)
+ && (((RoyaleJSProject)fjs.getWalker().getProject()).config.getJsVectorEmulationClass() != null))
{
- ContainerNode args = node.getArgumentsNode();
- if (args.getChildCount() == 0)
- {
- String vectorClassName = (((RoyaleJSProject)fjs.getWalker().getProject()).config.getJsVectorEmulationClass());
- if (vectorClassName != null)
- {
+ ContainerNode args = node.getArgumentsNode();
+ String vectorEmulationClass = ((RoyaleJSProject)fjs.getWalker().getProject()).config.getJsVectorEmulationClass();
+ if (args.getChildCount() == 0)
+ {
+ if (vectorEmulationClass.equals("Array")) {
+ write(ASEmitterTokens.SQUARE_OPEN);
+ write(ASEmitterTokens.SQUARE_CLOSE);
+ } else {
write(ASEmitterTokens.PAREN_OPEN);
- write(ASEmitterTokens.SQUARE_OPEN);
- write(ASEmitterTokens.SQUARE_CLOSE);
+ write(ASEmitterTokens.SQUARE_OPEN);
+ write(ASEmitterTokens.SQUARE_CLOSE);
write(ASEmitterTokens.COMMA);
write(ASEmitterTokens.SPACE);
write(ASEmitterTokens.SINGLE_QUOTE);
- write(((AppliedVectorDefinition)def).resolveElementType(getWalker().getProject()).getBaseName());
+ write(((AppliedVectorDefinition)def).resolveElementType(getWalker().getProject()).getQualifiedName());
write(ASEmitterTokens.SINGLE_QUOTE);
write(ASEmitterTokens.PAREN_CLOSE);
}
- else
- getEmitter().emitArguments(node.getArgumentsNode());
- }
- else
- {
+ } else {
+ if (vectorEmulationClass.equals("Array")) {
+ if (getProject() instanceof RoyaleJSProject)
+ ((RoyaleJSProject) getProject()).needLanguage = true;
+ getEmitter().getModel().needLanguage = true;
+ write(JSRoyaleEmitterTokens.LANGUAGE_QNAME);
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ startMapping(node.getNameNode());
+ write("arrayAsVector");
+ endMapping(node.getNameNode());
+ }
startMapping(node);
write(ASEmitterTokens.PAREN_OPEN);
endMapping(node);
@@ -208,28 +288,29 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
write(ASEmitterTokens.COMMA);
write(ASEmitterTokens.SPACE);
write(ASEmitterTokens.SINGLE_QUOTE);
- write(((AppliedVectorDefinition)def).resolveElementType(getWalker().getProject()).getBaseName());
+ write(((AppliedVectorDefinition) def).resolveElementType(getWalker().getProject()).getQualifiedName());
write(ASEmitterTokens.SINGLE_QUOTE);
- if (args.getChildCount() == 2)
- {
- IASNode second = args.getChild(1);
- if (second instanceof IExpressionNode)
- {
- ITypeDefinition secondType =
- ((IExpressionNode)second).resolveType(fjs.getWalker().getProject());
- if (fjs.getWalker().getProject().getBuiltinType(BuiltinType.BOOLEAN).equals(secondType))
- {
+ if (args.getChildCount() == 2 && !vectorEmulationClass.equals("Array")) {
+ IASNode second = args.getChild(1);
+ if (second instanceof IExpressionNode) {
+ ITypeDefinition secondType =
+ ((IExpressionNode) second).resolveType(fjs.getWalker().getProject());
+ if (fjs.getWalker().getProject().getBuiltinType(BuiltinType.BOOLEAN).equals(secondType)) {
write(ASEmitterTokens.COMMA);
write(ASEmitterTokens.SPACE);
- getWalker().walk(second);
- }
- }
+ getWalker().walk(second);
+ }
+ }
}
write(ASEmitterTokens.PAREN_CLOSE);
- }
+ }
+ } else {
+ getEmitter().emitArguments(node.getArgumentsNode());
+ }
+ //end wrap resolve
+ if (wrapResolve) {
+ write(ASEmitterTokens.PAREN_CLOSE);
}
- else
- getEmitter().emitArguments(node.getArgumentsNode());
}
else if (!isClassCast)
{
@@ -270,37 +351,99 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
}
else if (def.getBaseName().equals("sort"))
{
- if (def.getParent() != null &&
- def.getParent().getQualifiedName().equals("Array"))
- {
- IExpressionNode args[] = node.getArgumentNodes();
- if (args.length > 0)
- {
- IExpressionNode optionsParamCheck = args.length == 1 ? args[0] : args[1];
- ICompilerProject project = this.getProject();
- IDefinition paramCheck = optionsParamCheck.resolveType(project);
-
- if (paramCheck.getBaseName().equals(IASLanguageConstants._int)
- || paramCheck.getBaseName().equals(IASLanguageConstants.uint)
- || paramCheck.getBaseName().equals(IASLanguageConstants.Number))
+ if (def.getParent() != null) {
+ if (def.getParent().getQualifiedName().equals("Array")
+ || (node.getNameNode() instanceof MemberAccessExpressionNode
+ && (((MemberAccessExpressionNode) node.getNameNode()).getLeftOperandNode().resolveType(getProject()) instanceof AppliedVectorDefinition)
+ && getProject() instanceof RoyaleJSProject
+ && (((RoyaleJSProject)getProject()).config.getJsVectorEmulationClass() == null
+ || ((RoyaleJSProject)getProject()).config.getJsVectorEmulationClass().equals("Array"))))
+ {
+ IExpressionNode args[] = node.getArgumentNodes();
+ if (args.length > 0)
{
- //deal with specific numeric option argument variations
- //either: Array.sort(option:uint) or Array.sort(compareFunction:Function, option:uint)
- //use our Language sort implementation to support these actionscript-specific method signatures
- if (project instanceof RoyaleJSProject)
- ((RoyaleJSProject) project).needLanguage = true;
- getEmitter().getModel().needLanguage = true;
- write(JSRoyaleEmitterTokens.LANGUAGE_QNAME);
- write(ASEmitterTokens.MEMBER_ACCESS);
- write("sort");
- IContainerNode newArgs = EmitterUtils.insertArgumentsBefore(node.getArgumentsNode(), cnode);
- fjs.emitArguments(newArgs);
- return;
+ IExpressionNode optionsParamCheck = args.length == 1 ? args[0] : args[1];
+ ICompilerProject project = this.getProject();
+ IDefinition paramCheck = optionsParamCheck.resolveType(project);
+
+ if (paramCheck.getBaseName().equals(IASLanguageConstants._int)
+ || paramCheck.getBaseName().equals(IASLanguageConstants.uint)
+ || paramCheck.getBaseName().equals(IASLanguageConstants.Number))
+ {
+ //deal with specific numeric option argument variations
+ //either: Array.sort(option:uint) or Array.sort(compareFunction:Function, option:uint)
+ //use our Language sort implementation to support these actionscript-specific method signatures
+ if (project instanceof RoyaleJSProject)
+ ((RoyaleJSProject) project).needLanguage = true;
+ getEmitter().getModel().needLanguage = true;
+ write(JSRoyaleEmitterTokens.LANGUAGE_QNAME);
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write("sort");
+ IContainerNode newArgs = EmitterUtils.insertArgumentsBefore(node.getArgumentsNode(), cnode);
+ fjs.emitArguments(newArgs);
+ return;
+ }
}
- }
- }
+ }
+ }
+
}
+ else if ((def.getBaseName().equals("insertAt")
+ || def.getBaseName().equals("removeAt"))
+ && def.getParent() instanceof AppliedVectorDefinition
+ && ((getProject() instanceof RoyaleJSProject) && (
+ ((RoyaleJSProject)getProject()).config.getJsVectorEmulationClass() == null
+ || ((RoyaleJSProject)getProject()).config.getJsVectorEmulationClass().equals("Array")))
+ ) {
+ if ((((RoyaleJSProject)getProject()).config.getJsVectorEmulationClass() != null)
+ && ((RoyaleJSProject)getProject()).config.getJsVectorEmulationClass().equals("Array")) {
+ //use a similar approach to regular 'Array' insertAt/removeAt
+ //for Array Vector emulation only (not for other custom classes)
+ //replace the insertAt/removeAt method with 'splice'
+ IdentifierNode splice = new IdentifierNode("splice");
+ splice.setSourceLocation(((MemberAccessExpressionNode)node.getNameNode()).getRightOperandNode());
+ splice.setParent((MemberAccessExpressionNode)node.getNameNode());
+ ((MemberAccessExpressionNode)node.getNameNode()).setRightOperandNode(splice);
+ NumericLiteralNode spliceArg;
+ if (def.getBaseName().equals("insertAt")) {
+ //insertAt
+ spliceArg = new NumericLiteralNode("0");
+ //This works like 'insertAt' itself, pushing the insertee to 3rd position (correct position):
+ node.getArgumentsNode().addChild(spliceArg, 1);
+ } else {
+ //removeAt
+ spliceArg = new NumericLiteralNode("1");
+ node.getArgumentsNode().addChild(spliceArg, 1);
+ }
+ } else {
+ //default Vector implementation
+ //unlike Array implementation of these methods, the synthetic Vector implementation supports these methods at runtime,
+ //and they behave differently with fixed length vectors compared to the native 'splice' method output which is used to
+ //support them in Array, however they are not protected from GCL renaming in release builds by any actual class definition,
+ //so we explicitly 'protect' them here by using DynamicAccess instead of MemberAccess
+ ExpressionNodeBase leftSide = (ExpressionNodeBase)(((BinaryOperatorNodeBase) (node.getNameNode())).getLeftOperandNode());
+ LiteralNode dynamicName = new LiteralNode(ILiteralNode.LiteralType.STRING, "'" + def.getBaseName() + "'");
+ dynamicName.setSourceLocation(((BinaryOperatorNodeBase) (node.getNameNode())).getRightOperandNode());
+ DynamicAccessNode replacement = new DynamicAccessNode(leftSide);
+ leftSide.setParent(replacement);
+ replacement.setSourceLocation(node.getNameNode());
+ replacement.setRightOperandNode(dynamicName);
+ dynamicName.setParent(replacement);
+
+ FunctionCallNode replacer = new FunctionCallNode(replacement) ;
+ replacement.setParent(replacer);
+ IExpressionNode[] args = node.getArgumentNodes();
+ for (IExpressionNode arg : args) {
+ replacer.getArgumentsNode().addItem((NodeBase) arg);
+ }
+ replacer.getArgumentsNode().setParent(replacer);
+ replacer.getArgumentsNode().setSourceLocation(node.getArgumentsNode());
+ replacer.setParent((NodeBase) node.getParent());
+ //swap it out
+ node = replacer;
+ }
+ }
else if (def instanceof AppliedVectorDefinition)
{
IExpressionNode[] argumentNodes = node.getArgumentNodes();
@@ -315,9 +458,54 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
}
else
{
- IExpressionNode argumentNode = argumentNodes[0];
- getWalker().walk(argumentNode);
- write(".slice()");
+ String elementClassName = getEmitter().formatQualifiedName(((TypedExpressionNode)nameNode).getTypeNode().resolve(getProject()).getQualifiedName());
+ if (getProject() instanceof RoyaleJSProject
+ && ((RoyaleJSProject) getProject()).config.getJsVectorEmulationClass()!= null) {
+ String vectorEmulationClass = ((RoyaleJSProject) getProject()).config.getJsVectorEmulationClass();
+ if (vectorEmulationClass.equals("Array")) {
+ //just do a slice copy of the array which is the first argument
+ getWalker().walk(node.getArgumentsNode().getChild(0));
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write("slice");
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ } else {
+ //assume the emulation class can handle an array or numeric value for first constructor arg...
+ writeToken(ASEmitterTokens.NEW);
+ startMapping(node.getNameNode());
+ write(vectorEmulationClass);
+ endMapping(node.getNameNode());
+ write(ASEmitterTokens.PAREN_OPEN);
+ getWalker().walk(node.getArgumentsNode().getChild(0));
+ writeToken(ASEmitterTokens.COMMA);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ //the element type of the Vector:
+ write(elementClassName);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ }
+ } else {
+ //default Vector implementation
+ startMapping(node.getNameNode());
+ write(JSRoyaleEmitterTokens.SYNTH_VECTOR);
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ //the element type of the Vector:
+ write(elementClassName);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ write(ASEmitterTokens.SQUARE_OPEN);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write("coerce");
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.SQUARE_CLOSE);
+ endMapping(node.getNameNode());
+
+ getEmitter().emitArguments(node.getArgumentsNode());
+ if (getProject() instanceof RoyaleJSProject)
+ ((RoyaleJSProject)getProject()).needLanguage = true;
+ getEmitter().getModel().needLanguage = true;
+ }
}
return;
}
@@ -327,6 +515,22 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
getEmitter().emitArguments(node.getArgumentsNode());
return;
}
+ else if (def.getQualifiedName().equals(IASLanguageConstants.Object)) {
+ //'resolveUncertain' always output here
+ //unless a) there are no arguments
+ //or b) it is *explicitly* suppressed for 'Object'
+ if (node.getArgumentNodes().length > 0) {
+ if (shouldResolveUncertain(nameNode, true)) {
+ wrapResolve = true;
+ ((RoyaleJSProject) getProject()).needLanguage = true;
+ getModel().needLanguage = true;
+ write(JSRoyaleEmitterTokens.LANGUAGE_QNAME);
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write("resolveUncertain");
+ write(ASEmitterTokens.PAREN_OPEN);
+ }
+ }
+ }
else if (nameNode.getNodeID() == ASTNodeID.NamespaceAccessExpressionID && def instanceof FunctionDefinition)
{
if (fjs.isCustomNamespace((FunctionDefinition)def))
@@ -336,7 +540,7 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
NamespaceDefinition nsDef = (NamespaceDefinition)nin.resolve(getProject());
IdentifierNode idNode = (IdentifierNode)nameNode.getChild(1);
String propName = idNode.getName();
- fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names
+ fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names
String s = nsDef.getURI();
write(JSRoyaleEmitter.formatNamespacedProperty(s, propName, true));
getEmitter().emitArguments(node.getArgumentsNode());
@@ -367,6 +571,11 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
getWalker().walk(node.getNameNode());
getEmitter().emitArguments(node.getArgumentsNode());
+
+ //end wrap resolve
+ if (wrapResolve) {
+ write(ASEmitterTokens.PAREN_CLOSE);
+ }
}
else //function-style cast
{
@@ -378,5 +587,31 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
fjs.emitSuperCall(node, JSSessionModel.SUPER_FUNCTION_CALL);
}
}
+
+
+ private boolean shouldResolveUncertain(IExpressionNode nameNode, boolean forceExplicit) {
+ //default if not avoided globally
+ boolean should = ((RoyaleJSProject)getProject()).config.getJsResolveUncertain();
+ //just in case:
+ if (!(getProject() instanceof RoyaleJSProject)) return false;
+
+ IDocEmitter docEmitter = getEmitter().getDocEmitter();
+ if (docEmitter instanceof JSRoyaleDocEmitter)
+ {
+ JSRoyaleDocEmitter royaleDocEmitter = (JSRoyaleDocEmitter) docEmitter;
+ //look for local boolean toggle, unless forceExplicit is set
+ boolean suppress = !forceExplicit && royaleDocEmitter.getLocalSettingAsBoolean(
+ JSRoyaleEmitterTokens.SUPPRESS_RESOLVE_UNCERTAIN, !should);
+ //if it is still on, look for sepcific/named 'off' setting based on name node
+ if (!suppress && nameNode !=null) {
+ //check to suppress for indvidual named node
+ if (nameNode instanceof IdentifierNode) {
+ suppress = royaleDocEmitter.getLocalSettingIncludesString(JSRoyaleEmitterTokens.SUPPRESS_RESOLVE_UNCERTAIN, ((IdentifierNode) nameNode).getName());
+ }
+ }
+ should = !suppress;
+ }
+ return should;
+ }
}
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/IdentifierEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/IdentifierEmitter.java
index 26d8649..4d42069 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/IdentifierEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/IdentifierEmitter.java
@@ -34,18 +34,15 @@ import org.apache.royale.compiler.internal.codegen.as.ASEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.JSSubEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitter;
import org.apache.royale.compiler.internal.codegen.js.goog.JSGoogEmitterTokens;
+import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.utils.EmitterUtils;
-import org.apache.royale.compiler.internal.definitions.AccessorDefinition;
-import org.apache.royale.compiler.internal.definitions.ClassDefinition;
-import org.apache.royale.compiler.internal.definitions.FunctionDefinition;
-import org.apache.royale.compiler.internal.definitions.TypeDefinitionBase;
+import org.apache.royale.compiler.internal.definitions.*;
+import org.apache.royale.compiler.internal.tree.as.BinaryOperatorAssignmentNode;
+import org.apache.royale.compiler.internal.tree.as.BinaryOperatorDivisionAssignmentNode;
+import org.apache.royale.compiler.internal.tree.as.MemberAccessExpressionNode;
import org.apache.royale.compiler.internal.tree.as.NonResolvingIdentifierNode;
import org.apache.royale.compiler.tree.ASTNodeID;
-import org.apache.royale.compiler.tree.as.IASNode;
-import org.apache.royale.compiler.tree.as.IFunctionNode;
-import org.apache.royale.compiler.tree.as.IFunctionObjectNode;
-import org.apache.royale.compiler.tree.as.IIdentifierNode;
-import org.apache.royale.compiler.tree.as.IMemberAccessExpressionNode;
+import org.apache.royale.compiler.tree.as.*;
import org.apache.royale.compiler.utils.NativeUtils;
public class IdentifierEmitter extends JSSubEmitter implements
@@ -239,7 +236,7 @@ public class IdentifierEmitter extends JSSubEmitter implements
{
Namespace ns = (Namespace)((INamespaceResolvedReference)((FunctionDefinition)nodeDef).getNamespaceReference()).resolveAETNamespace(getProject());
INamespaceDefinition nsDef = ((FunctionDefinition)nodeDef).getNamespaceReference().resolveNamespaceReference(getProject());
- fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names
+ fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names
String nsName = ns.getName();
write(JSRoyaleEmitter.formatNamespacedProperty(nsName, node.getName(), true));
}
@@ -315,20 +312,31 @@ public class IdentifierEmitter extends JSSubEmitter implements
}
else if (identifierIsAccessorFunction && isStatic)
{
- write("[\"" +node.getName() + "\"]");
+ write("[\"" +node.getName() + "\"]");
}
else
{
qname = node.getName();
if (nodeDef != null && !isStatic && (nodeDef.getParent() instanceof ClassDefinition) && (!(nodeDef instanceof IParameterDefinition)) && nodeDef.isPrivate() && getProject().getAllowPrivateNameConflicts())
qname = getEmitter().formatPrivateName(nodeDef.getParent().getQualifiedName(), qname);
- write(qname);
+ write(qname);
}
}
else if (isPackageOrFileMember)
write(getEmitter().formatQualifiedName(qname));
else if (nodeDef instanceof TypeDefinitionBase)
- write(getEmitter().formatQualifiedName(qname));
+ {
+ if (NativeUtils.isSyntheticJSType(qname) && !(parentNode instanceof IFunctionCallNode)) {
+ getEmitter().getModel().needLanguage = true;
+ write(JSRoyaleEmitterTokens.SYNTH_TYPE);
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(getEmitter().formatQualifiedName(qname));
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ }
+ else write(getEmitter().formatQualifiedName(qname));
+ }
else if (isCustomNamespace)
{
String ns = ((INamespaceResolvedReference)((FunctionDefinition)nodeDef).getNamespaceReference()).resolveAETNamespace(getProject()).getName();
@@ -336,9 +344,9 @@ public class IdentifierEmitter extends JSSubEmitter implements
}
else if (identifierIsAccessorFunction && isStatic)
{
- write("[\"" + qname + "\"]");
+ write("[\"" + qname + "\"]");
}
- else
+ else
{
if (nodeDef != null && !isStatic && (nodeDef.getParent() instanceof ClassDefinition) && (!(nodeDef instanceof IParameterDefinition)) && nodeDef.isPrivate() && getProject().getAllowPrivateNameConflicts())
qname = getEmitter().formatPrivateName(nodeDef.getParent().getQualifiedName(), qname);
@@ -353,7 +361,7 @@ public class IdentifierEmitter extends JSSubEmitter implements
write("child('");
write(node.getName());
write("')");
- endMapping(node);
+ endMapping(node);
}
else
{
@@ -363,5 +371,7 @@ public class IdentifierEmitter extends JSSubEmitter implements
}
}
}
+
+
}
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/InterfaceEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/InterfaceEmitter.java
index 0221afc..eb8f079 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/InterfaceEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/InterfaceEmitter.java
@@ -26,9 +26,11 @@ import org.apache.royale.compiler.internal.codegen.as.ASEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.JSDocEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.JSEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.JSSubEmitter;
+import org.apache.royale.compiler.internal.codegen.js.goog.JSGoogDocEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleDocEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitterTokens;
+import org.apache.royale.compiler.internal.tree.as.TypedExpressionNode;
import org.apache.royale.compiler.projects.ICompilerProject;
import org.apache.royale.compiler.tree.ASTNodeID;
import org.apache.royale.compiler.tree.as.IAccessorNode;
@@ -114,6 +116,14 @@ public class InterfaceEmitter extends JSSubEmitter implements
ITypeDefinition typeDef = typeNode.resolveType(project);
String packageName = typeDef.getPackageName();
packageName = project.getActualPackageName(packageName);
+ if (typeNode instanceof TypedExpressionNode) {
+ propType = "Vector.<" +
+ JSGoogDocEmitter.convertASTypeToJSType(
+ ((TypedExpressionNode)typeNode).getTypeNode().resolveType(project).getQualifiedName(),
+ "")
+ +">";
+ packageName = "";
+ }
write(JSDocEmitterTokens.JSDOC_OPEN);
write(ASEmitterTokens.SPACE);
fjs.getDocEmitter().emitType(propType, packageName);
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/MemberAccessEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/MemberAccessEmitter.java
index 23e5ec0..741affb 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/MemberAccessEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/MemberAccessEmitter.java
@@ -26,6 +26,7 @@ import org.apache.royale.compiler.definitions.IDefinition;
import org.apache.royale.compiler.internal.codegen.as.ASEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.JSEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.JSSubEmitter;
+import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleDocEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.goog.JSGoogEmitterTokens;
@@ -34,22 +35,15 @@ import org.apache.royale.compiler.internal.definitions.AccessorDefinition;
import org.apache.royale.compiler.internal.definitions.AppliedVectorDefinition;
import org.apache.royale.compiler.internal.definitions.FunctionDefinition;
import org.apache.royale.compiler.internal.projects.RoyaleJSProject;
-import org.apache.royale.compiler.internal.tree.as.DynamicAccessNode;
-import org.apache.royale.compiler.internal.tree.as.FunctionCallNode;
-import org.apache.royale.compiler.internal.tree.as.GetterNode;
-import org.apache.royale.compiler.internal.tree.as.IdentifierNode;
-import org.apache.royale.compiler.internal.tree.as.MemberAccessExpressionNode;
-import org.apache.royale.compiler.internal.tree.as.NamespaceAccessExpressionNode;
+import org.apache.royale.compiler.internal.tree.as.*;
import org.apache.royale.compiler.projects.ICompilerProject;
import org.apache.royale.compiler.tree.ASTNodeID;
-import org.apache.royale.compiler.tree.as.IASNode;
-import org.apache.royale.compiler.tree.as.IExpressionNode;
-import org.apache.royale.compiler.tree.as.IIdentifierNode;
-import org.apache.royale.compiler.tree.as.ILanguageIdentifierNode;
-import org.apache.royale.compiler.tree.as.IMemberAccessExpressionNode;
+import org.apache.royale.compiler.tree.as.*;
import org.apache.royale.compiler.tree.as.IOperatorNode.OperatorType;
import org.apache.royale.compiler.utils.ASNodeUtils;
+import javax.sound.midi.SysexMessage;
+
public class MemberAccessEmitter extends JSSubEmitter implements
ISubEmitter<IMemberAccessExpressionNode>
{
@@ -199,21 +193,6 @@ public class MemberAccessEmitter extends JSSubEmitter implements
return;
}
}
- else if (def.getParent() instanceof AppliedVectorDefinition)
- {
- if (def.getBaseName().equals("removeAt"))
- {
- writeLeftSide(node, leftNode, rightNode);
- write(".splice");
- return;
- }
- else if (def.getBaseName().equals("insertAt"))
- {
- writeLeftSide(node, leftNode, rightNode);
- write(".splice");
- return;
- }
- }
else if (rightNode instanceof NamespaceAccessExpressionNode)
{
boolean isStatic = false;
@@ -234,6 +213,11 @@ public class MemberAccessEmitter extends JSSubEmitter implements
parentNodeId != ASTNodeID.ArrayIndexExpressionID;
}
}
+
+ if (needClosure
+ && getEmitter().getDocEmitter() instanceof JSRoyaleDocEmitter
+ && ((JSRoyaleDocEmitter)getEmitter().getDocEmitter()).getSuppressClosure())
+ needClosure = false;
if (needClosure)
getEmitter().emitClosureStart();
@@ -296,6 +280,11 @@ public class MemberAccessEmitter extends JSSubEmitter implements
needClosure = !isStatic && parentNodeId != ASTNodeID.FunctionCallID &&
parentNodeId != ASTNodeID.MemberAccessExpressionID &&
parentNodeId != ASTNodeID.ArrayIndexExpressionID;
+
+ if (needClosure
+ && getEmitter().getDocEmitter() instanceof JSRoyaleDocEmitter
+ && ((JSRoyaleDocEmitter)getEmitter().getDocEmitter()).getSuppressClosure())
+ needClosure = false;
}
}
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/MethodEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/MethodEmitter.java
index aad1184..0fc7b0b 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/MethodEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/MethodEmitter.java
@@ -108,8 +108,12 @@ public class MethodEmitter extends JSSubEmitter implements
}
endMapping(node.getNameExpressionNode());
}
-
- startMapping(node);
+ if (node.getMetaTags() != null) {
+ //offset mapping by any metadata tags that will be in the first child node
+ startMapping(node.getChild(1));
+ } else {
+ startMapping(node);
+ }
write(ASEmitterTokens.SPACE);
writeToken(ASEmitterTokens.EQUAL);
write(ASEmitterTokens.FUNCTION);
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/PackageFooterEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/PackageFooterEmitter.java
index 7c151ac..86bc80d 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/PackageFooterEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/PackageFooterEmitter.java
@@ -76,7 +76,7 @@ public class PackageFooterEmitter extends JSSubEmitter implements
JSRoyaleDocEmitter doc = (JSRoyaleDocEmitter) getEmitter()
.getDocEmitter();
- if (!getEmitter().getModel().isExterns)
+ if (!getEmitter().getModel().isExterns && doc.getEmitExports())
{
boolean isInterface = tnode instanceof IInterfaceNode;
boolean isDynamic = tnode instanceof IClassNode && tnode.hasModifier(ASModifier.DYNAMIC);
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/UnaryOperatorEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/UnaryOperatorEmitter.java
index b575d55..bc040e7 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/UnaryOperatorEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/UnaryOperatorEmitter.java
@@ -23,8 +23,12 @@ import org.apache.royale.compiler.codegen.ISubEmitter;
import org.apache.royale.compiler.codegen.js.IJSEmitter;
import org.apache.royale.compiler.internal.codegen.as.ASEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.JSSubEmitter;
+import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitterTokens;
+import org.apache.royale.compiler.internal.definitions.AppliedVectorDefinition;
+import org.apache.royale.compiler.internal.tree.as.*;
import org.apache.royale.compiler.tree.ASTNodeID;
import org.apache.royale.compiler.tree.as.IExpressionNode;
+import org.apache.royale.compiler.tree.as.ILiteralNode;
import org.apache.royale.compiler.tree.as.IUnaryOperatorNode;
import org.apache.royale.compiler.utils.ASNodeUtils;
@@ -41,6 +45,31 @@ public class UnaryOperatorEmitter extends JSSubEmitter implements
{
if (ASNodeUtils.hasParenOpen(node))
write(ASEmitterTokens.PAREN_OPEN);
+
+ Boolean isAssignment = (node.getNodeID() == ASTNodeID.Op_PreIncrID
+ || node.getNodeID() == ASTNodeID.Op_PreDecrID
+ || node.getNodeID() == ASTNodeID.Op_PostIncrID
+ || node.getNodeID() == ASTNodeID.Op_PostDecrID);
+
+ if (isAssignment && (node.getOperandNode() instanceof MemberAccessExpressionNode)
+ && (((MemberAccessExpressionNode)(node.getOperandNode())).getRightOperandNode() instanceof IdentifierNode)
+ && ((IdentifierNode)(((MemberAccessExpressionNode)(node.getOperandNode())).getRightOperandNode())).getName().equals("length")
+ && ((MemberAccessExpressionNode)(node.getOperandNode())).getLeftOperandNode().resolveType(getProject()) instanceof AppliedVectorDefinition
+ ) {
+ //support for output of alternate length setter, example: vectorInst.length++ as vectorInst['_synthType'].length++
+ //likewise for pre/post increment/decrement
+
+ String synthTagName = JSRoyaleEmitterTokens.LANGUAGE_QNAME.getToken() + ASEmitterTokens.MEMBER_ACCESS.getToken() + JSRoyaleEmitterTokens.ROYALE_SYNTH_TAG_FIELD_NAME.getToken();
+ LiteralNode synthType = new LiteralNode(ILiteralNode.LiteralType.STRING, synthTagName);
+ synthType.setSynthetic(true);
+ DynamicAccessNode patchedVectorReference = new DynamicAccessNode(((ExpressionNodeBase)((MemberAccessExpressionNode) node.getOperandNode()).getLeftOperandNode()));
+ ((ExpressionNodeBase)((MemberAccessExpressionNode) node.getOperandNode()).getLeftOperandNode()).setParent(patchedVectorReference);
+ patchedVectorReference.setRightOperandNode(synthType);
+ synthType.setParent(patchedVectorReference);
+ patchedVectorReference.setParent((NodeBase) node.getOperandNode());
+ patchedVectorReference.setSourceLocation(((MemberAccessExpressionNode) node.getOperandNode()).getLeftOperandNode());
+ ((MemberAccessExpressionNode) node.getOperandNode()).setLeftOperandNode(patchedVectorReference);
+ }
if (node.getNodeID() == ASTNodeID.Op_PreIncrID
|| node.getNodeID() == ASTNodeID.Op_PreDecrID
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleDocEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleDocEmitter.java
index 8cfd1c9..e32b148 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleDocEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleDocEmitter.java
@@ -19,8 +19,7 @@
package org.apache.royale.compiler.internal.codegen.js.royale;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.*;
import org.apache.royale.compiler.asdoc.royale.ASDocComment;
import org.apache.royale.compiler.codegen.as.IASEmitter;
@@ -41,6 +40,7 @@ import org.apache.royale.compiler.internal.codegen.js.goog.JSGoogDocEmitter;
import org.apache.royale.compiler.internal.codegen.js.jx.BindableEmitter;
import org.apache.royale.compiler.internal.projects.RoyaleJSProject;
import org.apache.royale.compiler.internal.scopes.ASScope;
+import org.apache.royale.compiler.parsing.IASToken;
import org.apache.royale.compiler.problems.PublicVarWarningProblem;
import org.apache.royale.compiler.projects.ICompilerProject;
import org.apache.royale.compiler.tree.ASTNodeID;
@@ -53,9 +53,12 @@ public class JSRoyaleDocEmitter extends JSGoogDocEmitter
private List<String> classIgnoreList;
private List<String> ignoreList;
private List<String> coercionList;
+ private Map<String,List<String>> localSettings;
public boolean emitStringConversions = true;
private boolean emitExports = true;
private boolean exportProtected = false;
+
+ private boolean suppressClosure = false;
public JSRoyaleDocEmitter(IJSEmitter emitter)
{
@@ -71,6 +74,14 @@ public class JSRoyaleDocEmitter extends JSGoogDocEmitter
{
this.classIgnoreList = value;
}
+
+ public Boolean getSuppressClosure() {
+ return suppressClosure;
+ }
+
+ public Boolean getEmitExports() {
+ return emitExports;
+ }
@Override
protected String convertASTypeToJS(String name, String pname)
@@ -95,7 +106,7 @@ public class JSRoyaleDocEmitter extends JSGoogDocEmitter
RoyaleJSProject fjp = (RoyaleJSProject)((IASEmitter)emitter).getWalker().getProject();
String vectorClassName = fjp.config == null ? null : fjp.config.getJsVectorEmulationClass();
if (vectorClassName != null) return vectorClassName;
- return IASLanguageConstants.Array;
+ return super.convertASTypeToJS(name, pname);
}
name = super.convertASTypeToJS(name, pname);
@@ -128,7 +139,9 @@ public class JSRoyaleDocEmitter extends JSGoogDocEmitter
coercionList = null;
ignoreList = null;
+ localSettings = null;
emitStringConversions = true;
+ suppressClosure = false;
IClassDefinition classDefinition = resolveClassDefinition(node);
@@ -228,6 +241,31 @@ public class JSRoyaleDocEmitter extends JSGoogDocEmitter
.getToken();
if (docText.contains(noStringToken))
emitStringConversions = false;
+
+ String noImplicitComplexCoercion = JSRoyaleEmitterTokens.SUPPRESS_COMPLEX_IMPLICIT_COERCION
+ .getToken();
+ if (docText.contains(noImplicitComplexCoercion))
+ loadLocalSettings(docText, noImplicitComplexCoercion, "true");
+
+ String noResolveUncertain = JSRoyaleEmitterTokens.SUPPRESS_RESOLVE_UNCERTAIN
+ .getToken();
+ if (docText.contains(noResolveUncertain))
+ loadLocalSettings(docText,noResolveUncertain, "true");
+
+ String suppressVectorIndexCheck = JSRoyaleEmitterTokens.SUPPRESS_VECTOR_INDEX_CHECK
+ .getToken();
+ if (docText.contains(suppressVectorIndexCheck))
+ loadLocalSettings(docText,suppressVectorIndexCheck, "true");
+
+ String suppressClosureToken = JSRoyaleEmitterTokens.SUPPRESS_CLOSURE.getToken();
+
+ if (docText.contains(suppressClosureToken))
+ suppressClosure = true;
+
+ String suppressExport = JSRoyaleEmitterTokens.SUPPRESS_EXPORT.getToken();
+ if (docText.contains(suppressExport))
+ emitExports = false;
+
write(changeAnnotations(asDoc.commentNoEnd()));
}
else
@@ -312,6 +350,82 @@ public class JSRoyaleDocEmitter extends JSGoogDocEmitter
end();
}
}
+
+ /**
+ *
+ */
+ private void loadLocalSettings(String doc, String settingToken, String defaultSetting)
+ {
+ if (localSettings == null) localSettings = new HashMap<String, List<String>>();
+ int index = doc.indexOf(settingToken);
+ List<String> settings = localSettings.containsKey(settingToken) ? localSettings.get(settingToken) : null;
+ while (index != -1)
+ {
+ String setting = doc.substring(index + settingToken.length());
+ int endIndex = setting.indexOf("\n");
+ setting = setting.substring(0, endIndex);
+ setting = setting.trim();
+ if (settings == null) {
+ settings = new ArrayList<String>();
+ localSettings.put(settingToken, settings);
+ }
+ List<String> settingItems = null;
+ if (setting.length() >0) {
+ settingItems = Arrays.asList(setting.split("\\s*(,\\s*)+"));
+ } else {
+ settingItems = Arrays.asList(defaultSetting);
+ }
+ for (String settingItem: settingItems) {
+ if (settings.contains(settingItem)) {
+ //change the order to reflect the latest addition
+ settings.remove(settingItem);
+ }
+ settings.add(settingItem);
+ //System.out.println("---Adding setting "+settingToken+":"+settingItem);
+ }
+
+ index = doc.indexOf(settingToken, index + endIndex);
+ }
+ }
+
+ public boolean hasLocalSetting(String settingToken) {
+ if (localSettings == null) return false;
+ return (localSettings.keySet().contains(settingToken));
+ }
+
+ public boolean getLocalSettingAsBoolean(JSRoyaleEmitterTokens token, Boolean defaultValue) {
+ return getLocalSettingAsBoolean(token.getToken(), defaultValue);
+ }
+
+ public boolean getLocalSettingAsBoolean(String settingToken, Boolean defaultValue) {
+ boolean setting = defaultValue;
+ if (hasLocalSetting(settingToken)) {
+ for (String stringVal: localSettings.get(settingToken)) {
+ //don't bail out after finding a boolean-ish string val
+ //'last one wins'
+ if (stringVal.equals("false")) setting = false;
+ else if (stringVal.equals("true")) setting = true;
+ }
+ }
+ return setting;
+ }
+
+ public boolean getLocalSettingIncludesString(JSRoyaleEmitterTokens token, String searchValue) {
+ return getLocalSettingIncludesString(token.getToken(), searchValue);
+ }
+
+ public boolean getLocalSettingIncludesString(String settingToken, String searchValue) {
+ boolean hasValue = false;
+ if (hasLocalSetting(settingToken)) {
+ for (String stringVal: localSettings.get(settingToken)) {
+ if (stringVal.equals(searchValue)) {
+ hasValue = true;
+ break;
+ }
+ }
+ }
+ return hasValue;
+ }
private void loadIgnores(String doc)
{
@@ -468,7 +582,12 @@ public class JSRoyaleDocEmitter extends JSGoogDocEmitter
}
- emitPublic(node);
+ if (!(node.getASDocComment() instanceof ASDocComment
+ && ((ASDocComment)node.getASDocComment()).commentNoEnd()
+ .contains(JSRoyaleEmitterTokens.SUPPRESS_EXPORT.getToken()))) {
+ emitPublic(node);
+ }
+
}
if (node.isConst())
@@ -478,7 +597,7 @@ public class JSRoyaleDocEmitter extends JSGoogDocEmitter
if (def != null)
packageName = def.getPackageName();
- emitType(node, project.getActualPackageName(packageName));
+ emitType(node, project.getActualPackageName(packageName), project);
end();
}
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleEmitter.java
index 834ce4d..5e82d8e 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleEmitter.java
@@ -718,12 +718,10 @@ public class JSRoyaleEmitter extends JSGoogEmitter implements IJSRoyaleEmitter
else if (name.equals(IASLanguageConstants._int)
|| name.equals(IASLanguageConstants.uint))
result = IASLanguageConstants.Number;
-
- boolean isBuiltinFunction = name.matches("Vector\\.<.*>");
- if (isBuiltinFunction)
- {
- result = IASLanguageConstants.Array;
+ else if (name.equals(IASLanguageConstants.Vector) || name.equals("__AS3__.vec.Vector")) {
+ result = JSRoyaleEmitterTokens.VECTOR.getToken();
}
+
return result;
}
@@ -925,10 +923,6 @@ public class JSRoyaleEmitter extends JSGoogEmitter implements IJSRoyaleEmitter
newNode = EmitterUtils.insertArgumentsAt(node, 1, new NumericLiteralNode("0"));
}
}
- else if (def.getParent() != null && def.getParent() instanceof AppliedVectorDefinition)
- {
- newNode = EmitterUtils.insertArgumentsAt(node, 1, new NumericLiteralNode("0"));
- }
}
}
if (len == 1)
@@ -947,10 +941,6 @@ public class JSRoyaleEmitter extends JSGoogEmitter implements IJSRoyaleEmitter
newNode = EmitterUtils.insertArgumentsAfter(node, new NumericLiteralNode("1"));
}
}
- else if (def.getParent() != null && def.getParent() instanceof AppliedVectorDefinition)
- {
- newNode = EmitterUtils.insertArgumentsAfter(node, new NumericLiteralNode("1"));
- }
}
else if (def != null && def.getBaseName().equals("parseInt"))
{
@@ -1095,7 +1085,8 @@ public class JSRoyaleEmitter extends JSGoogEmitter implements IJSRoyaleEmitter
@Override
public void emitClosureStart()
{
- ICompilerProject project = getWalker().getProject();;
+ if (getDocEmitter() instanceof JSRoyaleDocEmitter && ((JSRoyaleDocEmitter) getDocEmitter()).getSuppressClosure()) return;
+ ICompilerProject project = getWalker().getProject();
if (project instanceof RoyaleJSProject)
((RoyaleJSProject)project).needLanguage = true;
getModel().needLanguage = true;
@@ -1106,6 +1097,7 @@ public class JSRoyaleEmitter extends JSGoogEmitter implements IJSRoyaleEmitter
@Override
public void emitClosureEnd(IASNode node, IDefinition nodeDef)
{
+ if (getDocEmitter() instanceof JSRoyaleDocEmitter && ((JSRoyaleDocEmitter) getDocEmitter()).getSuppressClosure()) return;
write(ASEmitterTokens.COMMA);
write(ASEmitterTokens.SPACE);
write(ASEmitterTokens.SINGLE_QUOTE);
@@ -1448,6 +1440,9 @@ public class JSRoyaleEmitter extends JSGoogEmitter implements IJSRoyaleEmitter
{
return isXML(((MemberAccessExpressionNode)obj).getLeftOperandNode());
}
+ else if (leftDef != null && leftDef.getBaseName().equals("*") && obj instanceof DynamicAccessNode) {
+ return isXML(((DynamicAccessNode)obj).getLeftOperandNode());
+ }
return SemanticUtils.isXMLish(leftDef, getWalker().getProject());
}
@@ -1479,12 +1474,30 @@ public class JSRoyaleEmitter extends JSGoogEmitter implements IJSRoyaleEmitter
String vectorClassName = ((RoyaleJSProject)project).config == null ? null : ((RoyaleJSProject)project).config.getJsVectorEmulationClass();
if (vectorClassName != null)
{
- writeToken(ASEmitterTokens.NEW);
- write(vectorClassName);
+ if (!vectorClassName.equals("Array"))
+ write(vectorClassName);
return;
}
}
- write(JSRoyaleEmitterTokens.VECTOR);
+ Boolean written = false;
+ if (node instanceof TypedExpressionNode) {
+ startMapping(node);
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(JSRoyaleEmitterTokens.SYNTH_VECTOR);
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ //the element type of the Vector:
+ write(formatQualifiedName(node.getTypeNode().resolve(project).getQualifiedName()));
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ endMapping(node);
+ written = true;
+ }
+
+ if (!written) {
+ write(JSRoyaleEmitterTokens.VECTOR);
+ }
if (getModel().inStaticInitializer)
{
if (!staticUsedNames.contains(JSRoyaleEmitterTokens.LANGUAGE_QNAME.getToken()))
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleEmitterTokens.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleEmitterTokens.java
index 20bc298..d0ad79f 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleEmitterTokens.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleEmitterTokens.java
@@ -35,6 +35,7 @@ public enum JSRoyaleEmitterTokens implements IEmitterTokens
ROYALE_CLASS_INFO_CLASS_KIND("class"),
ROYALE_CLASS_INFO_INTERFACE_KIND("interface"),
ROYALE_CLASS_INFO_IS_DYNAMIC("isDynamic"),
+ ROYALE_SYNTH_TAG_FIELD_NAME("SYNTH_TAG_FIELD"),
GOOG_EXPORT_PROPERTY("goog.exportProperty"),
GOOG_EXPORT_SYMBOL("goog.exportSymbol"),
INDENT(" "),
@@ -49,7 +50,12 @@ public enum JSRoyaleEmitterTokens implements IEmitterTokens
IGNORE_COERCION("@royaleignorecoercion"),
IGNORE_IMPORT("@royaleignoreimport"),
IGNORE_STRING_COERCION("@royalenoimplicitstringconversion"),
+ SUPPRESS_EXPORT("@royalesuppressexport"),
+ SUPPRESS_CLOSURE("@royalesuppressclosure"),
SUPPRESS_PUBLIC_VAR_WARNING("@royalesuppresspublicvarwarning"),
+ SUPPRESS_COMPLEX_IMPLICIT_COERCION("@royalesuppresscompleximplicitcoercion"),
+ SUPPRESS_RESOLVE_UNCERTAIN("@royalesuppressresolveuncertain"),
+ SUPPRESS_VECTOR_INDEX_CHECK("@royalesuppressvectorindexcheck"),
DEBUG_COMMENT("@royaledebug"),
DEBUG_RETURN("if(!goog.DEBUG)return;"),
PREINCREMENT("preincrement"),
@@ -65,7 +71,10 @@ public enum JSRoyaleEmitterTokens implements IEmitterTokens
SKIP_AS_COERCIONS("skipAsCoercions"),
SKIP_FUNCTION_COERCIONS("skipFunctionCoercions"),
JSX("JSX"),
- VECTOR("org.apache.royale.utils.Language.Vector"),
+ VECTOR(LANGUAGE_QNAME.getToken() + ".Vector"),
+ SYNTH_TYPE(LANGUAGE_QNAME.getToken() + ".synthType"),
+ SYNTH_VECTOR(LANGUAGE_QNAME.getToken() + ".synthVector"),
+ VECTOR_INDEX_CHECK_METHOD_NAME(LANGUAGE_QNAME.getToken() + ".CHECK_INDEX"),
;
private String token;
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/utils/DocEmitterUtils.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/utils/DocEmitterUtils.java
index dd9ed44..2e03bb0 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/utils/DocEmitterUtils.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/utils/DocEmitterUtils.java
@@ -46,4 +46,13 @@ public class DocEmitterUtils
// TODO (mschmalle)
((JSRoyaleDocEmitter)emitter.getDocEmitter()).setClassIgnoreList(ignoreList);
}
+
+
+ public static Boolean hasSuppressExport(JSRoyaleEmitter emitter, String doc)
+ {
+
+ String ignoreToken = JSRoyaleEmitterTokens.SUPPRESS_EXPORT.getToken();
+ int index = doc.indexOf(ignoreToken);
+ return index != -1;
+ }
}
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleJSProject.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleJSProject.java
index 06348a5..42e647c 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleJSProject.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleJSProject.java
@@ -39,6 +39,7 @@ import org.apache.royale.compiler.config.Configurator;
import org.apache.royale.compiler.css.ICSSMediaQueryCondition;
import org.apache.royale.compiler.css.ICSSRule;
import org.apache.royale.compiler.definitions.IDefinition;
+import org.apache.royale.compiler.definitions.IFunctionDefinition;
import org.apache.royale.compiler.definitions.ITypeDefinition;
import org.apache.royale.compiler.definitions.metadata.IMetaTag;
import org.apache.royale.compiler.definitions.metadata.IMetaTagAttribute;
@@ -116,7 +117,7 @@ public class RoyaleJSProject extends RoyaleProject
if (defNode instanceof IClassNode || defNode instanceof IInterfaceNode)
{
String defname = def.getQualifiedName();
- IASDocComment asDoc = (defNode instanceof IClassNode) ?
+ IASDocComment asDoc = (defNode instanceof IClassNode) ?
(IASDocComment) ((IClassNode)defNode).getASDocComment() :
(IASDocComment) ((IInterfaceNode)defNode).getASDocComment();
if (asDoc != null && (asDoc instanceof ASDocComment))
@@ -163,7 +164,7 @@ public class RoyaleJSProject extends RoyaleProject
super.addDependency(from, to, dt, qname);
}
- private synchronized void updateRequiresMap(ICompilationUnit from, ICompilationUnit to,
+ private synchronized void updateRequiresMap(ICompilationUnit from, ICompilationUnit to,
DependencyType dt, String qname)
{
HashMap<String, DependencyType> reqs;
@@ -188,10 +189,10 @@ public class RoyaleJSProject extends RoyaleProject
if (qname.equals("XML"))
needXML = true;
reqs.put(qname, dt);
- }
+ }
}
- private synchronized void updateJSModulesMap(ICompilationUnit from, ICompilationUnit to,
+ private synchronized void updateJSModulesMap(ICompilationUnit from, ICompilationUnit to,
DependencyType dt, String qname)
{
HashMap<String, DependencyType> reqs;
@@ -219,7 +220,7 @@ public class RoyaleJSProject extends RoyaleProject
}
}
- private synchronized void updateInterfacesMap(ICompilationUnit from, ICompilationUnit to,
+ private synchronized void updateInterfacesMap(ICompilationUnit from, ICompilationUnit to,
DependencyType dt, String qname)
{
HashMap<String, String> interfacesArr;
@@ -530,6 +531,15 @@ public class RoyaleJSProject extends RoyaleProject
}
return false;
}
+
+ @Override
+ public boolean isParameterCountMismatchAllowed(IFunctionDefinition func,
+ int formalCount, int actualCount) {
+ if ((func.getBaseName().equals("int") || func.getBaseName().equals("uint")) && func.isConstructor()) {
+ if (actualCount == 1) return true;
+ }
+ return super.isParameterCountMismatchAllowed(func, formalCount, actualCount);
+ }
/**
* List of compiler defines so it can be overridden
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/utils/JSClosureCompilerWrapper.java b/compiler-jx/src/main/java/org/apache/royale/compiler/utils/JSClosureCompilerWrapper.java
index 74e1bb6..8d8ace0 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/utils/JSClosureCompilerWrapper.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/utils/JSClosureCompilerWrapper.java
@@ -356,6 +356,8 @@ public class JSClosureCompilerWrapper
"playerversion", "langversion", "copy", "span", "para", "throw", "tiptext",
"asparam", "asreturn", "asreturns", "asprivate",
"royaleignoreimport", "royaleignorecoercion", "royaleemitcoercion",
+ "royalesuppresscompleximplicitcoercion","royalesuppressresolveuncertain",
+ "royalesuppressvectorindexcheck","royalesuppressexport", "royalesuppressclosure",
"royalenoimplicitstringconversion","royaledebug"};
options_.setExtraAnnotationNames(Arrays.asList(asdocTags));
}
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/utils/NativeUtils.java b/compiler-jx/src/main/java/org/apache/royale/compiler/utils/NativeUtils.java
index 0653542..8ff320a 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/utils/NativeUtils.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/utils/NativeUtils.java
@@ -122,8 +122,8 @@ public class NativeUtils
unescape("unescape"),
window("window"),
- // (erikdebruin) These aren't strictly 'native' to JS, but the
- // Publisher provides global functions, so, for all
+ // (erikdebruin) These aren't strictly 'native' to JS, but the
+ // Publisher provides global functions, so, for all
// intends and purposes they behave like they are.
_int("int"),
trace("trace"),
@@ -154,6 +154,26 @@ public class NativeUtils
}
}
+ public enum SyntheticJSType
+ {
+ _int("int"),
+ uint("uint"),
+ Vector("Vector"),
+ Class("Class");
+
+ private final String value;
+
+ SyntheticJSType(String value)
+ {
+ this.value = value;
+ }
+
+ public String getValue()
+ {
+ return value;
+ }
+ }
+
public static boolean isNative(String type)
{
for (NativeASType test : NativeASType.values())
@@ -175,5 +195,24 @@ public class NativeUtils
}
return false;
}
+
+ public static boolean isSyntheticJSType(String type)
+ {
+ for (SyntheticJSType test : SyntheticJSType.values())
+ {
+ if (test.getValue().equals(type)) {
+ return true;
+ }
+ }
+ if (type.startsWith("Vector.<")) {
+ return true;
+ }
+ return false;
+ }
+
+ public static boolean isVector(String type)
+ {
+ return type != null && type.startsWith("Vector.<");
+ }
}
diff --git a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/goog/TestGoogFieldMembers.java b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/goog/TestGoogFieldMembers.java
index 9bb864d..a1318d4 100644
--- a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/goog/TestGoogFieldMembers.java
+++ b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/goog/TestGoogFieldMembers.java
@@ -97,7 +97,7 @@ public class TestGoogFieldMembers extends TestFieldMembers
{
IVariableNode node = getField("protected var foo:Vector.<Foo>;");
asBlockWalker.visitVariable(node);
- assertOut("/**\n * @protected\n * @type {Vector.<Foo>}\n */\nRoyaleTest_A.prototype.foo");
+ assertOut("/**\n * @protected\n * @type {Array.<Foo>}\n */\nRoyaleTest_A.prototype.foo");
}
@Override
@@ -106,7 +106,7 @@ public class TestGoogFieldMembers extends TestFieldMembers
{
IVariableNode node = getField("protected var foo:Vector.<Vector.<Vector.<Foo>>>;");
asBlockWalker.visitVariable(node);
- assertOut("/**\n * @protected\n * @type {Vector.<Vector.<Vector.<Foo>>>}\n */\nRoyaleTest_A.prototype.foo");
+ assertOut("/**\n * @protected\n * @type {Array.<Array.<Array.<Foo>>>}\n */\nRoyaleTest_A.prototype.foo");
}
@Override
diff --git a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/goog/TestGoogGlobalClasses.java b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/goog/TestGoogGlobalClasses.java
index 0bf0f4a..28aab2a 100644
--- a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/goog/TestGoogGlobalClasses.java
+++ b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/goog/TestGoogGlobalClasses.java
@@ -271,7 +271,7 @@ public class TestGoogGlobalClasses extends TestGlobalClasses
{
IVariableNode node = getVariable("var a:Vector.<String> = new Vector.<String>(['Hello', 'World']);");
asBlockWalker.visitVariable(node);
- assertOut("var /** @type {Vector.<string>} */ a = new Array(['Hello', 'World'])");
+ assertOut("var /** @type {Array.<string>} */ a = new Array(['Hello', 'World'])");
}
@Override
diff --git a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/goog/TestGoogGlobalFunctions.java b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/goog/TestGoogGlobalFunctions.java
index 107c1bc..f979f20 100644
--- a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/goog/TestGoogGlobalFunctions.java
+++ b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/goog/TestGoogGlobalFunctions.java
@@ -212,7 +212,7 @@ public class TestGoogGlobalFunctions extends TestGlobalFunctions
{
IVariableNode node = getVariable("var a:Vector.<String> = Vector.<String>(['Hello', 'World']);");
asBlockWalker.visitVariable(node);
- assertOut("var /** @type {Vector.<string>} */ a = Array(['Hello', 'World'])");
+ assertOut("var /** @type {Array.<string>} */ a = Array(['Hello', 'World'])");
}
@Override
diff --git a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleExpressions.java b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleExpressions.java
index 0b32b4a..55de5e5 100644
--- a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleExpressions.java
+++ b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleExpressions.java
@@ -1220,7 +1220,7 @@ public class TestRoyaleExpressions extends TestGoogExpressions
"public class B {public function b() { function c(f:Function):void {}; var f:Array = [b]; c(f[0]); }}",
IFunctionNode.class, WRAP_LEVEL_PACKAGE);
asBlockWalker.visitFunction(node);
- assertOut("/**\n * @export\n */\nB.prototype.b = function() {\n var self = this;\n function c(f) {\n };\n var /** @type {Array} */ f = [org.apache.royale.utils.Language.closure(this.b, this, 'b')];\n c(f[0]);\n}");
+ assertOut("/**\n * @export\n */\nB.prototype.b = function() {\n var self = this;\n function c(f) {\n };\n var /** @type {Array} */ f = [org.apache.royale.utils.Language.closure(this.b, this, 'b')];\n c(/* implicit cast */ org.apache.royale.utils.Language.as(f[0], Function, true));\n}");
}
@Test
@@ -1272,7 +1272,7 @@ public class TestRoyaleExpressions extends TestGoogExpressions
IFunctionNode.class, WRAP_LEVEL_PACKAGE, true);
asBlockWalker.visitFunction(node);
// String.length is a getter but is a property in JS, so don't generate set_length() call.
- assertOut("/**\n * @export\n * @return {number}\n */\nfoo.bar.B.prototype.b = function() {\n var /** @type {Array} */ a = null;\n return a.length;\n}");
+ assertOut("/**\n * @export\n * @return {number}\n */\nfoo.bar.B.prototype.b = function() {\n var /** @type {Array.<string>} */ a = null;\n return a.length;\n}");
}
//----------------------------------
@@ -1512,7 +1512,7 @@ public class TestRoyaleExpressions extends TestGoogExpressions
{
IBinaryOperatorNode node = getBinaryNode("a as int");
asBlockWalker.visitBinaryOperator(node);
- assertOut("org.apache.royale.utils.Language.as(a, Number)");
+ assertOut("org.apache.royale.utils.Language.as(a, org.apache.royale.utils.Language.synthType('int'))");
}
@Test
@@ -1520,7 +1520,7 @@ public class TestRoyaleExpressions extends TestGoogExpressions
{
IBinaryOperatorNode node = getBinaryNode("a as uint");
asBlockWalker.visitBinaryOperator(node);
- assertOut("org.apache.royale.utils.Language.as(a, Number)");
+ assertOut("org.apache.royale.utils.Language.as(a, org.apache.royale.utils.Language.synthType('uint'))");
}
@Test
@@ -1530,7 +1530,7 @@ public class TestRoyaleExpressions extends TestGoogExpressions
"public class B {private var memberVar:Class; public function b(o:Object):int { var a:B = null; a = o as memberVar; }}",
IFunctionNode.class, WRAP_LEVEL_PACKAGE, true);
asBlockWalker.visitFunction(node);
- assertOut("/**\n * @export\n * @param {Object} o\n * @return {number}\n */\nfoo.bar.B.prototype.b = function(o) {\n var /** @type {foo.bar.B} */ a = null;\n a = org.apache.royale.utils.Language.as(o, this.memberVar);\n}");
+ assertOut("/**\n * @export\n * @param {Object} o\n * @return {number}\n */\nfoo.bar.B.prototype.b = function(o) {\n var /** @type {foo.bar.B} */ a = null;\n a = /* implicit cast */ org.apache.royale.utils.Language.as(org.apache.royale.utils.Language.as(o, this.memberVar), foo.bar.B, true);\n}");
}
@Test
diff --git a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleFieldMembers.java b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleFieldMembers.java
index b8be801..5a8af9a 100644
--- a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleFieldMembers.java
+++ b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleFieldMembers.java
@@ -139,7 +139,7 @@ public class TestRoyaleFieldMembers extends TestGoogFieldMembers
{
IVariableNode node = getField("protected var foo:Vector.<Foo>;");
asBlockWalker.visitVariable(node);
- assertOut("/**\n * @protected\n * @type {Array}\n */\nRoyaleTest_A.prototype.foo");
+ assertOut("/**\n * @protected\n * @type {Array.<Foo>}\n */\nRoyaleTest_A.prototype.foo");
}
@Override
@@ -148,7 +148,7 @@ public class TestRoyaleFieldMembers extends TestGoogFieldMembers
{
IVariableNode node = getField("protected var foo:Vector.<Vector.<Vector.<Foo>>>;");
asBlockWalker.visitVariable(node);
- assertOut("/**\n * @protected\n * @type {Array}\n */\nRoyaleTest_A.prototype.foo");
+ assertOut("/**\n * @protected\n * @type {Array.<Array.<Array.<Foo>>>}\n */\nRoyaleTest_A.prototype.foo");
}
@Override
diff --git a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleGlobalClasses.java b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleGlobalClasses.java
index 4f590d3..15b8dd6 100644
--- a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleGlobalClasses.java
+++ b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleGlobalClasses.java
@@ -287,6 +287,16 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
asBlockWalker.visitVariable(node);
assertOut("var /** @type {number} */ a = Math[\"PI\"]");
}
+
+ @Override
+ @Test
+ public void testClass()
+ {
+ IVariableNode node = getVariable("var a:Class = String; var b:* = new a('test')");
+ node = (IVariableNode)(node.getParent().getChild(1));
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {*} */ b = org.apache.royale.utils.Language.resolveUncertain(new a('test'))");
+ }
@Test
public void testDateSetSeconds()
@@ -379,7 +389,7 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
IVariableNode node = getVariable("var a:Vector.<String> = new Vector.<String>(['Hello', 'World']);");
asBlockWalker.visitVariable(node);
//MXMLC does not report an error. Should we?
- assertOut("var /** @type {Array} */ a = org.apache.royale.utils.Language.Vector(['Hello', 'World'], 'String')");
+ assertOut("var /** @type {Array.<string>} */ a = new (org.apache.royale.utils.Language.synthVector('String'))(['Hello', 'World'])");
}
@Test
@@ -387,7 +397,7 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
{
IVariableNode node = getVariable("var a:Vector.<String> = new <String>[];");
asBlockWalker.visitVariable(node);
- assertOut("var /** @type {Array} */ a = []");
+ assertOut("var /** @type {Array.<string>} */ a = org.apache.royale.utils.Language.synthVector('String')['coerce']([])");
}
@Test
@@ -395,7 +405,7 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
{
IVariableNode node = getVariable("var a:Vector.<int> = new <int>[0, 1, 2, 3];");
asBlockWalker.visitVariable(node);
- assertOut("var /** @type {Array} */ a = [0, 1, 2, 3]");
+ assertOut("var /** @type {Array.<number>} */ a = org.apache.royale.utils.Language.synthVector('int')['coerce']([0, 1, 2, 3])");
}
@Test
@@ -403,7 +413,7 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
{
IVariableNode node = getVariable("var a:Vector.<String> = new <String>[\"one\", \"two\", \"three\";");
asBlockWalker.visitVariable(node);
- assertOut("var /** @type {Array} */ a = [\"one\", \"two\", \"three\"]");
+ assertOut("var /** @type {Array.<string>} */ a = org.apache.royale.utils.Language.synthVector('String')['coerce']([\"one\", \"two\", \"three\"])");
}
@Test
@@ -411,7 +421,7 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
{
IVariableNode node = getVariable("var a:Vector.<String> = new Vector.<String>();");
asBlockWalker.visitVariable(node);
- assertOut("var /** @type {Array} */ a = org.apache.royale.utils.Language.Vector()");
+ assertOut("var /** @type {Array.<string>} */ a = new (org.apache.royale.utils.Language.synthVector('String'))()");
}
@Test
@@ -420,7 +430,7 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
IVariableNode node = getVariable("var a:Vector.<String> = new Vector.<String>('Hello', 'World');");
asBlockWalker.visitVariable(node);
//MXMLC does not report an error. Should we?
- assertOut("var /** @type {Array} */ a = org.apache.royale.utils.Language.Vector('Hello', 'String')");
+ assertOut("var /** @type {Array.<string>} */ a = new (org.apache.royale.utils.Language.synthVector('String'))('Hello', 'World')");
}
@Test
@@ -429,7 +439,7 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
IVariableNode node = getVariable("var a:Vector.<String> = new Vector.<String>('Hello', 'World', 'Three');");
asBlockWalker.visitVariable(node);
//MXMLC does not report an error. Should we?
- assertOut("var /** @type {Array} */ a = org.apache.royale.utils.Language.Vector('Hello', 'String')");
+ assertOut("var /** @type {Array.<string>} */ a = new (org.apache.royale.utils.Language.synthVector('String'))('Hello', 'World', 'Three')");
}
@Test
@@ -437,7 +447,7 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
{
IVariableNode node = getVariable("var a:Vector.<String> = new Vector.<String>(30);");
asBlockWalker.visitVariable(node);
- assertOut("var /** @type {Array} */ a = org.apache.royale.utils.Language.Vector(30, 'String')");
+ assertOut("var /** @type {Array.<string>} */ a = new (org.apache.royale.utils.Language.synthVector('String'))(30)");
}
@Test
@@ -446,7 +456,7 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
IVariableNode node = getVariable("var a:Vector.<String> = new Vector.<String>(30, 40);");
asBlockWalker.visitVariable(node);
//MXMLC does not report an error. Should we?
- assertOut("var /** @type {Array} */ a = org.apache.royale.utils.Language.Vector(30, 'String')");
+ assertOut("var /** @type {Array.<string>} */ a = new (org.apache.royale.utils.Language.synthVector('String'))(30, 40)");
}
@Test
@@ -455,7 +465,24 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
IVariableNode node = getVariable("var a:Vector.<String> = new Vector.<String>(['Hello', 'World']);");
asBlockWalker.visitVariable(node);
//MXMLC does not report an error. Should we?
- assertOut("var /** @type {Array} */ a = org.apache.royale.utils.Language.Vector(['Hello', 'World'], 'String')");
+ assertOut("var /** @type {Array.<string>} */ a = new (org.apache.royale.utils.Language.synthVector('String'))(['Hello', 'World'])");
+ }
+
+ @Test
+ public void testVectorSetLength()
+ {
+ IBinaryOperatorNode node = getBinaryNode("var a:Vector.<String> = new Vector.<String>(); a.length = 20)");
+ asBlockWalker.visitBinaryOperator(node);
+ assertOut("a[org.apache.royale.utils.Language.SYNTH_TAG_FIELD].length = 20");
+ }
+
+ @Test
+ public void testCustomVectorSetLength()
+ {
+ project.config.setJsVectorEmulationClass(null, "Anything");
+ IBinaryOperatorNode node = getBinaryNode("var a:Vector.<String> = new Vector.<String>(); a.length = 20)");
+ asBlockWalker.visitBinaryOperator(node);
+ assertOut("a.length = 20");
}
@Test
@@ -468,9 +495,30 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
IBinaryOperatorNode node = getBinaryNode("var a:Vector.<String> = new Vector.<String>(); a.removeAt(2)");
IFunctionCallNode parentNode = (IFunctionCallNode)(node.getParent());
asBlockWalker.visitFunctionCall(parentNode);
- assertOut("a.splice(2, 1)");
+ assertOut("a['removeAt'](2)");
}
}
+
+ @Test
+ public void testCustomVectorRemoveAt()
+ {
+ project.config.setJsVectorEmulationClass(null, "CustomVector");
+ IBinaryOperatorNode node = getBinaryNode("var a:Vector.<String> = new Vector.<String>(); a.removeAt(2)");
+ IFunctionCallNode parentNode = (IFunctionCallNode)(node.getParent());
+ asBlockWalker.visitFunctionCall(parentNode);
+ assertOut("a.removeAt(2)");
+ }
+
+ @Test
+ public void testCustomVectorAsArrayRemoveAt()
+ {
+
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IBinaryOperatorNode node = getBinaryNode("var a:Vector.<String> = new Vector.<String>(); a.removeAt(2)");
+ IFunctionCallNode parentNode = (IFunctionCallNode)(node.getParent());
+ asBlockWalker.visitFunctionCall(parentNode);
+ assertOut("a.splice(2, 1)");
+ }
@Test
public void testVectorInsertAt()
@@ -482,9 +530,29 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
IBinaryOperatorNode node = getBinaryNode("var a:Vector.<String> = new Vector.<String>(); a.insertAt(2, 'foo')");
IFunctionCallNode parentNode = (IFunctionCallNode)(node.getParent());
asBlockWalker.visitFunctionCall(parentNode);
- assertOut("a.splice(2, 0, 'foo')");
+ assertOut("a['insertAt'](2, 'foo')");
}
}
+
+ @Test
+ public void testCustomVectorInsertAt()
+ {
+ project.config.setJsVectorEmulationClass(null, "CustomVector");
+ IBinaryOperatorNode node = getBinaryNode("var a:Vector.<String> = new Vector.<String>(); a.insertAt(2, 'foo')");
+ IFunctionCallNode parentNode = (IFunctionCallNode)(node.getParent());
+ asBlockWalker.visitFunctionCall(parentNode);
+ assertOut("a.insertAt(2, 'foo')");
+ }
+
+ @Test
+ public void testCustomVectorAsArrayInsertAt()
+ {
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IBinaryOperatorNode node = getBinaryNode("var a:Vector.<String> = new Vector.<String>(); a.insertAt(2, 'foo')");
+ IFunctionCallNode parentNode = (IFunctionCallNode)(node.getParent());
+ asBlockWalker.visitFunctionCall(parentNode);
+ assertOut("a.splice(2, 0, 'foo')");
+ }
@Test
public void testCustomVector()
@@ -504,6 +572,15 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
asBlockWalker.visitVariable(node);
assertOut("var /** @type {CustomVector} */ a = new CustomVector([], 'String')");
}
+
+ @Test
+ public void testCustomVectorLiteral_1a()
+ {
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IVariableNode node = getVariable("var a:Vector.<String> = new <String>[];");
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {Array} */ a = []");
+ }
@Test
public void testCustomVectorLiteral_2()
@@ -513,17 +590,35 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
asBlockWalker.visitVariable(node);
assertOut("var /** @type {CustomVector} */ a = new CustomVector([0, 1, 2, 3], 'int')");
}
+
+ @Test
+ public void testCustomVectorLiteral_2a()
+ {
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IVariableNode node = getVariable("var a:Vector.<int> = new <int>[0, 1, 2, 3];");
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {Array} */ a = [0, 1, 2, 3]");
+ }
@Test
public void testCustomVectorLiteral_3()
{
project.config.setJsVectorEmulationClass(null, "CustomVector");
- IVariableNode node = getVariable("var a:Vector.<String> = new <String>[\"one\", \"two\", \"three\";");
+ IVariableNode node = getVariable("var a:Vector.<String> = new <String>[\"one\", \"two\", \"three\"];");
asBlockWalker.visitVariable(node);
assertOut("var /** @type {CustomVector} */ a = new CustomVector([\"one\", \"two\", \"three\"], 'String')");
}
@Test
+ public void testCustomVectorLiteral_3a()
+ {
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IVariableNode node = getVariable("var a:Vector.<String> = new <String>[\"one\", \"two\", \"three\"];");
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {Array} */ a = [\"one\", \"two\", \"three\"]");
+ }
+
+ @Test
public void testCustomVectorNoArgs()
{
project.config.setJsVectorEmulationClass(null, "CustomVector");
@@ -531,6 +626,15 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
asBlockWalker.visitVariable(node);
assertOut("var /** @type {CustomVector} */ a = new CustomVector([], 'String')");
}
+
+ @Test
+ public void testCustomVectorNoArgs2()
+ {
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IVariableNode node = getVariable("var a:Vector.<String> = new Vector.<String>();");
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {Array} */ a = []");
+ }
@Test
public void testCustomVectorStringArgs()
@@ -562,6 +666,15 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
}
@Test
+ public void testCustomVectorSizeArg2()
+ {
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IVariableNode node = getVariable("var a:Vector.<String> = new Vector.<String>(30);");
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {Array} */ a = org.apache.royale.utils.Language.arrayAsVector(30, 'String')");
+ }
+
+ @Test
public void testCustomVectorSizeAndFixedArgs()
{
project.config.setJsVectorEmulationClass(null, "CustomVector");
@@ -569,6 +682,15 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
asBlockWalker.visitVariable(node);
assertOut("var /** @type {CustomVector} */ a = new CustomVector(30, 'String', true)");
}
+
+ @Test
+ public void testCustomVectorSizeAndFixedArgs2()
+ {
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IVariableNode node = getVariable("var a:Vector.<String> = new Vector.<String>(30, true);");
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {Array} */ a = org.apache.royale.utils.Language.arrayAsVector(30, 'String')");
+ }
@Test
public void testCustomVectorNumberArgs()
@@ -579,6 +701,16 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
//MXMLC does not report an error. Should we?
assertOut("var /** @type {CustomVector} */ a = new CustomVector(30, 'String')");
}
+
+ @Test
+ public void testCustomVectorNumberArgs2()
+ {
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IVariableNode node = getVariable("var a:Vector.<String> = new Vector.<String>(30, 40);");
+ asBlockWalker.visitVariable(node);
+ //MXMLC does not report an error. Should we?
+ assertOut("var /** @type {Array} */ a = org.apache.royale.utils.Language.arrayAsVector(30, 'String')");
+ }
@Test
public void testCustomVectorArrayArg()
@@ -591,6 +723,99 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
}
@Test
+ public void testCustomVectorArrayArg2()
+ {
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IVariableNode node = getVariable("var a:Vector.<String> = new Vector.<String>(['Hello', 'World']);");
+ asBlockWalker.visitVariable(node);
+ //MXMLC does not report an error. Should we?
+ assertOut("var /** @type {Array} */ a = org.apache.royale.utils.Language.arrayAsVector(['Hello', 'World'], 'String')");
+ }
+
+ @Test
+ public void testDefaultVectorClassRepresentation()
+ {
+ IVariableNode node = getVariable("var a:Class = Vector.<String>;");
+ asBlockWalker.visitVariable(node);
+ //MXMLC does not report an error. Should we?
+ assertOut("var /** @type {Object} */ a = org.apache.royale.utils.Language.synthVector('String')");
+ }
+
+ @Test
+ public void testCustomVectorClassRepresentation()
+ {
+ project.config.setJsVectorEmulationClass(null, "CustomVector");
+ IVariableNode node = getVariable("var a:Class = Vector.<String>;");
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {Object} */ a = CustomVector");
+ }
+
+ @Test
+ public void testCustomVectorClassRepresentation2()
+ {
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IVariableNode node = getVariable("var a:Class = Vector.<String>;");
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {Object} */ a = Array");
+ }
+
+ @Test
+ public void testDefaultVectorSortNumericArg()
+ {
+ IBinaryOperatorNode node = getBinaryNode("var a:Vector.<Number> = new Vector.<Number>();a.sort(Array.NUMERIC)");
+ IFunctionCallNode parentNode = (IFunctionCallNode)(node.getParent());
+ asBlockWalker.visitFunctionCall(parentNode);
+ assertOut("org.apache.royale.utils.Language.sort(a, 16)");
+ }
+
+ @Test
+ public void testCustomVectorRepresentationSortNumericArg()
+ {
+ project.config.setJsVectorEmulationClass(null, "CustomVector");
+ IBinaryOperatorNode node = getBinaryNode("var a:Vector.<Number> = new Vector.<Number>();a.sort(Array.NUMERIC)");
+ IFunctionCallNode parentNode = (IFunctionCallNode)(node.getParent());
+ asBlockWalker.visitFunctionCall(parentNode);
+ assertOut("a.sort(16)");
+ }
+
+ @Test
+ public void testCustomVectorAsArrayRepresentationSortNumericArg()
+ {
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IBinaryOperatorNode node = getBinaryNode("var a:Vector.<Number> = new Vector.<Number>();a.sort(Array.NUMERIC)");
+ IFunctionCallNode parentNode = (IFunctionCallNode)(node.getParent());
+ asBlockWalker.visitFunctionCall(parentNode);
+ assertOut("org.apache.royale.utils.Language.sort(a, 16)");
+ }
+
+ @Override
+ @Test
+ public void testBoolean()
+ {
+ IVariableNode node = getVariable("var a:Boolean = new Boolean(1);");
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {boolean} */ a = Boolean(1)");
+ }
+
+ @Override
+ @Test
+ public void testNumber()
+ {
+ IVariableNode node = getVariable("var a:Number = new Number(\"1\");");
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {number} */ a = Number(\"1\")");
+ }
+
+ @Override
+ @Test
+ public void testString()
+ {
+ IVariableNode node = getVariable("var a:String = new String(\"100\");");
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {string} */ a = String(\"100\")");
+ }
+
+ @Test
public void testXML()
{
IVariableNode node = getVariable("var a:XML = new XML(\"<top attr1='cat'><child attr2='dog'><grandchild attr3='fish'>text</grandchild></child></top>\");");
diff --git a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleGlobalFunctions.java b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleGlobalFunctions.java
index 8f2f9d1..5f8b6b2 100644
--- a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleGlobalFunctions.java
+++ b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleGlobalFunctions.java
@@ -100,6 +100,15 @@ public class TestRoyaleGlobalFunctions extends TestGoogGlobalFunctions
asBlockWalker.visitVariable(node);
assertOut("var /** @type {Array} */ a = Array(['Hello', 'World'])");
}
+
+ @Override
+ @Test
+ public void testObject()
+ {
+ IVariableNode node = getVariable("var a:Object = Object(\"1\");");
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {Object} */ a = org.apache.royale.utils.Language.resolveUncertain(Object(\"1\"))");
+ }
@Test
public void testParseInt()
@@ -159,6 +168,24 @@ public class TestRoyaleGlobalFunctions extends TestGoogGlobalFunctions
{
IVariableNode node = getVariable("var a:Vector.<String> = Vector.<String>(['Hello', 'World']);");
asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {Array.<string>} */ a = org.apache.royale.utils.Language.synthVector('String')['coerce'](['Hello', 'World'])");
+ }
+
+ @Test
+ public void testCustomVector()
+ {
+ project.config.setJsVectorEmulationClass(null, "CustomVector");
+ IVariableNode node = getVariable("var a:Vector.<String> = Vector.<String>(['Hello', 'World']);");
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {CustomVector} */ a = new CustomVector(['Hello', 'World'], 'String')");
+ }
+
+ @Test
+ public void testCustomVectorAsArray()
+ {
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IVariableNode node = getVariable("var a:Vector.<String> = Vector.<String>(['Hello', 'World']);");
+ asBlockWalker.visitVariable(node);
assertOut("var /** @type {Array} */ a = ['Hello', 'World'].slice()");
}
@@ -184,8 +211,29 @@ public class TestRoyaleGlobalFunctions extends TestGoogGlobalFunctions
IVariableNode node = getVariable("var a:Vector.<String> = Vector.<String>(30);");
asBlockWalker.visitVariable(node);
// MXMLC doesn't report an error either. Maybe we should.
+ assertOut("var /** @type {Array.<string>} */ a = org.apache.royale.utils.Language.synthVector('String')['coerce'](30)");
+ }
+
+ @Test
+ public void testCustomVectorSizeArg()
+ {
+ project.config.setJsVectorEmulationClass(null, "CustomVector");
+ IVariableNode node = getVariable("var a:Vector.<String> = Vector.<String>(30);");
+ asBlockWalker.visitVariable(node);
+ // MXMLC doesn't report an error either. Maybe we should.
+ assertOut("var /** @type {CustomVector} */ a = new CustomVector(30, 'String')");
+ }
+
+ @Test
+ public void testCustomVectorAsArraySizeArg()
+ {
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IVariableNode node = getVariable("var a:Vector.<String> = Vector.<String>(30);");
+ asBlockWalker.visitVariable(node);
+ // MXMLC doesn't report an error either. Maybe we should.
assertOut("var /** @type {Array} */ a = 30.slice()");
}
+
@Test
public void testVectorNumberArgs()
@@ -200,7 +248,7 @@ public class TestRoyaleGlobalFunctions extends TestGoogGlobalFunctions
{
IVariableNode node = getVariable("var a:Vector.<String> = Vector.<String>(['Hello', 'World']);");
asBlockWalker.visitVariable(node);
- assertOut("var /** @type {Array} */ a = ['Hello', 'World'].slice()");
+ assertOut("var /** @type {Array.<string>} */ a = org.apache.royale.utils.Language.synthVector('String')['coerce'](['Hello', 'World'])");
}
@Override
diff --git a/compiler/src/main/java/org/apache/royale/compiler/internal/tree/as/DynamicAccessNode.java b/compiler/src/main/java/org/apache/royale/compiler/internal/tree/as/DynamicAccessNode.java
index b616b9d..8df9fae 100644
--- a/compiler/src/main/java/org/apache/royale/compiler/internal/tree/as/DynamicAccessNode.java
+++ b/compiler/src/main/java/org/apache/royale/compiler/internal/tree/as/DynamicAccessNode.java
@@ -21,6 +21,7 @@ package org.apache.royale.compiler.internal.tree.as;
import org.apache.royale.compiler.definitions.IAppliedVectorDefinition;
import org.apache.royale.compiler.definitions.ITypeDefinition;
+import org.apache.royale.compiler.internal.semantics.SemanticUtils;
import org.apache.royale.compiler.projects.ICompilerProject;
import org.apache.royale.compiler.tree.ASTNodeID;
import org.apache.royale.compiler.tree.as.IDynamicAccessNode;
@@ -86,8 +87,10 @@ public class DynamicAccessNode extends BinaryOperatorNodeBase implements IDynami
ITypeDefinition leftType = getLeftOperandNode().resolveType(project);
if (leftType instanceof IAppliedVectorDefinition)
{
- IAppliedVectorDefinition vectorDef = (IAppliedVectorDefinition) leftType;
- return vectorDef.resolveElementType(project);
+ if (SemanticUtils.isNumericType(getRightOperandNode().resolveType(project), project)) {
+ IAppliedVectorDefinition vectorDef = (IAppliedVectorDefinition) leftType;
+ return vectorDef.resolveElementType(project);
+ }
}
return super.resolveType(project);
}
diff --git a/royale-ant-tasks/src/main/java/org/apache/royale/compiler/ant/FlexTask.java b/royale-ant-tasks/src/main/java/org/apache/royale/compiler/ant/FlexTask.java
index 79f7060..40e119f 100644
--- a/royale-ant-tasks/src/main/java/org/apache/royale/compiler/ant/FlexTask.java
+++ b/royale-ant-tasks/src/main/java/org/apache/royale/compiler/ant/FlexTask.java
@@ -308,9 +308,9 @@ public abstract class FlexTask extends Java
try
{
- Method toolMethod = toolClass.getMethod(toolMethodName, new Class[] {String[].class});
+ Method toolMethod = toolClass.getMethod(toolMethodName, String[].class);
Object result = toolMethod.invoke(null, new Object[] {cmdline.getArguments()});
- exitCode = ((Integer)result).intValue();
+ exitCode = ((Integer)result);
}
catch (Exception e)
{
@@ -337,9 +337,9 @@ public abstract class FlexTask extends Java
try
{
- Method toolFailureMethod = toolClass.getMethod(toolFailureMethodName, new Class[] {int.class});
- Object result = toolFailureMethod.invoke(null, new Object[] {exitCode});
- fatal = ((Boolean)result).booleanValue();
+ Method toolFailureMethod = toolClass.getMethod(toolFailureMethodName, int.class);
+ Object result = toolFailureMethod.invoke(null, exitCode);
+ fatal = ((Boolean)result);
}
catch (Exception e)
{
diff --git a/royale-maven-plugin/src/main/java/org/apache/royale/maven/BaseMojo.java b/royale-maven-plugin/src/main/java/org/apache/royale/maven/BaseMojo.java
index 74af100..ca1add1 100644
--- a/royale-maven-plugin/src/main/java/org/apache/royale/maven/BaseMojo.java
+++ b/royale-maven-plugin/src/main/java/org/apache/royale/maven/BaseMojo.java
@@ -236,16 +236,22 @@ public abstract class BaseMojo
List<String> args = new LinkedList<String>();
args.add("-load-config=" + configFile.getPath());
if(additionalCompilerOptions != null) {
+ if (additionalCompilerOptions.contains("\n")) {
+ additionalCompilerOptions = additionalCompilerOptions.replace("\n", "");
+ }
if (additionalCompilerOptions.contains(";"))
{
String[] options = additionalCompilerOptions.split(";");
for (String option : options)
{
- args.add(option);
+ if (option.trim().length() > 0)
+ args.add(option.trim());
}
}
- else
- args.add(additionalCompilerOptions);
+ else {
+ if (additionalCompilerOptions.trim().length() > 0)
+ args.add(additionalCompilerOptions.trim());
+ }
}
return args;
}
Re: [royale-compiler] branch develop updated: Squashed commit of the
following:
Posted by Alex Harui <ah...@adobe.com.INVALID>.
Hmm. Maybe related, but in examples/royale/ASDoc/src/main/royale/OptionalHashAnchorStringItemRenderer.as in the text setter, we have code like:
var n:int = (parent as List).dataProvider.length;
That is being transpiled without the "as" call. And I don't think I've turned off any options for that.
-Alex
On 6/17/19, 9:18 AM, "Alex Harui" <ah...@adobe.com.INVALID> wrote:
Is the positive/negative of SUPPRESS_COMPLEX_IMPLICIT_COERCION correct? It feels like it should be the opposite to me.
I just added:
/**
* @royalesuppresscompleximplicitcoercion false
*/
To turn OFF the implicit coercion.
Thoughts?
-Alex
On 6/10/19, 8:46 PM, "gregdove@apache.org" <gr...@apache.org> wrote:
This is an automated email from the ASF dual-hosted git repository.
gregdove pushed a commit to branch develop
in repository https://nam04.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgitbox.apache.org%2Frepos%2Fasf%2Froyale-compiler.git&data=02%7C01%7Caharui%40adobe.com%7C78a3009d8a244583dda308d6f33f6f50%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636963851129325211&sdata=tUlJ6v3zq11dI7nPq2x5tVdul4XdAVoMnKq6es46xfM%3D&reserved=0
The following commit(s) were added to refs/heads/develop by this push:
new 6224c1a Squashed commit of the following:
6224c1a is described below
commit 6224c1ad785a9e2d0dda444d5a2add69c21cdf5f
Author: greg-dove <gr...@gmail.com>
AuthorDate: Tue Jun 11 15:21:08 2019 +1200
Squashed commit of the following:
commit 628d09e862fc3ff6edc9df6b0689b3634d157684
Merge: 29f4ba04 806603c8
Author: greg-dove <gr...@gmail.com>
Date: Tue Jun 11 14:51:58 2019 +1200
Merge branch 'develop' into improvements/Language
commit 29f4ba04b6eae4d294586803133e14ce0486cf6b
Author: greg-dove <gr...@gmail.com>
Date: Tue Jun 11 14:38:33 2019 +1200
Fix synthVector output for file-private element types.
Also add Class as a synthType
commit 378c07814db83d4e0af5343de8288d6c23583c4a
Merge: e461980d 905517ef
Author: greg-dove <gr...@gmail.com>
Date: Sun Jun 9 14:04:15 2019 +1200
Merge branch 'develop' into improvements/Language
commit e461980d384b71bc85a7c5014b9da5c7f26dfd4b
Author: greg-dove <gr...@gmail.com>
Date: Sun Jun 9 11:23:34 2019 +1200
Support for legacy Vector-as-Array via vectorEmulationClass setting, including fixes for insertAt/removeAt
commit 7dd36596e73f122ddb0af76db2abeb3d0a7b4231
Merge: b7cb250c de4bdad6
Author: greg-dove <gr...@gmail.com>
Date: Sat May 25 13:47:42 2019 +1200
Merge branch 'develop' into improvements/Language
commit b7cb250cbdc98218c69a83293603179f0fe297a4
Merge: b3080422 f1e68b92
Author: greg-dove <gr...@gmail.com>
Date: Thu May 23 18:37:54 2019 +1200
Merge branch 'develop' into improvements/Language
commit b30804227ad9bb8b5763fb56517649749e433a54
Author: greg-dove <gr...@gmail.com>
Date: Thu May 23 18:20:28 2019 +1200
Fixes for Issue #424
commit 164d1a1a37c15e83dc1142f9f628c4e7a4e6ee78
Author: greg-dove <gr...@gmail.com>
Date: Thu May 23 11:36:07 2019 +1200
support @royalesuppressexport on public fields
commit cea3363e6b0c7220015ff423c14b708f320dd83a
Author: greg-dove <gr...@gmail.com>
Date: Wed May 22 13:35:20 2019 +1200
Added 2 new doc directives for tuning js output: royalesuppressclosure and royalesuppressexport
commit 68293a747ff8e49f9c6a9152cca82f3a656ec0a4
Author: greg-dove <gr...@gmail.com>
Date: Sun May 19 18:07:49 2019 +1200
Avoid some Language warnings
Avoid some java language warnings in this code
commit e59fbf8152c09b65dbf7bb2dc74913a06b10c69d
Author: greg-dove <gr...@gmail.com>
Date: Sun May 19 17:32:23 2019 +1200
Allow line-based separation of individual additionalCompilerOptions entries in pom.xml
commit 54b062bce8a75d4de52c2b2a9d25a4ba92b431b0
Author: greg-dove <gr...@gmail.com>
Date: Wed May 15 10:51:57 2019 +1200
Fix for an XML bug identified in testing.
commit 4dade1a0500767a35b051829ebf2908254f22438
Author: greg-dove <gr...@gmail.com>
Date: Tue May 7 17:57:32 2019 +1200
remove 'no' from new config settings and toggle defaults accordingly (group review decision)
commit f11f18215f5d4c127b9715bc2f1e19c5a7a88d51
Author: greg-dove <gr...@gmail.com>
Date: Sun May 5 07:39:10 2019 +1200
code tidy
commit 88b2c1f52e7b15d2573d1d40e6963de4aa15b24f
Author: greg-dove <gr...@gmail.com>
Date: Sat May 4 18:21:57 2019 +1200
Squashed commit of cumulative work on Language improvements
---
.../royale/compiler/asdoc/royale/ASDocComment.java | 2 +-
.../royale/compiler/clients/JSConfiguration.java | 121 +++++-
.../codegen/js/goog/IJSGoogDocEmitter.java | 2 +-
.../compiler/internal/codegen/js/JSEmitter.java | 207 +++++++++-
.../internal/codegen/js/goog/JSGoogDocEmitter.java | 48 ++-
.../internal/codegen/js/jx/AccessorEmitter.java | 8 +-
.../internal/codegen/js/jx/AsIsEmitter.java | 31 +-
.../codegen/js/jx/BinaryOperatorEmitter.java | 44 ++-
.../internal/codegen/js/jx/ClassEmitter.java | 4 +-
.../codegen/js/jx/DynamicAccessEmitter.java | 54 +++
.../codegen/js/jx/FunctionCallEmitter.java | 429 ++++++++++++++++-----
.../internal/codegen/js/jx/IdentifierEmitter.java | 42 +-
.../internal/codegen/js/jx/InterfaceEmitter.java | 10 +
.../codegen/js/jx/MemberAccessEmitter.java | 41 +-
.../internal/codegen/js/jx/MethodEmitter.java | 8 +-
.../codegen/js/jx/PackageFooterEmitter.java | 2 +-
.../codegen/js/jx/UnaryOperatorEmitter.java | 29 ++
.../codegen/js/royale/JSRoyaleDocEmitter.java | 129 ++++++-
.../codegen/js/royale/JSRoyaleEmitter.java | 47 ++-
.../codegen/js/royale/JSRoyaleEmitterTokens.java | 11 +-
.../internal/codegen/js/utils/DocEmitterUtils.java | 9 +
.../internal/projects/RoyaleJSProject.java | 20 +-
.../compiler/utils/JSClosureCompilerWrapper.java | 2 +
.../apache/royale/compiler/utils/NativeUtils.java | 43 ++-
.../codegen/js/goog/TestGoogFieldMembers.java | 4 +-
.../codegen/js/goog/TestGoogGlobalClasses.java | 2 +-
.../codegen/js/goog/TestGoogGlobalFunctions.java | 2 +-
.../codegen/js/royale/TestRoyaleExpressions.java | 10 +-
.../codegen/js/royale/TestRoyaleFieldMembers.java | 4 +-
.../codegen/js/royale/TestRoyaleGlobalClasses.java | 251 +++++++++++-
.../js/royale/TestRoyaleGlobalFunctions.java | 50 ++-
.../internal/tree/as/DynamicAccessNode.java | 7 +-
.../org/apache/royale/compiler/ant/FlexTask.java | 10 +-
.../java/org/apache/royale/maven/BaseMojo.java | 12 +-
34 files changed, 1447 insertions(+), 248 deletions(-)
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/asdoc/royale/ASDocComment.java b/compiler-jx/src/main/java/org/apache/royale/compiler/asdoc/royale/ASDocComment.java
index a1006dc..21bdc95 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/asdoc/royale/ASDocComment.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/asdoc/royale/ASDocComment.java
@@ -134,7 +134,7 @@ public class ASDocComment implements IASDocComment
tags = new ArrayList<IASDocTag>();
tagMap.put(tagName, tags);
}
- tags.add(new ASDocTag(tagName, line.substring(after + 1)));
+ tags.add(new ASDocTag(tagName, line.substring(after + 1).trim()));
}
}
}
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/clients/JSConfiguration.java b/compiler-jx/src/main/java/org/apache/royale/compiler/clients/JSConfiguration.java
index 357a838..eda4012 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/clients/JSConfiguration.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/clients/JSConfiguration.java
@@ -457,13 +457,128 @@ public class JSConfiguration extends Configuration
}
/**
- * The class to use instead of Array for handling Vector.
+ * The class to use instead of default Vector implementation for handling Vector.
*/
@Config(advanced = true)
public void setJsVectorEmulationClass(ConfigurationValue cv, String b)
{
jsVectorEmulationClass = b;
}
-
-
+
+
+ //
+ // 'js-complex-implicit-coercions'
+ //
+
+ private boolean jsComplexImplicitCoercions = true;
+
+ public boolean getJsComplexImplicitCoercions()
+ {
+ return jsComplexImplicitCoercions;
+ }
+
+ /**
+ * Support for including/avoiding more complex implicit assignment coercions
+ * example
+ * var array:Array = [new MyClass()];
+ * var myOtherClass:MyOtherClass = array[0];
+ *
+ * In the above example, the compiler will (by default) output an implicit coercion
+ * that is equivalent in actionscript to:
+ * var myOtherClass:MyOtherClass = MyOtherClass(array[0]);
+ *
+ * By setting this configuration option to false, the implicit coercion code in situations similar to the above
+ * is not generated (other primitive implicit coercions, such as int/uint/Number/String and Boolean coercions remain)
+ * This is a global setting for the current source code being compiled, it is possible to leave it on and specifically avoid it via doc
+ * settings. The doc comment compiler directive for that is: @royalesuppresscompleximplicitcoercion
+ * Another option is to add the explicit coercions in code and then avoid their output
+ * via specific @royaleignorecoercion doc comment directives. Doing so however may add extra unwanted output
+ * in other compiler targets (for example, swf bytecode) if the same source code is shared between targets.
+ */
+ @Config(advanced = true)
+ @Mapping("js-complex-implicit-coercions")
+ public void setJsComplexImplicitCoercions(ConfigurationValue cv, boolean value)
+ throws ConfigurationException
+ {
+ jsComplexImplicitCoercions = value;
+ }
+
+ //
+ // 'js-resolve-uncertain'
+ //
+
+ private boolean jsResolveUncertain = true;
+
+ public boolean getJsResolveUncertain()
+ {
+ return jsResolveUncertain;
+ }
+
+ /**
+ * Support for avoiding more overhead of resolving instantiations from
+ * unknown constructors
+ * example
+ * var myClass:Class = String;
+ * var myString:* = new myClass("test");
+ *
+ * In the above example, the compiler will (by default) output
+ * a call to a Language.resolveUncertain method which wraps the 'new myClass("test")'
+ *
+ *
+ * This normalizes the return value for some primitive constructors, so that (for example)
+ * strict equality and inequality operators provide the same results between compiler
+ * targets.
+ * In situations where it is certain that the resolveUncertain method is not needed,
+ * this option provides a way to switch it off 'globally' for the current source code being compiled.
+ * It can also be switched off or on locally using the '@royalesuppressresolveuncertain'
+ * doc comment compiler directive.
+ */
+ @Config(advanced = true)
+ @Mapping("js-resolve-uncertain")
+ public void setJsResolveUncertain(ConfigurationValue cv, boolean value)
+ throws ConfigurationException
+ {
+ jsResolveUncertain = value;
+ }
+
+ //
+ // 'js-vector-index-checks'
+ //
+
+ private boolean jsVectorIndexChecks = true;
+
+ public boolean getJsVectorIndexChecks()
+ {
+ return jsVectorIndexChecks;
+ }
+
+ /**
+ * Support for avoiding more overhead of adding checks into
+ * assignments via Vector index access
+ * example
+ * var myVector:Vector.<int> = new Vector.<int>();
+ * myVector[0] = 42;
+ *
+ * In the above example, the compiler will (by default) wrap
+ * the '0' inside myVector[0] with a method call on the vector instance
+ * that checks to see if the index is valid for the Vector it is being used against
+ *
+ * This check will throw an error if the index is out of range, and the
+ * range checking differs if the Vector is 'fixed' or non-'fixed'
+ *
+ * In situations where it is certain that the index will always be valid for Vector instance
+ * being targeted, or where all cases in a given codebase are certain to be valid, it is possible
+ * to avoid the overhead of this check. This is especially important in loops.
+ * This config setting affects the global setting for the current source code being compiled.
+ * It can be adjusted locally within code, using the '@royalesuppressvectorindexcheck'
+ * doc comment compiler directive.
+ */
+ @Config(advanced = true)
+ @Mapping("js-vector-index-checks")
+ public void setJsVectorIndexChecks(ConfigurationValue cv, boolean value)
+ throws ConfigurationException
+ {
+ jsVectorIndexChecks = value;
+ }
+
}
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/codegen/js/goog/IJSGoogDocEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/codegen/js/goog/IJSGoogDocEmitter.java
index 112f3a0..6c99459 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/codegen/js/goog/IJSGoogDocEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/codegen/js/goog/IJSGoogDocEmitter.java
@@ -134,7 +134,7 @@ public interface IJSGoogDocEmitter extends IJSDocEmitter
void emitThis(ITypeDefinition node, String packageName);
- void emitType(IASNode node, String packageName);
+ void emitType(IASNode node, String packageName, ICompilerProject project);
void emitType(String type, String packageName);
}
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/JSEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/JSEmitter.java
index 45baa5a..a60ffbc 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/JSEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/JSEmitter.java
@@ -23,6 +23,7 @@ import java.io.FilterWriter;
import java.util.ArrayList;
import java.util.List;
+import org.apache.royale.compiler.codegen.IASGlobalFunctionConstants;
import org.apache.royale.compiler.codegen.IDocEmitter;
import org.apache.royale.compiler.codegen.IEmitter;
import org.apache.royale.compiler.codegen.ISubEmitter;
@@ -32,6 +33,8 @@ import org.apache.royale.compiler.common.ISourceLocation;
import org.apache.royale.compiler.constants.IASLanguageConstants;
import org.apache.royale.compiler.constants.IMetaAttributeConstants;
import org.apache.royale.compiler.constants.IASLanguageConstants.BuiltinType;
+import org.apache.royale.compiler.definitions.IAppliedVectorDefinition;
+import org.apache.royale.compiler.definitions.IClassDefinition;
import org.apache.royale.compiler.definitions.IDefinition;
import org.apache.royale.compiler.definitions.metadata.IMetaTag;
import org.apache.royale.compiler.definitions.metadata.IMetaTagAttribute;
@@ -64,8 +67,10 @@ import org.apache.royale.compiler.internal.codegen.js.jx.UnaryOperatorEmitter;
import org.apache.royale.compiler.internal.codegen.js.jx.WhileLoopEmitter;
import org.apache.royale.compiler.internal.codegen.js.jx.WithEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleDocEmitter;
+import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitterTokens;
+import org.apache.royale.compiler.internal.projects.RoyaleJSProject;
import org.apache.royale.compiler.internal.semantics.SemanticUtils;
-import org.apache.royale.compiler.internal.tree.as.FunctionNode;
+import org.apache.royale.compiler.internal.tree.as.*;
import org.apache.royale.compiler.projects.ICompilerProject;
import org.apache.royale.compiler.tree.as.IASNode;
import org.apache.royale.compiler.tree.as.ICatchNode;
@@ -97,6 +102,9 @@ import org.apache.royale.compiler.tree.as.IWithNode;
import com.google.debugging.sourcemap.FilePosition;
+import org.apache.royale.compiler.internal.codegen.as.ASEmitterTokens;
+import org.apache.royale.compiler.utils.NativeUtils;
+
/**
* @author Michael Schmalle
*/
@@ -220,12 +228,12 @@ public class JSEmitter extends ASEmitter implements IJSEmitter
public void emitClosureStart()
{
-
+
}
public void emitClosureEnd(IASNode node, IDefinition nodeDef)
{
-
+
}
public void emitSourceMapDirective(ITypeNode node)
@@ -502,7 +510,7 @@ public class JSEmitter extends ASEmitter implements IJSEmitter
/**
* Adjusts the line numbers saved in the source map when a line should be
* removed during post processing.
- *
+ *
* @param lineIndex
*/
protected void removeLineFromMappings(int lineIndex)
@@ -547,6 +555,7 @@ public class JSEmitter extends ASEmitter implements IJSEmitter
}
String coercionStart = null;
String coercionEnd = null;
+ boolean avoidCoercion = false;
if (project.getBuiltinType(BuiltinType.INT).equals(definition))
{
boolean needsCoercion = false;
@@ -567,6 +576,10 @@ public class JSEmitter extends ASEmitter implements IJSEmitter
endMapping(assignedNode);
return;
}
+ else if(assignedNode instanceof BinaryOperatorAsNode)
+ {
+ needsCoercion = true;
+ }
else if(!project.getBuiltinType(BuiltinType.INT).equals(assignedTypeDef))
{
needsCoercion = true;
@@ -597,6 +610,10 @@ public class JSEmitter extends ASEmitter implements IJSEmitter
endMapping(assignedNode);
return;
}
+ else if(assignedNode instanceof BinaryOperatorAsNode)
+ {
+ needsCoercion = true;
+ }
else if(!project.getBuiltinType(BuiltinType.UINT).equals(assignedTypeDef))
{
needsCoercion = true;
@@ -632,6 +649,8 @@ public class JSEmitter extends ASEmitter implements IJSEmitter
if (t.equals(IASLanguageConstants.Number))
{
needsCoercion = false;
+ //explicitly prevent other coercion detection rules from picking this up
+ avoidCoercion = true;
}
}
}
@@ -696,6 +715,186 @@ public class JSEmitter extends ASEmitter implements IJSEmitter
coercionStart = "org.apache.royale.utils.Language.string(";
}
}
+ if ( assignedDef != null
+ && assignedDef instanceof IAppliedVectorDefinition
+ && assignedNode instanceof TypedExpressionNode) {
+ //assign a Vector class as the assigned value, e.g. var c:Class = Vector.<int>
+ if (project instanceof RoyaleJSProject
+ && ((RoyaleJSProject)project).config.getJsVectorEmulationClass() != null) {
+ startMapping(assignedNode);
+ write(((RoyaleJSProject)project).config.getJsVectorEmulationClass());
+ endMapping(assignedNode);
+ } else {
+ startMapping(assignedNode);
+ write(JSRoyaleEmitterTokens.SYNTH_VECTOR);
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ //the element type of the Vector:
+ write(formatQualifiedName(((TypedExpressionNode)assignedNode).getTypeNode().resolve(project).getQualifiedName()));
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ endMapping(assignedNode);
+ if (project instanceof RoyaleJSProject)
+ ((RoyaleJSProject)project).needLanguage = true;
+ getModel().needLanguage = true;
+ }
+ return;
+ }
+ if (assignedDef instanceof IClassDefinition
+ && assignedNode instanceof IdentifierNode
+ && ((IdentifierNode)assignedNode).getName().equals(IASGlobalFunctionConstants.Vector)
+ && project instanceof RoyaleJSProject
+ && ((RoyaleJSProject)project).config.getJsVectorEmulationClass() == null ){
+ startMapping(assignedNode);
+ write(JSRoyaleEmitterTokens.SYNTH_VECTOR);
+ write(ASEmitterTokens.PAREN_OPEN);
+ //null to signify not a valid constructor
+ write(ASEmitterTokens.NULL);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ endMapping(assignedNode);
+ if (project instanceof RoyaleJSProject)
+ ((RoyaleJSProject)project).needLanguage = true;
+ getModel().needLanguage = true;
+ return;
+ }
+ if (coercionStart == null
+ && !avoidCoercion
+ && assignedTypeDef !=null
+ && definition !=null
+ && (project.getBuiltinType(BuiltinType.ANY_TYPE).equals(assignedTypeDef)
+ || project.getBuiltinType(BuiltinType.OBJECT).equals(assignedTypeDef))
+ && !(project.getBuiltinType(BuiltinType.ANY_TYPE).equals(definition)
+ || project.getBuiltinType(BuiltinType.OBJECT).equals(definition))) {
+ //catch leftovers: remaining implicit coercion of loosely typed assigned values to strongly typed context
+ //assignment to Class definitions is excluded because there is no 'Class' type in JS
+ //Possibility: 'Class' could be implemented as a synthType
+ boolean needsCoercion = ((RoyaleJSProject)project).config.getJsComplexImplicitCoercions();
+
+ IDocEmitter docEmitter = getDocEmitter();
+ if (docEmitter instanceof JSRoyaleDocEmitter)
+ {
+ JSRoyaleDocEmitter royaleDocEmitter = (JSRoyaleDocEmitter) docEmitter;
+ //check for local toggle
+ needsCoercion = royaleDocEmitter.getLocalSettingAsBoolean(
+ JSRoyaleEmitterTokens.SUPPRESS_COMPLEX_IMPLICIT_COERCION, needsCoercion);
+ if (needsCoercion) {
+ //check for individual specified suppression
+
+ String definitionName = definition.getQualifiedName();
+ //for Vectors, use the unqualified name to match the source code
+ if (NativeUtils.isVector(definitionName)) {
+ definitionName = definition.getBaseName();
+ }
+
+ if (royaleDocEmitter.getLocalSettingIncludesString(
+ JSRoyaleEmitterTokens.SUPPRESS_COMPLEX_IMPLICIT_COERCION,
+ definitionName))
+ {
+ needsCoercion = false;
+ }
+
+ }
+ }
+
+ //Avoid specific compile-time 'fake' class(es)
+ if (needsCoercion && definition.getQualifiedName().equals("org.apache.royale.core.WrappedHTMLElement")) {
+ //*actual* coercion fails here, because this is not actually instantiated, it is
+ //simply a type definition representing the 'wrapped' (or tagged) HTMLElement
+ needsCoercion = false;
+ }
+
+ //Avoid XML/XMLList:
+ if (needsCoercion && project.getBuiltinType(BuiltinType.XML) != null) {
+ if (project.getBuiltinType(BuiltinType.XML).equals(definition)
+ || project.getBuiltinType(BuiltinType.XMLLIST).equals(definition)) {
+ //XML/XMLList has complex output and would need more work
+ needsCoercion = false;
+ }
+ }
+
+ //avoid scenario with ArrayElementType specified as metadata definition type - assume it is 'typed'
+ if (needsCoercion && assignedNode instanceof IDynamicAccessNode)
+ {
+ IDynamicAccessNode dynamicAccess = (IDynamicAccessNode) assignedNode;
+ IDefinition dynamicAccessIndexDef = dynamicAccess.getRightOperandNode().resolveType(project);
+ if (project.getBuiltinType(BuiltinType.NUMBER).equals(dynamicAccessIndexDef))
+ {
+ IDefinition leftDef = dynamicAccess.getLeftOperandNode().resolveType(project);
+ if (leftDef != null) {
+ IMetaTag[] metas = leftDef.getAllMetaTags();
+ for (IMetaTag meta : metas)
+ {
+ if (meta.getTagName().equals(IMetaAttributeConstants.ATTRIBUTE_ARRAYELEMENTTYPE))
+ {
+ IMetaTagAttribute[] attrs = meta.getAllAttributes();
+ for (IMetaTagAttribute attr : attrs)
+ {
+ String t = attr.getValue();
+ if (t.equals(definition.getQualifiedName()))
+ {
+ needsCoercion = false;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (needsCoercion && project.getBuiltinType(BuiltinType.STRING).equals(definition)) {
+ //explicit suppression of String coercion
+ if (docEmitter instanceof JSRoyaleDocEmitter)
+ {
+ JSRoyaleDocEmitter royaleDocEmitter = (JSRoyaleDocEmitter) docEmitter;
+ needsCoercion = royaleDocEmitter.emitStringConversions;
+ }
+ if (needsCoercion
+ && assignedNode instanceof FunctionCallNode
+ && ((FunctionCallNode) assignedNode).getNameNode() instanceof MemberAccessExpressionNode
+ && ((MemberAccessExpressionNode)((FunctionCallNode) assignedNode).getNameNode()).getRightOperandNode() instanceof IdentifierNode
+ && ((IdentifierNode)(((MemberAccessExpressionNode)((FunctionCallNode) assignedNode).getNameNode()).getRightOperandNode())).getName().equals("toString")) {
+ //even if toString() is called in an untyped way, assume a call to a method named 'toString' is actually providing a String
+ needsCoercion = false;
+ }
+ }
+
+ if (needsCoercion) {
+ //add a comment tag leader, so implicit casts are identifiable in the output
+ coercionStart = "/* implicit cast */ "
+ + JSRoyaleEmitterTokens.LANGUAGE_QNAME.getToken()
+ + ASEmitterTokens.MEMBER_ACCESS.getToken()
+ + ASEmitterTokens.AS.getToken()
+ + ASEmitterTokens.PAREN_OPEN.getToken();
+ String coercionTypeString = formatQualifiedName(definition.getQualifiedName());
+ if (NativeUtils.isSyntheticJSType(coercionTypeString)) {
+ String synthCall;
+ String synthethicType;
+ if (NativeUtils.isVector(coercionTypeString)) {
+ synthCall = JSRoyaleEmitterTokens.SYNTH_VECTOR.getToken();
+ synthethicType = formatQualifiedName(coercionTypeString.substring(8, coercionTypeString.length() -1));
+ } else {
+ synthCall = JSRoyaleEmitterTokens.SYNTH_TYPE.getToken();
+ synthethicType = coercionTypeString;
+ }
+ coercionTypeString = synthCall
+ + ASEmitterTokens.PAREN_OPEN.getToken()
+ + ASEmitterTokens.SINGLE_QUOTE.getToken()
+ + synthethicType
+ + ASEmitterTokens.SINGLE_QUOTE.getToken()
+ + ASEmitterTokens.PAREN_CLOSE.getToken();
+ }
+
+ coercionEnd = ASEmitterTokens.COMMA.getToken()
+ + ASEmitterTokens.SPACE.getToken()
+ + coercionTypeString
+ + ASEmitterTokens.COMMA.getToken()
+ + ASEmitterTokens.SPACE.getToken()
+ + ASEmitterTokens.TRUE.getToken()
+ + ASEmitterTokens.PAREN_CLOSE.getToken();
+ if (project instanceof RoyaleJSProject)
+ ((RoyaleJSProject)project).needLanguage = true;
+ getModel().needLanguage = true;
+ }
+ }
if (coercionStart != null)
{
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/goog/JSGoogDocEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/goog/JSGoogDocEmitter.java
index 6c94259..c64823a 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/goog/JSGoogDocEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/goog/JSGoogDocEmitter.java
@@ -39,6 +39,7 @@ import org.apache.royale.compiler.internal.codegen.js.JSSharedData;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitter;
import org.apache.royale.compiler.internal.scopes.ASScope;
import org.apache.royale.compiler.internal.semantics.SemanticUtils;
+import org.apache.royale.compiler.internal.tree.as.TypedExpressionNode;
import org.apache.royale.compiler.projects.ICompilerProject;
import org.apache.royale.compiler.tree.as.IASNode;
import org.apache.royale.compiler.tree.as.IClassNode;
@@ -128,7 +129,7 @@ public class JSGoogDocEmitter extends JSDocEmitter implements IJSGoogDocEmitter
if (def != null)
packageName = def.getPackageName();
- emitType(node, packageName);
+ emitType(node, packageName, project);
end();
}
@@ -257,15 +258,14 @@ public class JSGoogDocEmitter extends JSDocEmitter implements IJSGoogDocEmitter
packageName = ((ITypeDefinition) type).getPackageName();
}
}
-
- emitTypeShort(node, project.getActualPackageName(packageName));
+ emitTypeShort(node, project.getActualPackageName(packageName), project);
}
else
{
writeNewline();
begin();
emitConst(node);
- emitType(node, project.getActualPackageName(packageName));
+ emitType(node, project.getActualPackageName(packageName), project);
end();
}
}
@@ -361,9 +361,18 @@ public class JSGoogDocEmitter extends JSDocEmitter implements IJSGoogDocEmitter
}
@Override
- public void emitType(IASNode node, String packageName)
+ public void emitType(IASNode node, String packageName, ICompilerProject project)
{
String type = ((IVariableNode) node).getVariableType();
+ if (((IVariableNode) node).getVariableTypeNode() instanceof TypedExpressionNode) {
+ ITypeDefinition elemenTypeDef = ((TypedExpressionNode)(((IVariableNode) node).getVariableTypeNode())).getTypeNode().resolveType(project);
+ if (elemenTypeDef != null) {
+ type = "Vector.<" +
+ convertASTypeToJS(elemenTypeDef.getQualifiedName(),"")
+ +">";
+ packageName = "";
+ }
+ }
emitJSDocLine(JSGoogDocEmitterTokens.TYPE.getToken(),
convertASTypeToJS(type, packageName));
}
@@ -375,9 +384,18 @@ public class JSGoogDocEmitter extends JSDocEmitter implements IJSGoogDocEmitter
convertASTypeToJS(type, packageName));
}
- public void emitTypeShort(IASNode node, String packageName)
+ public void emitTypeShort(IASNode node, String packageName, ICompilerProject project)
{
String type = ((IVariableNode) node).getVariableType();
+ if (((IVariableNode) node).getVariableTypeNode() instanceof TypedExpressionNode) {
+ ITypeDefinition elemenTypeDef = ((TypedExpressionNode)(((IVariableNode) node).getVariableTypeNode())).getTypeNode().resolveType(project);
+ if (elemenTypeDef != null) {
+ type = "Vector.<" +
+ convertASTypeToJS(elemenTypeDef.getQualifiedName(),"")
+ +">";
+ packageName = "";
+ }
+ }
writeToken(JSDocEmitterTokens.JSDOC_OPEN);
write(ASEmitterTokens.ATSIGN);
writeToken(JSGoogDocEmitterTokens.TYPE);
@@ -494,16 +512,18 @@ public class JSGoogDocEmitter extends JSDocEmitter implements IJSGoogDocEmitter
// is a vector so convert the element type
String elementType = name.substring(8, name.length() - 1);
elementType = convertASTypeToJSType(elementType, pname);
- name = "Vector.<" + elementType + ">";
+ name = "Array.<" + elementType + ">";
}
- IASGlobalFunctionConstants.BuiltinType[] builtinTypes = IASGlobalFunctionConstants.BuiltinType
- .values();
- for (IASGlobalFunctionConstants.BuiltinType builtinType : builtinTypes)
- {
- if (name.equalsIgnoreCase(builtinType.getName()))
+ else {
+ IASGlobalFunctionConstants.BuiltinType[] builtinTypes = IASGlobalFunctionConstants.BuiltinType
+ .values();
+ for (IASGlobalFunctionConstants.BuiltinType builtinType : builtinTypes)
{
- isBuiltinFunction = true;
- break;
+ if (name.equalsIgnoreCase(builtinType.getName()))
+ {
+ isBuiltinFunction = true;
+ break;
+ }
}
}
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/AccessorEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/AccessorEmitter.java
index 428f542..e3bd834 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/AccessorEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/AccessorEmitter.java
@@ -105,7 +105,7 @@ public class AccessorEmitter extends JSSubEmitter implements
if (emitExports)
writeNewline(" * @export");
if (p.type != null)
- writeNewline(" * @type {"+JSGoogDocEmitter.convertASTypeToJSType(p.type.getBaseName(), p.type.getPackageName()) + "} */");
+ writeNewline(" * @type {"+ JSGoogDocEmitter.convertASTypeToJSType(p.type.getBaseName(), p.type.getPackageName()) + "} */");
else
writeNewline(" */");
write(getEmitter().formatQualifiedName(qname));
@@ -321,7 +321,7 @@ public class AccessorEmitter extends JSSubEmitter implements
if (emitExports)
writeNewline(" * @export");
if (p.type != null)
- writeNewline(" * @type {"+JSGoogDocEmitter.convertASTypeToJSType(p.type.getBaseName(), p.type.getPackageName()) + "} */");
+ writeNewline(" * @type {" + JSGoogDocEmitter.convertASTypeToJSType(p.type.getBaseName(), p.type.getPackageName()) + "} */");
else
writeNewline(" */");
FunctionNode fnNode = getterNode != null ? (FunctionNode) getterNode : (FunctionNode) setterNode;
@@ -483,7 +483,7 @@ public class AccessorEmitter extends JSSubEmitter implements
if (emitExports)
writeNewline(" * @export");
if (p.type != null)
- writeNewline(" * @type {"+JSGoogDocEmitter.convertASTypeToJSType(p.type.getBaseName(), p.type.getPackageName()) + "} */");
+ writeNewline(" * @type {" + JSGoogDocEmitter.convertASTypeToJSType(p.type.getBaseName(), p.type.getPackageName()) + "} */");
else
writeNewline(" */");
write(getEmitter().formatQualifiedName(qname));
@@ -602,7 +602,7 @@ public class AccessorEmitter extends JSSubEmitter implements
if (emitExports)
writeNewline(" * @export");
if (p.type != null)
- writeNewline(" * @type {"+JSGoogDocEmitter.convertASTypeToJSType(p.type.getBaseName(), p.type.getPackageName()) + "} */");
+ writeNewline(" * @type {" + JSGoogDocEmitter.convertASTypeToJSType(p.type.getBaseName(), p.type.getPackageName()) + "} */");
else
writeNewline(" */");
write(propName);
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/AsIsEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/AsIsEmitter.java
index e8ffe98..9ddea56 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/AsIsEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/AsIsEmitter.java
@@ -22,6 +22,7 @@ package org.apache.royale.compiler.internal.codegen.js.jx;
import org.apache.royale.compiler.asdoc.royale.ASDocComment;
import org.apache.royale.compiler.codegen.js.IJSEmitter;
import org.apache.royale.compiler.constants.IASLanguageConstants;
+import org.apache.royale.compiler.definitions.IAppliedVectorDefinition;
import org.apache.royale.compiler.definitions.IClassDefinition;
import org.apache.royale.compiler.definitions.IDefinition;
import org.apache.royale.compiler.internal.codegen.as.ASEmitterTokens;
@@ -29,12 +30,14 @@ import org.apache.royale.compiler.internal.codegen.js.JSSubEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitterTokens;
import org.apache.royale.compiler.internal.projects.RoyaleJSProject;
+import org.apache.royale.compiler.parsing.IASToken;
import org.apache.royale.compiler.projects.ICompilerProject;
import org.apache.royale.compiler.tree.ASTNodeID;
import org.apache.royale.compiler.tree.as.IASNode;
import org.apache.royale.compiler.tree.as.IBinaryOperatorNode;
import org.apache.royale.compiler.tree.as.IExpressionNode;
import org.apache.royale.compiler.tree.as.IFunctionNode;
+import org.apache.royale.compiler.utils.NativeUtils;
public class AsIsEmitter extends JSSubEmitter
{
@@ -53,7 +56,7 @@ public class AsIsEmitter extends JSSubEmitter
.resolve(getProject()) : null;
if (id != ASTNodeID.Op_IsID && dnode != null)
{
- boolean emit = coercion ?
+ boolean emit = coercion ?
!((RoyaleJSProject)getProject()).config.getJSOutputOptimizations().contains(JSRoyaleEmitterTokens.SKIP_FUNCTION_COERCIONS.getToken()) :
!((RoyaleJSProject)getProject()).config.getJSOutputOptimizations().contains(JSRoyaleEmitterTokens.SKIP_AS_COERCIONS.getToken());
@@ -147,7 +150,7 @@ public class AsIsEmitter extends JSSubEmitter
getEmitter().getModel().needLanguage = true;
if (node instanceof IBinaryOperatorNode)
{
- IBinaryOperatorNode binaryOperatorNode = (IBinaryOperatorNode) node;
+ IBinaryOperatorNode binaryOperatorNode = (IBinaryOperatorNode) node;
startMapping(node, binaryOperatorNode.getLeftOperandNode());
}
else
@@ -181,7 +184,29 @@ public class AsIsEmitter extends JSSubEmitter
if (dnode instanceof IClassDefinition)
{
startMapping(right);
- write(getEmitter().formatQualifiedName(((JSRoyaleEmitter)getEmitter()).convertASTypeToJS(dnode.getQualifiedName())));
+ if (NativeUtils.isSyntheticJSType(dnode.getQualifiedName())) {
+ JSRoyaleEmitterTokens langMethod;
+ String synthName;
+ if (NativeUtils.isVector(dnode.getQualifiedName()) && dnode instanceof IAppliedVectorDefinition) {
+ langMethod = JSRoyaleEmitterTokens.SYNTH_VECTOR;
+ synthName = getEmitter().formatQualifiedName(((IAppliedVectorDefinition) dnode).resolveElementType(project).getQualifiedName());
+ } else {
+ //non-vector, e.g. int/uint
+ langMethod = JSRoyaleEmitterTokens.SYNTH_TYPE;
+ synthName = getEmitter().formatQualifiedName(dnode.getQualifiedName());
+ }
+ write(langMethod);
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(synthName);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ if (project instanceof RoyaleJSProject)
+ ((RoyaleJSProject)project).needLanguage = true;
+ getEmitter().getModel().needLanguage = true;
+ } else {
+ write(getEmitter().formatQualifiedName(((JSRoyaleEmitter)getEmitter()).convertASTypeToJS(dnode.getQualifiedName())));
+ }
endMapping(right);
}
else
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java
index 1533bf4..8d6c103 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java
@@ -21,6 +21,7 @@ package org.apache.royale.compiler.internal.codegen.js.jx;
import org.apache.royale.compiler.codegen.ISubEmitter;
import org.apache.royale.compiler.codegen.js.IJSEmitter;
+import org.apache.royale.compiler.constants.IASLanguageConstants;
import org.apache.royale.compiler.definitions.IDefinition;
import org.apache.royale.compiler.definitions.ITypeDefinition;
import org.apache.royale.compiler.internal.codegen.as.ASEmitterTokens;
@@ -30,10 +31,10 @@ import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.goog.JSGoogEmitterTokens;
import org.apache.royale.compiler.internal.definitions.AccessorDefinition;
+import org.apache.royale.compiler.internal.definitions.AppliedVectorDefinition;
+import org.apache.royale.compiler.internal.projects.RoyaleJSProject;
import org.apache.royale.compiler.internal.semantics.SemanticUtils;
-import org.apache.royale.compiler.internal.tree.as.DynamicAccessNode;
-import org.apache.royale.compiler.internal.tree.as.MemberAccessExpressionNode;
-import org.apache.royale.compiler.internal.tree.as.UnaryOperatorAtNode;
+import org.apache.royale.compiler.internal.tree.as.*;
import org.apache.royale.compiler.tree.ASTNodeID;
import org.apache.royale.compiler.tree.as.IASNode;
import org.apache.royale.compiler.tree.as.IBinaryOperatorNode;
@@ -100,7 +101,7 @@ public class BinaryOperatorEmitter extends JSSubEmitter implements
{
IASNode lnode = leftSide.getChild(0);
IASNode rnode = leftSide.getChild(1);
- IDefinition rnodeDef = (rnode instanceof IIdentifierNode) ?
+ IDefinition rnodeDef = (rnode instanceof IIdentifierNode) ?
((IIdentifierNode) rnode).resolve(getWalker().getProject()) :
null;
boolean isDynamicAccess = rnode instanceof DynamicAccessNode;
@@ -117,7 +118,7 @@ public class BinaryOperatorEmitter extends JSSubEmitter implements
else
write(getEmitter().formatQualifiedName(
getModel().getCurrentClass().getQualifiedName()));
-
+
write(ASEmitterTokens.MEMBER_ACCESS);
write(JSGoogEmitterTokens.SUPERCLASS);
write(ASEmitterTokens.MEMBER_ACCESS);
@@ -391,10 +392,11 @@ public class BinaryOperatorEmitter extends JSSubEmitter implements
}
}
-
- super_emitBinaryOperator(node, isAssignment);
+
+ super_emitBinaryOperator(node, isAssignment);
}
}
+
private void super_emitBinaryOperator(IBinaryOperatorNode node, boolean isAssignment)
{
@@ -431,8 +433,28 @@ public class BinaryOperatorEmitter extends JSSubEmitter implements
}
else
{
- getWalker().walk(node.getLeftOperandNode());
-
+ if (isAssignment
+ && (getProject() instanceof RoyaleJSProject && ((RoyaleJSProject) getProject()).config != null && ((RoyaleJSProject) getProject()).config.getJsVectorEmulationClass() == null)
+ && node.getLeftOperandNode() instanceof MemberAccessExpressionNode
+ && ((MemberAccessExpressionNode) node.getLeftOperandNode()).getRightOperandNode() instanceof IdentifierNode
+ && ((IdentifierNode) ((MemberAccessExpressionNode) node.getLeftOperandNode()).getRightOperandNode()).getName().equals("length")
+ && ((MemberAccessExpressionNode) node.getLeftOperandNode()).getLeftOperandNode().resolveType(getProject()) instanceof AppliedVectorDefinition)
+ {
+ //for default Vector implementation, when setting length, we need to set it on the associated 'synthType' instance which tags the native
+ //Array representation of the Vector. This allows running 'setter' code because it is not possible to override the native length setter on Array
+ //unless using a different approach, like es6 Proxy.
+ //this code inserts the extra access name for setting length, e.g. myVectInstance['_synthType'].length = assignedValue
+ //the dynamic access field name is a constant on Language, so it can be different/shorter in release build
+ getWalker().walk(((MemberAccessExpressionNode) node.getLeftOperandNode()).getLeftOperandNode());
+ write(ASEmitterTokens.SQUARE_OPEN);
+ write(JSRoyaleEmitterTokens.LANGUAGE_QNAME.getToken());
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write(JSRoyaleEmitterTokens.ROYALE_SYNTH_TAG_FIELD_NAME);
+ write(ASEmitterTokens.SQUARE_CLOSE);
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ getWalker().walk(((MemberAccessExpressionNode) node.getLeftOperandNode()).getRightOperandNode());
+ }
+ else getWalker().walk(node.getLeftOperandNode());
startMapping(node, node.getLeftOperandNode());
if (id != ASTNodeID.Op_CommaID)
@@ -469,12 +491,14 @@ public class BinaryOperatorEmitter extends JSSubEmitter implements
}
else
{
+
getWalker().walk(node.getRightOperandNode());
+
if (node.getNodeID() == ASTNodeID.Op_InID &&
((JSRoyaleEmitter)getEmitter()).isXML(node.getRightOperandNode()))
{
write(".elementNames()");
- }
+ }
else if (node.getNodeID() == ASTNodeID.Op_InID &&
((JSRoyaleEmitter)getEmitter()).isProxy(node.getRightOperandNode()))
{
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/ClassEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/ClassEmitter.java
index 807e7ae..3f6e13e 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/ClassEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/ClassEmitter.java
@@ -67,6 +67,8 @@ public class ClassEmitter extends JSSubEmitter implements
ASDocComment asDoc = (ASDocComment) node.getASDocComment();
if (asDoc != null && keepASDoc)
DocEmitterUtils.loadImportIgnores(fjs, asDoc.commentNoEnd());
+
+ boolean suppressExport = (asDoc != null && DocEmitterUtils.hasSuppressExport(fjs, asDoc.commentNoEnd()));
IClassDefinition definition = node.getDefinition();
@@ -131,7 +133,7 @@ public class ClassEmitter extends JSSubEmitter implements
}
}
- if (!getEmitter().getModel().isExterns)
+ if (!getEmitter().getModel().isExterns && !suppressExport)
{
JSRoyaleDocEmitter doc = (JSRoyaleDocEmitter) getEmitter()
.getDocEmitter();
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/DynamicAccessEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/DynamicAccessEmitter.java
index 2fd5085..5b78317 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/DynamicAccessEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/DynamicAccessEmitter.java
@@ -19,20 +19,30 @@
package org.apache.royale.compiler.internal.codegen.js.jx;
+import org.apache.royale.compiler.codegen.IDocEmitter;
import org.apache.royale.compiler.codegen.ISubEmitter;
import org.apache.royale.compiler.codegen.js.IJSEmitter;
import org.apache.royale.compiler.constants.IASLanguageConstants;
import org.apache.royale.compiler.definitions.ITypeDefinition;
import org.apache.royale.compiler.internal.codegen.as.ASEmitterTokens;
+import org.apache.royale.compiler.internal.codegen.js.JSEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.JSSubEmitter;
+import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleDocEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitter;
+import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitterTokens;
+import org.apache.royale.compiler.internal.definitions.AppliedVectorDefinition;
+import org.apache.royale.compiler.internal.projects.RoyaleJSProject;
+import org.apache.royale.compiler.internal.tree.as.BinaryOperatorAssignmentNode;
import org.apache.royale.compiler.internal.tree.as.FunctionCallNode;
+import org.apache.royale.compiler.internal.tree.as.IdentifierNode;
import org.apache.royale.compiler.internal.tree.as.MemberAccessExpressionNode;
+import org.apache.royale.compiler.parsing.IASToken;
import org.apache.royale.compiler.tree.ASTNodeID;
import org.apache.royale.compiler.tree.as.IDynamicAccessNode;
import org.apache.royale.compiler.tree.as.IExpressionNode;
import org.apache.royale.compiler.tree.as.ILiteralNode;
import org.apache.royale.compiler.tree.as.IOperatorNode.OperatorType;
+import org.apache.royale.compiler.utils.NativeUtils;
public class DynamicAccessEmitter extends JSSubEmitter implements
ISubEmitter<IDynamicAccessNode>
@@ -98,8 +108,52 @@ public class DynamicAccessEmitter extends JSSubEmitter implements
startMapping(node, leftOperandNode);
write(ASEmitterTokens.SQUARE_OPEN);
endMapping(node);
+ boolean wrapVectorIndex = false;
+ if (getProject() instanceof RoyaleJSProject) {
+ if (node.getNodeID().equals(ASTNodeID.ArrayIndexExpressionID)){
+ if (node.getParent() instanceof BinaryOperatorAssignmentNode) {
+ if (node.getLeftOperandNode().resolveType(getProject()) instanceof AppliedVectorDefinition) {
+ boolean suppressVectorIndexCheck = !(((RoyaleJSProject)getProject()).config.getJsVectorIndexChecks());
+
+ IDocEmitter docEmitter = getEmitter().getDocEmitter();
+ if (docEmitter instanceof JSRoyaleDocEmitter)
+ {
+ JSRoyaleDocEmitter royaleDocEmitter = (JSRoyaleDocEmitter) docEmitter;
+ //check for local toggle
+ suppressVectorIndexCheck = royaleDocEmitter.getLocalSettingAsBoolean(
+ JSRoyaleEmitterTokens.SUPPRESS_VECTOR_INDEX_CHECK, suppressVectorIndexCheck);
+
+ if (!suppressVectorIndexCheck) {
+ //check for individual specified suppression, based on variable name
+ if (leftOperandNode instanceof IdentifierNode) {
+ if (royaleDocEmitter.getLocalSettingIncludesString(
+ JSRoyaleEmitterTokens.SUPPRESS_VECTOR_INDEX_CHECK,
+ ((IdentifierNode) leftOperandNode).getName()
+ )){
+ suppressVectorIndexCheck = true;
+ }
+ }
+ }
+ }
+ if (!suppressVectorIndexCheck) {
+ getModel().needLanguage = true;
+ ((RoyaleJSProject) getProject()).needLanguage = true;
+ getWalker().walk(leftOperandNode);
+ write(ASEmitterTokens.SQUARE_OPEN);
+ write(JSRoyaleEmitterTokens.VECTOR_INDEX_CHECK_METHOD_NAME);
+ write(ASEmitterTokens.SQUARE_CLOSE);
+ write(ASEmitterTokens.PAREN_OPEN);
+ wrapVectorIndex = true;
+ }
+ }
+ }
+ }
+ }
getWalker().walk(rightOperandNode);
+ if (wrapVectorIndex) {
+ write(ASEmitterTokens.PAREN_CLOSE);
+ }
if (type != null && type.getQualifiedName().contentEquals(IASLanguageConstants.QName))
write(".objectAccessFormat()");
startMapping(node, rightOperandNode);
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/FunctionCallEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/FunctionCallEmitter.java
index 1e0bae0..855dd76 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/FunctionCallEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/FunctionCallEmitter.java
@@ -20,8 +20,10 @@
package org.apache.royale.compiler.internal.codegen.js.jx;
import org.apache.royale.compiler.codegen.IASGlobalFunctionConstants;
+import org.apache.royale.compiler.codegen.IDocEmitter;
import org.apache.royale.compiler.codegen.ISubEmitter;
import org.apache.royale.compiler.codegen.js.IJSEmitter;
+import org.apache.royale.compiler.common.SourceLocation;
import org.apache.royale.compiler.constants.IASLanguageConstants;
import org.apache.royale.compiler.constants.IASLanguageConstants.BuiltinType;
import org.apache.royale.compiler.definitions.IDefinition;
@@ -29,28 +31,18 @@ import org.apache.royale.compiler.definitions.ITypeDefinition;
import org.apache.royale.compiler.internal.codegen.as.ASEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.JSSessionModel;
import org.apache.royale.compiler.internal.codegen.js.JSSubEmitter;
+import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleDocEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.utils.EmitterUtils;
-import org.apache.royale.compiler.internal.definitions.AppliedVectorDefinition;
-import org.apache.royale.compiler.internal.definitions.ClassDefinition;
-import org.apache.royale.compiler.internal.definitions.FunctionDefinition;
-import org.apache.royale.compiler.internal.definitions.InterfaceDefinition;
-import org.apache.royale.compiler.internal.definitions.NamespaceDefinition;
+import org.apache.royale.compiler.internal.definitions.*;
import org.apache.royale.compiler.internal.projects.RoyaleJSProject;
-import org.apache.royale.compiler.internal.tree.as.ContainerNode;
-import org.apache.royale.compiler.internal.tree.as.IdentifierNode;
-import org.apache.royale.compiler.internal.tree.as.MemberAccessExpressionNode;
-import org.apache.royale.compiler.internal.tree.as.NamespaceIdentifierNode;
-import org.apache.royale.compiler.internal.tree.as.VectorLiteralNode;
+import org.apache.royale.compiler.internal.tree.as.*;
import org.apache.royale.compiler.problems.TooFewFunctionParametersProblem;
import org.apache.royale.compiler.problems.TooManyFunctionParametersProblem;
import org.apache.royale.compiler.projects.ICompilerProject;
import org.apache.royale.compiler.tree.ASTNodeID;
-import org.apache.royale.compiler.tree.as.IASNode;
-import org.apache.royale.compiler.tree.as.IContainerNode;
-import org.apache.royale.compiler.tree.as.IExpressionNode;
-import org.apache.royale.compiler.tree.as.IFunctionCallNode;
+import org.apache.royale.compiler.tree.as.*;
import org.apache.royale.compiler.utils.NativeUtils;
public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFunctionCallNode>
@@ -66,7 +58,6 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
{
// TODO (mschmalle) will remove this cast as more things get abstracted
JSRoyaleEmitter fjs = (JSRoyaleEmitter) getEmitter();
-
IASNode cnode = node.getChild(0);
if (cnode.getNodeID() == ASTNodeID.MemberAccessExpressionID)
@@ -80,16 +71,45 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
def = nameNode.resolve(getProject());
boolean isClassCast = false;
-
+ boolean wrapResolve = false;
if (node.isNewExpression())
{
- if (!(node.getChild(1) instanceof VectorLiteralNode))
+ boolean omitNew = false;
+ if (nameNode instanceof IdentifierNode
+ && (((IdentifierNode) nameNode).getName().equals(IASLanguageConstants.String)
+ || ((IdentifierNode) nameNode).getName().equals(IASLanguageConstants.Boolean)
+ || ((IdentifierNode) nameNode).getName().equals(IASLanguageConstants.Number)))
+ {
+ omitNew = true;
+ }
+
+ if (!((node.getChild(1) instanceof VectorLiteralNode)))
{
- if (def == null || !(def.getBaseName().equals(IASGlobalFunctionConstants._int) ||
- def.getBaseName().equals(IASGlobalFunctionConstants.uint) ||
- def instanceof AppliedVectorDefinition))
+ if (!omitNew
+ && ((def == null
+ || !(def.getBaseName().equals(IASGlobalFunctionConstants._int) || def.getBaseName().equals(IASGlobalFunctionConstants.uint)))
+ && !(def instanceof AppliedVectorDefinition && (
+ ((RoyaleJSProject) getProject()).config.getJsVectorEmulationClass()!= null
+ && ((RoyaleJSProject) getProject()).config.getJsVectorEmulationClass().equals("Array"))
+ ))
+ )
{
- startMapping(node.getNewKeywordNode());
+ if (getProject() instanceof RoyaleJSProject
+ && nameNode.resolveType(getProject()) != null
+ && nameNode.resolveType(getProject()).getQualifiedName().equals("Class")) {
+
+ wrapResolve = shouldResolveUncertain(nameNode, false);
+
+ if (wrapResolve) {
+ ((RoyaleJSProject) getProject()).needLanguage = true;
+ getModel().needLanguage = true;
+ write(JSRoyaleEmitterTokens.LANGUAGE_QNAME);
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write("resolveUncertain");
+ write(ASEmitterTokens.PAREN_OPEN);
+ }
+ }
+ startMapping(node.getNewKeywordNode());
writeToken(ASEmitterTokens.NEW);
endMapping(node.getNewKeywordNode());
}
@@ -97,14 +117,52 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
else
{
VectorLiteralNode vectorLiteralNode = (VectorLiteralNode) node.getChild(1);
- String vectorClassName = (((RoyaleJSProject)fjs.getWalker().getProject()).config.getJsVectorEmulationClass());
- if (vectorClassName != null)
+ String vectorEmulationClass = (((RoyaleJSProject)fjs.getWalker().getProject()).config.getJsVectorEmulationClass());
+ SourceLocation mappingLocation;
+ String elementClassName;
+ IDefinition elementClass = (((AppliedVectorDefinition)def).resolveElementType(getWalker().getProject()));
+ elementClassName = getEmitter().formatQualifiedName(elementClass.getQualifiedName());
+ if (vectorEmulationClass != null)
{
- writeToken(ASEmitterTokens.NEW);
- write(vectorClassName);
- write(ASEmitterTokens.PAREN_OPEN);
+ if (!vectorEmulationClass.equals("Array")) {
+ //Explanation:
+ //this was how it was originally set up, but it assumes the constructor of the emulation
+ //class can handle first argument being an Array or numeric value...
+ writeToken(ASEmitterTokens.NEW);
+ write(vectorEmulationClass);
+ write(ASEmitterTokens.PAREN_OPEN);
+ }// otherwise.... if 'Array' is the emulation class, then just use the literal content
+ } else {
+ //no 'new' output in this case, just coercion, so map from the start of 'new'
+ startMapping(node);
+ write(JSRoyaleEmitterTokens.SYNTH_VECTOR);
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ //the element type of the Vector:
+ write(elementClassName);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ write(ASEmitterTokens.SQUARE_OPEN);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write("coerce");
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.SQUARE_CLOSE);
+ mappingLocation = new SourceLocation(vectorLiteralNode.getCollectionTypeNode());
+ mappingLocation.setEndColumn(mappingLocation.getEndColumn() + 1);
+ endMapping(mappingLocation);
+ write(ASEmitterTokens.PAREN_OPEN);
+ if (getProject() instanceof RoyaleJSProject)
+ ((RoyaleJSProject)getProject()).needLanguage = true;
+ getEmitter().getModel().needLanguage = true;
+
}
+ mappingLocation = new SourceLocation(vectorLiteralNode.getContentsNode());
+ if (mappingLocation.getColumn()>0) mappingLocation.setColumn(mappingLocation.getColumn() -1);
+ mappingLocation.setEndColumn(mappingLocation.getColumn()+1);
+ startMapping(mappingLocation);
write("[");
+
+ endMapping(mappingLocation);
ContainerNode contentsNode = vectorLiteralNode.getContentsNode();
int len = contentsNode.getChildCount();
for (int i = 0; i < len; i++)
@@ -115,14 +173,24 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
writeToken(ASEmitterTokens.COMMA);
}
}
+ mappingLocation = new SourceLocation(vectorLiteralNode.getContentsNode());
+ mappingLocation.setLine(vectorLiteralNode.getContentsNode().getEndLine());
+ mappingLocation.setColumn(vectorLiteralNode.getContentsNode().getEndColumn());
+ mappingLocation.setEndColumn(mappingLocation.getColumn() + 1);
+ startMapping(mappingLocation);
write("]");
- if (vectorClassName != null)
+ endMapping(mappingLocation);
+ if (vectorEmulationClass != null)
{
- writeToken(ASEmitterTokens.COMMA);
- write(ASEmitterTokens.SINGLE_QUOTE);
- write(((AppliedVectorDefinition)def).resolveElementType(getWalker().getProject()).getBaseName());
- write(ASEmitterTokens.SINGLE_QUOTE);
- write(ASEmitterTokens.PAREN_CLOSE);
+ if (!vectorEmulationClass.equals("Array")) {
+ writeToken(ASEmitterTokens.COMMA);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(elementClassName);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ }
+ } else {
+ write(ASEmitterTokens.PAREN_CLOSE);
}
return;
}
@@ -131,12 +199,15 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
{
def = node.getNameNode().resolve(getProject());
- isClassCast = (def instanceof ClassDefinition || def instanceof InterfaceDefinition)
+ isClassCast = def != null && (def instanceof ClassDefinition
+ || def instanceof InterfaceDefinition
+ || ( def instanceof VariableDefinition && ((VariableDefinition) def).resolveType(getProject()).getBaseName().equals("Class")))
&& !(NativeUtils.isJSNative(def.getBaseName()))
&& !def.getBaseName().equals(IASLanguageConstants.XML)
&& !def.getBaseName().equals(IASLanguageConstants.XMLList);
+
}
-
+
if (node.isNewExpression())
{
def = node.resolveCalledExpression(getProject());
@@ -177,30 +248,39 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
if (nameNode.hasParenthesis())
write(ASEmitterTokens.PAREN_CLOSE);
}
-
- if (def instanceof AppliedVectorDefinition)
+ if ( def instanceof AppliedVectorDefinition
+ && (fjs.getWalker().getProject() instanceof RoyaleJSProject)
+ && (((RoyaleJSProject)fjs.getWalker().getProject()).config.getJsVectorEmulationClass() != null))
{
- ContainerNode args = node.getArgumentsNode();
- if (args.getChildCount() == 0)
- {
- String vectorClassName = (((RoyaleJSProject)fjs.getWalker().getProject()).config.getJsVectorEmulationClass());
- if (vectorClassName != null)
- {
+ ContainerNode args = node.getArgumentsNode();
+ String vectorEmulationClass = ((RoyaleJSProject)fjs.getWalker().getProject()).config.getJsVectorEmulationClass();
+ if (args.getChildCount() == 0)
+ {
+ if (vectorEmulationClass.equals("Array")) {
+ write(ASEmitterTokens.SQUARE_OPEN);
+ write(ASEmitterTokens.SQUARE_CLOSE);
+ } else {
write(ASEmitterTokens.PAREN_OPEN);
- write(ASEmitterTokens.SQUARE_OPEN);
- write(ASEmitterTokens.SQUARE_CLOSE);
+ write(ASEmitterTokens.SQUARE_OPEN);
+ write(ASEmitterTokens.SQUARE_CLOSE);
write(ASEmitterTokens.COMMA);
write(ASEmitterTokens.SPACE);
write(ASEmitterTokens.SINGLE_QUOTE);
- write(((AppliedVectorDefinition)def).resolveElementType(getWalker().getProject()).getBaseName());
+ write(((AppliedVectorDefinition)def).resolveElementType(getWalker().getProject()).getQualifiedName());
write(ASEmitterTokens.SINGLE_QUOTE);
write(ASEmitterTokens.PAREN_CLOSE);
}
- else
- getEmitter().emitArguments(node.getArgumentsNode());
- }
- else
- {
+ } else {
+ if (vectorEmulationClass.equals("Array")) {
+ if (getProject() instanceof RoyaleJSProject)
+ ((RoyaleJSProject) getProject()).needLanguage = true;
+ getEmitter().getModel().needLanguage = true;
+ write(JSRoyaleEmitterTokens.LANGUAGE_QNAME);
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ startMapping(node.getNameNode());
+ write("arrayAsVector");
+ endMapping(node.getNameNode());
+ }
startMapping(node);
write(ASEmitterTokens.PAREN_OPEN);
endMapping(node);
@@ -208,28 +288,29 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
write(ASEmitterTokens.COMMA);
write(ASEmitterTokens.SPACE);
write(ASEmitterTokens.SINGLE_QUOTE);
- write(((AppliedVectorDefinition)def).resolveElementType(getWalker().getProject()).getBaseName());
+ write(((AppliedVectorDefinition) def).resolveElementType(getWalker().getProject()).getQualifiedName());
write(ASEmitterTokens.SINGLE_QUOTE);
- if (args.getChildCount() == 2)
- {
- IASNode second = args.getChild(1);
- if (second instanceof IExpressionNode)
- {
- ITypeDefinition secondType =
- ((IExpressionNode)second).resolveType(fjs.getWalker().getProject());
- if (fjs.getWalker().getProject().getBuiltinType(BuiltinType.BOOLEAN).equals(secondType))
- {
+ if (args.getChildCount() == 2 && !vectorEmulationClass.equals("Array")) {
+ IASNode second = args.getChild(1);
+ if (second instanceof IExpressionNode) {
+ ITypeDefinition secondType =
+ ((IExpressionNode) second).resolveType(fjs.getWalker().getProject());
+ if (fjs.getWalker().getProject().getBuiltinType(BuiltinType.BOOLEAN).equals(secondType)) {
write(ASEmitterTokens.COMMA);
write(ASEmitterTokens.SPACE);
- getWalker().walk(second);
- }
- }
+ getWalker().walk(second);
+ }
+ }
}
write(ASEmitterTokens.PAREN_CLOSE);
- }
+ }
+ } else {
+ getEmitter().emitArguments(node.getArgumentsNode());
+ }
+ //end wrap resolve
+ if (wrapResolve) {
+ write(ASEmitterTokens.PAREN_CLOSE);
}
- else
- getEmitter().emitArguments(node.getArgumentsNode());
}
else if (!isClassCast)
{
@@ -270,37 +351,99 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
}
else if (def.getBaseName().equals("sort"))
{
- if (def.getParent() != null &&
- def.getParent().getQualifiedName().equals("Array"))
- {
- IExpressionNode args[] = node.getArgumentNodes();
- if (args.length > 0)
- {
- IExpressionNode optionsParamCheck = args.length == 1 ? args[0] : args[1];
- ICompilerProject project = this.getProject();
- IDefinition paramCheck = optionsParamCheck.resolveType(project);
-
- if (paramCheck.getBaseName().equals(IASLanguageConstants._int)
- || paramCheck.getBaseName().equals(IASLanguageConstants.uint)
- || paramCheck.getBaseName().equals(IASLanguageConstants.Number))
+ if (def.getParent() != null) {
+ if (def.getParent().getQualifiedName().equals("Array")
+ || (node.getNameNode() instanceof MemberAccessExpressionNode
+ && (((MemberAccessExpressionNode) node.getNameNode()).getLeftOperandNode().resolveType(getProject()) instanceof AppliedVectorDefinition)
+ && getProject() instanceof RoyaleJSProject
+ && (((RoyaleJSProject)getProject()).config.getJsVectorEmulationClass() == null
+ || ((RoyaleJSProject)getProject()).config.getJsVectorEmulationClass().equals("Array"))))
+ {
+ IExpressionNode args[] = node.getArgumentNodes();
+ if (args.length > 0)
{
- //deal with specific numeric option argument variations
- //either: Array.sort(option:uint) or Array.sort(compareFunction:Function, option:uint)
- //use our Language sort implementation to support these actionscript-specific method signatures
- if (project instanceof RoyaleJSProject)
- ((RoyaleJSProject) project).needLanguage = true;
- getEmitter().getModel().needLanguage = true;
- write(JSRoyaleEmitterTokens.LANGUAGE_QNAME);
- write(ASEmitterTokens.MEMBER_ACCESS);
- write("sort");
- IContainerNode newArgs = EmitterUtils.insertArgumentsBefore(node.getArgumentsNode(), cnode);
- fjs.emitArguments(newArgs);
- return;
+ IExpressionNode optionsParamCheck = args.length == 1 ? args[0] : args[1];
+ ICompilerProject project = this.getProject();
+ IDefinition paramCheck = optionsParamCheck.resolveType(project);
+
+ if (paramCheck.getBaseName().equals(IASLanguageConstants._int)
+ || paramCheck.getBaseName().equals(IASLanguageConstants.uint)
+ || paramCheck.getBaseName().equals(IASLanguageConstants.Number))
+ {
+ //deal with specific numeric option argument variations
+ //either: Array.sort(option:uint) or Array.sort(compareFunction:Function, option:uint)
+ //use our Language sort implementation to support these actionscript-specific method signatures
+ if (project instanceof RoyaleJSProject)
+ ((RoyaleJSProject) project).needLanguage = true;
+ getEmitter().getModel().needLanguage = true;
+ write(JSRoyaleEmitterTokens.LANGUAGE_QNAME);
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write("sort");
+ IContainerNode newArgs = EmitterUtils.insertArgumentsBefore(node.getArgumentsNode(), cnode);
+ fjs.emitArguments(newArgs);
+ return;
+ }
}
- }
- }
+ }
+ }
+
}
+ else if ((def.getBaseName().equals("insertAt")
+ || def.getBaseName().equals("removeAt"))
+ && def.getParent() instanceof AppliedVectorDefinition
+ && ((getProject() instanceof RoyaleJSProject) && (
+ ((RoyaleJSProject)getProject()).config.getJsVectorEmulationClass() == null
+ || ((RoyaleJSProject)getProject()).config.getJsVectorEmulationClass().equals("Array")))
+ ) {
+ if ((((RoyaleJSProject)getProject()).config.getJsVectorEmulationClass() != null)
+ && ((RoyaleJSProject)getProject()).config.getJsVectorEmulationClass().equals("Array")) {
+ //use a similar approach to regular 'Array' insertAt/removeAt
+ //for Array Vector emulation only (not for other custom classes)
+ //replace the insertAt/removeAt method with 'splice'
+ IdentifierNode splice = new IdentifierNode("splice");
+ splice.setSourceLocation(((MemberAccessExpressionNode)node.getNameNode()).getRightOperandNode());
+ splice.setParent((MemberAccessExpressionNode)node.getNameNode());
+ ((MemberAccessExpressionNode)node.getNameNode()).setRightOperandNode(splice);
+ NumericLiteralNode spliceArg;
+ if (def.getBaseName().equals("insertAt")) {
+ //insertAt
+ spliceArg = new NumericLiteralNode("0");
+ //This works like 'insertAt' itself, pushing the insertee to 3rd position (correct position):
+ node.getArgumentsNode().addChild(spliceArg, 1);
+ } else {
+ //removeAt
+ spliceArg = new NumericLiteralNode("1");
+ node.getArgumentsNode().addChild(spliceArg, 1);
+ }
+ } else {
+ //default Vector implementation
+ //unlike Array implementation of these methods, the synthetic Vector implementation supports these methods at runtime,
+ //and they behave differently with fixed length vectors compared to the native 'splice' method output which is used to
+ //support them in Array, however they are not protected from GCL renaming in release builds by any actual class definition,
+ //so we explicitly 'protect' them here by using DynamicAccess instead of MemberAccess
+ ExpressionNodeBase leftSide = (ExpressionNodeBase)(((BinaryOperatorNodeBase) (node.getNameNode())).getLeftOperandNode());
+ LiteralNode dynamicName = new LiteralNode(ILiteralNode.LiteralType.STRING, "'" + def.getBaseName() + "'");
+ dynamicName.setSourceLocation(((BinaryOperatorNodeBase) (node.getNameNode())).getRightOperandNode());
+ DynamicAccessNode replacement = new DynamicAccessNode(leftSide);
+ leftSide.setParent(replacement);
+ replacement.setSourceLocation(node.getNameNode());
+ replacement.setRightOperandNode(dynamicName);
+ dynamicName.setParent(replacement);
+
+ FunctionCallNode replacer = new FunctionCallNode(replacement) ;
+ replacement.setParent(replacer);
+ IExpressionNode[] args = node.getArgumentNodes();
+ for (IExpressionNode arg : args) {
+ replacer.getArgumentsNode().addItem((NodeBase) arg);
+ }
+ replacer.getArgumentsNode().setParent(replacer);
+ replacer.getArgumentsNode().setSourceLocation(node.getArgumentsNode());
+ replacer.setParent((NodeBase) node.getParent());
+ //swap it out
+ node = replacer;
+ }
+ }
else if (def instanceof AppliedVectorDefinition)
{
IExpressionNode[] argumentNodes = node.getArgumentNodes();
@@ -315,9 +458,54 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
}
else
{
- IExpressionNode argumentNode = argumentNodes[0];
- getWalker().walk(argumentNode);
- write(".slice()");
+ String elementClassName = getEmitter().formatQualifiedName(((TypedExpressionNode)nameNode).getTypeNode().resolve(getProject()).getQualifiedName());
+ if (getProject() instanceof RoyaleJSProject
+ && ((RoyaleJSProject) getProject()).config.getJsVectorEmulationClass()!= null) {
+ String vectorEmulationClass = ((RoyaleJSProject) getProject()).config.getJsVectorEmulationClass();
+ if (vectorEmulationClass.equals("Array")) {
+ //just do a slice copy of the array which is the first argument
+ getWalker().walk(node.getArgumentsNode().getChild(0));
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write("slice");
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ } else {
+ //assume the emulation class can handle an array or numeric value for first constructor arg...
+ writeToken(ASEmitterTokens.NEW);
+ startMapping(node.getNameNode());
+ write(vectorEmulationClass);
+ endMapping(node.getNameNode());
+ write(ASEmitterTokens.PAREN_OPEN);
+ getWalker().walk(node.getArgumentsNode().getChild(0));
+ writeToken(ASEmitterTokens.COMMA);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ //the element type of the Vector:
+ write(elementClassName);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ }
+ } else {
+ //default Vector implementation
+ startMapping(node.getNameNode());
+ write(JSRoyaleEmitterTokens.SYNTH_VECTOR);
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ //the element type of the Vector:
+ write(elementClassName);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ write(ASEmitterTokens.SQUARE_OPEN);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write("coerce");
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.SQUARE_CLOSE);
+ endMapping(node.getNameNode());
+
+ getEmitter().emitArguments(node.getArgumentsNode());
+ if (getProject() instanceof RoyaleJSProject)
+ ((RoyaleJSProject)getProject()).needLanguage = true;
+ getEmitter().getModel().needLanguage = true;
+ }
}
return;
}
@@ -327,6 +515,22 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
getEmitter().emitArguments(node.getArgumentsNode());
return;
}
+ else if (def.getQualifiedName().equals(IASLanguageConstants.Object)) {
+ //'resolveUncertain' always output here
+ //unless a) there are no arguments
+ //or b) it is *explicitly* suppressed for 'Object'
+ if (node.getArgumentNodes().length > 0) {
+ if (shouldResolveUncertain(nameNode, true)) {
+ wrapResolve = true;
+ ((RoyaleJSProject) getProject()).needLanguage = true;
+ getModel().needLanguage = true;
+ write(JSRoyaleEmitterTokens.LANGUAGE_QNAME);
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write("resolveUncertain");
+ write(ASEmitterTokens.PAREN_OPEN);
+ }
+ }
+ }
else if (nameNode.getNodeID() == ASTNodeID.NamespaceAccessExpressionID && def instanceof FunctionDefinition)
{
if (fjs.isCustomNamespace((FunctionDefinition)def))
@@ -336,7 +540,7 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
NamespaceDefinition nsDef = (NamespaceDefinition)nin.resolve(getProject());
IdentifierNode idNode = (IdentifierNode)nameNode.getChild(1);
String propName = idNode.getName();
- fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names
+ fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names
String s = nsDef.getURI();
write(JSRoyaleEmitter.formatNamespacedProperty(s, propName, true));
getEmitter().emitArguments(node.getArgumentsNode());
@@ -367,6 +571,11 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
getWalker().walk(node.getNameNode());
getEmitter().emitArguments(node.getArgumentsNode());
+
+ //end wrap resolve
+ if (wrapResolve) {
+ write(ASEmitterTokens.PAREN_CLOSE);
+ }
}
else //function-style cast
{
@@ -378,5 +587,31 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
fjs.emitSuperCall(node, JSSessionModel.SUPER_FUNCTION_CALL);
}
}
+
+
+ private boolean shouldResolveUncertain(IExpressionNode nameNode, boolean forceExplicit) {
+ //default if not avoided globally
+ boolean should = ((RoyaleJSProject)getProject()).config.getJsResolveUncertain();
+ //just in case:
+ if (!(getProject() instanceof RoyaleJSProject)) return false;
+
+ IDocEmitter docEmitter = getEmitter().getDocEmitter();
+ if (docEmitter instanceof JSRoyaleDocEmitter)
+ {
+ JSRoyaleDocEmitter royaleDocEmitter = (JSRoyaleDocEmitter) docEmitter;
+ //look for local boolean toggle, unless forceExplicit is set
+ boolean suppress = !forceExplicit && royaleDocEmitter.getLocalSettingAsBoolean(
+ JSRoyaleEmitterTokens.SUPPRESS_RESOLVE_UNCERTAIN, !should);
+ //if it is still on, look for sepcific/named 'off' setting based on name node
+ if (!suppress && nameNode !=null) {
+ //check to suppress for indvidual named node
+ if (nameNode instanceof IdentifierNode) {
+ suppress = royaleDocEmitter.getLocalSettingIncludesString(JSRoyaleEmitterTokens.SUPPRESS_RESOLVE_UNCERTAIN, ((IdentifierNode) nameNode).getName());
+ }
+ }
+ should = !suppress;
+ }
+ return should;
+ }
}
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/IdentifierEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/IdentifierEmitter.java
index 26d8649..4d42069 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/IdentifierEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/IdentifierEmitter.java
@@ -34,18 +34,15 @@ import org.apache.royale.compiler.internal.codegen.as.ASEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.JSSubEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitter;
import org.apache.royale.compiler.internal.codegen.js.goog.JSGoogEmitterTokens;
+import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.utils.EmitterUtils;
-import org.apache.royale.compiler.internal.definitions.AccessorDefinition;
-import org.apache.royale.compiler.internal.definitions.ClassDefinition;
-import org.apache.royale.compiler.internal.definitions.FunctionDefinition;
-import org.apache.royale.compiler.internal.definitions.TypeDefinitionBase;
+import org.apache.royale.compiler.internal.definitions.*;
+import org.apache.royale.compiler.internal.tree.as.BinaryOperatorAssignmentNode;
+import org.apache.royale.compiler.internal.tree.as.BinaryOperatorDivisionAssignmentNode;
+import org.apache.royale.compiler.internal.tree.as.MemberAccessExpressionNode;
import org.apache.royale.compiler.internal.tree.as.NonResolvingIdentifierNode;
import org.apache.royale.compiler.tree.ASTNodeID;
-import org.apache.royale.compiler.tree.as.IASNode;
-import org.apache.royale.compiler.tree.as.IFunctionNode;
-import org.apache.royale.compiler.tree.as.IFunctionObjectNode;
-import org.apache.royale.compiler.tree.as.IIdentifierNode;
-import org.apache.royale.compiler.tree.as.IMemberAccessExpressionNode;
+import org.apache.royale.compiler.tree.as.*;
import org.apache.royale.compiler.utils.NativeUtils;
public class IdentifierEmitter extends JSSubEmitter implements
@@ -239,7 +236,7 @@ public class IdentifierEmitter extends JSSubEmitter implements
{
Namespace ns = (Namespace)((INamespaceResolvedReference)((FunctionDefinition)nodeDef).getNamespaceReference()).resolveAETNamespace(getProject());
INamespaceDefinition nsDef = ((FunctionDefinition)nodeDef).getNamespaceReference().resolveNamespaceReference(getProject());
- fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names
+ fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names
String nsName = ns.getName();
write(JSRoyaleEmitter.formatNamespacedProperty(nsName, node.getName(), true));
}
@@ -315,20 +312,31 @@ public class IdentifierEmitter extends JSSubEmitter implements
}
else if (identifierIsAccessorFunction && isStatic)
{
- write("[\"" +node.getName() + "\"]");
+ write("[\"" +node.getName() + "\"]");
}
else
{
qname = node.getName();
if (nodeDef != null && !isStatic && (nodeDef.getParent() instanceof ClassDefinition) && (!(nodeDef instanceof IParameterDefinition)) && nodeDef.isPrivate() && getProject().getAllowPrivateNameConflicts())
qname = getEmitter().formatPrivateName(nodeDef.getParent().getQualifiedName(), qname);
- write(qname);
+ write(qname);
}
}
else if (isPackageOrFileMember)
write(getEmitter().formatQualifiedName(qname));
else if (nodeDef instanceof TypeDefinitionBase)
- write(getEmitter().formatQualifiedName(qname));
+ {
+ if (NativeUtils.isSyntheticJSType(qname) && !(parentNode instanceof IFunctionCallNode)) {
+ getEmitter().getModel().needLanguage = true;
+ write(JSRoyaleEmitterTokens.SYNTH_TYPE);
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(getEmitter().formatQualifiedName(qname));
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ }
+ else write(getEmitter().formatQualifiedName(qname));
+ }
else if (isCustomNamespace)
{
String ns = ((INamespaceResolvedReference)((FunctionDefinition)nodeDef).getNamespaceReference()).resolveAETNamespace(getProject()).getName();
@@ -336,9 +344,9 @@ public class IdentifierEmitter extends JSSubEmitter implements
}
else if (identifierIsAccessorFunction && isStatic)
{
- write("[\"" + qname + "\"]");
+ write("[\"" + qname + "\"]");
}
- else
+ else
{
if (nodeDef != null && !isStatic && (nodeDef.getParent() instanceof ClassDefinition) && (!(nodeDef instanceof IParameterDefinition)) && nodeDef.isPrivate() && getProject().getAllowPrivateNameConflicts())
qname = getEmitter().formatPrivateName(nodeDef.getParent().getQualifiedName(), qname);
@@ -353,7 +361,7 @@ public class IdentifierEmitter extends JSSubEmitter implements
write("child('");
write(node.getName());
write("')");
- endMapping(node);
+ endMapping(node);
}
else
{
@@ -363,5 +371,7 @@ public class IdentifierEmitter extends JSSubEmitter implements
}
}
}
+
+
}
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/InterfaceEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/InterfaceEmitter.java
index 0221afc..eb8f079 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/InterfaceEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/InterfaceEmitter.java
@@ -26,9 +26,11 @@ import org.apache.royale.compiler.internal.codegen.as.ASEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.JSDocEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.JSEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.JSSubEmitter;
+import org.apache.royale.compiler.internal.codegen.js.goog.JSGoogDocEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleDocEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitterTokens;
+import org.apache.royale.compiler.internal.tree.as.TypedExpressionNode;
import org.apache.royale.compiler.projects.ICompilerProject;
import org.apache.royale.compiler.tree.ASTNodeID;
import org.apache.royale.compiler.tree.as.IAccessorNode;
@@ -114,6 +116,14 @@ public class InterfaceEmitter extends JSSubEmitter implements
ITypeDefinition typeDef = typeNode.resolveType(project);
String packageName = typeDef.getPackageName();
packageName = project.getActualPackageName(packageName);
+ if (typeNode instanceof TypedExpressionNode) {
+ propType = "Vector.<" +
+ JSGoogDocEmitter.convertASTypeToJSType(
+ ((TypedExpressionNode)typeNode).getTypeNode().resolveType(project).getQualifiedName(),
+ "")
+ +">";
+ packageName = "";
+ }
write(JSDocEmitterTokens.JSDOC_OPEN);
write(ASEmitterTokens.SPACE);
fjs.getDocEmitter().emitType(propType, packageName);
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/MemberAccessEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/MemberAccessEmitter.java
index 23e5ec0..741affb 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/MemberAccessEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/MemberAccessEmitter.java
@@ -26,6 +26,7 @@ import org.apache.royale.compiler.definitions.IDefinition;
import org.apache.royale.compiler.internal.codegen.as.ASEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.JSEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.JSSubEmitter;
+import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleDocEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.goog.JSGoogEmitterTokens;
@@ -34,22 +35,15 @@ import org.apache.royale.compiler.internal.definitions.AccessorDefinition;
import org.apache.royale.compiler.internal.definitions.AppliedVectorDefinition;
import org.apache.royale.compiler.internal.definitions.FunctionDefinition;
import org.apache.royale.compiler.internal.projects.RoyaleJSProject;
-import org.apache.royale.compiler.internal.tree.as.DynamicAccessNode;
-import org.apache.royale.compiler.internal.tree.as.FunctionCallNode;
-import org.apache.royale.compiler.internal.tree.as.GetterNode;
-import org.apache.royale.compiler.internal.tree.as.IdentifierNode;
-import org.apache.royale.compiler.internal.tree.as.MemberAccessExpressionNode;
-import org.apache.royale.compiler.internal.tree.as.NamespaceAccessExpressionNode;
+import org.apache.royale.compiler.internal.tree.as.*;
import org.apache.royale.compiler.projects.ICompilerProject;
import org.apache.royale.compiler.tree.ASTNodeID;
-import org.apache.royale.compiler.tree.as.IASNode;
-import org.apache.royale.compiler.tree.as.IExpressionNode;
-import org.apache.royale.compiler.tree.as.IIdentifierNode;
-import org.apache.royale.compiler.tree.as.ILanguageIdentifierNode;
-import org.apache.royale.compiler.tree.as.IMemberAccessExpressionNode;
+import org.apache.royale.compiler.tree.as.*;
import org.apache.royale.compiler.tree.as.IOperatorNode.OperatorType;
import org.apache.royale.compiler.utils.ASNodeUtils;
+import javax.sound.midi.SysexMessage;
+
public class MemberAccessEmitter extends JSSubEmitter implements
ISubEmitter<IMemberAccessExpressionNode>
{
@@ -199,21 +193,6 @@ public class MemberAccessEmitter extends JSSubEmitter implements
return;
}
}
- else if (def.getParent() instanceof AppliedVectorDefinition)
- {
- if (def.getBaseName().equals("removeAt"))
- {
- writeLeftSide(node, leftNode, rightNode);
- write(".splice");
- return;
- }
- else if (def.getBaseName().equals("insertAt"))
- {
- writeLeftSide(node, leftNode, rightNode);
- write(".splice");
- return;
- }
- }
else if (rightNode instanceof NamespaceAccessExpressionNode)
{
boolean isStatic = false;
@@ -234,6 +213,11 @@ public class MemberAccessEmitter extends JSSubEmitter implements
parentNodeId != ASTNodeID.ArrayIndexExpressionID;
}
}
+
+ if (needClosure
+ && getEmitter().getDocEmitter() instanceof JSRoyaleDocEmitter
+ && ((JSRoyaleDocEmitter)getEmitter().getDocEmitter()).getSuppressClosure())
+ needClosure = false;
if (needClosure)
getEmitter().emitClosureStart();
@@ -296,6 +280,11 @@ public class MemberAccessEmitter extends JSSubEmitter implements
needClosure = !isStatic && parentNodeId != ASTNodeID.FunctionCallID &&
parentNodeId != ASTNodeID.MemberAccessExpressionID &&
parentNodeId != ASTNodeID.ArrayIndexExpressionID;
+
+ if (needClosure
+ && getEmitter().getDocEmitter() instanceof JSRoyaleDocEmitter
+ && ((JSRoyaleDocEmitter)getEmitter().getDocEmitter()).getSuppressClosure())
+ needClosure = false;
}
}
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/MethodEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/MethodEmitter.java
index aad1184..0fc7b0b 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/MethodEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/MethodEmitter.java
@@ -108,8 +108,12 @@ public class MethodEmitter extends JSSubEmitter implements
}
endMapping(node.getNameExpressionNode());
}
-
- startMapping(node);
+ if (node.getMetaTags() != null) {
+ //offset mapping by any metadata tags that will be in the first child node
+ startMapping(node.getChild(1));
+ } else {
+ startMapping(node);
+ }
write(ASEmitterTokens.SPACE);
writeToken(ASEmitterTokens.EQUAL);
write(ASEmitterTokens.FUNCTION);
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/PackageFooterEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/PackageFooterEmitter.java
index 7c151ac..86bc80d 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/PackageFooterEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/PackageFooterEmitter.java
@@ -76,7 +76,7 @@ public class PackageFooterEmitter extends JSSubEmitter implements
JSRoyaleDocEmitter doc = (JSRoyaleDocEmitter) getEmitter()
.getDocEmitter();
- if (!getEmitter().getModel().isExterns)
+ if (!getEmitter().getModel().isExterns && doc.getEmitExports())
{
boolean isInterface = tnode instanceof IInterfaceNode;
boolean isDynamic = tnode instanceof IClassNode && tnode.hasModifier(ASModifier.DYNAMIC);
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/UnaryOperatorEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/UnaryOperatorEmitter.java
index b575d55..bc040e7 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/UnaryOperatorEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/UnaryOperatorEmitter.java
@@ -23,8 +23,12 @@ import org.apache.royale.compiler.codegen.ISubEmitter;
import org.apache.royale.compiler.codegen.js.IJSEmitter;
import org.apache.royale.compiler.internal.codegen.as.ASEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.JSSubEmitter;
+import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitterTokens;
+import org.apache.royale.compiler.internal.definitions.AppliedVectorDefinition;
+import org.apache.royale.compiler.internal.tree.as.*;
import org.apache.royale.compiler.tree.ASTNodeID;
import org.apache.royale.compiler.tree.as.IExpressionNode;
+import org.apache.royale.compiler.tree.as.ILiteralNode;
import org.apache.royale.compiler.tree.as.IUnaryOperatorNode;
import org.apache.royale.compiler.utils.ASNodeUtils;
@@ -41,6 +45,31 @@ public class UnaryOperatorEmitter extends JSSubEmitter implements
{
if (ASNodeUtils.hasParenOpen(node))
write(ASEmitterTokens.PAREN_OPEN);
+
+ Boolean isAssignment = (node.getNodeID() == ASTNodeID.Op_PreIncrID
+ || node.getNodeID() == ASTNodeID.Op_PreDecrID
+ || node.getNodeID() == ASTNodeID.Op_PostIncrID
+ || node.getNodeID() == ASTNodeID.Op_PostDecrID);
+
+ if (isAssignment && (node.getOperandNode() instanceof MemberAccessExpressionNode)
+ && (((MemberAccessExpressionNode)(node.getOperandNode())).getRightOperandNode() instanceof IdentifierNode)
+ && ((IdentifierNode)(((MemberAccessExpressionNode)(node.getOperandNode())).getRightOperandNode())).getName().equals("length")
+ && ((MemberAccessExpressionNode)(node.getOperandNode())).getLeftOperandNode().resolveType(getProject()) instanceof AppliedVectorDefinition
+ ) {
+ //support for output of alternate length setter, example: vectorInst.length++ as vectorInst['_synthType'].length++
+ //likewise for pre/post increment/decrement
+
+ String synthTagName = JSRoyaleEmitterTokens.LANGUAGE_QNAME.getToken() + ASEmitterTokens.MEMBER_ACCESS.getToken() + JSRoyaleEmitterTokens.ROYALE_SYNTH_TAG_FIELD_NAME.getToken();
+ LiteralNode synthType = new LiteralNode(ILiteralNode.LiteralType.STRING, synthTagName);
+ synthType.setSynthetic(true);
+ DynamicAccessNode patchedVectorReference = new DynamicAccessNode(((ExpressionNodeBase)((MemberAccessExpressionNode) node.getOperandNode()).getLeftOperandNode()));
+ ((ExpressionNodeBase)((MemberAccessExpressionNode) node.getOperandNode()).getLeftOperandNode()).setParent(patchedVectorReference);
+ patchedVectorReference.setRightOperandNode(synthType);
+ synthType.setParent(patchedVectorReference);
+ patchedVectorReference.setParent((NodeBase) node.getOperandNode());
+ patchedVectorReference.setSourceLocation(((MemberAccessExpressionNode) node.getOperandNode()).getLeftOperandNode());
+ ((MemberAccessExpressionNode) node.getOperandNode()).setLeftOperandNode(patchedVectorReference);
+ }
if (node.getNodeID() == ASTNodeID.Op_PreIncrID
|| node.getNodeID() == ASTNodeID.Op_PreDecrID
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleDocEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleDocEmitter.java
index 8cfd1c9..e32b148 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleDocEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleDocEmitter.java
@@ -19,8 +19,7 @@
package org.apache.royale.compiler.internal.codegen.js.royale;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.*;
import org.apache.royale.compiler.asdoc.royale.ASDocComment;
import org.apache.royale.compiler.codegen.as.IASEmitter;
@@ -41,6 +40,7 @@ import org.apache.royale.compiler.internal.codegen.js.goog.JSGoogDocEmitter;
import org.apache.royale.compiler.internal.codegen.js.jx.BindableEmitter;
import org.apache.royale.compiler.internal.projects.RoyaleJSProject;
import org.apache.royale.compiler.internal.scopes.ASScope;
+import org.apache.royale.compiler.parsing.IASToken;
import org.apache.royale.compiler.problems.PublicVarWarningProblem;
import org.apache.royale.compiler.projects.ICompilerProject;
import org.apache.royale.compiler.tree.ASTNodeID;
@@ -53,9 +53,12 @@ public class JSRoyaleDocEmitter extends JSGoogDocEmitter
private List<String> classIgnoreList;
private List<String> ignoreList;
private List<String> coercionList;
+ private Map<String,List<String>> localSettings;
public boolean emitStringConversions = true;
private boolean emitExports = true;
private boolean exportProtected = false;
+
+ private boolean suppressClosure = false;
public JSRoyaleDocEmitter(IJSEmitter emitter)
{
@@ -71,6 +74,14 @@ public class JSRoyaleDocEmitter extends JSGoogDocEmitter
{
this.classIgnoreList = value;
}
+
+ public Boolean getSuppressClosure() {
+ return suppressClosure;
+ }
+
+ public Boolean getEmitExports() {
+ return emitExports;
+ }
@Override
protected String convertASTypeToJS(String name, String pname)
@@ -95,7 +106,7 @@ public class JSRoyaleDocEmitter extends JSGoogDocEmitter
RoyaleJSProject fjp = (RoyaleJSProject)((IASEmitter)emitter).getWalker().getProject();
String vectorClassName = fjp.config == null ? null : fjp.config.getJsVectorEmulationClass();
if (vectorClassName != null) return vectorClassName;
- return IASLanguageConstants.Array;
+ return super.convertASTypeToJS(name, pname);
}
name = super.convertASTypeToJS(name, pname);
@@ -128,7 +139,9 @@ public class JSRoyaleDocEmitter extends JSGoogDocEmitter
coercionList = null;
ignoreList = null;
+ localSettings = null;
emitStringConversions = true;
+ suppressClosure = false;
IClassDefinition classDefinition = resolveClassDefinition(node);
@@ -228,6 +241,31 @@ public class JSRoyaleDocEmitter extends JSGoogDocEmitter
.getToken();
if (docText.contains(noStringToken))
emitStringConversions = false;
+
+ String noImplicitComplexCoercion = JSRoyaleEmitterTokens.SUPPRESS_COMPLEX_IMPLICIT_COERCION
+ .getToken();
+ if (docText.contains(noImplicitComplexCoercion))
+ loadLocalSettings(docText, noImplicitComplexCoercion, "true");
+
+ String noResolveUncertain = JSRoyaleEmitterTokens.SUPPRESS_RESOLVE_UNCERTAIN
+ .getToken();
+ if (docText.contains(noResolveUncertain))
+ loadLocalSettings(docText,noResolveUncertain, "true");
+
+ String suppressVectorIndexCheck = JSRoyaleEmitterTokens.SUPPRESS_VECTOR_INDEX_CHECK
+ .getToken();
+ if (docText.contains(suppressVectorIndexCheck))
+ loadLocalSettings(docText,suppressVectorIndexCheck, "true");
+
+ String suppressClosureToken = JSRoyaleEmitterTokens.SUPPRESS_CLOSURE.getToken();
+
+ if (docText.contains(suppressClosureToken))
+ suppressClosure = true;
+
+ String suppressExport = JSRoyaleEmitterTokens.SUPPRESS_EXPORT.getToken();
+ if (docText.contains(suppressExport))
+ emitExports = false;
+
write(changeAnnotations(asDoc.commentNoEnd()));
}
else
@@ -312,6 +350,82 @@ public class JSRoyaleDocEmitter extends JSGoogDocEmitter
end();
}
}
+
+ /**
+ *
+ */
+ private void loadLocalSettings(String doc, String settingToken, String defaultSetting)
+ {
+ if (localSettings == null) localSettings = new HashMap<String, List<String>>();
+ int index = doc.indexOf(settingToken);
+ List<String> settings = localSettings.containsKey(settingToken) ? localSettings.get(settingToken) : null;
+ while (index != -1)
+ {
+ String setting = doc.substring(index + settingToken.length());
+ int endIndex = setting.indexOf("\n");
+ setting = setting.substring(0, endIndex);
+ setting = setting.trim();
+ if (settings == null) {
+ settings = new ArrayList<String>();
+ localSettings.put(settingToken, settings);
+ }
+ List<String> settingItems = null;
+ if (setting.length() >0) {
+ settingItems = Arrays.asList(setting.split("\\s*(,\\s*)+"));
+ } else {
+ settingItems = Arrays.asList(defaultSetting);
+ }
+ for (String settingItem: settingItems) {
+ if (settings.contains(settingItem)) {
+ //change the order to reflect the latest addition
+ settings.remove(settingItem);
+ }
+ settings.add(settingItem);
+ //System.out.println("---Adding setting "+settingToken+":"+settingItem);
+ }
+
+ index = doc.indexOf(settingToken, index + endIndex);
+ }
+ }
+
+ public boolean hasLocalSetting(String settingToken) {
+ if (localSettings == null) return false;
+ return (localSettings.keySet().contains(settingToken));
+ }
+
+ public boolean getLocalSettingAsBoolean(JSRoyaleEmitterTokens token, Boolean defaultValue) {
+ return getLocalSettingAsBoolean(token.getToken(), defaultValue);
+ }
+
+ public boolean getLocalSettingAsBoolean(String settingToken, Boolean defaultValue) {
+ boolean setting = defaultValue;
+ if (hasLocalSetting(settingToken)) {
+ for (String stringVal: localSettings.get(settingToken)) {
+ //don't bail out after finding a boolean-ish string val
+ //'last one wins'
+ if (stringVal.equals("false")) setting = false;
+ else if (stringVal.equals("true")) setting = true;
+ }
+ }
+ return setting;
+ }
+
+ public boolean getLocalSettingIncludesString(JSRoyaleEmitterTokens token, String searchValue) {
+ return getLocalSettingIncludesString(token.getToken(), searchValue);
+ }
+
+ public boolean getLocalSettingIncludesString(String settingToken, String searchValue) {
+ boolean hasValue = false;
+ if (hasLocalSetting(settingToken)) {
+ for (String stringVal: localSettings.get(settingToken)) {
+ if (stringVal.equals(searchValue)) {
+ hasValue = true;
+ break;
+ }
+ }
+ }
+ return hasValue;
+ }
private void loadIgnores(String doc)
{
@@ -468,7 +582,12 @@ public class JSRoyaleDocEmitter extends JSGoogDocEmitter
}
- emitPublic(node);
+ if (!(node.getASDocComment() instanceof ASDocComment
+ && ((ASDocComment)node.getASDocComment()).commentNoEnd()
+ .contains(JSRoyaleEmitterTokens.SUPPRESS_EXPORT.getToken()))) {
+ emitPublic(node);
+ }
+
}
if (node.isConst())
@@ -478,7 +597,7 @@ public class JSRoyaleDocEmitter extends JSGoogDocEmitter
if (def != null)
packageName = def.getPackageName();
- emitType(node, project.getActualPackageName(packageName));
+ emitType(node, project.getActualPackageName(packageName), project);
end();
}
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleEmitter.java
index 834ce4d..5e82d8e 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleEmitter.java
@@ -718,12 +718,10 @@ public class JSRoyaleEmitter extends JSGoogEmitter implements IJSRoyaleEmitter
else if (name.equals(IASLanguageConstants._int)
|| name.equals(IASLanguageConstants.uint))
result = IASLanguageConstants.Number;
-
- boolean isBuiltinFunction = name.matches("Vector\\.<.*>");
- if (isBuiltinFunction)
- {
- result = IASLanguageConstants.Array;
+ else if (name.equals(IASLanguageConstants.Vector) || name.equals("__AS3__.vec.Vector")) {
+ result = JSRoyaleEmitterTokens.VECTOR.getToken();
}
+
return result;
}
@@ -925,10 +923,6 @@ public class JSRoyaleEmitter extends JSGoogEmitter implements IJSRoyaleEmitter
newNode = EmitterUtils.insertArgumentsAt(node, 1, new NumericLiteralNode("0"));
}
}
- else if (def.getParent() != null && def.getParent() instanceof AppliedVectorDefinition)
- {
- newNode = EmitterUtils.insertArgumentsAt(node, 1, new NumericLiteralNode("0"));
- }
}
}
if (len == 1)
@@ -947,10 +941,6 @@ public class JSRoyaleEmitter extends JSGoogEmitter implements IJSRoyaleEmitter
newNode = EmitterUtils.insertArgumentsAfter(node, new NumericLiteralNode("1"));
}
}
- else if (def.getParent() != null && def.getParent() instanceof AppliedVectorDefinition)
- {
- newNode = EmitterUtils.insertArgumentsAfter(node, new NumericLiteralNode("1"));
- }
}
else if (def != null && def.getBaseName().equals("parseInt"))
{
@@ -1095,7 +1085,8 @@ public class JSRoyaleEmitter extends JSGoogEmitter implements IJSRoyaleEmitter
@Override
public void emitClosureStart()
{
- ICompilerProject project = getWalker().getProject();;
+ if (getDocEmitter() instanceof JSRoyaleDocEmitter && ((JSRoyaleDocEmitter) getDocEmitter()).getSuppressClosure()) return;
+ ICompilerProject project = getWalker().getProject();
if (project instanceof RoyaleJSProject)
((RoyaleJSProject)project).needLanguage = true;
getModel().needLanguage = true;
@@ -1106,6 +1097,7 @@ public class JSRoyaleEmitter extends JSGoogEmitter implements IJSRoyaleEmitter
@Override
public void emitClosureEnd(IASNode node, IDefinition nodeDef)
{
+ if (getDocEmitter() instanceof JSRoyaleDocEmitter && ((JSRoyaleDocEmitter) getDocEmitter()).getSuppressClosure()) return;
write(ASEmitterTokens.COMMA);
write(ASEmitterTokens.SPACE);
write(ASEmitterTokens.SINGLE_QUOTE);
@@ -1448,6 +1440,9 @@ public class JSRoyaleEmitter extends JSGoogEmitter implements IJSRoyaleEmitter
{
return isXML(((MemberAccessExpressionNode)obj).getLeftOperandNode());
}
+ else if (leftDef != null && leftDef.getBaseName().equals("*") && obj instanceof DynamicAccessNode) {
+ return isXML(((DynamicAccessNode)obj).getLeftOperandNode());
+ }
return SemanticUtils.isXMLish(leftDef, getWalker().getProject());
}
@@ -1479,12 +1474,30 @@ public class JSRoyaleEmitter extends JSGoogEmitter implements IJSRoyaleEmitter
String vectorClassName = ((RoyaleJSProject)project).config == null ? null : ((RoyaleJSProject)project).config.getJsVectorEmulationClass();
if (vectorClassName != null)
{
- writeToken(ASEmitterTokens.NEW);
- write(vectorClassName);
+ if (!vectorClassName.equals("Array"))
+ write(vectorClassName);
return;
}
}
- write(JSRoyaleEmitterTokens.VECTOR);
+ Boolean written = false;
+ if (node instanceof TypedExpressionNode) {
+ startMapping(node);
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(JSRoyaleEmitterTokens.SYNTH_VECTOR);
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ //the element type of the Vector:
+ write(formatQualifiedName(node.getTypeNode().resolve(project).getQualifiedName()));
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ endMapping(node);
+ written = true;
+ }
+
+ if (!written) {
+ write(JSRoyaleEmitterTokens.VECTOR);
+ }
if (getModel().inStaticInitializer)
{
if (!staticUsedNames.contains(JSRoyaleEmitterTokens.LANGUAGE_QNAME.getToken()))
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleEmitterTokens.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleEmitterTokens.java
index 20bc298..d0ad79f 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleEmitterTokens.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleEmitterTokens.java
@@ -35,6 +35,7 @@ public enum JSRoyaleEmitterTokens implements IEmitterTokens
ROYALE_CLASS_INFO_CLASS_KIND("class"),
ROYALE_CLASS_INFO_INTERFACE_KIND("interface"),
ROYALE_CLASS_INFO_IS_DYNAMIC("isDynamic"),
+ ROYALE_SYNTH_TAG_FIELD_NAME("SYNTH_TAG_FIELD"),
GOOG_EXPORT_PROPERTY("goog.exportProperty"),
GOOG_EXPORT_SYMBOL("goog.exportSymbol"),
INDENT(" "),
@@ -49,7 +50,12 @@ public enum JSRoyaleEmitterTokens implements IEmitterTokens
IGNORE_COERCION("@royaleignorecoercion"),
IGNORE_IMPORT("@royaleignoreimport"),
IGNORE_STRING_COERCION("@royalenoimplicitstringconversion"),
+ SUPPRESS_EXPORT("@royalesuppressexport"),
+ SUPPRESS_CLOSURE("@royalesuppressclosure"),
SUPPRESS_PUBLIC_VAR_WARNING("@royalesuppresspublicvarwarning"),
+ SUPPRESS_COMPLEX_IMPLICIT_COERCION("@royalesuppresscompleximplicitcoercion"),
+ SUPPRESS_RESOLVE_UNCERTAIN("@royalesuppressresolveuncertain"),
+ SUPPRESS_VECTOR_INDEX_CHECK("@royalesuppressvectorindexcheck"),
DEBUG_COMMENT("@royaledebug"),
DEBUG_RETURN("if(!goog.DEBUG)return;"),
PREINCREMENT("preincrement"),
@@ -65,7 +71,10 @@ public enum JSRoyaleEmitterTokens implements IEmitterTokens
SKIP_AS_COERCIONS("skipAsCoercions"),
SKIP_FUNCTION_COERCIONS("skipFunctionCoercions"),
JSX("JSX"),
- VECTOR("org.apache.royale.utils.Language.Vector"),
+ VECTOR(LANGUAGE_QNAME.getToken() + ".Vector"),
+ SYNTH_TYPE(LANGUAGE_QNAME.getToken() + ".synthType"),
+ SYNTH_VECTOR(LANGUAGE_QNAME.getToken() + ".synthVector"),
+ VECTOR_INDEX_CHECK_METHOD_NAME(LANGUAGE_QNAME.getToken() + ".CHECK_INDEX"),
;
private String token;
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/utils/DocEmitterUtils.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/utils/DocEmitterUtils.java
index dd9ed44..2e03bb0 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/utils/DocEmitterUtils.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/utils/DocEmitterUtils.java
@@ -46,4 +46,13 @@ public class DocEmitterUtils
// TODO (mschmalle)
((JSRoyaleDocEmitter)emitter.getDocEmitter()).setClassIgnoreList(ignoreList);
}
+
+
+ public static Boolean hasSuppressExport(JSRoyaleEmitter emitter, String doc)
+ {
+
+ String ignoreToken = JSRoyaleEmitterTokens.SUPPRESS_EXPORT.getToken();
+ int index = doc.indexOf(ignoreToken);
+ return index != -1;
+ }
}
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleJSProject.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleJSProject.java
index 06348a5..42e647c 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleJSProject.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleJSProject.java
@@ -39,6 +39,7 @@ import org.apache.royale.compiler.config.Configurator;
import org.apache.royale.compiler.css.ICSSMediaQueryCondition;
import org.apache.royale.compiler.css.ICSSRule;
import org.apache.royale.compiler.definitions.IDefinition;
+import org.apache.royale.compiler.definitions.IFunctionDefinition;
import org.apache.royale.compiler.definitions.ITypeDefinition;
import org.apache.royale.compiler.definitions.metadata.IMetaTag;
import org.apache.royale.compiler.definitions.metadata.IMetaTagAttribute;
@@ -116,7 +117,7 @@ public class RoyaleJSProject extends RoyaleProject
if (defNode instanceof IClassNode || defNode instanceof IInterfaceNode)
{
String defname = def.getQualifiedName();
- IASDocComment asDoc = (defNode instanceof IClassNode) ?
+ IASDocComment asDoc = (defNode instanceof IClassNode) ?
(IASDocComment) ((IClassNode)defNode).getASDocComment() :
(IASDocComment) ((IInterfaceNode)defNode).getASDocComment();
if (asDoc != null && (asDoc instanceof ASDocComment))
@@ -163,7 +164,7 @@ public class RoyaleJSProject extends RoyaleProject
super.addDependency(from, to, dt, qname);
}
- private synchronized void updateRequiresMap(ICompilationUnit from, ICompilationUnit to,
+ private synchronized void updateRequiresMap(ICompilationUnit from, ICompilationUnit to,
DependencyType dt, String qname)
{
HashMap<String, DependencyType> reqs;
@@ -188,10 +189,10 @@ public class RoyaleJSProject extends RoyaleProject
if (qname.equals("XML"))
needXML = true;
reqs.put(qname, dt);
- }
+ }
}
- private synchronized void updateJSModulesMap(ICompilationUnit from, ICompilationUnit to,
+ private synchronized void updateJSModulesMap(ICompilationUnit from, ICompilationUnit to,
DependencyType dt, String qname)
{
HashMap<String, DependencyType> reqs;
@@ -219,7 +220,7 @@ public class RoyaleJSProject extends RoyaleProject
}
}
- private synchronized void updateInterfacesMap(ICompilationUnit from, ICompilationUnit to,
+ private synchronized void updateInterfacesMap(ICompilationUnit from, ICompilationUnit to,
DependencyType dt, String qname)
{
HashMap<String, String> interfacesArr;
@@ -530,6 +531,15 @@ public class RoyaleJSProject extends RoyaleProject
}
return false;
}
+
+ @Override
+ public boolean isParameterCountMismatchAllowed(IFunctionDefinition func,
+ int formalCount, int actualCount) {
+ if ((func.getBaseName().equals("int") || func.getBaseName().equals("uint")) && func.isConstructor()) {
+ if (actualCount == 1) return true;
+ }
+ return super.isParameterCountMismatchAllowed(func, formalCount, actualCount);
+ }
/**
* List of compiler defines so it can be overridden
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/utils/JSClosureCompilerWrapper.java b/compiler-jx/src/main/java/org/apache/royale/compiler/utils/JSClosureCompilerWrapper.java
index 74e1bb6..8d8ace0 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/utils/JSClosureCompilerWrapper.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/utils/JSClosureCompilerWrapper.java
@@ -356,6 +356,8 @@ public class JSClosureCompilerWrapper
"playerversion", "langversion", "copy", "span", "para", "throw", "tiptext",
"asparam", "asreturn", "asreturns", "asprivate",
"royaleignoreimport", "royaleignorecoercion", "royaleemitcoercion",
+ "royalesuppresscompleximplicitcoercion","royalesuppressresolveuncertain",
+ "royalesuppressvectorindexcheck","royalesuppressexport", "royalesuppressclosure",
"royalenoimplicitstringconversion","royaledebug"};
options_.setExtraAnnotationNames(Arrays.asList(asdocTags));
}
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/utils/NativeUtils.java b/compiler-jx/src/main/java/org/apache/royale/compiler/utils/NativeUtils.java
index 0653542..8ff320a 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/utils/NativeUtils.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/utils/NativeUtils.java
@@ -122,8 +122,8 @@ public class NativeUtils
unescape("unescape"),
window("window"),
- // (erikdebruin) These aren't strictly 'native' to JS, but the
- // Publisher provides global functions, so, for all
+ // (erikdebruin) These aren't strictly 'native' to JS, but the
+ // Publisher provides global functions, so, for all
// intends and purposes they behave like they are.
_int("int"),
trace("trace"),
@@ -154,6 +154,26 @@ public class NativeUtils
}
}
+ public enum SyntheticJSType
+ {
+ _int("int"),
+ uint("uint"),
+ Vector("Vector"),
+ Class("Class");
+
+ private final String value;
+
+ SyntheticJSType(String value)
+ {
+ this.value = value;
+ }
+
+ public String getValue()
+ {
+ return value;
+ }
+ }
+
public static boolean isNative(String type)
{
for (NativeASType test : NativeASType.values())
@@ -175,5 +195,24 @@ public class NativeUtils
}
return false;
}
+
+ public static boolean isSyntheticJSType(String type)
+ {
+ for (SyntheticJSType test : SyntheticJSType.values())
+ {
+ if (test.getValue().equals(type)) {
+ return true;
+ }
+ }
+ if (type.startsWith("Vector.<")) {
+ return true;
+ }
+ return false;
+ }
+
+ public static boolean isVector(String type)
+ {
+ return type != null && type.startsWith("Vector.<");
+ }
}
diff --git a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/goog/TestGoogFieldMembers.java b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/goog/TestGoogFieldMembers.java
index 9bb864d..a1318d4 100644
--- a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/goog/TestGoogFieldMembers.java
+++ b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/goog/TestGoogFieldMembers.java
@@ -97,7 +97,7 @@ public class TestGoogFieldMembers extends TestFieldMembers
{
IVariableNode node = getField("protected var foo:Vector.<Foo>;");
asBlockWalker.visitVariable(node);
- assertOut("/**\n * @protected\n * @type {Vector.<Foo>}\n */\nRoyaleTest_A.prototype.foo");
+ assertOut("/**\n * @protected\n * @type {Array.<Foo>}\n */\nRoyaleTest_A.prototype.foo");
}
@Override
@@ -106,7 +106,7 @@ public class TestGoogFieldMembers extends TestFieldMembers
{
IVariableNode node = getField("protected var foo:Vector.<Vector.<Vector.<Foo>>>;");
asBlockWalker.visitVariable(node);
- assertOut("/**\n * @protected\n * @type {Vector.<Vector.<Vector.<Foo>>>}\n */\nRoyaleTest_A.prototype.foo");
+ assertOut("/**\n * @protected\n * @type {Array.<Array.<Array.<Foo>>>}\n */\nRoyaleTest_A.prototype.foo");
}
@Override
diff --git a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/goog/TestGoogGlobalClasses.java b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/goog/TestGoogGlobalClasses.java
index 0bf0f4a..28aab2a 100644
--- a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/goog/TestGoogGlobalClasses.java
+++ b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/goog/TestGoogGlobalClasses.java
@@ -271,7 +271,7 @@ public class TestGoogGlobalClasses extends TestGlobalClasses
{
IVariableNode node = getVariable("var a:Vector.<String> = new Vector.<String>(['Hello', 'World']);");
asBlockWalker.visitVariable(node);
- assertOut("var /** @type {Vector.<string>} */ a = new Array(['Hello', 'World'])");
+ assertOut("var /** @type {Array.<string>} */ a = new Array(['Hello', 'World'])");
}
@Override
diff --git a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/goog/TestGoogGlobalFunctions.java b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/goog/TestGoogGlobalFunctions.java
index 107c1bc..f979f20 100644
--- a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/goog/TestGoogGlobalFunctions.java
+++ b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/goog/TestGoogGlobalFunctions.java
@@ -212,7 +212,7 @@ public class TestGoogGlobalFunctions extends TestGlobalFunctions
{
IVariableNode node = getVariable("var a:Vector.<String> = Vector.<String>(['Hello', 'World']);");
asBlockWalker.visitVariable(node);
- assertOut("var /** @type {Vector.<string>} */ a = Array(['Hello', 'World'])");
+ assertOut("var /** @type {Array.<string>} */ a = Array(['Hello', 'World'])");
}
@Override
diff --git a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleExpressions.java b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleExpressions.java
index 0b32b4a..55de5e5 100644
--- a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleExpressions.java
+++ b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleExpressions.java
@@ -1220,7 +1220,7 @@ public class TestRoyaleExpressions extends TestGoogExpressions
"public class B {public function b() { function c(f:Function):void {}; var f:Array = [b]; c(f[0]); }}",
IFunctionNode.class, WRAP_LEVEL_PACKAGE);
asBlockWalker.visitFunction(node);
- assertOut("/**\n * @export\n */\nB.prototype.b = function() {\n var self = this;\n function c(f) {\n };\n var /** @type {Array} */ f = [org.apache.royale.utils.Language.closure(this.b, this, 'b')];\n c(f[0]);\n}");
+ assertOut("/**\n * @export\n */\nB.prototype.b = function() {\n var self = this;\n function c(f) {\n };\n var /** @type {Array} */ f = [org.apache.royale.utils.Language.closure(this.b, this, 'b')];\n c(/* implicit cast */ org.apache.royale.utils.Language.as(f[0], Function, true));\n}");
}
@Test
@@ -1272,7 +1272,7 @@ public class TestRoyaleExpressions extends TestGoogExpressions
IFunctionNode.class, WRAP_LEVEL_PACKAGE, true);
asBlockWalker.visitFunction(node);
// String.length is a getter but is a property in JS, so don't generate set_length() call.
- assertOut("/**\n * @export\n * @return {number}\n */\nfoo.bar.B.prototype.b = function() {\n var /** @type {Array} */ a = null;\n return a.length;\n}");
+ assertOut("/**\n * @export\n * @return {number}\n */\nfoo.bar.B.prototype.b = function() {\n var /** @type {Array.<string>} */ a = null;\n return a.length;\n}");
}
//----------------------------------
@@ -1512,7 +1512,7 @@ public class TestRoyaleExpressions extends TestGoogExpressions
{
IBinaryOperatorNode node = getBinaryNode("a as int");
asBlockWalker.visitBinaryOperator(node);
- assertOut("org.apache.royale.utils.Language.as(a, Number)");
+ assertOut("org.apache.royale.utils.Language.as(a, org.apache.royale.utils.Language.synthType('int'))");
}
@Test
@@ -1520,7 +1520,7 @@ public class TestRoyaleExpressions extends TestGoogExpressions
{
IBinaryOperatorNode node = getBinaryNode("a as uint");
asBlockWalker.visitBinaryOperator(node);
- assertOut("org.apache.royale.utils.Language.as(a, Number)");
+ assertOut("org.apache.royale.utils.Language.as(a, org.apache.royale.utils.Language.synthType('uint'))");
}
@Test
@@ -1530,7 +1530,7 @@ public class TestRoyaleExpressions extends TestGoogExpressions
"public class B {private var memberVar:Class; public function b(o:Object):int { var a:B = null; a = o as memberVar; }}",
IFunctionNode.class, WRAP_LEVEL_PACKAGE, true);
asBlockWalker.visitFunction(node);
- assertOut("/**\n * @export\n * @param {Object} o\n * @return {number}\n */\nfoo.bar.B.prototype.b = function(o) {\n var /** @type {foo.bar.B} */ a = null;\n a = org.apache.royale.utils.Language.as(o, this.memberVar);\n}");
+ assertOut("/**\n * @export\n * @param {Object} o\n * @return {number}\n */\nfoo.bar.B.prototype.b = function(o) {\n var /** @type {foo.bar.B} */ a = null;\n a = /* implicit cast */ org.apache.royale.utils.Language.as(org.apache.royale.utils.Language.as(o, this.memberVar), foo.bar.B, true);\n}");
}
@Test
diff --git a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleFieldMembers.java b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleFieldMembers.java
index b8be801..5a8af9a 100644
--- a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleFieldMembers.java
+++ b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleFieldMembers.java
@@ -139,7 +139,7 @@ public class TestRoyaleFieldMembers extends TestGoogFieldMembers
{
IVariableNode node = getField("protected var foo:Vector.<Foo>;");
asBlockWalker.visitVariable(node);
- assertOut("/**\n * @protected\n * @type {Array}\n */\nRoyaleTest_A.prototype.foo");
+ assertOut("/**\n * @protected\n * @type {Array.<Foo>}\n */\nRoyaleTest_A.prototype.foo");
}
@Override
@@ -148,7 +148,7 @@ public class TestRoyaleFieldMembers extends TestGoogFieldMembers
{
IVariableNode node = getField("protected var foo:Vector.<Vector.<Vector.<Foo>>>;");
asBlockWalker.visitVariable(node);
- assertOut("/**\n * @protected\n * @type {Array}\n */\nRoyaleTest_A.prototype.foo");
+ assertOut("/**\n * @protected\n * @type {Array.<Array.<Array.<Foo>>>}\n */\nRoyaleTest_A.prototype.foo");
}
@Override
diff --git a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleGlobalClasses.java b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleGlobalClasses.java
index 4f590d3..15b8dd6 100644
--- a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleGlobalClasses.java
+++ b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleGlobalClasses.java
@@ -287,6 +287,16 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
asBlockWalker.visitVariable(node);
assertOut("var /** @type {number} */ a = Math[\"PI\"]");
}
+
+ @Override
+ @Test
+ public void testClass()
+ {
+ IVariableNode node = getVariable("var a:Class = String; var b:* = new a('test')");
+ node = (IVariableNode)(node.getParent().getChild(1));
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {*} */ b = org.apache.royale.utils.Language.resolveUncertain(new a('test'))");
+ }
@Test
public void testDateSetSeconds()
@@ -379,7 +389,7 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
IVariableNode node = getVariable("var a:Vector.<String> = new Vector.<String>(['Hello', 'World']);");
asBlockWalker.visitVariable(node);
//MXMLC does not report an error. Should we?
- assertOut("var /** @type {Array} */ a = org.apache.royale.utils.Language.Vector(['Hello', 'World'], 'String')");
+ assertOut("var /** @type {Array.<string>} */ a = new (org.apache.royale.utils.Language.synthVector('String'))(['Hello', 'World'])");
}
@Test
@@ -387,7 +397,7 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
{
IVariableNode node = getVariable("var a:Vector.<String> = new <String>[];");
asBlockWalker.visitVariable(node);
- assertOut("var /** @type {Array} */ a = []");
+ assertOut("var /** @type {Array.<string>} */ a = org.apache.royale.utils.Language.synthVector('String')['coerce']([])");
}
@Test
@@ -395,7 +405,7 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
{
IVariableNode node = getVariable("var a:Vector.<int> = new <int>[0, 1, 2, 3];");
asBlockWalker.visitVariable(node);
- assertOut("var /** @type {Array} */ a = [0, 1, 2, 3]");
+ assertOut("var /** @type {Array.<number>} */ a = org.apache.royale.utils.Language.synthVector('int')['coerce']([0, 1, 2, 3])");
}
@Test
@@ -403,7 +413,7 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
{
IVariableNode node = getVariable("var a:Vector.<String> = new <String>[\"one\", \"two\", \"three\";");
asBlockWalker.visitVariable(node);
- assertOut("var /** @type {Array} */ a = [\"one\", \"two\", \"three\"]");
+ assertOut("var /** @type {Array.<string>} */ a = org.apache.royale.utils.Language.synthVector('String')['coerce']([\"one\", \"two\", \"three\"])");
}
@Test
@@ -411,7 +421,7 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
{
IVariableNode node = getVariable("var a:Vector.<String> = new Vector.<String>();");
asBlockWalker.visitVariable(node);
- assertOut("var /** @type {Array} */ a = org.apache.royale.utils.Language.Vector()");
+ assertOut("var /** @type {Array.<string>} */ a = new (org.apache.royale.utils.Language.synthVector('String'))()");
}
@Test
@@ -420,7 +430,7 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
IVariableNode node = getVariable("var a:Vector.<String> = new Vector.<String>('Hello', 'World');");
asBlockWalker.visitVariable(node);
//MXMLC does not report an error. Should we?
- assertOut("var /** @type {Array} */ a = org.apache.royale.utils.Language.Vector('Hello', 'String')");
+ assertOut("var /** @type {Array.<string>} */ a = new (org.apache.royale.utils.Language.synthVector('String'))('Hello', 'World')");
}
@Test
@@ -429,7 +439,7 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
IVariableNode node = getVariable("var a:Vector.<String> = new Vector.<String>('Hello', 'World', 'Three');");
asBlockWalker.visitVariable(node);
//MXMLC does not report an error. Should we?
- assertOut("var /** @type {Array} */ a = org.apache.royale.utils.Language.Vector('Hello', 'String')");
+ assertOut("var /** @type {Array.<string>} */ a = new (org.apache.royale.utils.Language.synthVector('String'))('Hello', 'World', 'Three')");
}
@Test
@@ -437,7 +447,7 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
{
IVariableNode node = getVariable("var a:Vector.<String> = new Vector.<String>(30);");
asBlockWalker.visitVariable(node);
- assertOut("var /** @type {Array} */ a = org.apache.royale.utils.Language.Vector(30, 'String')");
+ assertOut("var /** @type {Array.<string>} */ a = new (org.apache.royale.utils.Language.synthVector('String'))(30)");
}
@Test
@@ -446,7 +456,7 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
IVariableNode node = getVariable("var a:Vector.<String> = new Vector.<String>(30, 40);");
asBlockWalker.visitVariable(node);
//MXMLC does not report an error. Should we?
- assertOut("var /** @type {Array} */ a = org.apache.royale.utils.Language.Vector(30, 'String')");
+ assertOut("var /** @type {Array.<string>} */ a = new (org.apache.royale.utils.Language.synthVector('String'))(30, 40)");
}
@Test
@@ -455,7 +465,24 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
IVariableNode node = getVariable("var a:Vector.<String> = new Vector.<String>(['Hello', 'World']);");
asBlockWalker.visitVariable(node);
//MXMLC does not report an error. Should we?
- assertOut("var /** @type {Array} */ a = org.apache.royale.utils.Language.Vector(['Hello', 'World'], 'String')");
+ assertOut("var /** @type {Array.<string>} */ a = new (org.apache.royale.utils.Language.synthVector('String'))(['Hello', 'World'])");
+ }
+
+ @Test
+ public void testVectorSetLength()
+ {
+ IBinaryOperatorNode node = getBinaryNode("var a:Vector.<String> = new Vector.<String>(); a.length = 20)");
+ asBlockWalker.visitBinaryOperator(node);
+ assertOut("a[org.apache.royale.utils.Language.SYNTH_TAG_FIELD].length = 20");
+ }
+
+ @Test
+ public void testCustomVectorSetLength()
+ {
+ project.config.setJsVectorEmulationClass(null, "Anything");
+ IBinaryOperatorNode node = getBinaryNode("var a:Vector.<String> = new Vector.<String>(); a.length = 20)");
+ asBlockWalker.visitBinaryOperator(node);
+ assertOut("a.length = 20");
}
@Test
@@ -468,9 +495,30 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
IBinaryOperatorNode node = getBinaryNode("var a:Vector.<String> = new Vector.<String>(); a.removeAt(2)");
IFunctionCallNode parentNode = (IFunctionCallNode)(node.getParent());
asBlockWalker.visitFunctionCall(parentNode);
- assertOut("a.splice(2, 1)");
+ assertOut("a['removeAt'](2)");
}
}
+
+ @Test
+ public void testCustomVectorRemoveAt()
+ {
+ project.config.setJsVectorEmulationClass(null, "CustomVector");
+ IBinaryOperatorNode node = getBinaryNode("var a:Vector.<String> = new Vector.<String>(); a.removeAt(2)");
+ IFunctionCallNode parentNode = (IFunctionCallNode)(node.getParent());
+ asBlockWalker.visitFunctionCall(parentNode);
+ assertOut("a.removeAt(2)");
+ }
+
+ @Test
+ public void testCustomVectorAsArrayRemoveAt()
+ {
+
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IBinaryOperatorNode node = getBinaryNode("var a:Vector.<String> = new Vector.<String>(); a.removeAt(2)");
+ IFunctionCallNode parentNode = (IFunctionCallNode)(node.getParent());
+ asBlockWalker.visitFunctionCall(parentNode);
+ assertOut("a.splice(2, 1)");
+ }
@Test
public void testVectorInsertAt()
@@ -482,9 +530,29 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
IBinaryOperatorNode node = getBinaryNode("var a:Vector.<String> = new Vector.<String>(); a.insertAt(2, 'foo')");
IFunctionCallNode parentNode = (IFunctionCallNode)(node.getParent());
asBlockWalker.visitFunctionCall(parentNode);
- assertOut("a.splice(2, 0, 'foo')");
+ assertOut("a['insertAt'](2, 'foo')");
}
}
+
+ @Test
+ public void testCustomVectorInsertAt()
+ {
+ project.config.setJsVectorEmulationClass(null, "CustomVector");
+ IBinaryOperatorNode node = getBinaryNode("var a:Vector.<String> = new Vector.<String>(); a.insertAt(2, 'foo')");
+ IFunctionCallNode parentNode = (IFunctionCallNode)(node.getParent());
+ asBlockWalker.visitFunctionCall(parentNode);
+ assertOut("a.insertAt(2, 'foo')");
+ }
+
+ @Test
+ public void testCustomVectorAsArrayInsertAt()
+ {
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IBinaryOperatorNode node = getBinaryNode("var a:Vector.<String> = new Vector.<String>(); a.insertAt(2, 'foo')");
+ IFunctionCallNode parentNode = (IFunctionCallNode)(node.getParent());
+ asBlockWalker.visitFunctionCall(parentNode);
+ assertOut("a.splice(2, 0, 'foo')");
+ }
@Test
public void testCustomVector()
@@ -504,6 +572,15 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
asBlockWalker.visitVariable(node);
assertOut("var /** @type {CustomVector} */ a = new CustomVector([], 'String')");
}
+
+ @Test
+ public void testCustomVectorLiteral_1a()
+ {
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IVariableNode node = getVariable("var a:Vector.<String> = new <String>[];");
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {Array} */ a = []");
+ }
@Test
public void testCustomVectorLiteral_2()
@@ -513,17 +590,35 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
asBlockWalker.visitVariable(node);
assertOut("var /** @type {CustomVector} */ a = new CustomVector([0, 1, 2, 3], 'int')");
}
+
+ @Test
+ public void testCustomVectorLiteral_2a()
+ {
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IVariableNode node = getVariable("var a:Vector.<int> = new <int>[0, 1, 2, 3];");
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {Array} */ a = [0, 1, 2, 3]");
+ }
@Test
public void testCustomVectorLiteral_3()
{
project.config.setJsVectorEmulationClass(null, "CustomVector");
- IVariableNode node = getVariable("var a:Vector.<String> = new <String>[\"one\", \"two\", \"three\";");
+ IVariableNode node = getVariable("var a:Vector.<String> = new <String>[\"one\", \"two\", \"three\"];");
asBlockWalker.visitVariable(node);
assertOut("var /** @type {CustomVector} */ a = new CustomVector([\"one\", \"two\", \"three\"], 'String')");
}
@Test
+ public void testCustomVectorLiteral_3a()
+ {
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IVariableNode node = getVariable("var a:Vector.<String> = new <String>[\"one\", \"two\", \"three\"];");
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {Array} */ a = [\"one\", \"two\", \"three\"]");
+ }
+
+ @Test
public void testCustomVectorNoArgs()
{
project.config.setJsVectorEmulationClass(null, "CustomVector");
@@ -531,6 +626,15 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
asBlockWalker.visitVariable(node);
assertOut("var /** @type {CustomVector} */ a = new CustomVector([], 'String')");
}
+
+ @Test
+ public void testCustomVectorNoArgs2()
+ {
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IVariableNode node = getVariable("var a:Vector.<String> = new Vector.<String>();");
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {Array} */ a = []");
+ }
@Test
public void testCustomVectorStringArgs()
@@ -562,6 +666,15 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
}
@Test
+ public void testCustomVectorSizeArg2()
+ {
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IVariableNode node = getVariable("var a:Vector.<String> = new Vector.<String>(30);");
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {Array} */ a = org.apache.royale.utils.Language.arrayAsVector(30, 'String')");
+ }
+
+ @Test
public void testCustomVectorSizeAndFixedArgs()
{
project.config.setJsVectorEmulationClass(null, "CustomVector");
@@ -569,6 +682,15 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
asBlockWalker.visitVariable(node);
assertOut("var /** @type {CustomVector} */ a = new CustomVector(30, 'String', true)");
}
+
+ @Test
+ public void testCustomVectorSizeAndFixedArgs2()
+ {
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IVariableNode node = getVariable("var a:Vector.<String> = new Vector.<String>(30, true);");
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {Array} */ a = org.apache.royale.utils.Language.arrayAsVector(30, 'String')");
+ }
@Test
public void testCustomVectorNumberArgs()
@@ -579,6 +701,16 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
//MXMLC does not report an error. Should we?
assertOut("var /** @type {CustomVector} */ a = new CustomVector(30, 'String')");
}
+
+ @Test
+ public void testCustomVectorNumberArgs2()
+ {
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IVariableNode node = getVariable("var a:Vector.<String> = new Vector.<String>(30, 40);");
+ asBlockWalker.visitVariable(node);
+ //MXMLC does not report an error. Should we?
+ assertOut("var /** @type {Array} */ a = org.apache.royale.utils.Language.arrayAsVector(30, 'String')");
+ }
@Test
public void testCustomVectorArrayArg()
@@ -591,6 +723,99 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
}
@Test
+ public void testCustomVectorArrayArg2()
+ {
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IVariableNode node = getVariable("var a:Vector.<String> = new Vector.<String>(['Hello', 'World']);");
+ asBlockWalker.visitVariable(node);
+ //MXMLC does not report an error. Should we?
+ assertOut("var /** @type {Array} */ a = org.apache.royale.utils.Language.arrayAsVector(['Hello', 'World'], 'String')");
+ }
+
+ @Test
+ public void testDefaultVectorClassRepresentation()
+ {
+ IVariableNode node = getVariable("var a:Class = Vector.<String>;");
+ asBlockWalker.visitVariable(node);
+ //MXMLC does not report an error. Should we?
+ assertOut("var /** @type {Object} */ a = org.apache.royale.utils.Language.synthVector('String')");
+ }
+
+ @Test
+ public void testCustomVectorClassRepresentation()
+ {
+ project.config.setJsVectorEmulationClass(null, "CustomVector");
+ IVariableNode node = getVariable("var a:Class = Vector.<String>;");
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {Object} */ a = CustomVector");
+ }
+
+ @Test
+ public void testCustomVectorClassRepresentation2()
+ {
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IVariableNode node = getVariable("var a:Class = Vector.<String>;");
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {Object} */ a = Array");
+ }
+
+ @Test
+ public void testDefaultVectorSortNumericArg()
+ {
+ IBinaryOperatorNode node = getBinaryNode("var a:Vector.<Number> = new Vector.<Number>();a.sort(Array.NUMERIC)");
+ IFunctionCallNode parentNode = (IFunctionCallNode)(node.getParent());
+ asBlockWalker.visitFunctionCall(parentNode);
+ assertOut("org.apache.royale.utils.Language.sort(a, 16)");
+ }
+
+ @Test
+ public void testCustomVectorRepresentationSortNumericArg()
+ {
+ project.config.setJsVectorEmulationClass(null, "CustomVector");
+ IBinaryOperatorNode node = getBinaryNode("var a:Vector.<Number> = new Vector.<Number>();a.sort(Array.NUMERIC)");
+ IFunctionCallNode parentNode = (IFunctionCallNode)(node.getParent());
+ asBlockWalker.visitFunctionCall(parentNode);
+ assertOut("a.sort(16)");
+ }
+
+ @Test
+ public void testCustomVectorAsArrayRepresentationSortNumericArg()
+ {
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IBinaryOperatorNode node = getBinaryNode("var a:Vector.<Number> = new Vector.<Number>();a.sort(Array.NUMERIC)");
+ IFunctionCallNode parentNode = (IFunctionCallNode)(node.getParent());
+ asBlockWalker.visitFunctionCall(parentNode);
+ assertOut("org.apache.royale.utils.Language.sort(a, 16)");
+ }
+
+ @Override
+ @Test
+ public void testBoolean()
+ {
+ IVariableNode node = getVariable("var a:Boolean = new Boolean(1);");
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {boolean} */ a = Boolean(1)");
+ }
+
+ @Override
+ @Test
+ public void testNumber()
+ {
+ IVariableNode node = getVariable("var a:Number = new Number(\"1\");");
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {number} */ a = Number(\"1\")");
+ }
+
+ @Override
+ @Test
+ public void testString()
+ {
+ IVariableNode node = getVariable("var a:String = new String(\"100\");");
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {string} */ a = String(\"100\")");
+ }
+
+ @Test
public void testXML()
{
IVariableNode node = getVariable("var a:XML = new XML(\"<top attr1='cat'><child attr2='dog'><grandchild attr3='fish'>text</grandchild></child></top>\");");
diff --git a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleGlobalFunctions.java b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleGlobalFunctions.java
index 8f2f9d1..5f8b6b2 100644
--- a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleGlobalFunctions.java
+++ b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleGlobalFunctions.java
@@ -100,6 +100,15 @@ public class TestRoyaleGlobalFunctions extends TestGoogGlobalFunctions
asBlockWalker.visitVariable(node);
assertOut("var /** @type {Array} */ a = Array(['Hello', 'World'])");
}
+
+ @Override
+ @Test
+ public void testObject()
+ {
+ IVariableNode node = getVariable("var a:Object = Object(\"1\");");
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {Object} */ a = org.apache.royale.utils.Language.resolveUncertain(Object(\"1\"))");
+ }
@Test
public void testParseInt()
@@ -159,6 +168,24 @@ public class TestRoyaleGlobalFunctions extends TestGoogGlobalFunctions
{
IVariableNode node = getVariable("var a:Vector.<String> = Vector.<String>(['Hello', 'World']);");
asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {Array.<string>} */ a = org.apache.royale.utils.Language.synthVector('String')['coerce'](['Hello', 'World'])");
+ }
+
+ @Test
+ public void testCustomVector()
+ {
+ project.config.setJsVectorEmulationClass(null, "CustomVector");
+ IVariableNode node = getVariable("var a:Vector.<String> = Vector.<String>(['Hello', 'World']);");
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {CustomVector} */ a = new CustomVector(['Hello', 'World'], 'String')");
+ }
+
+ @Test
+ public void testCustomVectorAsArray()
+ {
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IVariableNode node = getVariable("var a:Vector.<String> = Vector.<String>(['Hello', 'World']);");
+ asBlockWalker.visitVariable(node);
assertOut("var /** @type {Array} */ a = ['Hello', 'World'].slice()");
}
@@ -184,8 +211,29 @@ public class TestRoyaleGlobalFunctions extends TestGoogGlobalFunctions
IVariableNode node = getVariable("var a:Vector.<String> = Vector.<String>(30);");
asBlockWalker.visitVariable(node);
// MXMLC doesn't report an error either. Maybe we should.
+ assertOut("var /** @type {Array.<string>} */ a = org.apache.royale.utils.Language.synthVector('String')['coerce'](30)");
+ }
+
+ @Test
+ public void testCustomVectorSizeArg()
+ {
+ project.config.setJsVectorEmulationClass(null, "CustomVector");
+ IVariableNode node = getVariable("var a:Vector.<String> = Vector.<String>(30);");
+ asBlockWalker.visitVariable(node);
+ // MXMLC doesn't report an error either. Maybe we should.
+ assertOut("var /** @type {CustomVector} */ a = new CustomVector(30, 'String')");
+ }
+
+ @Test
+ public void testCustomVectorAsArraySizeArg()
+ {
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IVariableNode node = getVariable("var a:Vector.<String> = Vector.<String>(30);");
+ asBlockWalker.visitVariable(node);
+ // MXMLC doesn't report an error either. Maybe we should.
assertOut("var /** @type {Array} */ a = 30.slice()");
}
+
@Test
public void testVectorNumberArgs()
@@ -200,7 +248,7 @@ public class TestRoyaleGlobalFunctions extends TestGoogGlobalFunctions
{
IVariableNode node = getVariable("var a:Vector.<String> = Vector.<String>(['Hello', 'World']);");
asBlockWalker.visitVariable(node);
- assertOut("var /** @type {Array} */ a = ['Hello', 'World'].slice()");
+ assertOut("var /** @type {Array.<string>} */ a = org.apache.royale.utils.Language.synthVector('String')['coerce'](['Hello', 'World'])");
}
@Override
diff --git a/compiler/src/main/java/org/apache/royale/compiler/internal/tree/as/DynamicAccessNode.java b/compiler/src/main/java/org/apache/royale/compiler/internal/tree/as/DynamicAccessNode.java
index b616b9d..8df9fae 100644
--- a/compiler/src/main/java/org/apache/royale/compiler/internal/tree/as/DynamicAccessNode.java
+++ b/compiler/src/main/java/org/apache/royale/compiler/internal/tree/as/DynamicAccessNode.java
@@ -21,6 +21,7 @@ package org.apache.royale.compiler.internal.tree.as;
import org.apache.royale.compiler.definitions.IAppliedVectorDefinition;
import org.apache.royale.compiler.definitions.ITypeDefinition;
+import org.apache.royale.compiler.internal.semantics.SemanticUtils;
import org.apache.royale.compiler.projects.ICompilerProject;
import org.apache.royale.compiler.tree.ASTNodeID;
import org.apache.royale.compiler.tree.as.IDynamicAccessNode;
@@ -86,8 +87,10 @@ public class DynamicAccessNode extends BinaryOperatorNodeBase implements IDynami
ITypeDefinition leftType = getLeftOperandNode().resolveType(project);
if (leftType instanceof IAppliedVectorDefinition)
{
- IAppliedVectorDefinition vectorDef = (IAppliedVectorDefinition) leftType;
- return vectorDef.resolveElementType(project);
+ if (SemanticUtils.isNumericType(getRightOperandNode().resolveType(project), project)) {
+ IAppliedVectorDefinition vectorDef = (IAppliedVectorDefinition) leftType;
+ return vectorDef.resolveElementType(project);
+ }
}
return super.resolveType(project);
}
diff --git a/royale-ant-tasks/src/main/java/org/apache/royale/compiler/ant/FlexTask.java b/royale-ant-tasks/src/main/java/org/apache/royale/compiler/ant/FlexTask.java
index 79f7060..40e119f 100644
--- a/royale-ant-tasks/src/main/java/org/apache/royale/compiler/ant/FlexTask.java
+++ b/royale-ant-tasks/src/main/java/org/apache/royale/compiler/ant/FlexTask.java
@@ -308,9 +308,9 @@ public abstract class FlexTask extends Java
try
{
- Method toolMethod = toolClass.getMethod(toolMethodName, new Class[] {String[].class});
+ Method toolMethod = toolClass.getMethod(toolMethodName, String[].class);
Object result = toolMethod.invoke(null, new Object[] {cmdline.getArguments()});
- exitCode = ((Integer)result).intValue();
+ exitCode = ((Integer)result);
}
catch (Exception e)
{
@@ -337,9 +337,9 @@ public abstract class FlexTask extends Java
try
{
- Method toolFailureMethod = toolClass.getMethod(toolFailureMethodName, new Class[] {int.class});
- Object result = toolFailureMethod.invoke(null, new Object[] {exitCode});
- fatal = ((Boolean)result).booleanValue();
+ Method toolFailureMethod = toolClass.getMethod(toolFailureMethodName, int.class);
+ Object result = toolFailureMethod.invoke(null, exitCode);
+ fatal = ((Boolean)result);
}
catch (Exception e)
{
diff --git a/royale-maven-plugin/src/main/java/org/apache/royale/maven/BaseMojo.java b/royale-maven-plugin/src/main/java/org/apache/royale/maven/BaseMojo.java
index 74af100..ca1add1 100644
--- a/royale-maven-plugin/src/main/java/org/apache/royale/maven/BaseMojo.java
+++ b/royale-maven-plugin/src/main/java/org/apache/royale/maven/BaseMojo.java
@@ -236,16 +236,22 @@ public abstract class BaseMojo
List<String> args = new LinkedList<String>();
args.add("-load-config=" + configFile.getPath());
if(additionalCompilerOptions != null) {
+ if (additionalCompilerOptions.contains("\n")) {
+ additionalCompilerOptions = additionalCompilerOptions.replace("\n", "");
+ }
if (additionalCompilerOptions.contains(";"))
{
String[] options = additionalCompilerOptions.split(";");
for (String option : options)
{
- args.add(option);
+ if (option.trim().length() > 0)
+ args.add(option.trim());
}
}
- else
- args.add(additionalCompilerOptions);
+ else {
+ if (additionalCompilerOptions.trim().length() > 0)
+ args.add(additionalCompilerOptions.trim());
+ }
}
return args;
}
Re: [royale-compiler] branch develop updated: Squashed commit of the
following:
Posted by Alex Harui <ah...@adobe.com.INVALID>.
Is the positive/negative of SUPPRESS_COMPLEX_IMPLICIT_COERCION correct? It feels like it should be the opposite to me.
I just added:
/**
* @royalesuppresscompleximplicitcoercion false
*/
To turn OFF the implicit coercion.
Thoughts?
-Alex
On 6/10/19, 8:46 PM, "gregdove@apache.org" <gr...@apache.org> wrote:
This is an automated email from the ASF dual-hosted git repository.
gregdove pushed a commit to branch develop
in repository https://nam04.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgitbox.apache.org%2Frepos%2Fasf%2Froyale-compiler.git&data=02%7C01%7Caharui%40adobe.com%7C49e2f6d198e749c8793208d6ee1f5670%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636958215773729408&sdata=FAmo%2FZOA5U%2F3T%2BZzdaZlPjO7DLFL%2FiqDf1KSLkT61iE%3D&reserved=0
The following commit(s) were added to refs/heads/develop by this push:
new 6224c1a Squashed commit of the following:
6224c1a is described below
commit 6224c1ad785a9e2d0dda444d5a2add69c21cdf5f
Author: greg-dove <gr...@gmail.com>
AuthorDate: Tue Jun 11 15:21:08 2019 +1200
Squashed commit of the following:
commit 628d09e862fc3ff6edc9df6b0689b3634d157684
Merge: 29f4ba04 806603c8
Author: greg-dove <gr...@gmail.com>
Date: Tue Jun 11 14:51:58 2019 +1200
Merge branch 'develop' into improvements/Language
commit 29f4ba04b6eae4d294586803133e14ce0486cf6b
Author: greg-dove <gr...@gmail.com>
Date: Tue Jun 11 14:38:33 2019 +1200
Fix synthVector output for file-private element types.
Also add Class as a synthType
commit 378c07814db83d4e0af5343de8288d6c23583c4a
Merge: e461980d 905517ef
Author: greg-dove <gr...@gmail.com>
Date: Sun Jun 9 14:04:15 2019 +1200
Merge branch 'develop' into improvements/Language
commit e461980d384b71bc85a7c5014b9da5c7f26dfd4b
Author: greg-dove <gr...@gmail.com>
Date: Sun Jun 9 11:23:34 2019 +1200
Support for legacy Vector-as-Array via vectorEmulationClass setting, including fixes for insertAt/removeAt
commit 7dd36596e73f122ddb0af76db2abeb3d0a7b4231
Merge: b7cb250c de4bdad6
Author: greg-dove <gr...@gmail.com>
Date: Sat May 25 13:47:42 2019 +1200
Merge branch 'develop' into improvements/Language
commit b7cb250cbdc98218c69a83293603179f0fe297a4
Merge: b3080422 f1e68b92
Author: greg-dove <gr...@gmail.com>
Date: Thu May 23 18:37:54 2019 +1200
Merge branch 'develop' into improvements/Language
commit b30804227ad9bb8b5763fb56517649749e433a54
Author: greg-dove <gr...@gmail.com>
Date: Thu May 23 18:20:28 2019 +1200
Fixes for Issue #424
commit 164d1a1a37c15e83dc1142f9f628c4e7a4e6ee78
Author: greg-dove <gr...@gmail.com>
Date: Thu May 23 11:36:07 2019 +1200
support @royalesuppressexport on public fields
commit cea3363e6b0c7220015ff423c14b708f320dd83a
Author: greg-dove <gr...@gmail.com>
Date: Wed May 22 13:35:20 2019 +1200
Added 2 new doc directives for tuning js output: royalesuppressclosure and royalesuppressexport
commit 68293a747ff8e49f9c6a9152cca82f3a656ec0a4
Author: greg-dove <gr...@gmail.com>
Date: Sun May 19 18:07:49 2019 +1200
Avoid some Language warnings
Avoid some java language warnings in this code
commit e59fbf8152c09b65dbf7bb2dc74913a06b10c69d
Author: greg-dove <gr...@gmail.com>
Date: Sun May 19 17:32:23 2019 +1200
Allow line-based separation of individual additionalCompilerOptions entries in pom.xml
commit 54b062bce8a75d4de52c2b2a9d25a4ba92b431b0
Author: greg-dove <gr...@gmail.com>
Date: Wed May 15 10:51:57 2019 +1200
Fix for an XML bug identified in testing.
commit 4dade1a0500767a35b051829ebf2908254f22438
Author: greg-dove <gr...@gmail.com>
Date: Tue May 7 17:57:32 2019 +1200
remove 'no' from new config settings and toggle defaults accordingly (group review decision)
commit f11f18215f5d4c127b9715bc2f1e19c5a7a88d51
Author: greg-dove <gr...@gmail.com>
Date: Sun May 5 07:39:10 2019 +1200
code tidy
commit 88b2c1f52e7b15d2573d1d40e6963de4aa15b24f
Author: greg-dove <gr...@gmail.com>
Date: Sat May 4 18:21:57 2019 +1200
Squashed commit of cumulative work on Language improvements
---
.../royale/compiler/asdoc/royale/ASDocComment.java | 2 +-
.../royale/compiler/clients/JSConfiguration.java | 121 +++++-
.../codegen/js/goog/IJSGoogDocEmitter.java | 2 +-
.../compiler/internal/codegen/js/JSEmitter.java | 207 +++++++++-
.../internal/codegen/js/goog/JSGoogDocEmitter.java | 48 ++-
.../internal/codegen/js/jx/AccessorEmitter.java | 8 +-
.../internal/codegen/js/jx/AsIsEmitter.java | 31 +-
.../codegen/js/jx/BinaryOperatorEmitter.java | 44 ++-
.../internal/codegen/js/jx/ClassEmitter.java | 4 +-
.../codegen/js/jx/DynamicAccessEmitter.java | 54 +++
.../codegen/js/jx/FunctionCallEmitter.java | 429 ++++++++++++++++-----
.../internal/codegen/js/jx/IdentifierEmitter.java | 42 +-
.../internal/codegen/js/jx/InterfaceEmitter.java | 10 +
.../codegen/js/jx/MemberAccessEmitter.java | 41 +-
.../internal/codegen/js/jx/MethodEmitter.java | 8 +-
.../codegen/js/jx/PackageFooterEmitter.java | 2 +-
.../codegen/js/jx/UnaryOperatorEmitter.java | 29 ++
.../codegen/js/royale/JSRoyaleDocEmitter.java | 129 ++++++-
.../codegen/js/royale/JSRoyaleEmitter.java | 47 ++-
.../codegen/js/royale/JSRoyaleEmitterTokens.java | 11 +-
.../internal/codegen/js/utils/DocEmitterUtils.java | 9 +
.../internal/projects/RoyaleJSProject.java | 20 +-
.../compiler/utils/JSClosureCompilerWrapper.java | 2 +
.../apache/royale/compiler/utils/NativeUtils.java | 43 ++-
.../codegen/js/goog/TestGoogFieldMembers.java | 4 +-
.../codegen/js/goog/TestGoogGlobalClasses.java | 2 +-
.../codegen/js/goog/TestGoogGlobalFunctions.java | 2 +-
.../codegen/js/royale/TestRoyaleExpressions.java | 10 +-
.../codegen/js/royale/TestRoyaleFieldMembers.java | 4 +-
.../codegen/js/royale/TestRoyaleGlobalClasses.java | 251 +++++++++++-
.../js/royale/TestRoyaleGlobalFunctions.java | 50 ++-
.../internal/tree/as/DynamicAccessNode.java | 7 +-
.../org/apache/royale/compiler/ant/FlexTask.java | 10 +-
.../java/org/apache/royale/maven/BaseMojo.java | 12 +-
34 files changed, 1447 insertions(+), 248 deletions(-)
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/asdoc/royale/ASDocComment.java b/compiler-jx/src/main/java/org/apache/royale/compiler/asdoc/royale/ASDocComment.java
index a1006dc..21bdc95 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/asdoc/royale/ASDocComment.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/asdoc/royale/ASDocComment.java
@@ -134,7 +134,7 @@ public class ASDocComment implements IASDocComment
tags = new ArrayList<IASDocTag>();
tagMap.put(tagName, tags);
}
- tags.add(new ASDocTag(tagName, line.substring(after + 1)));
+ tags.add(new ASDocTag(tagName, line.substring(after + 1).trim()));
}
}
}
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/clients/JSConfiguration.java b/compiler-jx/src/main/java/org/apache/royale/compiler/clients/JSConfiguration.java
index 357a838..eda4012 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/clients/JSConfiguration.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/clients/JSConfiguration.java
@@ -457,13 +457,128 @@ public class JSConfiguration extends Configuration
}
/**
- * The class to use instead of Array for handling Vector.
+ * The class to use instead of default Vector implementation for handling Vector.
*/
@Config(advanced = true)
public void setJsVectorEmulationClass(ConfigurationValue cv, String b)
{
jsVectorEmulationClass = b;
}
-
-
+
+
+ //
+ // 'js-complex-implicit-coercions'
+ //
+
+ private boolean jsComplexImplicitCoercions = true;
+
+ public boolean getJsComplexImplicitCoercions()
+ {
+ return jsComplexImplicitCoercions;
+ }
+
+ /**
+ * Support for including/avoiding more complex implicit assignment coercions
+ * example
+ * var array:Array = [new MyClass()];
+ * var myOtherClass:MyOtherClass = array[0];
+ *
+ * In the above example, the compiler will (by default) output an implicit coercion
+ * that is equivalent in actionscript to:
+ * var myOtherClass:MyOtherClass = MyOtherClass(array[0]);
+ *
+ * By setting this configuration option to false, the implicit coercion code in situations similar to the above
+ * is not generated (other primitive implicit coercions, such as int/uint/Number/String and Boolean coercions remain)
+ * This is a global setting for the current source code being compiled, it is possible to leave it on and specifically avoid it via doc
+ * settings. The doc comment compiler directive for that is: @royalesuppresscompleximplicitcoercion
+ * Another option is to add the explicit coercions in code and then avoid their output
+ * via specific @royaleignorecoercion doc comment directives. Doing so however may add extra unwanted output
+ * in other compiler targets (for example, swf bytecode) if the same source code is shared between targets.
+ */
+ @Config(advanced = true)
+ @Mapping("js-complex-implicit-coercions")
+ public void setJsComplexImplicitCoercions(ConfigurationValue cv, boolean value)
+ throws ConfigurationException
+ {
+ jsComplexImplicitCoercions = value;
+ }
+
+ //
+ // 'js-resolve-uncertain'
+ //
+
+ private boolean jsResolveUncertain = true;
+
+ public boolean getJsResolveUncertain()
+ {
+ return jsResolveUncertain;
+ }
+
+ /**
+ * Support for avoiding more overhead of resolving instantiations from
+ * unknown constructors
+ * example
+ * var myClass:Class = String;
+ * var myString:* = new myClass("test");
+ *
+ * In the above example, the compiler will (by default) output
+ * a call to a Language.resolveUncertain method which wraps the 'new myClass("test")'
+ *
+ *
+ * This normalizes the return value for some primitive constructors, so that (for example)
+ * strict equality and inequality operators provide the same results between compiler
+ * targets.
+ * In situations where it is certain that the resolveUncertain method is not needed,
+ * this option provides a way to switch it off 'globally' for the current source code being compiled.
+ * It can also be switched off or on locally using the '@royalesuppressresolveuncertain'
+ * doc comment compiler directive.
+ */
+ @Config(advanced = true)
+ @Mapping("js-resolve-uncertain")
+ public void setJsResolveUncertain(ConfigurationValue cv, boolean value)
+ throws ConfigurationException
+ {
+ jsResolveUncertain = value;
+ }
+
+ //
+ // 'js-vector-index-checks'
+ //
+
+ private boolean jsVectorIndexChecks = true;
+
+ public boolean getJsVectorIndexChecks()
+ {
+ return jsVectorIndexChecks;
+ }
+
+ /**
+ * Support for avoiding more overhead of adding checks into
+ * assignments via Vector index access
+ * example
+ * var myVector:Vector.<int> = new Vector.<int>();
+ * myVector[0] = 42;
+ *
+ * In the above example, the compiler will (by default) wrap
+ * the '0' inside myVector[0] with a method call on the vector instance
+ * that checks to see if the index is valid for the Vector it is being used against
+ *
+ * This check will throw an error if the index is out of range, and the
+ * range checking differs if the Vector is 'fixed' or non-'fixed'
+ *
+ * In situations where it is certain that the index will always be valid for Vector instance
+ * being targeted, or where all cases in a given codebase are certain to be valid, it is possible
+ * to avoid the overhead of this check. This is especially important in loops.
+ * This config setting affects the global setting for the current source code being compiled.
+ * It can be adjusted locally within code, using the '@royalesuppressvectorindexcheck'
+ * doc comment compiler directive.
+ */
+ @Config(advanced = true)
+ @Mapping("js-vector-index-checks")
+ public void setJsVectorIndexChecks(ConfigurationValue cv, boolean value)
+ throws ConfigurationException
+ {
+ jsVectorIndexChecks = value;
+ }
+
}
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/codegen/js/goog/IJSGoogDocEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/codegen/js/goog/IJSGoogDocEmitter.java
index 112f3a0..6c99459 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/codegen/js/goog/IJSGoogDocEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/codegen/js/goog/IJSGoogDocEmitter.java
@@ -134,7 +134,7 @@ public interface IJSGoogDocEmitter extends IJSDocEmitter
void emitThis(ITypeDefinition node, String packageName);
- void emitType(IASNode node, String packageName);
+ void emitType(IASNode node, String packageName, ICompilerProject project);
void emitType(String type, String packageName);
}
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/JSEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/JSEmitter.java
index 45baa5a..a60ffbc 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/JSEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/JSEmitter.java
@@ -23,6 +23,7 @@ import java.io.FilterWriter;
import java.util.ArrayList;
import java.util.List;
+import org.apache.royale.compiler.codegen.IASGlobalFunctionConstants;
import org.apache.royale.compiler.codegen.IDocEmitter;
import org.apache.royale.compiler.codegen.IEmitter;
import org.apache.royale.compiler.codegen.ISubEmitter;
@@ -32,6 +33,8 @@ import org.apache.royale.compiler.common.ISourceLocation;
import org.apache.royale.compiler.constants.IASLanguageConstants;
import org.apache.royale.compiler.constants.IMetaAttributeConstants;
import org.apache.royale.compiler.constants.IASLanguageConstants.BuiltinType;
+import org.apache.royale.compiler.definitions.IAppliedVectorDefinition;
+import org.apache.royale.compiler.definitions.IClassDefinition;
import org.apache.royale.compiler.definitions.IDefinition;
import org.apache.royale.compiler.definitions.metadata.IMetaTag;
import org.apache.royale.compiler.definitions.metadata.IMetaTagAttribute;
@@ -64,8 +67,10 @@ import org.apache.royale.compiler.internal.codegen.js.jx.UnaryOperatorEmitter;
import org.apache.royale.compiler.internal.codegen.js.jx.WhileLoopEmitter;
import org.apache.royale.compiler.internal.codegen.js.jx.WithEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleDocEmitter;
+import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitterTokens;
+import org.apache.royale.compiler.internal.projects.RoyaleJSProject;
import org.apache.royale.compiler.internal.semantics.SemanticUtils;
-import org.apache.royale.compiler.internal.tree.as.FunctionNode;
+import org.apache.royale.compiler.internal.tree.as.*;
import org.apache.royale.compiler.projects.ICompilerProject;
import org.apache.royale.compiler.tree.as.IASNode;
import org.apache.royale.compiler.tree.as.ICatchNode;
@@ -97,6 +102,9 @@ import org.apache.royale.compiler.tree.as.IWithNode;
import com.google.debugging.sourcemap.FilePosition;
+import org.apache.royale.compiler.internal.codegen.as.ASEmitterTokens;
+import org.apache.royale.compiler.utils.NativeUtils;
+
/**
* @author Michael Schmalle
*/
@@ -220,12 +228,12 @@ public class JSEmitter extends ASEmitter implements IJSEmitter
public void emitClosureStart()
{
-
+
}
public void emitClosureEnd(IASNode node, IDefinition nodeDef)
{
-
+
}
public void emitSourceMapDirective(ITypeNode node)
@@ -502,7 +510,7 @@ public class JSEmitter extends ASEmitter implements IJSEmitter
/**
* Adjusts the line numbers saved in the source map when a line should be
* removed during post processing.
- *
+ *
* @param lineIndex
*/
protected void removeLineFromMappings(int lineIndex)
@@ -547,6 +555,7 @@ public class JSEmitter extends ASEmitter implements IJSEmitter
}
String coercionStart = null;
String coercionEnd = null;
+ boolean avoidCoercion = false;
if (project.getBuiltinType(BuiltinType.INT).equals(definition))
{
boolean needsCoercion = false;
@@ -567,6 +576,10 @@ public class JSEmitter extends ASEmitter implements IJSEmitter
endMapping(assignedNode);
return;
}
+ else if(assignedNode instanceof BinaryOperatorAsNode)
+ {
+ needsCoercion = true;
+ }
else if(!project.getBuiltinType(BuiltinType.INT).equals(assignedTypeDef))
{
needsCoercion = true;
@@ -597,6 +610,10 @@ public class JSEmitter extends ASEmitter implements IJSEmitter
endMapping(assignedNode);
return;
}
+ else if(assignedNode instanceof BinaryOperatorAsNode)
+ {
+ needsCoercion = true;
+ }
else if(!project.getBuiltinType(BuiltinType.UINT).equals(assignedTypeDef))
{
needsCoercion = true;
@@ -632,6 +649,8 @@ public class JSEmitter extends ASEmitter implements IJSEmitter
if (t.equals(IASLanguageConstants.Number))
{
needsCoercion = false;
+ //explicitly prevent other coercion detection rules from picking this up
+ avoidCoercion = true;
}
}
}
@@ -696,6 +715,186 @@ public class JSEmitter extends ASEmitter implements IJSEmitter
coercionStart = "org.apache.royale.utils.Language.string(";
}
}
+ if ( assignedDef != null
+ && assignedDef instanceof IAppliedVectorDefinition
+ && assignedNode instanceof TypedExpressionNode) {
+ //assign a Vector class as the assigned value, e.g. var c:Class = Vector.<int>
+ if (project instanceof RoyaleJSProject
+ && ((RoyaleJSProject)project).config.getJsVectorEmulationClass() != null) {
+ startMapping(assignedNode);
+ write(((RoyaleJSProject)project).config.getJsVectorEmulationClass());
+ endMapping(assignedNode);
+ } else {
+ startMapping(assignedNode);
+ write(JSRoyaleEmitterTokens.SYNTH_VECTOR);
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ //the element type of the Vector:
+ write(formatQualifiedName(((TypedExpressionNode)assignedNode).getTypeNode().resolve(project).getQualifiedName()));
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ endMapping(assignedNode);
+ if (project instanceof RoyaleJSProject)
+ ((RoyaleJSProject)project).needLanguage = true;
+ getModel().needLanguage = true;
+ }
+ return;
+ }
+ if (assignedDef instanceof IClassDefinition
+ && assignedNode instanceof IdentifierNode
+ && ((IdentifierNode)assignedNode).getName().equals(IASGlobalFunctionConstants.Vector)
+ && project instanceof RoyaleJSProject
+ && ((RoyaleJSProject)project).config.getJsVectorEmulationClass() == null ){
+ startMapping(assignedNode);
+ write(JSRoyaleEmitterTokens.SYNTH_VECTOR);
+ write(ASEmitterTokens.PAREN_OPEN);
+ //null to signify not a valid constructor
+ write(ASEmitterTokens.NULL);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ endMapping(assignedNode);
+ if (project instanceof RoyaleJSProject)
+ ((RoyaleJSProject)project).needLanguage = true;
+ getModel().needLanguage = true;
+ return;
+ }
+ if (coercionStart == null
+ && !avoidCoercion
+ && assignedTypeDef !=null
+ && definition !=null
+ && (project.getBuiltinType(BuiltinType.ANY_TYPE).equals(assignedTypeDef)
+ || project.getBuiltinType(BuiltinType.OBJECT).equals(assignedTypeDef))
+ && !(project.getBuiltinType(BuiltinType.ANY_TYPE).equals(definition)
+ || project.getBuiltinType(BuiltinType.OBJECT).equals(definition))) {
+ //catch leftovers: remaining implicit coercion of loosely typed assigned values to strongly typed context
+ //assignment to Class definitions is excluded because there is no 'Class' type in JS
+ //Possibility: 'Class' could be implemented as a synthType
+ boolean needsCoercion = ((RoyaleJSProject)project).config.getJsComplexImplicitCoercions();
+
+ IDocEmitter docEmitter = getDocEmitter();
+ if (docEmitter instanceof JSRoyaleDocEmitter)
+ {
+ JSRoyaleDocEmitter royaleDocEmitter = (JSRoyaleDocEmitter) docEmitter;
+ //check for local toggle
+ needsCoercion = royaleDocEmitter.getLocalSettingAsBoolean(
+ JSRoyaleEmitterTokens.SUPPRESS_COMPLEX_IMPLICIT_COERCION, needsCoercion);
+ if (needsCoercion) {
+ //check for individual specified suppression
+
+ String definitionName = definition.getQualifiedName();
+ //for Vectors, use the unqualified name to match the source code
+ if (NativeUtils.isVector(definitionName)) {
+ definitionName = definition.getBaseName();
+ }
+
+ if (royaleDocEmitter.getLocalSettingIncludesString(
+ JSRoyaleEmitterTokens.SUPPRESS_COMPLEX_IMPLICIT_COERCION,
+ definitionName))
+ {
+ needsCoercion = false;
+ }
+
+ }
+ }
+
+ //Avoid specific compile-time 'fake' class(es)
+ if (needsCoercion && definition.getQualifiedName().equals("org.apache.royale.core.WrappedHTMLElement")) {
+ //*actual* coercion fails here, because this is not actually instantiated, it is
+ //simply a type definition representing the 'wrapped' (or tagged) HTMLElement
+ needsCoercion = false;
+ }
+
+ //Avoid XML/XMLList:
+ if (needsCoercion && project.getBuiltinType(BuiltinType.XML) != null) {
+ if (project.getBuiltinType(BuiltinType.XML).equals(definition)
+ || project.getBuiltinType(BuiltinType.XMLLIST).equals(definition)) {
+ //XML/XMLList has complex output and would need more work
+ needsCoercion = false;
+ }
+ }
+
+ //avoid scenario with ArrayElementType specified as metadata definition type - assume it is 'typed'
+ if (needsCoercion && assignedNode instanceof IDynamicAccessNode)
+ {
+ IDynamicAccessNode dynamicAccess = (IDynamicAccessNode) assignedNode;
+ IDefinition dynamicAccessIndexDef = dynamicAccess.getRightOperandNode().resolveType(project);
+ if (project.getBuiltinType(BuiltinType.NUMBER).equals(dynamicAccessIndexDef))
+ {
+ IDefinition leftDef = dynamicAccess.getLeftOperandNode().resolveType(project);
+ if (leftDef != null) {
+ IMetaTag[] metas = leftDef.getAllMetaTags();
+ for (IMetaTag meta : metas)
+ {
+ if (meta.getTagName().equals(IMetaAttributeConstants.ATTRIBUTE_ARRAYELEMENTTYPE))
+ {
+ IMetaTagAttribute[] attrs = meta.getAllAttributes();
+ for (IMetaTagAttribute attr : attrs)
+ {
+ String t = attr.getValue();
+ if (t.equals(definition.getQualifiedName()))
+ {
+ needsCoercion = false;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (needsCoercion && project.getBuiltinType(BuiltinType.STRING).equals(definition)) {
+ //explicit suppression of String coercion
+ if (docEmitter instanceof JSRoyaleDocEmitter)
+ {
+ JSRoyaleDocEmitter royaleDocEmitter = (JSRoyaleDocEmitter) docEmitter;
+ needsCoercion = royaleDocEmitter.emitStringConversions;
+ }
+ if (needsCoercion
+ && assignedNode instanceof FunctionCallNode
+ && ((FunctionCallNode) assignedNode).getNameNode() instanceof MemberAccessExpressionNode
+ && ((MemberAccessExpressionNode)((FunctionCallNode) assignedNode).getNameNode()).getRightOperandNode() instanceof IdentifierNode
+ && ((IdentifierNode)(((MemberAccessExpressionNode)((FunctionCallNode) assignedNode).getNameNode()).getRightOperandNode())).getName().equals("toString")) {
+ //even if toString() is called in an untyped way, assume a call to a method named 'toString' is actually providing a String
+ needsCoercion = false;
+ }
+ }
+
+ if (needsCoercion) {
+ //add a comment tag leader, so implicit casts are identifiable in the output
+ coercionStart = "/* implicit cast */ "
+ + JSRoyaleEmitterTokens.LANGUAGE_QNAME.getToken()
+ + ASEmitterTokens.MEMBER_ACCESS.getToken()
+ + ASEmitterTokens.AS.getToken()
+ + ASEmitterTokens.PAREN_OPEN.getToken();
+ String coercionTypeString = formatQualifiedName(definition.getQualifiedName());
+ if (NativeUtils.isSyntheticJSType(coercionTypeString)) {
+ String synthCall;
+ String synthethicType;
+ if (NativeUtils.isVector(coercionTypeString)) {
+ synthCall = JSRoyaleEmitterTokens.SYNTH_VECTOR.getToken();
+ synthethicType = formatQualifiedName(coercionTypeString.substring(8, coercionTypeString.length() -1));
+ } else {
+ synthCall = JSRoyaleEmitterTokens.SYNTH_TYPE.getToken();
+ synthethicType = coercionTypeString;
+ }
+ coercionTypeString = synthCall
+ + ASEmitterTokens.PAREN_OPEN.getToken()
+ + ASEmitterTokens.SINGLE_QUOTE.getToken()
+ + synthethicType
+ + ASEmitterTokens.SINGLE_QUOTE.getToken()
+ + ASEmitterTokens.PAREN_CLOSE.getToken();
+ }
+
+ coercionEnd = ASEmitterTokens.COMMA.getToken()
+ + ASEmitterTokens.SPACE.getToken()
+ + coercionTypeString
+ + ASEmitterTokens.COMMA.getToken()
+ + ASEmitterTokens.SPACE.getToken()
+ + ASEmitterTokens.TRUE.getToken()
+ + ASEmitterTokens.PAREN_CLOSE.getToken();
+ if (project instanceof RoyaleJSProject)
+ ((RoyaleJSProject)project).needLanguage = true;
+ getModel().needLanguage = true;
+ }
+ }
if (coercionStart != null)
{
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/goog/JSGoogDocEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/goog/JSGoogDocEmitter.java
index 6c94259..c64823a 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/goog/JSGoogDocEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/goog/JSGoogDocEmitter.java
@@ -39,6 +39,7 @@ import org.apache.royale.compiler.internal.codegen.js.JSSharedData;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitter;
import org.apache.royale.compiler.internal.scopes.ASScope;
import org.apache.royale.compiler.internal.semantics.SemanticUtils;
+import org.apache.royale.compiler.internal.tree.as.TypedExpressionNode;
import org.apache.royale.compiler.projects.ICompilerProject;
import org.apache.royale.compiler.tree.as.IASNode;
import org.apache.royale.compiler.tree.as.IClassNode;
@@ -128,7 +129,7 @@ public class JSGoogDocEmitter extends JSDocEmitter implements IJSGoogDocEmitter
if (def != null)
packageName = def.getPackageName();
- emitType(node, packageName);
+ emitType(node, packageName, project);
end();
}
@@ -257,15 +258,14 @@ public class JSGoogDocEmitter extends JSDocEmitter implements IJSGoogDocEmitter
packageName = ((ITypeDefinition) type).getPackageName();
}
}
-
- emitTypeShort(node, project.getActualPackageName(packageName));
+ emitTypeShort(node, project.getActualPackageName(packageName), project);
}
else
{
writeNewline();
begin();
emitConst(node);
- emitType(node, project.getActualPackageName(packageName));
+ emitType(node, project.getActualPackageName(packageName), project);
end();
}
}
@@ -361,9 +361,18 @@ public class JSGoogDocEmitter extends JSDocEmitter implements IJSGoogDocEmitter
}
@Override
- public void emitType(IASNode node, String packageName)
+ public void emitType(IASNode node, String packageName, ICompilerProject project)
{
String type = ((IVariableNode) node).getVariableType();
+ if (((IVariableNode) node).getVariableTypeNode() instanceof TypedExpressionNode) {
+ ITypeDefinition elemenTypeDef = ((TypedExpressionNode)(((IVariableNode) node).getVariableTypeNode())).getTypeNode().resolveType(project);
+ if (elemenTypeDef != null) {
+ type = "Vector.<" +
+ convertASTypeToJS(elemenTypeDef.getQualifiedName(),"")
+ +">";
+ packageName = "";
+ }
+ }
emitJSDocLine(JSGoogDocEmitterTokens.TYPE.getToken(),
convertASTypeToJS(type, packageName));
}
@@ -375,9 +384,18 @@ public class JSGoogDocEmitter extends JSDocEmitter implements IJSGoogDocEmitter
convertASTypeToJS(type, packageName));
}
- public void emitTypeShort(IASNode node, String packageName)
+ public void emitTypeShort(IASNode node, String packageName, ICompilerProject project)
{
String type = ((IVariableNode) node).getVariableType();
+ if (((IVariableNode) node).getVariableTypeNode() instanceof TypedExpressionNode) {
+ ITypeDefinition elemenTypeDef = ((TypedExpressionNode)(((IVariableNode) node).getVariableTypeNode())).getTypeNode().resolveType(project);
+ if (elemenTypeDef != null) {
+ type = "Vector.<" +
+ convertASTypeToJS(elemenTypeDef.getQualifiedName(),"")
+ +">";
+ packageName = "";
+ }
+ }
writeToken(JSDocEmitterTokens.JSDOC_OPEN);
write(ASEmitterTokens.ATSIGN);
writeToken(JSGoogDocEmitterTokens.TYPE);
@@ -494,16 +512,18 @@ public class JSGoogDocEmitter extends JSDocEmitter implements IJSGoogDocEmitter
// is a vector so convert the element type
String elementType = name.substring(8, name.length() - 1);
elementType = convertASTypeToJSType(elementType, pname);
- name = "Vector.<" + elementType + ">";
+ name = "Array.<" + elementType + ">";
}
- IASGlobalFunctionConstants.BuiltinType[] builtinTypes = IASGlobalFunctionConstants.BuiltinType
- .values();
- for (IASGlobalFunctionConstants.BuiltinType builtinType : builtinTypes)
- {
- if (name.equalsIgnoreCase(builtinType.getName()))
+ else {
+ IASGlobalFunctionConstants.BuiltinType[] builtinTypes = IASGlobalFunctionConstants.BuiltinType
+ .values();
+ for (IASGlobalFunctionConstants.BuiltinType builtinType : builtinTypes)
{
- isBuiltinFunction = true;
- break;
+ if (name.equalsIgnoreCase(builtinType.getName()))
+ {
+ isBuiltinFunction = true;
+ break;
+ }
}
}
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/AccessorEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/AccessorEmitter.java
index 428f542..e3bd834 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/AccessorEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/AccessorEmitter.java
@@ -105,7 +105,7 @@ public class AccessorEmitter extends JSSubEmitter implements
if (emitExports)
writeNewline(" * @export");
if (p.type != null)
- writeNewline(" * @type {"+JSGoogDocEmitter.convertASTypeToJSType(p.type.getBaseName(), p.type.getPackageName()) + "} */");
+ writeNewline(" * @type {"+ JSGoogDocEmitter.convertASTypeToJSType(p.type.getBaseName(), p.type.getPackageName()) + "} */");
else
writeNewline(" */");
write(getEmitter().formatQualifiedName(qname));
@@ -321,7 +321,7 @@ public class AccessorEmitter extends JSSubEmitter implements
if (emitExports)
writeNewline(" * @export");
if (p.type != null)
- writeNewline(" * @type {"+JSGoogDocEmitter.convertASTypeToJSType(p.type.getBaseName(), p.type.getPackageName()) + "} */");
+ writeNewline(" * @type {" + JSGoogDocEmitter.convertASTypeToJSType(p.type.getBaseName(), p.type.getPackageName()) + "} */");
else
writeNewline(" */");
FunctionNode fnNode = getterNode != null ? (FunctionNode) getterNode : (FunctionNode) setterNode;
@@ -483,7 +483,7 @@ public class AccessorEmitter extends JSSubEmitter implements
if (emitExports)
writeNewline(" * @export");
if (p.type != null)
- writeNewline(" * @type {"+JSGoogDocEmitter.convertASTypeToJSType(p.type.getBaseName(), p.type.getPackageName()) + "} */");
+ writeNewline(" * @type {" + JSGoogDocEmitter.convertASTypeToJSType(p.type.getBaseName(), p.type.getPackageName()) + "} */");
else
writeNewline(" */");
write(getEmitter().formatQualifiedName(qname));
@@ -602,7 +602,7 @@ public class AccessorEmitter extends JSSubEmitter implements
if (emitExports)
writeNewline(" * @export");
if (p.type != null)
- writeNewline(" * @type {"+JSGoogDocEmitter.convertASTypeToJSType(p.type.getBaseName(), p.type.getPackageName()) + "} */");
+ writeNewline(" * @type {" + JSGoogDocEmitter.convertASTypeToJSType(p.type.getBaseName(), p.type.getPackageName()) + "} */");
else
writeNewline(" */");
write(propName);
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/AsIsEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/AsIsEmitter.java
index e8ffe98..9ddea56 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/AsIsEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/AsIsEmitter.java
@@ -22,6 +22,7 @@ package org.apache.royale.compiler.internal.codegen.js.jx;
import org.apache.royale.compiler.asdoc.royale.ASDocComment;
import org.apache.royale.compiler.codegen.js.IJSEmitter;
import org.apache.royale.compiler.constants.IASLanguageConstants;
+import org.apache.royale.compiler.definitions.IAppliedVectorDefinition;
import org.apache.royale.compiler.definitions.IClassDefinition;
import org.apache.royale.compiler.definitions.IDefinition;
import org.apache.royale.compiler.internal.codegen.as.ASEmitterTokens;
@@ -29,12 +30,14 @@ import org.apache.royale.compiler.internal.codegen.js.JSSubEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitterTokens;
import org.apache.royale.compiler.internal.projects.RoyaleJSProject;
+import org.apache.royale.compiler.parsing.IASToken;
import org.apache.royale.compiler.projects.ICompilerProject;
import org.apache.royale.compiler.tree.ASTNodeID;
import org.apache.royale.compiler.tree.as.IASNode;
import org.apache.royale.compiler.tree.as.IBinaryOperatorNode;
import org.apache.royale.compiler.tree.as.IExpressionNode;
import org.apache.royale.compiler.tree.as.IFunctionNode;
+import org.apache.royale.compiler.utils.NativeUtils;
public class AsIsEmitter extends JSSubEmitter
{
@@ -53,7 +56,7 @@ public class AsIsEmitter extends JSSubEmitter
.resolve(getProject()) : null;
if (id != ASTNodeID.Op_IsID && dnode != null)
{
- boolean emit = coercion ?
+ boolean emit = coercion ?
!((RoyaleJSProject)getProject()).config.getJSOutputOptimizations().contains(JSRoyaleEmitterTokens.SKIP_FUNCTION_COERCIONS.getToken()) :
!((RoyaleJSProject)getProject()).config.getJSOutputOptimizations().contains(JSRoyaleEmitterTokens.SKIP_AS_COERCIONS.getToken());
@@ -147,7 +150,7 @@ public class AsIsEmitter extends JSSubEmitter
getEmitter().getModel().needLanguage = true;
if (node instanceof IBinaryOperatorNode)
{
- IBinaryOperatorNode binaryOperatorNode = (IBinaryOperatorNode) node;
+ IBinaryOperatorNode binaryOperatorNode = (IBinaryOperatorNode) node;
startMapping(node, binaryOperatorNode.getLeftOperandNode());
}
else
@@ -181,7 +184,29 @@ public class AsIsEmitter extends JSSubEmitter
if (dnode instanceof IClassDefinition)
{
startMapping(right);
- write(getEmitter().formatQualifiedName(((JSRoyaleEmitter)getEmitter()).convertASTypeToJS(dnode.getQualifiedName())));
+ if (NativeUtils.isSyntheticJSType(dnode.getQualifiedName())) {
+ JSRoyaleEmitterTokens langMethod;
+ String synthName;
+ if (NativeUtils.isVector(dnode.getQualifiedName()) && dnode instanceof IAppliedVectorDefinition) {
+ langMethod = JSRoyaleEmitterTokens.SYNTH_VECTOR;
+ synthName = getEmitter().formatQualifiedName(((IAppliedVectorDefinition) dnode).resolveElementType(project).getQualifiedName());
+ } else {
+ //non-vector, e.g. int/uint
+ langMethod = JSRoyaleEmitterTokens.SYNTH_TYPE;
+ synthName = getEmitter().formatQualifiedName(dnode.getQualifiedName());
+ }
+ write(langMethod);
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(synthName);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ if (project instanceof RoyaleJSProject)
+ ((RoyaleJSProject)project).needLanguage = true;
+ getEmitter().getModel().needLanguage = true;
+ } else {
+ write(getEmitter().formatQualifiedName(((JSRoyaleEmitter)getEmitter()).convertASTypeToJS(dnode.getQualifiedName())));
+ }
endMapping(right);
}
else
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java
index 1533bf4..8d6c103 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java
@@ -21,6 +21,7 @@ package org.apache.royale.compiler.internal.codegen.js.jx;
import org.apache.royale.compiler.codegen.ISubEmitter;
import org.apache.royale.compiler.codegen.js.IJSEmitter;
+import org.apache.royale.compiler.constants.IASLanguageConstants;
import org.apache.royale.compiler.definitions.IDefinition;
import org.apache.royale.compiler.definitions.ITypeDefinition;
import org.apache.royale.compiler.internal.codegen.as.ASEmitterTokens;
@@ -30,10 +31,10 @@ import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.goog.JSGoogEmitterTokens;
import org.apache.royale.compiler.internal.definitions.AccessorDefinition;
+import org.apache.royale.compiler.internal.definitions.AppliedVectorDefinition;
+import org.apache.royale.compiler.internal.projects.RoyaleJSProject;
import org.apache.royale.compiler.internal.semantics.SemanticUtils;
-import org.apache.royale.compiler.internal.tree.as.DynamicAccessNode;
-import org.apache.royale.compiler.internal.tree.as.MemberAccessExpressionNode;
-import org.apache.royale.compiler.internal.tree.as.UnaryOperatorAtNode;
+import org.apache.royale.compiler.internal.tree.as.*;
import org.apache.royale.compiler.tree.ASTNodeID;
import org.apache.royale.compiler.tree.as.IASNode;
import org.apache.royale.compiler.tree.as.IBinaryOperatorNode;
@@ -100,7 +101,7 @@ public class BinaryOperatorEmitter extends JSSubEmitter implements
{
IASNode lnode = leftSide.getChild(0);
IASNode rnode = leftSide.getChild(1);
- IDefinition rnodeDef = (rnode instanceof IIdentifierNode) ?
+ IDefinition rnodeDef = (rnode instanceof IIdentifierNode) ?
((IIdentifierNode) rnode).resolve(getWalker().getProject()) :
null;
boolean isDynamicAccess = rnode instanceof DynamicAccessNode;
@@ -117,7 +118,7 @@ public class BinaryOperatorEmitter extends JSSubEmitter implements
else
write(getEmitter().formatQualifiedName(
getModel().getCurrentClass().getQualifiedName()));
-
+
write(ASEmitterTokens.MEMBER_ACCESS);
write(JSGoogEmitterTokens.SUPERCLASS);
write(ASEmitterTokens.MEMBER_ACCESS);
@@ -391,10 +392,11 @@ public class BinaryOperatorEmitter extends JSSubEmitter implements
}
}
-
- super_emitBinaryOperator(node, isAssignment);
+
+ super_emitBinaryOperator(node, isAssignment);
}
}
+
private void super_emitBinaryOperator(IBinaryOperatorNode node, boolean isAssignment)
{
@@ -431,8 +433,28 @@ public class BinaryOperatorEmitter extends JSSubEmitter implements
}
else
{
- getWalker().walk(node.getLeftOperandNode());
-
+ if (isAssignment
+ && (getProject() instanceof RoyaleJSProject && ((RoyaleJSProject) getProject()).config != null && ((RoyaleJSProject) getProject()).config.getJsVectorEmulationClass() == null)
+ && node.getLeftOperandNode() instanceof MemberAccessExpressionNode
+ && ((MemberAccessExpressionNode) node.getLeftOperandNode()).getRightOperandNode() instanceof IdentifierNode
+ && ((IdentifierNode) ((MemberAccessExpressionNode) node.getLeftOperandNode()).getRightOperandNode()).getName().equals("length")
+ && ((MemberAccessExpressionNode) node.getLeftOperandNode()).getLeftOperandNode().resolveType(getProject()) instanceof AppliedVectorDefinition)
+ {
+ //for default Vector implementation, when setting length, we need to set it on the associated 'synthType' instance which tags the native
+ //Array representation of the Vector. This allows running 'setter' code because it is not possible to override the native length setter on Array
+ //unless using a different approach, like es6 Proxy.
+ //this code inserts the extra access name for setting length, e.g. myVectInstance['_synthType'].length = assignedValue
+ //the dynamic access field name is a constant on Language, so it can be different/shorter in release build
+ getWalker().walk(((MemberAccessExpressionNode) node.getLeftOperandNode()).getLeftOperandNode());
+ write(ASEmitterTokens.SQUARE_OPEN);
+ write(JSRoyaleEmitterTokens.LANGUAGE_QNAME.getToken());
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write(JSRoyaleEmitterTokens.ROYALE_SYNTH_TAG_FIELD_NAME);
+ write(ASEmitterTokens.SQUARE_CLOSE);
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ getWalker().walk(((MemberAccessExpressionNode) node.getLeftOperandNode()).getRightOperandNode());
+ }
+ else getWalker().walk(node.getLeftOperandNode());
startMapping(node, node.getLeftOperandNode());
if (id != ASTNodeID.Op_CommaID)
@@ -469,12 +491,14 @@ public class BinaryOperatorEmitter extends JSSubEmitter implements
}
else
{
+
getWalker().walk(node.getRightOperandNode());
+
if (node.getNodeID() == ASTNodeID.Op_InID &&
((JSRoyaleEmitter)getEmitter()).isXML(node.getRightOperandNode()))
{
write(".elementNames()");
- }
+ }
else if (node.getNodeID() == ASTNodeID.Op_InID &&
((JSRoyaleEmitter)getEmitter()).isProxy(node.getRightOperandNode()))
{
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/ClassEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/ClassEmitter.java
index 807e7ae..3f6e13e 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/ClassEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/ClassEmitter.java
@@ -67,6 +67,8 @@ public class ClassEmitter extends JSSubEmitter implements
ASDocComment asDoc = (ASDocComment) node.getASDocComment();
if (asDoc != null && keepASDoc)
DocEmitterUtils.loadImportIgnores(fjs, asDoc.commentNoEnd());
+
+ boolean suppressExport = (asDoc != null && DocEmitterUtils.hasSuppressExport(fjs, asDoc.commentNoEnd()));
IClassDefinition definition = node.getDefinition();
@@ -131,7 +133,7 @@ public class ClassEmitter extends JSSubEmitter implements
}
}
- if (!getEmitter().getModel().isExterns)
+ if (!getEmitter().getModel().isExterns && !suppressExport)
{
JSRoyaleDocEmitter doc = (JSRoyaleDocEmitter) getEmitter()
.getDocEmitter();
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/DynamicAccessEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/DynamicAccessEmitter.java
index 2fd5085..5b78317 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/DynamicAccessEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/DynamicAccessEmitter.java
@@ -19,20 +19,30 @@
package org.apache.royale.compiler.internal.codegen.js.jx;
+import org.apache.royale.compiler.codegen.IDocEmitter;
import org.apache.royale.compiler.codegen.ISubEmitter;
import org.apache.royale.compiler.codegen.js.IJSEmitter;
import org.apache.royale.compiler.constants.IASLanguageConstants;
import org.apache.royale.compiler.definitions.ITypeDefinition;
import org.apache.royale.compiler.internal.codegen.as.ASEmitterTokens;
+import org.apache.royale.compiler.internal.codegen.js.JSEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.JSSubEmitter;
+import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleDocEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitter;
+import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitterTokens;
+import org.apache.royale.compiler.internal.definitions.AppliedVectorDefinition;
+import org.apache.royale.compiler.internal.projects.RoyaleJSProject;
+import org.apache.royale.compiler.internal.tree.as.BinaryOperatorAssignmentNode;
import org.apache.royale.compiler.internal.tree.as.FunctionCallNode;
+import org.apache.royale.compiler.internal.tree.as.IdentifierNode;
import org.apache.royale.compiler.internal.tree.as.MemberAccessExpressionNode;
+import org.apache.royale.compiler.parsing.IASToken;
import org.apache.royale.compiler.tree.ASTNodeID;
import org.apache.royale.compiler.tree.as.IDynamicAccessNode;
import org.apache.royale.compiler.tree.as.IExpressionNode;
import org.apache.royale.compiler.tree.as.ILiteralNode;
import org.apache.royale.compiler.tree.as.IOperatorNode.OperatorType;
+import org.apache.royale.compiler.utils.NativeUtils;
public class DynamicAccessEmitter extends JSSubEmitter implements
ISubEmitter<IDynamicAccessNode>
@@ -98,8 +108,52 @@ public class DynamicAccessEmitter extends JSSubEmitter implements
startMapping(node, leftOperandNode);
write(ASEmitterTokens.SQUARE_OPEN);
endMapping(node);
+ boolean wrapVectorIndex = false;
+ if (getProject() instanceof RoyaleJSProject) {
+ if (node.getNodeID().equals(ASTNodeID.ArrayIndexExpressionID)){
+ if (node.getParent() instanceof BinaryOperatorAssignmentNode) {
+ if (node.getLeftOperandNode().resolveType(getProject()) instanceof AppliedVectorDefinition) {
+ boolean suppressVectorIndexCheck = !(((RoyaleJSProject)getProject()).config.getJsVectorIndexChecks());
+
+ IDocEmitter docEmitter = getEmitter().getDocEmitter();
+ if (docEmitter instanceof JSRoyaleDocEmitter)
+ {
+ JSRoyaleDocEmitter royaleDocEmitter = (JSRoyaleDocEmitter) docEmitter;
+ //check for local toggle
+ suppressVectorIndexCheck = royaleDocEmitter.getLocalSettingAsBoolean(
+ JSRoyaleEmitterTokens.SUPPRESS_VECTOR_INDEX_CHECK, suppressVectorIndexCheck);
+
+ if (!suppressVectorIndexCheck) {
+ //check for individual specified suppression, based on variable name
+ if (leftOperandNode instanceof IdentifierNode) {
+ if (royaleDocEmitter.getLocalSettingIncludesString(
+ JSRoyaleEmitterTokens.SUPPRESS_VECTOR_INDEX_CHECK,
+ ((IdentifierNode) leftOperandNode).getName()
+ )){
+ suppressVectorIndexCheck = true;
+ }
+ }
+ }
+ }
+ if (!suppressVectorIndexCheck) {
+ getModel().needLanguage = true;
+ ((RoyaleJSProject) getProject()).needLanguage = true;
+ getWalker().walk(leftOperandNode);
+ write(ASEmitterTokens.SQUARE_OPEN);
+ write(JSRoyaleEmitterTokens.VECTOR_INDEX_CHECK_METHOD_NAME);
+ write(ASEmitterTokens.SQUARE_CLOSE);
+ write(ASEmitterTokens.PAREN_OPEN);
+ wrapVectorIndex = true;
+ }
+ }
+ }
+ }
+ }
getWalker().walk(rightOperandNode);
+ if (wrapVectorIndex) {
+ write(ASEmitterTokens.PAREN_CLOSE);
+ }
if (type != null && type.getQualifiedName().contentEquals(IASLanguageConstants.QName))
write(".objectAccessFormat()");
startMapping(node, rightOperandNode);
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/FunctionCallEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/FunctionCallEmitter.java
index 1e0bae0..855dd76 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/FunctionCallEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/FunctionCallEmitter.java
@@ -20,8 +20,10 @@
package org.apache.royale.compiler.internal.codegen.js.jx;
import org.apache.royale.compiler.codegen.IASGlobalFunctionConstants;
+import org.apache.royale.compiler.codegen.IDocEmitter;
import org.apache.royale.compiler.codegen.ISubEmitter;
import org.apache.royale.compiler.codegen.js.IJSEmitter;
+import org.apache.royale.compiler.common.SourceLocation;
import org.apache.royale.compiler.constants.IASLanguageConstants;
import org.apache.royale.compiler.constants.IASLanguageConstants.BuiltinType;
import org.apache.royale.compiler.definitions.IDefinition;
@@ -29,28 +31,18 @@ import org.apache.royale.compiler.definitions.ITypeDefinition;
import org.apache.royale.compiler.internal.codegen.as.ASEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.JSSessionModel;
import org.apache.royale.compiler.internal.codegen.js.JSSubEmitter;
+import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleDocEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.utils.EmitterUtils;
-import org.apache.royale.compiler.internal.definitions.AppliedVectorDefinition;
-import org.apache.royale.compiler.internal.definitions.ClassDefinition;
-import org.apache.royale.compiler.internal.definitions.FunctionDefinition;
-import org.apache.royale.compiler.internal.definitions.InterfaceDefinition;
-import org.apache.royale.compiler.internal.definitions.NamespaceDefinition;
+import org.apache.royale.compiler.internal.definitions.*;
import org.apache.royale.compiler.internal.projects.RoyaleJSProject;
-import org.apache.royale.compiler.internal.tree.as.ContainerNode;
-import org.apache.royale.compiler.internal.tree.as.IdentifierNode;
-import org.apache.royale.compiler.internal.tree.as.MemberAccessExpressionNode;
-import org.apache.royale.compiler.internal.tree.as.NamespaceIdentifierNode;
-import org.apache.royale.compiler.internal.tree.as.VectorLiteralNode;
+import org.apache.royale.compiler.internal.tree.as.*;
import org.apache.royale.compiler.problems.TooFewFunctionParametersProblem;
import org.apache.royale.compiler.problems.TooManyFunctionParametersProblem;
import org.apache.royale.compiler.projects.ICompilerProject;
import org.apache.royale.compiler.tree.ASTNodeID;
-import org.apache.royale.compiler.tree.as.IASNode;
-import org.apache.royale.compiler.tree.as.IContainerNode;
-import org.apache.royale.compiler.tree.as.IExpressionNode;
-import org.apache.royale.compiler.tree.as.IFunctionCallNode;
+import org.apache.royale.compiler.tree.as.*;
import org.apache.royale.compiler.utils.NativeUtils;
public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFunctionCallNode>
@@ -66,7 +58,6 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
{
// TODO (mschmalle) will remove this cast as more things get abstracted
JSRoyaleEmitter fjs = (JSRoyaleEmitter) getEmitter();
-
IASNode cnode = node.getChild(0);
if (cnode.getNodeID() == ASTNodeID.MemberAccessExpressionID)
@@ -80,16 +71,45 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
def = nameNode.resolve(getProject());
boolean isClassCast = false;
-
+ boolean wrapResolve = false;
if (node.isNewExpression())
{
- if (!(node.getChild(1) instanceof VectorLiteralNode))
+ boolean omitNew = false;
+ if (nameNode instanceof IdentifierNode
+ && (((IdentifierNode) nameNode).getName().equals(IASLanguageConstants.String)
+ || ((IdentifierNode) nameNode).getName().equals(IASLanguageConstants.Boolean)
+ || ((IdentifierNode) nameNode).getName().equals(IASLanguageConstants.Number)))
+ {
+ omitNew = true;
+ }
+
+ if (!((node.getChild(1) instanceof VectorLiteralNode)))
{
- if (def == null || !(def.getBaseName().equals(IASGlobalFunctionConstants._int) ||
- def.getBaseName().equals(IASGlobalFunctionConstants.uint) ||
- def instanceof AppliedVectorDefinition))
+ if (!omitNew
+ && ((def == null
+ || !(def.getBaseName().equals(IASGlobalFunctionConstants._int) || def.getBaseName().equals(IASGlobalFunctionConstants.uint)))
+ && !(def instanceof AppliedVectorDefinition && (
+ ((RoyaleJSProject) getProject()).config.getJsVectorEmulationClass()!= null
+ && ((RoyaleJSProject) getProject()).config.getJsVectorEmulationClass().equals("Array"))
+ ))
+ )
{
- startMapping(node.getNewKeywordNode());
+ if (getProject() instanceof RoyaleJSProject
+ && nameNode.resolveType(getProject()) != null
+ && nameNode.resolveType(getProject()).getQualifiedName().equals("Class")) {
+
+ wrapResolve = shouldResolveUncertain(nameNode, false);
+
+ if (wrapResolve) {
+ ((RoyaleJSProject) getProject()).needLanguage = true;
+ getModel().needLanguage = true;
+ write(JSRoyaleEmitterTokens.LANGUAGE_QNAME);
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write("resolveUncertain");
+ write(ASEmitterTokens.PAREN_OPEN);
+ }
+ }
+ startMapping(node.getNewKeywordNode());
writeToken(ASEmitterTokens.NEW);
endMapping(node.getNewKeywordNode());
}
@@ -97,14 +117,52 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
else
{
VectorLiteralNode vectorLiteralNode = (VectorLiteralNode) node.getChild(1);
- String vectorClassName = (((RoyaleJSProject)fjs.getWalker().getProject()).config.getJsVectorEmulationClass());
- if (vectorClassName != null)
+ String vectorEmulationClass = (((RoyaleJSProject)fjs.getWalker().getProject()).config.getJsVectorEmulationClass());
+ SourceLocation mappingLocation;
+ String elementClassName;
+ IDefinition elementClass = (((AppliedVectorDefinition)def).resolveElementType(getWalker().getProject()));
+ elementClassName = getEmitter().formatQualifiedName(elementClass.getQualifiedName());
+ if (vectorEmulationClass != null)
{
- writeToken(ASEmitterTokens.NEW);
- write(vectorClassName);
- write(ASEmitterTokens.PAREN_OPEN);
+ if (!vectorEmulationClass.equals("Array")) {
+ //Explanation:
+ //this was how it was originally set up, but it assumes the constructor of the emulation
+ //class can handle first argument being an Array or numeric value...
+ writeToken(ASEmitterTokens.NEW);
+ write(vectorEmulationClass);
+ write(ASEmitterTokens.PAREN_OPEN);
+ }// otherwise.... if 'Array' is the emulation class, then just use the literal content
+ } else {
+ //no 'new' output in this case, just coercion, so map from the start of 'new'
+ startMapping(node);
+ write(JSRoyaleEmitterTokens.SYNTH_VECTOR);
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ //the element type of the Vector:
+ write(elementClassName);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ write(ASEmitterTokens.SQUARE_OPEN);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write("coerce");
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.SQUARE_CLOSE);
+ mappingLocation = new SourceLocation(vectorLiteralNode.getCollectionTypeNode());
+ mappingLocation.setEndColumn(mappingLocation.getEndColumn() + 1);
+ endMapping(mappingLocation);
+ write(ASEmitterTokens.PAREN_OPEN);
+ if (getProject() instanceof RoyaleJSProject)
+ ((RoyaleJSProject)getProject()).needLanguage = true;
+ getEmitter().getModel().needLanguage = true;
+
}
+ mappingLocation = new SourceLocation(vectorLiteralNode.getContentsNode());
+ if (mappingLocation.getColumn()>0) mappingLocation.setColumn(mappingLocation.getColumn() -1);
+ mappingLocation.setEndColumn(mappingLocation.getColumn()+1);
+ startMapping(mappingLocation);
write("[");
+
+ endMapping(mappingLocation);
ContainerNode contentsNode = vectorLiteralNode.getContentsNode();
int len = contentsNode.getChildCount();
for (int i = 0; i < len; i++)
@@ -115,14 +173,24 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
writeToken(ASEmitterTokens.COMMA);
}
}
+ mappingLocation = new SourceLocation(vectorLiteralNode.getContentsNode());
+ mappingLocation.setLine(vectorLiteralNode.getContentsNode().getEndLine());
+ mappingLocation.setColumn(vectorLiteralNode.getContentsNode().getEndColumn());
+ mappingLocation.setEndColumn(mappingLocation.getColumn() + 1);
+ startMapping(mappingLocation);
write("]");
- if (vectorClassName != null)
+ endMapping(mappingLocation);
+ if (vectorEmulationClass != null)
{
- writeToken(ASEmitterTokens.COMMA);
- write(ASEmitterTokens.SINGLE_QUOTE);
- write(((AppliedVectorDefinition)def).resolveElementType(getWalker().getProject()).getBaseName());
- write(ASEmitterTokens.SINGLE_QUOTE);
- write(ASEmitterTokens.PAREN_CLOSE);
+ if (!vectorEmulationClass.equals("Array")) {
+ writeToken(ASEmitterTokens.COMMA);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(elementClassName);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ }
+ } else {
+ write(ASEmitterTokens.PAREN_CLOSE);
}
return;
}
@@ -131,12 +199,15 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
{
def = node.getNameNode().resolve(getProject());
- isClassCast = (def instanceof ClassDefinition || def instanceof InterfaceDefinition)
+ isClassCast = def != null && (def instanceof ClassDefinition
+ || def instanceof InterfaceDefinition
+ || ( def instanceof VariableDefinition && ((VariableDefinition) def).resolveType(getProject()).getBaseName().equals("Class")))
&& !(NativeUtils.isJSNative(def.getBaseName()))
&& !def.getBaseName().equals(IASLanguageConstants.XML)
&& !def.getBaseName().equals(IASLanguageConstants.XMLList);
+
}
-
+
if (node.isNewExpression())
{
def = node.resolveCalledExpression(getProject());
@@ -177,30 +248,39 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
if (nameNode.hasParenthesis())
write(ASEmitterTokens.PAREN_CLOSE);
}
-
- if (def instanceof AppliedVectorDefinition)
+ if ( def instanceof AppliedVectorDefinition
+ && (fjs.getWalker().getProject() instanceof RoyaleJSProject)
+ && (((RoyaleJSProject)fjs.getWalker().getProject()).config.getJsVectorEmulationClass() != null))
{
- ContainerNode args = node.getArgumentsNode();
- if (args.getChildCount() == 0)
- {
- String vectorClassName = (((RoyaleJSProject)fjs.getWalker().getProject()).config.getJsVectorEmulationClass());
- if (vectorClassName != null)
- {
+ ContainerNode args = node.getArgumentsNode();
+ String vectorEmulationClass = ((RoyaleJSProject)fjs.getWalker().getProject()).config.getJsVectorEmulationClass();
+ if (args.getChildCount() == 0)
+ {
+ if (vectorEmulationClass.equals("Array")) {
+ write(ASEmitterTokens.SQUARE_OPEN);
+ write(ASEmitterTokens.SQUARE_CLOSE);
+ } else {
write(ASEmitterTokens.PAREN_OPEN);
- write(ASEmitterTokens.SQUARE_OPEN);
- write(ASEmitterTokens.SQUARE_CLOSE);
+ write(ASEmitterTokens.SQUARE_OPEN);
+ write(ASEmitterTokens.SQUARE_CLOSE);
write(ASEmitterTokens.COMMA);
write(ASEmitterTokens.SPACE);
write(ASEmitterTokens.SINGLE_QUOTE);
- write(((AppliedVectorDefinition)def).resolveElementType(getWalker().getProject()).getBaseName());
+ write(((AppliedVectorDefinition)def).resolveElementType(getWalker().getProject()).getQualifiedName());
write(ASEmitterTokens.SINGLE_QUOTE);
write(ASEmitterTokens.PAREN_CLOSE);
}
- else
- getEmitter().emitArguments(node.getArgumentsNode());
- }
- else
- {
+ } else {
+ if (vectorEmulationClass.equals("Array")) {
+ if (getProject() instanceof RoyaleJSProject)
+ ((RoyaleJSProject) getProject()).needLanguage = true;
+ getEmitter().getModel().needLanguage = true;
+ write(JSRoyaleEmitterTokens.LANGUAGE_QNAME);
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ startMapping(node.getNameNode());
+ write("arrayAsVector");
+ endMapping(node.getNameNode());
+ }
startMapping(node);
write(ASEmitterTokens.PAREN_OPEN);
endMapping(node);
@@ -208,28 +288,29 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
write(ASEmitterTokens.COMMA);
write(ASEmitterTokens.SPACE);
write(ASEmitterTokens.SINGLE_QUOTE);
- write(((AppliedVectorDefinition)def).resolveElementType(getWalker().getProject()).getBaseName());
+ write(((AppliedVectorDefinition) def).resolveElementType(getWalker().getProject()).getQualifiedName());
write(ASEmitterTokens.SINGLE_QUOTE);
- if (args.getChildCount() == 2)
- {
- IASNode second = args.getChild(1);
- if (second instanceof IExpressionNode)
- {
- ITypeDefinition secondType =
- ((IExpressionNode)second).resolveType(fjs.getWalker().getProject());
- if (fjs.getWalker().getProject().getBuiltinType(BuiltinType.BOOLEAN).equals(secondType))
- {
+ if (args.getChildCount() == 2 && !vectorEmulationClass.equals("Array")) {
+ IASNode second = args.getChild(1);
+ if (second instanceof IExpressionNode) {
+ ITypeDefinition secondType =
+ ((IExpressionNode) second).resolveType(fjs.getWalker().getProject());
+ if (fjs.getWalker().getProject().getBuiltinType(BuiltinType.BOOLEAN).equals(secondType)) {
write(ASEmitterTokens.COMMA);
write(ASEmitterTokens.SPACE);
- getWalker().walk(second);
- }
- }
+ getWalker().walk(second);
+ }
+ }
}
write(ASEmitterTokens.PAREN_CLOSE);
- }
+ }
+ } else {
+ getEmitter().emitArguments(node.getArgumentsNode());
+ }
+ //end wrap resolve
+ if (wrapResolve) {
+ write(ASEmitterTokens.PAREN_CLOSE);
}
- else
- getEmitter().emitArguments(node.getArgumentsNode());
}
else if (!isClassCast)
{
@@ -270,37 +351,99 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
}
else if (def.getBaseName().equals("sort"))
{
- if (def.getParent() != null &&
- def.getParent().getQualifiedName().equals("Array"))
- {
- IExpressionNode args[] = node.getArgumentNodes();
- if (args.length > 0)
- {
- IExpressionNode optionsParamCheck = args.length == 1 ? args[0] : args[1];
- ICompilerProject project = this.getProject();
- IDefinition paramCheck = optionsParamCheck.resolveType(project);
-
- if (paramCheck.getBaseName().equals(IASLanguageConstants._int)
- || paramCheck.getBaseName().equals(IASLanguageConstants.uint)
- || paramCheck.getBaseName().equals(IASLanguageConstants.Number))
+ if (def.getParent() != null) {
+ if (def.getParent().getQualifiedName().equals("Array")
+ || (node.getNameNode() instanceof MemberAccessExpressionNode
+ && (((MemberAccessExpressionNode) node.getNameNode()).getLeftOperandNode().resolveType(getProject()) instanceof AppliedVectorDefinition)
+ && getProject() instanceof RoyaleJSProject
+ && (((RoyaleJSProject)getProject()).config.getJsVectorEmulationClass() == null
+ || ((RoyaleJSProject)getProject()).config.getJsVectorEmulationClass().equals("Array"))))
+ {
+ IExpressionNode args[] = node.getArgumentNodes();
+ if (args.length > 0)
{
- //deal with specific numeric option argument variations
- //either: Array.sort(option:uint) or Array.sort(compareFunction:Function, option:uint)
- //use our Language sort implementation to support these actionscript-specific method signatures
- if (project instanceof RoyaleJSProject)
- ((RoyaleJSProject) project).needLanguage = true;
- getEmitter().getModel().needLanguage = true;
- write(JSRoyaleEmitterTokens.LANGUAGE_QNAME);
- write(ASEmitterTokens.MEMBER_ACCESS);
- write("sort");
- IContainerNode newArgs = EmitterUtils.insertArgumentsBefore(node.getArgumentsNode(), cnode);
- fjs.emitArguments(newArgs);
- return;
+ IExpressionNode optionsParamCheck = args.length == 1 ? args[0] : args[1];
+ ICompilerProject project = this.getProject();
+ IDefinition paramCheck = optionsParamCheck.resolveType(project);
+
+ if (paramCheck.getBaseName().equals(IASLanguageConstants._int)
+ || paramCheck.getBaseName().equals(IASLanguageConstants.uint)
+ || paramCheck.getBaseName().equals(IASLanguageConstants.Number))
+ {
+ //deal with specific numeric option argument variations
+ //either: Array.sort(option:uint) or Array.sort(compareFunction:Function, option:uint)
+ //use our Language sort implementation to support these actionscript-specific method signatures
+ if (project instanceof RoyaleJSProject)
+ ((RoyaleJSProject) project).needLanguage = true;
+ getEmitter().getModel().needLanguage = true;
+ write(JSRoyaleEmitterTokens.LANGUAGE_QNAME);
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write("sort");
+ IContainerNode newArgs = EmitterUtils.insertArgumentsBefore(node.getArgumentsNode(), cnode);
+ fjs.emitArguments(newArgs);
+ return;
+ }
}
- }
- }
+ }
+ }
+
}
+ else if ((def.getBaseName().equals("insertAt")
+ || def.getBaseName().equals("removeAt"))
+ && def.getParent() instanceof AppliedVectorDefinition
+ && ((getProject() instanceof RoyaleJSProject) && (
+ ((RoyaleJSProject)getProject()).config.getJsVectorEmulationClass() == null
+ || ((RoyaleJSProject)getProject()).config.getJsVectorEmulationClass().equals("Array")))
+ ) {
+ if ((((RoyaleJSProject)getProject()).config.getJsVectorEmulationClass() != null)
+ && ((RoyaleJSProject)getProject()).config.getJsVectorEmulationClass().equals("Array")) {
+ //use a similar approach to regular 'Array' insertAt/removeAt
+ //for Array Vector emulation only (not for other custom classes)
+ //replace the insertAt/removeAt method with 'splice'
+ IdentifierNode splice = new IdentifierNode("splice");
+ splice.setSourceLocation(((MemberAccessExpressionNode)node.getNameNode()).getRightOperandNode());
+ splice.setParent((MemberAccessExpressionNode)node.getNameNode());
+ ((MemberAccessExpressionNode)node.getNameNode()).setRightOperandNode(splice);
+ NumericLiteralNode spliceArg;
+ if (def.getBaseName().equals("insertAt")) {
+ //insertAt
+ spliceArg = new NumericLiteralNode("0");
+ //This works like 'insertAt' itself, pushing the insertee to 3rd position (correct position):
+ node.getArgumentsNode().addChild(spliceArg, 1);
+ } else {
+ //removeAt
+ spliceArg = new NumericLiteralNode("1");
+ node.getArgumentsNode().addChild(spliceArg, 1);
+ }
+ } else {
+ //default Vector implementation
+ //unlike Array implementation of these methods, the synthetic Vector implementation supports these methods at runtime,
+ //and they behave differently with fixed length vectors compared to the native 'splice' method output which is used to
+ //support them in Array, however they are not protected from GCL renaming in release builds by any actual class definition,
+ //so we explicitly 'protect' them here by using DynamicAccess instead of MemberAccess
+ ExpressionNodeBase leftSide = (ExpressionNodeBase)(((BinaryOperatorNodeBase) (node.getNameNode())).getLeftOperandNode());
+ LiteralNode dynamicName = new LiteralNode(ILiteralNode.LiteralType.STRING, "'" + def.getBaseName() + "'");
+ dynamicName.setSourceLocation(((BinaryOperatorNodeBase) (node.getNameNode())).getRightOperandNode());
+ DynamicAccessNode replacement = new DynamicAccessNode(leftSide);
+ leftSide.setParent(replacement);
+ replacement.setSourceLocation(node.getNameNode());
+ replacement.setRightOperandNode(dynamicName);
+ dynamicName.setParent(replacement);
+
+ FunctionCallNode replacer = new FunctionCallNode(replacement) ;
+ replacement.setParent(replacer);
+ IExpressionNode[] args = node.getArgumentNodes();
+ for (IExpressionNode arg : args) {
+ replacer.getArgumentsNode().addItem((NodeBase) arg);
+ }
+ replacer.getArgumentsNode().setParent(replacer);
+ replacer.getArgumentsNode().setSourceLocation(node.getArgumentsNode());
+ replacer.setParent((NodeBase) node.getParent());
+ //swap it out
+ node = replacer;
+ }
+ }
else if (def instanceof AppliedVectorDefinition)
{
IExpressionNode[] argumentNodes = node.getArgumentNodes();
@@ -315,9 +458,54 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
}
else
{
- IExpressionNode argumentNode = argumentNodes[0];
- getWalker().walk(argumentNode);
- write(".slice()");
+ String elementClassName = getEmitter().formatQualifiedName(((TypedExpressionNode)nameNode).getTypeNode().resolve(getProject()).getQualifiedName());
+ if (getProject() instanceof RoyaleJSProject
+ && ((RoyaleJSProject) getProject()).config.getJsVectorEmulationClass()!= null) {
+ String vectorEmulationClass = ((RoyaleJSProject) getProject()).config.getJsVectorEmulationClass();
+ if (vectorEmulationClass.equals("Array")) {
+ //just do a slice copy of the array which is the first argument
+ getWalker().walk(node.getArgumentsNode().getChild(0));
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write("slice");
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ } else {
+ //assume the emulation class can handle an array or numeric value for first constructor arg...
+ writeToken(ASEmitterTokens.NEW);
+ startMapping(node.getNameNode());
+ write(vectorEmulationClass);
+ endMapping(node.getNameNode());
+ write(ASEmitterTokens.PAREN_OPEN);
+ getWalker().walk(node.getArgumentsNode().getChild(0));
+ writeToken(ASEmitterTokens.COMMA);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ //the element type of the Vector:
+ write(elementClassName);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ }
+ } else {
+ //default Vector implementation
+ startMapping(node.getNameNode());
+ write(JSRoyaleEmitterTokens.SYNTH_VECTOR);
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ //the element type of the Vector:
+ write(elementClassName);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ write(ASEmitterTokens.SQUARE_OPEN);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write("coerce");
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.SQUARE_CLOSE);
+ endMapping(node.getNameNode());
+
+ getEmitter().emitArguments(node.getArgumentsNode());
+ if (getProject() instanceof RoyaleJSProject)
+ ((RoyaleJSProject)getProject()).needLanguage = true;
+ getEmitter().getModel().needLanguage = true;
+ }
}
return;
}
@@ -327,6 +515,22 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
getEmitter().emitArguments(node.getArgumentsNode());
return;
}
+ else if (def.getQualifiedName().equals(IASLanguageConstants.Object)) {
+ //'resolveUncertain' always output here
+ //unless a) there are no arguments
+ //or b) it is *explicitly* suppressed for 'Object'
+ if (node.getArgumentNodes().length > 0) {
+ if (shouldResolveUncertain(nameNode, true)) {
+ wrapResolve = true;
+ ((RoyaleJSProject) getProject()).needLanguage = true;
+ getModel().needLanguage = true;
+ write(JSRoyaleEmitterTokens.LANGUAGE_QNAME);
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write("resolveUncertain");
+ write(ASEmitterTokens.PAREN_OPEN);
+ }
+ }
+ }
else if (nameNode.getNodeID() == ASTNodeID.NamespaceAccessExpressionID && def instanceof FunctionDefinition)
{
if (fjs.isCustomNamespace((FunctionDefinition)def))
@@ -336,7 +540,7 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
NamespaceDefinition nsDef = (NamespaceDefinition)nin.resolve(getProject());
IdentifierNode idNode = (IdentifierNode)nameNode.getChild(1);
String propName = idNode.getName();
- fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names
+ fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names
String s = nsDef.getURI();
write(JSRoyaleEmitter.formatNamespacedProperty(s, propName, true));
getEmitter().emitArguments(node.getArgumentsNode());
@@ -367,6 +571,11 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
getWalker().walk(node.getNameNode());
getEmitter().emitArguments(node.getArgumentsNode());
+
+ //end wrap resolve
+ if (wrapResolve) {
+ write(ASEmitterTokens.PAREN_CLOSE);
+ }
}
else //function-style cast
{
@@ -378,5 +587,31 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
fjs.emitSuperCall(node, JSSessionModel.SUPER_FUNCTION_CALL);
}
}
+
+
+ private boolean shouldResolveUncertain(IExpressionNode nameNode, boolean forceExplicit) {
+ //default if not avoided globally
+ boolean should = ((RoyaleJSProject)getProject()).config.getJsResolveUncertain();
+ //just in case:
+ if (!(getProject() instanceof RoyaleJSProject)) return false;
+
+ IDocEmitter docEmitter = getEmitter().getDocEmitter();
+ if (docEmitter instanceof JSRoyaleDocEmitter)
+ {
+ JSRoyaleDocEmitter royaleDocEmitter = (JSRoyaleDocEmitter) docEmitter;
+ //look for local boolean toggle, unless forceExplicit is set
+ boolean suppress = !forceExplicit && royaleDocEmitter.getLocalSettingAsBoolean(
+ JSRoyaleEmitterTokens.SUPPRESS_RESOLVE_UNCERTAIN, !should);
+ //if it is still on, look for sepcific/named 'off' setting based on name node
+ if (!suppress && nameNode !=null) {
+ //check to suppress for indvidual named node
+ if (nameNode instanceof IdentifierNode) {
+ suppress = royaleDocEmitter.getLocalSettingIncludesString(JSRoyaleEmitterTokens.SUPPRESS_RESOLVE_UNCERTAIN, ((IdentifierNode) nameNode).getName());
+ }
+ }
+ should = !suppress;
+ }
+ return should;
+ }
}
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/IdentifierEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/IdentifierEmitter.java
index 26d8649..4d42069 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/IdentifierEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/IdentifierEmitter.java
@@ -34,18 +34,15 @@ import org.apache.royale.compiler.internal.codegen.as.ASEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.JSSubEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitter;
import org.apache.royale.compiler.internal.codegen.js.goog.JSGoogEmitterTokens;
+import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.utils.EmitterUtils;
-import org.apache.royale.compiler.internal.definitions.AccessorDefinition;
-import org.apache.royale.compiler.internal.definitions.ClassDefinition;
-import org.apache.royale.compiler.internal.definitions.FunctionDefinition;
-import org.apache.royale.compiler.internal.definitions.TypeDefinitionBase;
+import org.apache.royale.compiler.internal.definitions.*;
+import org.apache.royale.compiler.internal.tree.as.BinaryOperatorAssignmentNode;
+import org.apache.royale.compiler.internal.tree.as.BinaryOperatorDivisionAssignmentNode;
+import org.apache.royale.compiler.internal.tree.as.MemberAccessExpressionNode;
import org.apache.royale.compiler.internal.tree.as.NonResolvingIdentifierNode;
import org.apache.royale.compiler.tree.ASTNodeID;
-import org.apache.royale.compiler.tree.as.IASNode;
-import org.apache.royale.compiler.tree.as.IFunctionNode;
-import org.apache.royale.compiler.tree.as.IFunctionObjectNode;
-import org.apache.royale.compiler.tree.as.IIdentifierNode;
-import org.apache.royale.compiler.tree.as.IMemberAccessExpressionNode;
+import org.apache.royale.compiler.tree.as.*;
import org.apache.royale.compiler.utils.NativeUtils;
public class IdentifierEmitter extends JSSubEmitter implements
@@ -239,7 +236,7 @@ public class IdentifierEmitter extends JSSubEmitter implements
{
Namespace ns = (Namespace)((INamespaceResolvedReference)((FunctionDefinition)nodeDef).getNamespaceReference()).resolveAETNamespace(getProject());
INamespaceDefinition nsDef = ((FunctionDefinition)nodeDef).getNamespaceReference().resolveNamespaceReference(getProject());
- fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names
+ fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names
String nsName = ns.getName();
write(JSRoyaleEmitter.formatNamespacedProperty(nsName, node.getName(), true));
}
@@ -315,20 +312,31 @@ public class IdentifierEmitter extends JSSubEmitter implements
}
else if (identifierIsAccessorFunction && isStatic)
{
- write("[\"" +node.getName() + "\"]");
+ write("[\"" +node.getName() + "\"]");
}
else
{
qname = node.getName();
if (nodeDef != null && !isStatic && (nodeDef.getParent() instanceof ClassDefinition) && (!(nodeDef instanceof IParameterDefinition)) && nodeDef.isPrivate() && getProject().getAllowPrivateNameConflicts())
qname = getEmitter().formatPrivateName(nodeDef.getParent().getQualifiedName(), qname);
- write(qname);
+ write(qname);
}
}
else if (isPackageOrFileMember)
write(getEmitter().formatQualifiedName(qname));
else if (nodeDef instanceof TypeDefinitionBase)
- write(getEmitter().formatQualifiedName(qname));
+ {
+ if (NativeUtils.isSyntheticJSType(qname) && !(parentNode instanceof IFunctionCallNode)) {
+ getEmitter().getModel().needLanguage = true;
+ write(JSRoyaleEmitterTokens.SYNTH_TYPE);
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(getEmitter().formatQualifiedName(qname));
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ }
+ else write(getEmitter().formatQualifiedName(qname));
+ }
else if (isCustomNamespace)
{
String ns = ((INamespaceResolvedReference)((FunctionDefinition)nodeDef).getNamespaceReference()).resolveAETNamespace(getProject()).getName();
@@ -336,9 +344,9 @@ public class IdentifierEmitter extends JSSubEmitter implements
}
else if (identifierIsAccessorFunction && isStatic)
{
- write("[\"" + qname + "\"]");
+ write("[\"" + qname + "\"]");
}
- else
+ else
{
if (nodeDef != null && !isStatic && (nodeDef.getParent() instanceof ClassDefinition) && (!(nodeDef instanceof IParameterDefinition)) && nodeDef.isPrivate() && getProject().getAllowPrivateNameConflicts())
qname = getEmitter().formatPrivateName(nodeDef.getParent().getQualifiedName(), qname);
@@ -353,7 +361,7 @@ public class IdentifierEmitter extends JSSubEmitter implements
write("child('");
write(node.getName());
write("')");
- endMapping(node);
+ endMapping(node);
}
else
{
@@ -363,5 +371,7 @@ public class IdentifierEmitter extends JSSubEmitter implements
}
}
}
+
+
}
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/InterfaceEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/InterfaceEmitter.java
index 0221afc..eb8f079 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/InterfaceEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/InterfaceEmitter.java
@@ -26,9 +26,11 @@ import org.apache.royale.compiler.internal.codegen.as.ASEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.JSDocEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.JSEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.JSSubEmitter;
+import org.apache.royale.compiler.internal.codegen.js.goog.JSGoogDocEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleDocEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitterTokens;
+import org.apache.royale.compiler.internal.tree.as.TypedExpressionNode;
import org.apache.royale.compiler.projects.ICompilerProject;
import org.apache.royale.compiler.tree.ASTNodeID;
import org.apache.royale.compiler.tree.as.IAccessorNode;
@@ -114,6 +116,14 @@ public class InterfaceEmitter extends JSSubEmitter implements
ITypeDefinition typeDef = typeNode.resolveType(project);
String packageName = typeDef.getPackageName();
packageName = project.getActualPackageName(packageName);
+ if (typeNode instanceof TypedExpressionNode) {
+ propType = "Vector.<" +
+ JSGoogDocEmitter.convertASTypeToJSType(
+ ((TypedExpressionNode)typeNode).getTypeNode().resolveType(project).getQualifiedName(),
+ "")
+ +">";
+ packageName = "";
+ }
write(JSDocEmitterTokens.JSDOC_OPEN);
write(ASEmitterTokens.SPACE);
fjs.getDocEmitter().emitType(propType, packageName);
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/MemberAccessEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/MemberAccessEmitter.java
index 23e5ec0..741affb 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/MemberAccessEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/MemberAccessEmitter.java
@@ -26,6 +26,7 @@ import org.apache.royale.compiler.definitions.IDefinition;
import org.apache.royale.compiler.internal.codegen.as.ASEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.JSEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.JSSubEmitter;
+import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleDocEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.goog.JSGoogEmitterTokens;
@@ -34,22 +35,15 @@ import org.apache.royale.compiler.internal.definitions.AccessorDefinition;
import org.apache.royale.compiler.internal.definitions.AppliedVectorDefinition;
import org.apache.royale.compiler.internal.definitions.FunctionDefinition;
import org.apache.royale.compiler.internal.projects.RoyaleJSProject;
-import org.apache.royale.compiler.internal.tree.as.DynamicAccessNode;
-import org.apache.royale.compiler.internal.tree.as.FunctionCallNode;
-import org.apache.royale.compiler.internal.tree.as.GetterNode;
-import org.apache.royale.compiler.internal.tree.as.IdentifierNode;
-import org.apache.royale.compiler.internal.tree.as.MemberAccessExpressionNode;
-import org.apache.royale.compiler.internal.tree.as.NamespaceAccessExpressionNode;
+import org.apache.royale.compiler.internal.tree.as.*;
import org.apache.royale.compiler.projects.ICompilerProject;
import org.apache.royale.compiler.tree.ASTNodeID;
-import org.apache.royale.compiler.tree.as.IASNode;
-import org.apache.royale.compiler.tree.as.IExpressionNode;
-import org.apache.royale.compiler.tree.as.IIdentifierNode;
-import org.apache.royale.compiler.tree.as.ILanguageIdentifierNode;
-import org.apache.royale.compiler.tree.as.IMemberAccessExpressionNode;
+import org.apache.royale.compiler.tree.as.*;
import org.apache.royale.compiler.tree.as.IOperatorNode.OperatorType;
import org.apache.royale.compiler.utils.ASNodeUtils;
+import javax.sound.midi.SysexMessage;
+
public class MemberAccessEmitter extends JSSubEmitter implements
ISubEmitter<IMemberAccessExpressionNode>
{
@@ -199,21 +193,6 @@ public class MemberAccessEmitter extends JSSubEmitter implements
return;
}
}
- else if (def.getParent() instanceof AppliedVectorDefinition)
- {
- if (def.getBaseName().equals("removeAt"))
- {
- writeLeftSide(node, leftNode, rightNode);
- write(".splice");
- return;
- }
- else if (def.getBaseName().equals("insertAt"))
- {
- writeLeftSide(node, leftNode, rightNode);
- write(".splice");
- return;
- }
- }
else if (rightNode instanceof NamespaceAccessExpressionNode)
{
boolean isStatic = false;
@@ -234,6 +213,11 @@ public class MemberAccessEmitter extends JSSubEmitter implements
parentNodeId != ASTNodeID.ArrayIndexExpressionID;
}
}
+
+ if (needClosure
+ && getEmitter().getDocEmitter() instanceof JSRoyaleDocEmitter
+ && ((JSRoyaleDocEmitter)getEmitter().getDocEmitter()).getSuppressClosure())
+ needClosure = false;
if (needClosure)
getEmitter().emitClosureStart();
@@ -296,6 +280,11 @@ public class MemberAccessEmitter extends JSSubEmitter implements
needClosure = !isStatic && parentNodeId != ASTNodeID.FunctionCallID &&
parentNodeId != ASTNodeID.MemberAccessExpressionID &&
parentNodeId != ASTNodeID.ArrayIndexExpressionID;
+
+ if (needClosure
+ && getEmitter().getDocEmitter() instanceof JSRoyaleDocEmitter
+ && ((JSRoyaleDocEmitter)getEmitter().getDocEmitter()).getSuppressClosure())
+ needClosure = false;
}
}
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/MethodEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/MethodEmitter.java
index aad1184..0fc7b0b 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/MethodEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/MethodEmitter.java
@@ -108,8 +108,12 @@ public class MethodEmitter extends JSSubEmitter implements
}
endMapping(node.getNameExpressionNode());
}
-
- startMapping(node);
+ if (node.getMetaTags() != null) {
+ //offset mapping by any metadata tags that will be in the first child node
+ startMapping(node.getChild(1));
+ } else {
+ startMapping(node);
+ }
write(ASEmitterTokens.SPACE);
writeToken(ASEmitterTokens.EQUAL);
write(ASEmitterTokens.FUNCTION);
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/PackageFooterEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/PackageFooterEmitter.java
index 7c151ac..86bc80d 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/PackageFooterEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/PackageFooterEmitter.java
@@ -76,7 +76,7 @@ public class PackageFooterEmitter extends JSSubEmitter implements
JSRoyaleDocEmitter doc = (JSRoyaleDocEmitter) getEmitter()
.getDocEmitter();
- if (!getEmitter().getModel().isExterns)
+ if (!getEmitter().getModel().isExterns && doc.getEmitExports())
{
boolean isInterface = tnode instanceof IInterfaceNode;
boolean isDynamic = tnode instanceof IClassNode && tnode.hasModifier(ASModifier.DYNAMIC);
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/UnaryOperatorEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/UnaryOperatorEmitter.java
index b575d55..bc040e7 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/UnaryOperatorEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/UnaryOperatorEmitter.java
@@ -23,8 +23,12 @@ import org.apache.royale.compiler.codegen.ISubEmitter;
import org.apache.royale.compiler.codegen.js.IJSEmitter;
import org.apache.royale.compiler.internal.codegen.as.ASEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.JSSubEmitter;
+import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitterTokens;
+import org.apache.royale.compiler.internal.definitions.AppliedVectorDefinition;
+import org.apache.royale.compiler.internal.tree.as.*;
import org.apache.royale.compiler.tree.ASTNodeID;
import org.apache.royale.compiler.tree.as.IExpressionNode;
+import org.apache.royale.compiler.tree.as.ILiteralNode;
import org.apache.royale.compiler.tree.as.IUnaryOperatorNode;
import org.apache.royale.compiler.utils.ASNodeUtils;
@@ -41,6 +45,31 @@ public class UnaryOperatorEmitter extends JSSubEmitter implements
{
if (ASNodeUtils.hasParenOpen(node))
write(ASEmitterTokens.PAREN_OPEN);
+
+ Boolean isAssignment = (node.getNodeID() == ASTNodeID.Op_PreIncrID
+ || node.getNodeID() == ASTNodeID.Op_PreDecrID
+ || node.getNodeID() == ASTNodeID.Op_PostIncrID
+ || node.getNodeID() == ASTNodeID.Op_PostDecrID);
+
+ if (isAssignment && (node.getOperandNode() instanceof MemberAccessExpressionNode)
+ && (((MemberAccessExpressionNode)(node.getOperandNode())).getRightOperandNode() instanceof IdentifierNode)
+ && ((IdentifierNode)(((MemberAccessExpressionNode)(node.getOperandNode())).getRightOperandNode())).getName().equals("length")
+ && ((MemberAccessExpressionNode)(node.getOperandNode())).getLeftOperandNode().resolveType(getProject()) instanceof AppliedVectorDefinition
+ ) {
+ //support for output of alternate length setter, example: vectorInst.length++ as vectorInst['_synthType'].length++
+ //likewise for pre/post increment/decrement
+
+ String synthTagName = JSRoyaleEmitterTokens.LANGUAGE_QNAME.getToken() + ASEmitterTokens.MEMBER_ACCESS.getToken() + JSRoyaleEmitterTokens.ROYALE_SYNTH_TAG_FIELD_NAME.getToken();
+ LiteralNode synthType = new LiteralNode(ILiteralNode.LiteralType.STRING, synthTagName);
+ synthType.setSynthetic(true);
+ DynamicAccessNode patchedVectorReference = new DynamicAccessNode(((ExpressionNodeBase)((MemberAccessExpressionNode) node.getOperandNode()).getLeftOperandNode()));
+ ((ExpressionNodeBase)((MemberAccessExpressionNode) node.getOperandNode()).getLeftOperandNode()).setParent(patchedVectorReference);
+ patchedVectorReference.setRightOperandNode(synthType);
+ synthType.setParent(patchedVectorReference);
+ patchedVectorReference.setParent((NodeBase) node.getOperandNode());
+ patchedVectorReference.setSourceLocation(((MemberAccessExpressionNode) node.getOperandNode()).getLeftOperandNode());
+ ((MemberAccessExpressionNode) node.getOperandNode()).setLeftOperandNode(patchedVectorReference);
+ }
if (node.getNodeID() == ASTNodeID.Op_PreIncrID
|| node.getNodeID() == ASTNodeID.Op_PreDecrID
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleDocEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleDocEmitter.java
index 8cfd1c9..e32b148 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleDocEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleDocEmitter.java
@@ -19,8 +19,7 @@
package org.apache.royale.compiler.internal.codegen.js.royale;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.*;
import org.apache.royale.compiler.asdoc.royale.ASDocComment;
import org.apache.royale.compiler.codegen.as.IASEmitter;
@@ -41,6 +40,7 @@ import org.apache.royale.compiler.internal.codegen.js.goog.JSGoogDocEmitter;
import org.apache.royale.compiler.internal.codegen.js.jx.BindableEmitter;
import org.apache.royale.compiler.internal.projects.RoyaleJSProject;
import org.apache.royale.compiler.internal.scopes.ASScope;
+import org.apache.royale.compiler.parsing.IASToken;
import org.apache.royale.compiler.problems.PublicVarWarningProblem;
import org.apache.royale.compiler.projects.ICompilerProject;
import org.apache.royale.compiler.tree.ASTNodeID;
@@ -53,9 +53,12 @@ public class JSRoyaleDocEmitter extends JSGoogDocEmitter
private List<String> classIgnoreList;
private List<String> ignoreList;
private List<String> coercionList;
+ private Map<String,List<String>> localSettings;
public boolean emitStringConversions = true;
private boolean emitExports = true;
private boolean exportProtected = false;
+
+ private boolean suppressClosure = false;
public JSRoyaleDocEmitter(IJSEmitter emitter)
{
@@ -71,6 +74,14 @@ public class JSRoyaleDocEmitter extends JSGoogDocEmitter
{
this.classIgnoreList = value;
}
+
+ public Boolean getSuppressClosure() {
+ return suppressClosure;
+ }
+
+ public Boolean getEmitExports() {
+ return emitExports;
+ }
@Override
protected String convertASTypeToJS(String name, String pname)
@@ -95,7 +106,7 @@ public class JSRoyaleDocEmitter extends JSGoogDocEmitter
RoyaleJSProject fjp = (RoyaleJSProject)((IASEmitter)emitter).getWalker().getProject();
String vectorClassName = fjp.config == null ? null : fjp.config.getJsVectorEmulationClass();
if (vectorClassName != null) return vectorClassName;
- return IASLanguageConstants.Array;
+ return super.convertASTypeToJS(name, pname);
}
name = super.convertASTypeToJS(name, pname);
@@ -128,7 +139,9 @@ public class JSRoyaleDocEmitter extends JSGoogDocEmitter
coercionList = null;
ignoreList = null;
+ localSettings = null;
emitStringConversions = true;
+ suppressClosure = false;
IClassDefinition classDefinition = resolveClassDefinition(node);
@@ -228,6 +241,31 @@ public class JSRoyaleDocEmitter extends JSGoogDocEmitter
.getToken();
if (docText.contains(noStringToken))
emitStringConversions = false;
+
+ String noImplicitComplexCoercion = JSRoyaleEmitterTokens.SUPPRESS_COMPLEX_IMPLICIT_COERCION
+ .getToken();
+ if (docText.contains(noImplicitComplexCoercion))
+ loadLocalSettings(docText, noImplicitComplexCoercion, "true");
+
+ String noResolveUncertain = JSRoyaleEmitterTokens.SUPPRESS_RESOLVE_UNCERTAIN
+ .getToken();
+ if (docText.contains(noResolveUncertain))
+ loadLocalSettings(docText,noResolveUncertain, "true");
+
+ String suppressVectorIndexCheck = JSRoyaleEmitterTokens.SUPPRESS_VECTOR_INDEX_CHECK
+ .getToken();
+ if (docText.contains(suppressVectorIndexCheck))
+ loadLocalSettings(docText,suppressVectorIndexCheck, "true");
+
+ String suppressClosureToken = JSRoyaleEmitterTokens.SUPPRESS_CLOSURE.getToken();
+
+ if (docText.contains(suppressClosureToken))
+ suppressClosure = true;
+
+ String suppressExport = JSRoyaleEmitterTokens.SUPPRESS_EXPORT.getToken();
+ if (docText.contains(suppressExport))
+ emitExports = false;
+
write(changeAnnotations(asDoc.commentNoEnd()));
}
else
@@ -312,6 +350,82 @@ public class JSRoyaleDocEmitter extends JSGoogDocEmitter
end();
}
}
+
+ /**
+ *
+ */
+ private void loadLocalSettings(String doc, String settingToken, String defaultSetting)
+ {
+ if (localSettings == null) localSettings = new HashMap<String, List<String>>();
+ int index = doc.indexOf(settingToken);
+ List<String> settings = localSettings.containsKey(settingToken) ? localSettings.get(settingToken) : null;
+ while (index != -1)
+ {
+ String setting = doc.substring(index + settingToken.length());
+ int endIndex = setting.indexOf("\n");
+ setting = setting.substring(0, endIndex);
+ setting = setting.trim();
+ if (settings == null) {
+ settings = new ArrayList<String>();
+ localSettings.put(settingToken, settings);
+ }
+ List<String> settingItems = null;
+ if (setting.length() >0) {
+ settingItems = Arrays.asList(setting.split("\\s*(,\\s*)+"));
+ } else {
+ settingItems = Arrays.asList(defaultSetting);
+ }
+ for (String settingItem: settingItems) {
+ if (settings.contains(settingItem)) {
+ //change the order to reflect the latest addition
+ settings.remove(settingItem);
+ }
+ settings.add(settingItem);
+ //System.out.println("---Adding setting "+settingToken+":"+settingItem);
+ }
+
+ index = doc.indexOf(settingToken, index + endIndex);
+ }
+ }
+
+ public boolean hasLocalSetting(String settingToken) {
+ if (localSettings == null) return false;
+ return (localSettings.keySet().contains(settingToken));
+ }
+
+ public boolean getLocalSettingAsBoolean(JSRoyaleEmitterTokens token, Boolean defaultValue) {
+ return getLocalSettingAsBoolean(token.getToken(), defaultValue);
+ }
+
+ public boolean getLocalSettingAsBoolean(String settingToken, Boolean defaultValue) {
+ boolean setting = defaultValue;
+ if (hasLocalSetting(settingToken)) {
+ for (String stringVal: localSettings.get(settingToken)) {
+ //don't bail out after finding a boolean-ish string val
+ //'last one wins'
+ if (stringVal.equals("false")) setting = false;
+ else if (stringVal.equals("true")) setting = true;
+ }
+ }
+ return setting;
+ }
+
+ public boolean getLocalSettingIncludesString(JSRoyaleEmitterTokens token, String searchValue) {
+ return getLocalSettingIncludesString(token.getToken(), searchValue);
+ }
+
+ public boolean getLocalSettingIncludesString(String settingToken, String searchValue) {
+ boolean hasValue = false;
+ if (hasLocalSetting(settingToken)) {
+ for (String stringVal: localSettings.get(settingToken)) {
+ if (stringVal.equals(searchValue)) {
+ hasValue = true;
+ break;
+ }
+ }
+ }
+ return hasValue;
+ }
private void loadIgnores(String doc)
{
@@ -468,7 +582,12 @@ public class JSRoyaleDocEmitter extends JSGoogDocEmitter
}
- emitPublic(node);
+ if (!(node.getASDocComment() instanceof ASDocComment
+ && ((ASDocComment)node.getASDocComment()).commentNoEnd()
+ .contains(JSRoyaleEmitterTokens.SUPPRESS_EXPORT.getToken()))) {
+ emitPublic(node);
+ }
+
}
if (node.isConst())
@@ -478,7 +597,7 @@ public class JSRoyaleDocEmitter extends JSGoogDocEmitter
if (def != null)
packageName = def.getPackageName();
- emitType(node, project.getActualPackageName(packageName));
+ emitType(node, project.getActualPackageName(packageName), project);
end();
}
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleEmitter.java
index 834ce4d..5e82d8e 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleEmitter.java
@@ -718,12 +718,10 @@ public class JSRoyaleEmitter extends JSGoogEmitter implements IJSRoyaleEmitter
else if (name.equals(IASLanguageConstants._int)
|| name.equals(IASLanguageConstants.uint))
result = IASLanguageConstants.Number;
-
- boolean isBuiltinFunction = name.matches("Vector\\.<.*>");
- if (isBuiltinFunction)
- {
- result = IASLanguageConstants.Array;
+ else if (name.equals(IASLanguageConstants.Vector) || name.equals("__AS3__.vec.Vector")) {
+ result = JSRoyaleEmitterTokens.VECTOR.getToken();
}
+
return result;
}
@@ -925,10 +923,6 @@ public class JSRoyaleEmitter extends JSGoogEmitter implements IJSRoyaleEmitter
newNode = EmitterUtils.insertArgumentsAt(node, 1, new NumericLiteralNode("0"));
}
}
- else if (def.getParent() != null && def.getParent() instanceof AppliedVectorDefinition)
- {
- newNode = EmitterUtils.insertArgumentsAt(node, 1, new NumericLiteralNode("0"));
- }
}
}
if (len == 1)
@@ -947,10 +941,6 @@ public class JSRoyaleEmitter extends JSGoogEmitter implements IJSRoyaleEmitter
newNode = EmitterUtils.insertArgumentsAfter(node, new NumericLiteralNode("1"));
}
}
- else if (def.getParent() != null && def.getParent() instanceof AppliedVectorDefinition)
- {
- newNode = EmitterUtils.insertArgumentsAfter(node, new NumericLiteralNode("1"));
- }
}
else if (def != null && def.getBaseName().equals("parseInt"))
{
@@ -1095,7 +1085,8 @@ public class JSRoyaleEmitter extends JSGoogEmitter implements IJSRoyaleEmitter
@Override
public void emitClosureStart()
{
- ICompilerProject project = getWalker().getProject();;
+ if (getDocEmitter() instanceof JSRoyaleDocEmitter && ((JSRoyaleDocEmitter) getDocEmitter()).getSuppressClosure()) return;
+ ICompilerProject project = getWalker().getProject();
if (project instanceof RoyaleJSProject)
((RoyaleJSProject)project).needLanguage = true;
getModel().needLanguage = true;
@@ -1106,6 +1097,7 @@ public class JSRoyaleEmitter extends JSGoogEmitter implements IJSRoyaleEmitter
@Override
public void emitClosureEnd(IASNode node, IDefinition nodeDef)
{
+ if (getDocEmitter() instanceof JSRoyaleDocEmitter && ((JSRoyaleDocEmitter) getDocEmitter()).getSuppressClosure()) return;
write(ASEmitterTokens.COMMA);
write(ASEmitterTokens.SPACE);
write(ASEmitterTokens.SINGLE_QUOTE);
@@ -1448,6 +1440,9 @@ public class JSRoyaleEmitter extends JSGoogEmitter implements IJSRoyaleEmitter
{
return isXML(((MemberAccessExpressionNode)obj).getLeftOperandNode());
}
+ else if (leftDef != null && leftDef.getBaseName().equals("*") && obj instanceof DynamicAccessNode) {
+ return isXML(((DynamicAccessNode)obj).getLeftOperandNode());
+ }
return SemanticUtils.isXMLish(leftDef, getWalker().getProject());
}
@@ -1479,12 +1474,30 @@ public class JSRoyaleEmitter extends JSGoogEmitter implements IJSRoyaleEmitter
String vectorClassName = ((RoyaleJSProject)project).config == null ? null : ((RoyaleJSProject)project).config.getJsVectorEmulationClass();
if (vectorClassName != null)
{
- writeToken(ASEmitterTokens.NEW);
- write(vectorClassName);
+ if (!vectorClassName.equals("Array"))
+ write(vectorClassName);
return;
}
}
- write(JSRoyaleEmitterTokens.VECTOR);
+ Boolean written = false;
+ if (node instanceof TypedExpressionNode) {
+ startMapping(node);
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(JSRoyaleEmitterTokens.SYNTH_VECTOR);
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ //the element type of the Vector:
+ write(formatQualifiedName(node.getTypeNode().resolve(project).getQualifiedName()));
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ endMapping(node);
+ written = true;
+ }
+
+ if (!written) {
+ write(JSRoyaleEmitterTokens.VECTOR);
+ }
if (getModel().inStaticInitializer)
{
if (!staticUsedNames.contains(JSRoyaleEmitterTokens.LANGUAGE_QNAME.getToken()))
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleEmitterTokens.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleEmitterTokens.java
index 20bc298..d0ad79f 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleEmitterTokens.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleEmitterTokens.java
@@ -35,6 +35,7 @@ public enum JSRoyaleEmitterTokens implements IEmitterTokens
ROYALE_CLASS_INFO_CLASS_KIND("class"),
ROYALE_CLASS_INFO_INTERFACE_KIND("interface"),
ROYALE_CLASS_INFO_IS_DYNAMIC("isDynamic"),
+ ROYALE_SYNTH_TAG_FIELD_NAME("SYNTH_TAG_FIELD"),
GOOG_EXPORT_PROPERTY("goog.exportProperty"),
GOOG_EXPORT_SYMBOL("goog.exportSymbol"),
INDENT(" "),
@@ -49,7 +50,12 @@ public enum JSRoyaleEmitterTokens implements IEmitterTokens
IGNORE_COERCION("@royaleignorecoercion"),
IGNORE_IMPORT("@royaleignoreimport"),
IGNORE_STRING_COERCION("@royalenoimplicitstringconversion"),
+ SUPPRESS_EXPORT("@royalesuppressexport"),
+ SUPPRESS_CLOSURE("@royalesuppressclosure"),
SUPPRESS_PUBLIC_VAR_WARNING("@royalesuppresspublicvarwarning"),
+ SUPPRESS_COMPLEX_IMPLICIT_COERCION("@royalesuppresscompleximplicitcoercion"),
+ SUPPRESS_RESOLVE_UNCERTAIN("@royalesuppressresolveuncertain"),
+ SUPPRESS_VECTOR_INDEX_CHECK("@royalesuppressvectorindexcheck"),
DEBUG_COMMENT("@royaledebug"),
DEBUG_RETURN("if(!goog.DEBUG)return;"),
PREINCREMENT("preincrement"),
@@ -65,7 +71,10 @@ public enum JSRoyaleEmitterTokens implements IEmitterTokens
SKIP_AS_COERCIONS("skipAsCoercions"),
SKIP_FUNCTION_COERCIONS("skipFunctionCoercions"),
JSX("JSX"),
- VECTOR("org.apache.royale.utils.Language.Vector"),
+ VECTOR(LANGUAGE_QNAME.getToken() + ".Vector"),
+ SYNTH_TYPE(LANGUAGE_QNAME.getToken() + ".synthType"),
+ SYNTH_VECTOR(LANGUAGE_QNAME.getToken() + ".synthVector"),
+ VECTOR_INDEX_CHECK_METHOD_NAME(LANGUAGE_QNAME.getToken() + ".CHECK_INDEX"),
;
private String token;
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/utils/DocEmitterUtils.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/utils/DocEmitterUtils.java
index dd9ed44..2e03bb0 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/utils/DocEmitterUtils.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/utils/DocEmitterUtils.java
@@ -46,4 +46,13 @@ public class DocEmitterUtils
// TODO (mschmalle)
((JSRoyaleDocEmitter)emitter.getDocEmitter()).setClassIgnoreList(ignoreList);
}
+
+
+ public static Boolean hasSuppressExport(JSRoyaleEmitter emitter, String doc)
+ {
+
+ String ignoreToken = JSRoyaleEmitterTokens.SUPPRESS_EXPORT.getToken();
+ int index = doc.indexOf(ignoreToken);
+ return index != -1;
+ }
}
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleJSProject.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleJSProject.java
index 06348a5..42e647c 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleJSProject.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleJSProject.java
@@ -39,6 +39,7 @@ import org.apache.royale.compiler.config.Configurator;
import org.apache.royale.compiler.css.ICSSMediaQueryCondition;
import org.apache.royale.compiler.css.ICSSRule;
import org.apache.royale.compiler.definitions.IDefinition;
+import org.apache.royale.compiler.definitions.IFunctionDefinition;
import org.apache.royale.compiler.definitions.ITypeDefinition;
import org.apache.royale.compiler.definitions.metadata.IMetaTag;
import org.apache.royale.compiler.definitions.metadata.IMetaTagAttribute;
@@ -116,7 +117,7 @@ public class RoyaleJSProject extends RoyaleProject
if (defNode instanceof IClassNode || defNode instanceof IInterfaceNode)
{
String defname = def.getQualifiedName();
- IASDocComment asDoc = (defNode instanceof IClassNode) ?
+ IASDocComment asDoc = (defNode instanceof IClassNode) ?
(IASDocComment) ((IClassNode)defNode).getASDocComment() :
(IASDocComment) ((IInterfaceNode)defNode).getASDocComment();
if (asDoc != null && (asDoc instanceof ASDocComment))
@@ -163,7 +164,7 @@ public class RoyaleJSProject extends RoyaleProject
super.addDependency(from, to, dt, qname);
}
- private synchronized void updateRequiresMap(ICompilationUnit from, ICompilationUnit to,
+ private synchronized void updateRequiresMap(ICompilationUnit from, ICompilationUnit to,
DependencyType dt, String qname)
{
HashMap<String, DependencyType> reqs;
@@ -188,10 +189,10 @@ public class RoyaleJSProject extends RoyaleProject
if (qname.equals("XML"))
needXML = true;
reqs.put(qname, dt);
- }
+ }
}
- private synchronized void updateJSModulesMap(ICompilationUnit from, ICompilationUnit to,
+ private synchronized void updateJSModulesMap(ICompilationUnit from, ICompilationUnit to,
DependencyType dt, String qname)
{
HashMap<String, DependencyType> reqs;
@@ -219,7 +220,7 @@ public class RoyaleJSProject extends RoyaleProject
}
}
- private synchronized void updateInterfacesMap(ICompilationUnit from, ICompilationUnit to,
+ private synchronized void updateInterfacesMap(ICompilationUnit from, ICompilationUnit to,
DependencyType dt, String qname)
{
HashMap<String, String> interfacesArr;
@@ -530,6 +531,15 @@ public class RoyaleJSProject extends RoyaleProject
}
return false;
}
+
+ @Override
+ public boolean isParameterCountMismatchAllowed(IFunctionDefinition func,
+ int formalCount, int actualCount) {
+ if ((func.getBaseName().equals("int") || func.getBaseName().equals("uint")) && func.isConstructor()) {
+ if (actualCount == 1) return true;
+ }
+ return super.isParameterCountMismatchAllowed(func, formalCount, actualCount);
+ }
/**
* List of compiler defines so it can be overridden
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/utils/JSClosureCompilerWrapper.java b/compiler-jx/src/main/java/org/apache/royale/compiler/utils/JSClosureCompilerWrapper.java
index 74e1bb6..8d8ace0 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/utils/JSClosureCompilerWrapper.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/utils/JSClosureCompilerWrapper.java
@@ -356,6 +356,8 @@ public class JSClosureCompilerWrapper
"playerversion", "langversion", "copy", "span", "para", "throw", "tiptext",
"asparam", "asreturn", "asreturns", "asprivate",
"royaleignoreimport", "royaleignorecoercion", "royaleemitcoercion",
+ "royalesuppresscompleximplicitcoercion","royalesuppressresolveuncertain",
+ "royalesuppressvectorindexcheck","royalesuppressexport", "royalesuppressclosure",
"royalenoimplicitstringconversion","royaledebug"};
options_.setExtraAnnotationNames(Arrays.asList(asdocTags));
}
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/utils/NativeUtils.java b/compiler-jx/src/main/java/org/apache/royale/compiler/utils/NativeUtils.java
index 0653542..8ff320a 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/utils/NativeUtils.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/utils/NativeUtils.java
@@ -122,8 +122,8 @@ public class NativeUtils
unescape("unescape"),
window("window"),
- // (erikdebruin) These aren't strictly 'native' to JS, but the
- // Publisher provides global functions, so, for all
+ // (erikdebruin) These aren't strictly 'native' to JS, but the
+ // Publisher provides global functions, so, for all
// intends and purposes they behave like they are.
_int("int"),
trace("trace"),
@@ -154,6 +154,26 @@ public class NativeUtils
}
}
+ public enum SyntheticJSType
+ {
+ _int("int"),
+ uint("uint"),
+ Vector("Vector"),
+ Class("Class");
+
+ private final String value;
+
+ SyntheticJSType(String value)
+ {
+ this.value = value;
+ }
+
+ public String getValue()
+ {
+ return value;
+ }
+ }
+
public static boolean isNative(String type)
{
for (NativeASType test : NativeASType.values())
@@ -175,5 +195,24 @@ public class NativeUtils
}
return false;
}
+
+ public static boolean isSyntheticJSType(String type)
+ {
+ for (SyntheticJSType test : SyntheticJSType.values())
+ {
+ if (test.getValue().equals(type)) {
+ return true;
+ }
+ }
+ if (type.startsWith("Vector.<")) {
+ return true;
+ }
+ return false;
+ }
+
+ public static boolean isVector(String type)
+ {
+ return type != null && type.startsWith("Vector.<");
+ }
}
diff --git a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/goog/TestGoogFieldMembers.java b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/goog/TestGoogFieldMembers.java
index 9bb864d..a1318d4 100644
--- a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/goog/TestGoogFieldMembers.java
+++ b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/goog/TestGoogFieldMembers.java
@@ -97,7 +97,7 @@ public class TestGoogFieldMembers extends TestFieldMembers
{
IVariableNode node = getField("protected var foo:Vector.<Foo>;");
asBlockWalker.visitVariable(node);
- assertOut("/**\n * @protected\n * @type {Vector.<Foo>}\n */\nRoyaleTest_A.prototype.foo");
+ assertOut("/**\n * @protected\n * @type {Array.<Foo>}\n */\nRoyaleTest_A.prototype.foo");
}
@Override
@@ -106,7 +106,7 @@ public class TestGoogFieldMembers extends TestFieldMembers
{
IVariableNode node = getField("protected var foo:Vector.<Vector.<Vector.<Foo>>>;");
asBlockWalker.visitVariable(node);
- assertOut("/**\n * @protected\n * @type {Vector.<Vector.<Vector.<Foo>>>}\n */\nRoyaleTest_A.prototype.foo");
+ assertOut("/**\n * @protected\n * @type {Array.<Array.<Array.<Foo>>>}\n */\nRoyaleTest_A.prototype.foo");
}
@Override
diff --git a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/goog/TestGoogGlobalClasses.java b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/goog/TestGoogGlobalClasses.java
index 0bf0f4a..28aab2a 100644
--- a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/goog/TestGoogGlobalClasses.java
+++ b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/goog/TestGoogGlobalClasses.java
@@ -271,7 +271,7 @@ public class TestGoogGlobalClasses extends TestGlobalClasses
{
IVariableNode node = getVariable("var a:Vector.<String> = new Vector.<String>(['Hello', 'World']);");
asBlockWalker.visitVariable(node);
- assertOut("var /** @type {Vector.<string>} */ a = new Array(['Hello', 'World'])");
+ assertOut("var /** @type {Array.<string>} */ a = new Array(['Hello', 'World'])");
}
@Override
diff --git a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/goog/TestGoogGlobalFunctions.java b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/goog/TestGoogGlobalFunctions.java
index 107c1bc..f979f20 100644
--- a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/goog/TestGoogGlobalFunctions.java
+++ b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/goog/TestGoogGlobalFunctions.java
@@ -212,7 +212,7 @@ public class TestGoogGlobalFunctions extends TestGlobalFunctions
{
IVariableNode node = getVariable("var a:Vector.<String> = Vector.<String>(['Hello', 'World']);");
asBlockWalker.visitVariable(node);
- assertOut("var /** @type {Vector.<string>} */ a = Array(['Hello', 'World'])");
+ assertOut("var /** @type {Array.<string>} */ a = Array(['Hello', 'World'])");
}
@Override
diff --git a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleExpressions.java b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleExpressions.java
index 0b32b4a..55de5e5 100644
--- a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleExpressions.java
+++ b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleExpressions.java
@@ -1220,7 +1220,7 @@ public class TestRoyaleExpressions extends TestGoogExpressions
"public class B {public function b() { function c(f:Function):void {}; var f:Array = [b]; c(f[0]); }}",
IFunctionNode.class, WRAP_LEVEL_PACKAGE);
asBlockWalker.visitFunction(node);
- assertOut("/**\n * @export\n */\nB.prototype.b = function() {\n var self = this;\n function c(f) {\n };\n var /** @type {Array} */ f = [org.apache.royale.utils.Language.closure(this.b, this, 'b')];\n c(f[0]);\n}");
+ assertOut("/**\n * @export\n */\nB.prototype.b = function() {\n var self = this;\n function c(f) {\n };\n var /** @type {Array} */ f = [org.apache.royale.utils.Language.closure(this.b, this, 'b')];\n c(/* implicit cast */ org.apache.royale.utils.Language.as(f[0], Function, true));\n}");
}
@Test
@@ -1272,7 +1272,7 @@ public class TestRoyaleExpressions extends TestGoogExpressions
IFunctionNode.class, WRAP_LEVEL_PACKAGE, true);
asBlockWalker.visitFunction(node);
// String.length is a getter but is a property in JS, so don't generate set_length() call.
- assertOut("/**\n * @export\n * @return {number}\n */\nfoo.bar.B.prototype.b = function() {\n var /** @type {Array} */ a = null;\n return a.length;\n}");
+ assertOut("/**\n * @export\n * @return {number}\n */\nfoo.bar.B.prototype.b = function() {\n var /** @type {Array.<string>} */ a = null;\n return a.length;\n}");
}
//----------------------------------
@@ -1512,7 +1512,7 @@ public class TestRoyaleExpressions extends TestGoogExpressions
{
IBinaryOperatorNode node = getBinaryNode("a as int");
asBlockWalker.visitBinaryOperator(node);
- assertOut("org.apache.royale.utils.Language.as(a, Number)");
+ assertOut("org.apache.royale.utils.Language.as(a, org.apache.royale.utils.Language.synthType('int'))");
}
@Test
@@ -1520,7 +1520,7 @@ public class TestRoyaleExpressions extends TestGoogExpressions
{
IBinaryOperatorNode node = getBinaryNode("a as uint");
asBlockWalker.visitBinaryOperator(node);
- assertOut("org.apache.royale.utils.Language.as(a, Number)");
+ assertOut("org.apache.royale.utils.Language.as(a, org.apache.royale.utils.Language.synthType('uint'))");
}
@Test
@@ -1530,7 +1530,7 @@ public class TestRoyaleExpressions extends TestGoogExpressions
"public class B {private var memberVar:Class; public function b(o:Object):int { var a:B = null; a = o as memberVar; }}",
IFunctionNode.class, WRAP_LEVEL_PACKAGE, true);
asBlockWalker.visitFunction(node);
- assertOut("/**\n * @export\n * @param {Object} o\n * @return {number}\n */\nfoo.bar.B.prototype.b = function(o) {\n var /** @type {foo.bar.B} */ a = null;\n a = org.apache.royale.utils.Language.as(o, this.memberVar);\n}");
+ assertOut("/**\n * @export\n * @param {Object} o\n * @return {number}\n */\nfoo.bar.B.prototype.b = function(o) {\n var /** @type {foo.bar.B} */ a = null;\n a = /* implicit cast */ org.apache.royale.utils.Language.as(org.apache.royale.utils.Language.as(o, this.memberVar), foo.bar.B, true);\n}");
}
@Test
diff --git a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleFieldMembers.java b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleFieldMembers.java
index b8be801..5a8af9a 100644
--- a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleFieldMembers.java
+++ b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleFieldMembers.java
@@ -139,7 +139,7 @@ public class TestRoyaleFieldMembers extends TestGoogFieldMembers
{
IVariableNode node = getField("protected var foo:Vector.<Foo>;");
asBlockWalker.visitVariable(node);
- assertOut("/**\n * @protected\n * @type {Array}\n */\nRoyaleTest_A.prototype.foo");
+ assertOut("/**\n * @protected\n * @type {Array.<Foo>}\n */\nRoyaleTest_A.prototype.foo");
}
@Override
@@ -148,7 +148,7 @@ public class TestRoyaleFieldMembers extends TestGoogFieldMembers
{
IVariableNode node = getField("protected var foo:Vector.<Vector.<Vector.<Foo>>>;");
asBlockWalker.visitVariable(node);
- assertOut("/**\n * @protected\n * @type {Array}\n */\nRoyaleTest_A.prototype.foo");
+ assertOut("/**\n * @protected\n * @type {Array.<Array.<Array.<Foo>>>}\n */\nRoyaleTest_A.prototype.foo");
}
@Override
diff --git a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleGlobalClasses.java b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleGlobalClasses.java
index 4f590d3..15b8dd6 100644
--- a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleGlobalClasses.java
+++ b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleGlobalClasses.java
@@ -287,6 +287,16 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
asBlockWalker.visitVariable(node);
assertOut("var /** @type {number} */ a = Math[\"PI\"]");
}
+
+ @Override
+ @Test
+ public void testClass()
+ {
+ IVariableNode node = getVariable("var a:Class = String; var b:* = new a('test')");
+ node = (IVariableNode)(node.getParent().getChild(1));
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {*} */ b = org.apache.royale.utils.Language.resolveUncertain(new a('test'))");
+ }
@Test
public void testDateSetSeconds()
@@ -379,7 +389,7 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
IVariableNode node = getVariable("var a:Vector.<String> = new Vector.<String>(['Hello', 'World']);");
asBlockWalker.visitVariable(node);
//MXMLC does not report an error. Should we?
- assertOut("var /** @type {Array} */ a = org.apache.royale.utils.Language.Vector(['Hello', 'World'], 'String')");
+ assertOut("var /** @type {Array.<string>} */ a = new (org.apache.royale.utils.Language.synthVector('String'))(['Hello', 'World'])");
}
@Test
@@ -387,7 +397,7 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
{
IVariableNode node = getVariable("var a:Vector.<String> = new <String>[];");
asBlockWalker.visitVariable(node);
- assertOut("var /** @type {Array} */ a = []");
+ assertOut("var /** @type {Array.<string>} */ a = org.apache.royale.utils.Language.synthVector('String')['coerce']([])");
}
@Test
@@ -395,7 +405,7 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
{
IVariableNode node = getVariable("var a:Vector.<int> = new <int>[0, 1, 2, 3];");
asBlockWalker.visitVariable(node);
- assertOut("var /** @type {Array} */ a = [0, 1, 2, 3]");
+ assertOut("var /** @type {Array.<number>} */ a = org.apache.royale.utils.Language.synthVector('int')['coerce']([0, 1, 2, 3])");
}
@Test
@@ -403,7 +413,7 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
{
IVariableNode node = getVariable("var a:Vector.<String> = new <String>[\"one\", \"two\", \"three\";");
asBlockWalker.visitVariable(node);
- assertOut("var /** @type {Array} */ a = [\"one\", \"two\", \"three\"]");
+ assertOut("var /** @type {Array.<string>} */ a = org.apache.royale.utils.Language.synthVector('String')['coerce']([\"one\", \"two\", \"three\"])");
}
@Test
@@ -411,7 +421,7 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
{
IVariableNode node = getVariable("var a:Vector.<String> = new Vector.<String>();");
asBlockWalker.visitVariable(node);
- assertOut("var /** @type {Array} */ a = org.apache.royale.utils.Language.Vector()");
+ assertOut("var /** @type {Array.<string>} */ a = new (org.apache.royale.utils.Language.synthVector('String'))()");
}
@Test
@@ -420,7 +430,7 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
IVariableNode node = getVariable("var a:Vector.<String> = new Vector.<String>('Hello', 'World');");
asBlockWalker.visitVariable(node);
//MXMLC does not report an error. Should we?
- assertOut("var /** @type {Array} */ a = org.apache.royale.utils.Language.Vector('Hello', 'String')");
+ assertOut("var /** @type {Array.<string>} */ a = new (org.apache.royale.utils.Language.synthVector('String'))('Hello', 'World')");
}
@Test
@@ -429,7 +439,7 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
IVariableNode node = getVariable("var a:Vector.<String> = new Vector.<String>('Hello', 'World', 'Three');");
asBlockWalker.visitVariable(node);
//MXMLC does not report an error. Should we?
- assertOut("var /** @type {Array} */ a = org.apache.royale.utils.Language.Vector('Hello', 'String')");
+ assertOut("var /** @type {Array.<string>} */ a = new (org.apache.royale.utils.Language.synthVector('String'))('Hello', 'World', 'Three')");
}
@Test
@@ -437,7 +447,7 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
{
IVariableNode node = getVariable("var a:Vector.<String> = new Vector.<String>(30);");
asBlockWalker.visitVariable(node);
- assertOut("var /** @type {Array} */ a = org.apache.royale.utils.Language.Vector(30, 'String')");
+ assertOut("var /** @type {Array.<string>} */ a = new (org.apache.royale.utils.Language.synthVector('String'))(30)");
}
@Test
@@ -446,7 +456,7 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
IVariableNode node = getVariable("var a:Vector.<String> = new Vector.<String>(30, 40);");
asBlockWalker.visitVariable(node);
//MXMLC does not report an error. Should we?
- assertOut("var /** @type {Array} */ a = org.apache.royale.utils.Language.Vector(30, 'String')");
+ assertOut("var /** @type {Array.<string>} */ a = new (org.apache.royale.utils.Language.synthVector('String'))(30, 40)");
}
@Test
@@ -455,7 +465,24 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
IVariableNode node = getVariable("var a:Vector.<String> = new Vector.<String>(['Hello', 'World']);");
asBlockWalker.visitVariable(node);
//MXMLC does not report an error. Should we?
- assertOut("var /** @type {Array} */ a = org.apache.royale.utils.Language.Vector(['Hello', 'World'], 'String')");
+ assertOut("var /** @type {Array.<string>} */ a = new (org.apache.royale.utils.Language.synthVector('String'))(['Hello', 'World'])");
+ }
+
+ @Test
+ public void testVectorSetLength()
+ {
+ IBinaryOperatorNode node = getBinaryNode("var a:Vector.<String> = new Vector.<String>(); a.length = 20)");
+ asBlockWalker.visitBinaryOperator(node);
+ assertOut("a[org.apache.royale.utils.Language.SYNTH_TAG_FIELD].length = 20");
+ }
+
+ @Test
+ public void testCustomVectorSetLength()
+ {
+ project.config.setJsVectorEmulationClass(null, "Anything");
+ IBinaryOperatorNode node = getBinaryNode("var a:Vector.<String> = new Vector.<String>(); a.length = 20)");
+ asBlockWalker.visitBinaryOperator(node);
+ assertOut("a.length = 20");
}
@Test
@@ -468,9 +495,30 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
IBinaryOperatorNode node = getBinaryNode("var a:Vector.<String> = new Vector.<String>(); a.removeAt(2)");
IFunctionCallNode parentNode = (IFunctionCallNode)(node.getParent());
asBlockWalker.visitFunctionCall(parentNode);
- assertOut("a.splice(2, 1)");
+ assertOut("a['removeAt'](2)");
}
}
+
+ @Test
+ public void testCustomVectorRemoveAt()
+ {
+ project.config.setJsVectorEmulationClass(null, "CustomVector");
+ IBinaryOperatorNode node = getBinaryNode("var a:Vector.<String> = new Vector.<String>(); a.removeAt(2)");
+ IFunctionCallNode parentNode = (IFunctionCallNode)(node.getParent());
+ asBlockWalker.visitFunctionCall(parentNode);
+ assertOut("a.removeAt(2)");
+ }
+
+ @Test
+ public void testCustomVectorAsArrayRemoveAt()
+ {
+
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IBinaryOperatorNode node = getBinaryNode("var a:Vector.<String> = new Vector.<String>(); a.removeAt(2)");
+ IFunctionCallNode parentNode = (IFunctionCallNode)(node.getParent());
+ asBlockWalker.visitFunctionCall(parentNode);
+ assertOut("a.splice(2, 1)");
+ }
@Test
public void testVectorInsertAt()
@@ -482,9 +530,29 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
IBinaryOperatorNode node = getBinaryNode("var a:Vector.<String> = new Vector.<String>(); a.insertAt(2, 'foo')");
IFunctionCallNode parentNode = (IFunctionCallNode)(node.getParent());
asBlockWalker.visitFunctionCall(parentNode);
- assertOut("a.splice(2, 0, 'foo')");
+ assertOut("a['insertAt'](2, 'foo')");
}
}
+
+ @Test
+ public void testCustomVectorInsertAt()
+ {
+ project.config.setJsVectorEmulationClass(null, "CustomVector");
+ IBinaryOperatorNode node = getBinaryNode("var a:Vector.<String> = new Vector.<String>(); a.insertAt(2, 'foo')");
+ IFunctionCallNode parentNode = (IFunctionCallNode)(node.getParent());
+ asBlockWalker.visitFunctionCall(parentNode);
+ assertOut("a.insertAt(2, 'foo')");
+ }
+
+ @Test
+ public void testCustomVectorAsArrayInsertAt()
+ {
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IBinaryOperatorNode node = getBinaryNode("var a:Vector.<String> = new Vector.<String>(); a.insertAt(2, 'foo')");
+ IFunctionCallNode parentNode = (IFunctionCallNode)(node.getParent());
+ asBlockWalker.visitFunctionCall(parentNode);
+ assertOut("a.splice(2, 0, 'foo')");
+ }
@Test
public void testCustomVector()
@@ -504,6 +572,15 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
asBlockWalker.visitVariable(node);
assertOut("var /** @type {CustomVector} */ a = new CustomVector([], 'String')");
}
+
+ @Test
+ public void testCustomVectorLiteral_1a()
+ {
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IVariableNode node = getVariable("var a:Vector.<String> = new <String>[];");
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {Array} */ a = []");
+ }
@Test
public void testCustomVectorLiteral_2()
@@ -513,17 +590,35 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
asBlockWalker.visitVariable(node);
assertOut("var /** @type {CustomVector} */ a = new CustomVector([0, 1, 2, 3], 'int')");
}
+
+ @Test
+ public void testCustomVectorLiteral_2a()
+ {
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IVariableNode node = getVariable("var a:Vector.<int> = new <int>[0, 1, 2, 3];");
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {Array} */ a = [0, 1, 2, 3]");
+ }
@Test
public void testCustomVectorLiteral_3()
{
project.config.setJsVectorEmulationClass(null, "CustomVector");
- IVariableNode node = getVariable("var a:Vector.<String> = new <String>[\"one\", \"two\", \"three\";");
+ IVariableNode node = getVariable("var a:Vector.<String> = new <String>[\"one\", \"two\", \"three\"];");
asBlockWalker.visitVariable(node);
assertOut("var /** @type {CustomVector} */ a = new CustomVector([\"one\", \"two\", \"three\"], 'String')");
}
@Test
+ public void testCustomVectorLiteral_3a()
+ {
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IVariableNode node = getVariable("var a:Vector.<String> = new <String>[\"one\", \"two\", \"three\"];");
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {Array} */ a = [\"one\", \"two\", \"three\"]");
+ }
+
+ @Test
public void testCustomVectorNoArgs()
{
project.config.setJsVectorEmulationClass(null, "CustomVector");
@@ -531,6 +626,15 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
asBlockWalker.visitVariable(node);
assertOut("var /** @type {CustomVector} */ a = new CustomVector([], 'String')");
}
+
+ @Test
+ public void testCustomVectorNoArgs2()
+ {
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IVariableNode node = getVariable("var a:Vector.<String> = new Vector.<String>();");
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {Array} */ a = []");
+ }
@Test
public void testCustomVectorStringArgs()
@@ -562,6 +666,15 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
}
@Test
+ public void testCustomVectorSizeArg2()
+ {
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IVariableNode node = getVariable("var a:Vector.<String> = new Vector.<String>(30);");
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {Array} */ a = org.apache.royale.utils.Language.arrayAsVector(30, 'String')");
+ }
+
+ @Test
public void testCustomVectorSizeAndFixedArgs()
{
project.config.setJsVectorEmulationClass(null, "CustomVector");
@@ -569,6 +682,15 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
asBlockWalker.visitVariable(node);
assertOut("var /** @type {CustomVector} */ a = new CustomVector(30, 'String', true)");
}
+
+ @Test
+ public void testCustomVectorSizeAndFixedArgs2()
+ {
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IVariableNode node = getVariable("var a:Vector.<String> = new Vector.<String>(30, true);");
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {Array} */ a = org.apache.royale.utils.Language.arrayAsVector(30, 'String')");
+ }
@Test
public void testCustomVectorNumberArgs()
@@ -579,6 +701,16 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
//MXMLC does not report an error. Should we?
assertOut("var /** @type {CustomVector} */ a = new CustomVector(30, 'String')");
}
+
+ @Test
+ public void testCustomVectorNumberArgs2()
+ {
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IVariableNode node = getVariable("var a:Vector.<String> = new Vector.<String>(30, 40);");
+ asBlockWalker.visitVariable(node);
+ //MXMLC does not report an error. Should we?
+ assertOut("var /** @type {Array} */ a = org.apache.royale.utils.Language.arrayAsVector(30, 'String')");
+ }
@Test
public void testCustomVectorArrayArg()
@@ -591,6 +723,99 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
}
@Test
+ public void testCustomVectorArrayArg2()
+ {
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IVariableNode node = getVariable("var a:Vector.<String> = new Vector.<String>(['Hello', 'World']);");
+ asBlockWalker.visitVariable(node);
+ //MXMLC does not report an error. Should we?
+ assertOut("var /** @type {Array} */ a = org.apache.royale.utils.Language.arrayAsVector(['Hello', 'World'], 'String')");
+ }
+
+ @Test
+ public void testDefaultVectorClassRepresentation()
+ {
+ IVariableNode node = getVariable("var a:Class = Vector.<String>;");
+ asBlockWalker.visitVariable(node);
+ //MXMLC does not report an error. Should we?
+ assertOut("var /** @type {Object} */ a = org.apache.royale.utils.Language.synthVector('String')");
+ }
+
+ @Test
+ public void testCustomVectorClassRepresentation()
+ {
+ project.config.setJsVectorEmulationClass(null, "CustomVector");
+ IVariableNode node = getVariable("var a:Class = Vector.<String>;");
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {Object} */ a = CustomVector");
+ }
+
+ @Test
+ public void testCustomVectorClassRepresentation2()
+ {
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IVariableNode node = getVariable("var a:Class = Vector.<String>;");
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {Object} */ a = Array");
+ }
+
+ @Test
+ public void testDefaultVectorSortNumericArg()
+ {
+ IBinaryOperatorNode node = getBinaryNode("var a:Vector.<Number> = new Vector.<Number>();a.sort(Array.NUMERIC)");
+ IFunctionCallNode parentNode = (IFunctionCallNode)(node.getParent());
+ asBlockWalker.visitFunctionCall(parentNode);
+ assertOut("org.apache.royale.utils.Language.sort(a, 16)");
+ }
+
+ @Test
+ public void testCustomVectorRepresentationSortNumericArg()
+ {
+ project.config.setJsVectorEmulationClass(null, "CustomVector");
+ IBinaryOperatorNode node = getBinaryNode("var a:Vector.<Number> = new Vector.<Number>();a.sort(Array.NUMERIC)");
+ IFunctionCallNode parentNode = (IFunctionCallNode)(node.getParent());
+ asBlockWalker.visitFunctionCall(parentNode);
+ assertOut("a.sort(16)");
+ }
+
+ @Test
+ public void testCustomVectorAsArrayRepresentationSortNumericArg()
+ {
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IBinaryOperatorNode node = getBinaryNode("var a:Vector.<Number> = new Vector.<Number>();a.sort(Array.NUMERIC)");
+ IFunctionCallNode parentNode = (IFunctionCallNode)(node.getParent());
+ asBlockWalker.visitFunctionCall(parentNode);
+ assertOut("org.apache.royale.utils.Language.sort(a, 16)");
+ }
+
+ @Override
+ @Test
+ public void testBoolean()
+ {
+ IVariableNode node = getVariable("var a:Boolean = new Boolean(1);");
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {boolean} */ a = Boolean(1)");
+ }
+
+ @Override
+ @Test
+ public void testNumber()
+ {
+ IVariableNode node = getVariable("var a:Number = new Number(\"1\");");
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {number} */ a = Number(\"1\")");
+ }
+
+ @Override
+ @Test
+ public void testString()
+ {
+ IVariableNode node = getVariable("var a:String = new String(\"100\");");
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {string} */ a = String(\"100\")");
+ }
+
+ @Test
public void testXML()
{
IVariableNode node = getVariable("var a:XML = new XML(\"<top attr1='cat'><child attr2='dog'><grandchild attr3='fish'>text</grandchild></child></top>\");");
diff --git a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleGlobalFunctions.java b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleGlobalFunctions.java
index 8f2f9d1..5f8b6b2 100644
--- a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleGlobalFunctions.java
+++ b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleGlobalFunctions.java
@@ -100,6 +100,15 @@ public class TestRoyaleGlobalFunctions extends TestGoogGlobalFunctions
asBlockWalker.visitVariable(node);
assertOut("var /** @type {Array} */ a = Array(['Hello', 'World'])");
}
+
+ @Override
+ @Test
+ public void testObject()
+ {
+ IVariableNode node = getVariable("var a:Object = Object(\"1\");");
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {Object} */ a = org.apache.royale.utils.Language.resolveUncertain(Object(\"1\"))");
+ }
@Test
public void testParseInt()
@@ -159,6 +168,24 @@ public class TestRoyaleGlobalFunctions extends TestGoogGlobalFunctions
{
IVariableNode node = getVariable("var a:Vector.<String> = Vector.<String>(['Hello', 'World']);");
asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {Array.<string>} */ a = org.apache.royale.utils.Language.synthVector('String')['coerce'](['Hello', 'World'])");
+ }
+
+ @Test
+ public void testCustomVector()
+ {
+ project.config.setJsVectorEmulationClass(null, "CustomVector");
+ IVariableNode node = getVariable("var a:Vector.<String> = Vector.<String>(['Hello', 'World']);");
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {CustomVector} */ a = new CustomVector(['Hello', 'World'], 'String')");
+ }
+
+ @Test
+ public void testCustomVectorAsArray()
+ {
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IVariableNode node = getVariable("var a:Vector.<String> = Vector.<String>(['Hello', 'World']);");
+ asBlockWalker.visitVariable(node);
assertOut("var /** @type {Array} */ a = ['Hello', 'World'].slice()");
}
@@ -184,8 +211,29 @@ public class TestRoyaleGlobalFunctions extends TestGoogGlobalFunctions
IVariableNode node = getVariable("var a:Vector.<String> = Vector.<String>(30);");
asBlockWalker.visitVariable(node);
// MXMLC doesn't report an error either. Maybe we should.
+ assertOut("var /** @type {Array.<string>} */ a = org.apache.royale.utils.Language.synthVector('String')['coerce'](30)");
+ }
+
+ @Test
+ public void testCustomVectorSizeArg()
+ {
+ project.config.setJsVectorEmulationClass(null, "CustomVector");
+ IVariableNode node = getVariable("var a:Vector.<String> = Vector.<String>(30);");
+ asBlockWalker.visitVariable(node);
+ // MXMLC doesn't report an error either. Maybe we should.
+ assertOut("var /** @type {CustomVector} */ a = new CustomVector(30, 'String')");
+ }
+
+ @Test
+ public void testCustomVectorAsArraySizeArg()
+ {
+ project.config.setJsVectorEmulationClass(null, "Array");
+ IVariableNode node = getVariable("var a:Vector.<String> = Vector.<String>(30);");
+ asBlockWalker.visitVariable(node);
+ // MXMLC doesn't report an error either. Maybe we should.
assertOut("var /** @type {Array} */ a = 30.slice()");
}
+
@Test
public void testVectorNumberArgs()
@@ -200,7 +248,7 @@ public class TestRoyaleGlobalFunctions extends TestGoogGlobalFunctions
{
IVariableNode node = getVariable("var a:Vector.<String> = Vector.<String>(['Hello', 'World']);");
asBlockWalker.visitVariable(node);
- assertOut("var /** @type {Array} */ a = ['Hello', 'World'].slice()");
+ assertOut("var /** @type {Array.<string>} */ a = org.apache.royale.utils.Language.synthVector('String')['coerce'](['Hello', 'World'])");
}
@Override
diff --git a/compiler/src/main/java/org/apache/royale/compiler/internal/tree/as/DynamicAccessNode.java b/compiler/src/main/java/org/apache/royale/compiler/internal/tree/as/DynamicAccessNode.java
index b616b9d..8df9fae 100644
--- a/compiler/src/main/java/org/apache/royale/compiler/internal/tree/as/DynamicAccessNode.java
+++ b/compiler/src/main/java/org/apache/royale/compiler/internal/tree/as/DynamicAccessNode.java
@@ -21,6 +21,7 @@ package org.apache.royale.compiler.internal.tree.as;
import org.apache.royale.compiler.definitions.IAppliedVectorDefinition;
import org.apache.royale.compiler.definitions.ITypeDefinition;
+import org.apache.royale.compiler.internal.semantics.SemanticUtils;
import org.apache.royale.compiler.projects.ICompilerProject;
import org.apache.royale.compiler.tree.ASTNodeID;
import org.apache.royale.compiler.tree.as.IDynamicAccessNode;
@@ -86,8 +87,10 @@ public class DynamicAccessNode extends BinaryOperatorNodeBase implements IDynami
ITypeDefinition leftType = getLeftOperandNode().resolveType(project);
if (leftType instanceof IAppliedVectorDefinition)
{
- IAppliedVectorDefinition vectorDef = (IAppliedVectorDefinition) leftType;
- return vectorDef.resolveElementType(project);
+ if (SemanticUtils.isNumericType(getRightOperandNode().resolveType(project), project)) {
+ IAppliedVectorDefinition vectorDef = (IAppliedVectorDefinition) leftType;
+ return vectorDef.resolveElementType(project);
+ }
}
return super.resolveType(project);
}
diff --git a/royale-ant-tasks/src/main/java/org/apache/royale/compiler/ant/FlexTask.java b/royale-ant-tasks/src/main/java/org/apache/royale/compiler/ant/FlexTask.java
index 79f7060..40e119f 100644
--- a/royale-ant-tasks/src/main/java/org/apache/royale/compiler/ant/FlexTask.java
+++ b/royale-ant-tasks/src/main/java/org/apache/royale/compiler/ant/FlexTask.java
@@ -308,9 +308,9 @@ public abstract class FlexTask extends Java
try
{
- Method toolMethod = toolClass.getMethod(toolMethodName, new Class[] {String[].class});
+ Method toolMethod = toolClass.getMethod(toolMethodName, String[].class);
Object result = toolMethod.invoke(null, new Object[] {cmdline.getArguments()});
- exitCode = ((Integer)result).intValue();
+ exitCode = ((Integer)result);
}
catch (Exception e)
{
@@ -337,9 +337,9 @@ public abstract class FlexTask extends Java
try
{
- Method toolFailureMethod = toolClass.getMethod(toolFailureMethodName, new Class[] {int.class});
- Object result = toolFailureMethod.invoke(null, new Object[] {exitCode});
- fatal = ((Boolean)result).booleanValue();
+ Method toolFailureMethod = toolClass.getMethod(toolFailureMethodName, int.class);
+ Object result = toolFailureMethod.invoke(null, exitCode);
+ fatal = ((Boolean)result);
}
catch (Exception e)
{
diff --git a/royale-maven-plugin/src/main/java/org/apache/royale/maven/BaseMojo.java b/royale-maven-plugin/src/main/java/org/apache/royale/maven/BaseMojo.java
index 74af100..ca1add1 100644
--- a/royale-maven-plugin/src/main/java/org/apache/royale/maven/BaseMojo.java
+++ b/royale-maven-plugin/src/main/java/org/apache/royale/maven/BaseMojo.java
@@ -236,16 +236,22 @@ public abstract class BaseMojo
List<String> args = new LinkedList<String>();
args.add("-load-config=" + configFile.getPath());
if(additionalCompilerOptions != null) {
+ if (additionalCompilerOptions.contains("\n")) {
+ additionalCompilerOptions = additionalCompilerOptions.replace("\n", "");
+ }
if (additionalCompilerOptions.contains(";"))
{
String[] options = additionalCompilerOptions.split(";");
for (String option : options)
{
- args.add(option);
+ if (option.trim().length() > 0)
+ args.add(option.trim());
}
}
- else
- args.add(additionalCompilerOptions);
+ else {
+ if (additionalCompilerOptions.trim().length() > 0)
+ args.add(additionalCompilerOptions.trim());
+ }
}
return args;
}