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.

Reply via email to