This document describes the known backward compatibility issues between ActionScript Compiler 2.0 (ASC 2.0) and the legacy compiler. The document also includes features that are no longer available in ASC 2.0 and deprecated features that are no longer supported.
- Stricter: ASC 2.0 emits an error or warning where legacy compilers did not
- More lenient: ASC 2.0 accepts code that legacy compilers did not
- Change in code generation with diagnostic: ASC 2.0 emits code that behaves differently than code emitted by the legacy compiler and issues an error or warning
- Silent change in code generation: ASC 2.0 emits code that behaves differently than code emitted by the legacy compiler without issuing an error or warning
- Diagnostic change: ASC 2.0 emits different diagnostics than the legacy compiler
These changes are for greater conformance with the ActionScript 3.0 Language Specification. The legacy compiler had bugs that allowed code to circumvent the language rules, these bugs have been addressed in ASC 2.0.
This document includes information related to:
Behavior change |
Behavior in legacy compiler |
Behavior in ASC 2.0 |
When will you encounter this issue? |
Severity of change |
'public', 'private', and 'protected' are now keywords |
'public', 'private', and 'protected' were contextually reserved identifiers. They could be used in some places, such as in a member expression. |
'public', 'private', and 'protected' are now keywords, and will be interpreted as such no matter where they are used. That is, certain usages allowed by the legacy compiler, like in a member expression, will now be disallowed. |
When you use 'public' in a member expression:
a.public = "foo"; |
Stricter |
'internal' is now a keyword, and is treated the same as 'public', 'protected', or 'private' |
'internal' was not a keyword and could be used as an identifier, such as the name of a variable. |
'internal' is now a keyword and a parse error is generated if you try to use it as an identifier. |
When you use 'internal' as an identifier, such as in a var declaration: var internal:String; |
Stricter |
Curly braces are required for config blocks |
You can define code in config blocks as follows: CONFIG::debug import foo.debug.*; |
ASC 2.0 reports a syntax error if you don't use curly braces. You need to enclose the code within curly braces as follows: CONFIG::debug |
When you use a config block without curly braces |
Stricter |
Vector only allows one type parameter |
You can specify multiple type parameters, and the extra ones would just be ignored. |
A syntax error occurs. |
When you specify multiple type of parameters for a Vector: var x:Vector.<String, int>; |
Stricter |
'default' cannot be used as an identifier name |
You can define code as follows: var x = <{default} /> However, a runtime error occurs. |
The following syntax error occurs: "Expecting identifier but found keyword 'default'." |
When you use the keyword 'default' as an identifier name embedded in XML literals.
|
Stricter |
Warn when local variable has the same name as function argument |
You do not receive a warning when you define code as follows: function bas(x:int) |
The following warning appears: “Warning 5040: variable definition duplicates function parameter: arg.” |
When you try to redefine a function argument: function bas(x:int) |
Stricter |
Warn on duplicate definitions of local functions |
You do not receive a warning when you define code as follows: function foo() |
The following warning appears: “Warning 1021 : Duplicate function definition: baz” |
When you define duplicate local function definitions as follows: function foo() |
Stricter |
public:: qualifier may now resolve to multiple namespaces depending on the context |
Defining public:: in a package meant public(package-name) |
Defining public:: in a package context now means public(package-name), unnamed public | When you qualify an expression with public:: |
More lenient (some unresolved errors will now resolve), and silent change in code generation |
Type annotations that resolve to locals are detected more consistently in ASC 2.0 |
The compiler would not always give an error if a type annotation resolved to a local, such as in "var String:String". And in some cases, the compiler did not report an error, though it should have. |
ASC 2.0 will always issue the appropriate error if a type annotation does not resolve to a type. |
When you define code that collides with a type as follows: |
Stricter |
Package directives must be first |
Any package directives had to occur before any other code in a file. |
Packages can be declared anywhere in a file, as long as they are declared in a global context (and not nested inside another construct). | When you define a package declaration after some other code. |
More lenient |
Improve constant evaluation |
Not many constants were evaluated at compile time. |
Many more constants are evaluated at compile time. This could change initialization order of classes. Since references to static constants may be replaced by the computed constant values, MyClass.SOME_CONSTANT may not cause MyClass to be statically initialized. |
When referencing static constants and when depending on classes to be initialized in a particular order. |
Silent change in code generation |
More consistent warnings for "scoped to default namespace" |
Only warned on classes and class methods that didn't have namespace specs (like "public") |
ASC 2.0 also warns on namespaces, functions, and variables |
Users will often see this with legacy code. |
Stricter |
Hoist local variables earlier |
Local variables were hoisted as they were encountered. |
All local variables are hoisted before any identifiers are resolved. An identifier in a function will always resolve to a local variable in that function if such a local variable exists. |
When referencing a local variable before its declaration. |
Silent change in code generation |
Evaluate “CONFIG const” expressions correctly |
Initial-value expressions for config constants, like the following, were often not evaluated correctly: CONFIG const myConst = 10 || 0; |
Initial-value expressions for config constants are evaluated correctly, using the same rules as other expressions. |
When using config constant expressions. |
Silent change in code generation |
Strip metadata in debug SWFs |
Metadata was stripped in release SWF files, based on the -keep-as3-metadata option, but not in debug SWF files. | Metadata is stripped in both debug and release SWF files. |
When you use -keep-as3-metadata. |
Silent change in code generation |
Generate fewer classes for embedded assets |
A class was generated for each variable with Embed(...) metadata, even if multiple variables referred to the same embedded asset tag. Embed variables were never equal because they referred to different classes. |
A class is generated for each embedded asset tag. |
When you use embedded assets. |
Silent change in code generation |
Disallow Array and Object literals at the beginning of a statement |
Code like the following is compiled without errors: [1,2].length
|
You get a compiler error: "unbound metadata problem" for:
|
When you define Array literal or Object literal at the beginning of a statement. [1,2].length |
Stricter |
Disallow a for-loop iterator const that conflicts with an existing variable |
Code like the following is compiled without errors: function |
You get the following compiler error: "const x" conflicts with "var x" |
When re-declaring an existing variable as a const loop iterator variable. function |
Stricter |
Disallow a local const that conflicts with a function parameter |
Code like the following is compiled without errors: function f(p:*) |
A compiler error occurs. |
When declaring a local const with the same name as a parameter of the containing function. function f(p:*) |
Stricter |
Disallow void as an expression |
Code like the following is compiled without errors: foo(void) |
The following compiler error occurs: Syntax error: "void" is not allowed here. |
When you use void as an expression instead of a type annotation or an operator: foo(void) |
Stricter |
Disallow a function definition in a 'with' statement without a curly block |
Code like the following is compiled without errors: with(...) function x() {} |
The following compiler error occurs: Syntax error: "function" is not allowed here. |
When defining a function using a 'with' statement without curly braces: with(...) function x() {} |
Stricter |
Allow an anonymous function as an expression statement |
The following compiler error occurs: Syntax error: Expecting identifier before "(". |
No compiler error. |
When defining an anonymous function without assigning it to any variable. |
More lenient |
Evaluate the left-hand-side of compound assignments only once |
Code like: onlyOnce().a += 1 would run onlyOnce() twice. |
Runs onlyOnce() only once. |
When you write compound assignments with complex left-hand side values, which depend on whether parts of the left-hand side values are evaluated once or twice. |
Silent change in code generation |
Process metadata on global functions |
Code like: [Foo] function bar() did not produce metadata for bar() |
Metadata is produced for bar(). |
When writing metadata on global functions and expecting it to be ignored. |
Silent change in code generation |
Always use "static mode" semantics |
Static semantics were turned on by -strict flag. |
Static semantics are always enabled. |
Trait entries of global and nested functions are allocated as const entries of type Function. Names that can be resolved to a unique definition are written out as QNames. This could be problematic if a program were compiled with one version of a library and run with a different version of that library. |
Stricter |
Allow multiple definitions with the same unqualified name as long as they have disjoint namespaces |
Code like: public class Foo {} produces a compiler error. |
No compiler error occurs. | When you declare multiple definitions with the same unqualified name: public class Foo {} |
Lenient |
Report all ambiguous definitions |
Only the second and subsequent ambiguous definition sites were reported. | All ambiguous definition sites are reported. |
When declaring multiple definitions with the same unqualified name. |
Diagnostic change |
Disallow const / var conflicts |
Code like: var foo; is compiled without errors. The var "overrode" the const. |
A compiler error occurs. The const declaration conflicts with var declaration independent of their order. |
When you declare a const with the same name as a var: var foo; |
Stricter |
Disallow increment/decrement of const |
Code like: const i; is compiled without errors. |
The following compiler error occurs: "Increment operand is invalid." |
When you try to increment or decrement a const: const i; |
Stricter |
Prevent leakage of packages from import statements into other scopes |
While import p.C, p was interpreted as a package later in the file, even outside the scope where the import statement occurred. | p is interpreted as a package only within the scope where the import occurs. |
When you use a fully-qualified type name without an import statement within scope. |
Stricter |
Disallow duplicate fully qualified names in the source path |
No compiler error occurred when there were duplicate names in the source path. However, if the duplicate name is referenced, a "Could not resolve X to a component implementation" error is reported. | The following compiler error occurs: Error: X is defined by multiple files: src/X.mxml, src/X.as
|
When setting the source path of the project. |
Stricter |
Disallow reassignment of a named function |
A named function could be re-assigned a different value. |
The following runtime error occurs: "Error #1074: Illegal write to read-only property factorial on <anonymous>." |
When trying to reassign the value of a named function. |
Stricter |
Disallow metadata that requires runtime evaluation |
Metadata that contained expressions that would need to be evaluated at runtime was completely ignored by the compiler. | A compiler error occurs. A syntax error is generated for metadata constructs that contain function calls or other expressions that do not match the metadata syntax. |
When writing metadata that requires runtime evaluation. |
Stricter |
Disallow invalid Vector assignment |
The compiler did not catch invalid vector type assignment, such as assigning Vector.<int> to Vector.<uint> or Vector.<Number> to Vector.<int>. This would fail at runtime. | A compiler error occurs. |
When assigning one Vector type to another Vector type. |
Stricter |
Allow null to be divided by any value |
Code like: x = null / 2; produced the compiler error: |
No compiler error occurs. |
When attempting to divide null by anything. |
More lenient |
Flow-aware analysis looks inside tautological if/else alternatives |
The legacy compiler was "slightly" flow-aware when it analyzed code; problems in tautologies were ignored. |
A non-flow-aware analysis finds problems in tautologies. |
When you define code like the following: function AClassConstructor() { function f():int |
Stricter |
Disallow classes nested within try, catch, and finally |
The legacy compiler allowed definitions in package-level and file-level try and finally blocks. |
A compiler error occurs. A syntax error occurs when a class is encountered in a try, catch, or finally block. |
When attempting to declare a class nested within a try, catch, or finally block. |
Stricter |
Warn on assignment in any conditional expression |
The legacy compiler only warns for assignment as an immediate child of an if. |
A warning appears if an assignment is used (alone or via Boolean operations) as part of a conditional expression. However, no warning appears if an assignment is part of an arithmetic or comparison expression. | When attempting to use an assignment expression in a conditional, for example, while (x = 3). |
Stricter |
Detect ambiguous base class names caused by import |
The legacy compiler resolved names inside packages as if the package was a defining-scope but it's a weaker opening-scope. |
The compiler identifies ambiguous references caused by importing other package names: "Error: Ambiguous reference to A |
When you define code, like the following, where Base class A is ambiguous: package P1 package P2 |
Stricter |
Initialize constants in locals at their hoist point |
Legacy compiler initialized constants at the point where they were declared. |
The compiler initializes the constant at its definition. |
When you use such a constant: the code emits 5, the legacy compiler emits 3: function test() |
Silent change in code generation |
"goto" is a keyword |
Functions, variables, and classes could be named "goto" |
"goto" is a keyword in ASC 2.0, and thus cannot be used as the name of a definition. |
While compiling AS3 code that uses "goto" as the name of a definition. |
|
Warn about unbound metadata |
The legacy compiler silently ignored metadata that wasn't immediately above a definition. | ASC 2.0 will ignore such metadata but report a warning. |
When writing metadata. |
Stricter |
Issue |
Behavior in legacy compiler |
Behavior in ASC 2.0 |
When will a user encounter this issue? |
Severity of change |
Path resolution rules have changed |
Inconsistent logic for resolving paths. |
The compiler now has a defined path resolution behavior.
|
When using relative paths in configuration, embedded assets, source includes. |
Stricter |
Disallow more ambiguous references |
The old mxmlc and compc did not find certain ambiguous references that the legacy ActionScript compiler found. |
Ambiguous references are correctly found. |
For example, when you declare protected foo and ns foo and do use namespace ns and refer to just foo. |
Stricter |
Disallow URIs for embedded assets |
Code like: Embed(source="http://...") compiles without errors, downloading and embedding the remote asset. |
A compiler error occurs.
The compiler no longer supports URIs as source locations. http:// and {{ file://}} produce an error saying that the source could not be found. |
When you use an URI to specify an embedded asset. |
Stricter |
Change the compc error message when looking for an include-class in the source-path that is not defined |
Code like: foo/bar.as: produces the error: "A file found in a source-path must have an externally visible definition. If a definition in the file is meant to be externally visible, please put the definition in a package." |
The following error occurs: Could not find source for class foo.bar. |
When you use compc to compile a class with no externally visible definitions: |
Diagnostic change |
No longer report the optimized ABC size in link reports |
Generated an optimized size entry in SWF link reports. |
The entry is removed. |
When you use -link-report. |
N/A |