On Fri, Jan 8, 2016 at 1:43 AM, Alex Harui <aha...@adobe.com> wrote: > > But, IMO, for FlexJS, what really matters is what should happen in the JS > output, and the essence of this thread is that in many cases, we can > optimize away the call to Language.as. >
> Right now, "function" casting also results in a Language.as call with a > flag that throws an error if "as" fails. I think we can optimize out a > lot of these calls as well. Here are some different situations to consider: 1.) (x as Foo).bar(a,b); Foo(x).bar(a,b); Can optimize either? MAYBE - you MAY get a different error if x is not of type Foo (possibly "function bar not found on x"). 2.) var y:Foo = x as Foo; var y:Foo = Foo(x); Can optimize "as"? NO - the code is enforcing x to either be null or an instance of Foo. The code that follows is not expecting x to be of any type besides Foo or null. Can optimize (cast)? NO - the code is not expecting to continue if x is not of type Foo. If either cast is removed the code becomes incorrect. 3.) var y = (x as Foo).property; var y = Foo(x).property; Can optimize either? NO - the code should either get the property of an instance of Foo or throw an error. If "as" is optimized out, you can either get the property of an unrelated type, or you can get y=undefined. Either behavior is wrong and could be very hard to track down. The code is not expecting to continue if x is not of type Foo. 4.) (x as Foo).property = value; Foo(x).property = value; Can optimize either? NO - the code should either set the property of an instance of Foo or throw an error. If either cast is removed, you may be setting the property of an unrelated type which will be very hard to track down. The code is not expecting to continue if x is not of type Foo. We may be able to make the distinction between the first case and the rest and optimize out the first call to "as", but since the resulting code is still unpredictable, it should not be the default behavior of the cross-compiler. In all above cases, if Foo is a primitive type, function-style casting can never be optimized out because Foo(x) will actually change the type of x. For example, String(x) will convert null to the String "null". > In the past, we always generated > the call and you could suppress it with @flexjsignorecoercion, but I'm > considering pushing the change where we default to not generating the call > and you have to opt-in with @flexjsemitcoercion. But when you opt-in, we > do want to cause the same behavior that you will get in a SWF. > > A better solution would be to introduce new syntax that always gets optimized out in both AS+JS and only serves the purpose of "making the compiler happy". I suggest the following: (x:Foo) instead of (x as Foo) Examples: (x:Foo).bar(a,b); var y:Foo = x:Foo; var y = (x:Foo).property; (x:Foo).property = value; (obj.prop : Foo).bar(); var y:Number = (a + b):Number; (obj.prop : pkg.name.Foo).bar(); It's easily readable, Action-Scripty, and I believe it can be distinguished from all other syntax, including ternary operator, line labels, and namespacing. I can work on implementing this feature. Maybe someday, we can get the compiler to do > code-flow analysis and determine if we can optimize out these calls to > Language.as, but for now, not having these calls makes the code smaller, > and reduces some of the dependencies/goog.requires which reduces the > likelihood the Closure Compiler will find a circular dependency. > > -Alex > IMO, circular dependencies are developer errors and need not be addressed by the compiler. They simply cannot be resolved in certain situations. Ignored, sure, but not necessarily resolved. Circular dependencies are not specifically related to casting, so I don't think they should be a factor in this decision.