After looking at some of the code, I remembered that the DependencyGraph
generated by the compiler is not useful for JS output as it currently is. The
DependencyGraph is tuned for SWF code where class and instance properties have
types and those types are verified by the runtime. IOW, if UIComponent has a
"public var foo:SystemManager", then in SWF code, UIComponent is dependent on
SystemManager, but in JS it isn't because the JS output is just "var foo". The
SystemManager class doesn't even have to be in the JS output (until someone
actually instantiates it or references a static API). So any ordering that is
useful for SWF is probably not the same order for JS. It might be true that
SWF order is valid for JS, but I think I found that isn't quite true once,
although I might be mis-remembering that.
I don't think there is a way to know a class is about to be used without more
sophisticated (and thus slower) code, so we've so far not gone down that road.
I believe that the compiler will catch the circularities that are truly illegal
in SWF (class Foo extends Bar and class Bar extends Foo, and similar things
where static const Foo.baz = Bar.baz and static const Bar.baz = Foo.baz. And
more complex variants where the Flash runtime really could not do the right
thing. There may be more illegal situations in JS where static APIs in
different classes in JS depend on each other, but many are legal and we just
need to remove circulars differently by giving priority to static usage. I
think we may not need to catch truly illegal static initializer scenarios in JS
at compile/emitter time and can rely on errors generated by GoogDepsWriter and
Google Closure Compiler to catch those circularities (because the
provides/requires will be circular or GoogDepsWriter can see they are
circular). So, IMO, the next set of improvements are really just around
detecting more static dependencies at Emitter time and handing that information
to GoogDepsWriter. I don't think we need to change the actual JS we output.
I'm certain that we can detect that we're emitting static initializer code, but
I don't think the compiler currently detects it in a way that the rest of the
emitter code can track dependency usage differently.
My 2 cents,
-Alex
On 7/20/18, 8:10 AM, "Frost, Andrew" wrote:
Yes good point: so to protect ourselves it might be that we need to try to
mimic what the avmplus does and just call a 'class initialiser' method to set
up all the static properties, when the class is first referenced. Although I'm
not sure whether we can detect from JavaScript when the class is first
referenced..?!
In terms of trying to make the dependency emitter a little more clever:
aren't we always going to face problems if there really are two classes that
have a reference to each other? So a real circular reference that can't be
resolved? Maybe this isn't so common in real life... I guess if it doesn't yet
know that it's emitting a static initializer then yes there's a more basic
issue to address!
thanks
Andrew
-Original Message-
From: Alex Harui [mailto:aha...@adobe.com.INVALID]
Sent: 20 July 2018 15:55
To: dev@royale.apache.org
Subject: [EXTERNAL] Re: Query on Royale dependency generation
Personally, I'm not convinced the problem is truly different in SWF vs JS,
other than that in JS, the google closure compiler and
goog.provides/requires/addDependency don't really let you specify the
difference between static and non-static initializer dependencies. I think you
may have seen that when you played with the "verifyAll" setting.
The main difference, AIUI, is that the Flash runtime only initializes the
statics on a class when first used instead of when loaded. JS initializes all
statics when loaded. But I think that the order in many cases still matters in
the SWF. I see code in the SWF output section of the compiler that figures out
the order of classes to output into the SWF. There is a DependencyGraph that
is managed by the compiler. It is possible that the problem is simply a matter
of translating that SWF order into the goog.provides/requires/addDependency.
I think that at Emitter time, we can know that we are initializing a static
initializer and can record that information in the output for use in
GoogDepsWriter.
I worry that the workaround in #2 may not always work. The workaround
changes when the initializer runs, but I wonder if there will be scenarios
where the initializers are still going to be needed "early".
Whether we do #2 or #3, the Emitter logic still needs to detect that it is
outputting a static initializer. So it isn't clear that it is worth the
overhead of outputting different code vs just leaving more data for
GoogDepsWriter.
My 2 cents,
-Alex
On 7/20/18, 6:49 AM, "Frost, Andrew" wrote:
Hi guys