I don't know where I got 'overally' from. I think I started that one with
generally and got halfway through changing it. :)

On Wed, Nov 6, 2019 at 1:07 PM Greg Dove <[email protected]> wrote:

> Yeah, that's pretty much what I meant. And the issue you expressed is a
> more detailed analysis of what I was anticipating as the main issue with
> this approach. The split out of private statics was not something that I
> thought about, but overally it could still be a viable option - at least
> worth a bit more investigation, but definitely not something urgent at this
> point.
> I actually just tried the following static init code:
>
> private static var i:uint;
>
> {
>    for (i=0;i<10;i++) {
>       trace('static init block testing '+i);
>    }
> }
>
> You should simply be able to paste that into pretty much any class that
> does not have a static var i already defined.
> It is a very rare pattern and probably rightly so (I have used it for some
> things in the past, but it was never a 'goto' option), but it is valid in
> as3 and does allow for some one-off processing on first class access. I had
> forgotten some of the 'rules' inside the code block, it seems that
> declaring local vars is not an option, so you can't use 'for (var i:uint=0;
> ...' above. I am pretty sure I 'learnt' that on previous occasions too.
> For Royale, this works the same for swf as it did for legacy flex compiler
> and you get the trace output. At the moment the code in the static init
> above is not generated at all for js. But like I said, this does not seem
> high priority!
>
>
>
> On Wed, Nov 6, 2019 at 12:10 PM Alex Harui <[email protected]>
> wrote:
>
>> I won't be doing any more work in this area unless the lack of
>> minification of private statics becomes a major issue for a user.  Or if
>> there is a bug in the just-committed implementation.
>>
>> I think I now understand what you are proposing.  That's really good
>> thinking, however, I'm not sure it would work for minified code as statics
>> are essentially removed from the class and turned into a global var.  IOW:
>>
>> package org.apache.royale.events {
>>   public class MouseEvent {
>>     private static somePrivateStatic = <some expression>
>>   }
>> }
>>
>> Gets transpiled to:
>>
>> org.apache.royale.events.MouseEvent = function() {}
>> org.apache.royale.events.MouseEvent.somePrivateStatic = <some expression>
>>
>> which gets minified to something like
>>
>> pv = function() {}
>> exportSymbol(pv, " org.apache.royale.events.MouseEvent");
>> pu = <some expression>
>>
>> so there isn't always a package tree of objects to hook and add a getter
>> to, and there could be direct access to "pu" before any access to
>> org.apache.royale.events.MouseEvent or even "pv".
>>
>> Of course, I could be wrong...
>> -Alex
>>
>>
>> On 11/5/19, 2:51 PM, "Greg Dove" <[email protected]> wrote:
>>
>>     Suggestions for better terminology and acronyms are welcome, although
>> I
>>     don't think I agree on what is "optimized compiler output".
>>
>>     All I was trying to say is that I think we over-use the term 'PAYG'
>> for
>>     things outside its specific and unique (for Royale) meaning. As far
>> as I
>>     can see, this topic is focused on getting emulation of something to
>> work
>>     right at the language level, and then making sure it is optimized (in
>> some
>>     way - the common tradeoff between performance and size). That is
>> pretty
>>     general and easily understood and does not need a new name or
>> acronym, imo.
>>     I think about it in terms of how easy it would be for someone new to
>> read
>>     this thread and how much they could understand it. Anyway, I just
>> wanted to
>>     point that out as I have thought about doing so on other occasions
>> and did
>>     not, but I have no intention of pursuing it further as a topic.
>>
>>
>>     "I'm not sure what you mean by "string name for a renamed member",
>> but if
>>     you look at the modules examples they output the renaming map so the
>> module
>>     can use the same renaming."
>>     I know it is available 'outside'. I was thinking more in terms of
>> injecting
>>     the renamed name into the code somehow, but even if it were possible
>> I am
>>     not sure it would make sense, because it would mean code that would
>> rely on
>>     something that would only ever work with GCC. I presume that there is
>> no
>>     way to add this into GCC/GCL in such a way that the javascript would
>> work
>>     the same in other minifiers.  This was more of a pipe dream, I could
>> have
>>     used something like this to do variables reflection differently, for
>>     example, but I'm happy with what we have now, which I think will
>> support
>>     other future targets.
>>
>>     "Flash runs class verification and class initialization in the
>> runtime's
>>     verifier at the first use of a class.  I have no idea how to
>> replicate that
>>     in JS.  IOW, in JS, I don't know what line of code is going to be the
>> first
>>     reference to a class. "
>>     I thought about it the same way, until reviewing both Harbs and your
>>     earlier examples in this thread.
>>     A javascript class itself is basically a static access of a value on
>> its
>>     package chain.
>>     My point was to consider make the class itself a getter for first
>> access in
>>     the same way you are proposing for its static members.
>>
>>     org.apache.royale.MyClass <- 'MyClass' could a js getter for first
>> access
>>     if the class has static init code it needs to run.
>>
>>     The initialization code could then run in the getter for the class and
>>     replace itself on 'org.apache.royale' as a 'value' similar to what
>> you are
>>     proposing for its static members. That is the trick to how it might
>> be a
>>     way to replicate (sort of) what SWF does in js, I think, without doing
>>     something complicated at compile time.
>>
>>     The one issue I can think of is that while it is exported with the
>> full
>>     package path, there is also a minified reference. That means it might
>> need
>>     to reassign to both its exported package name (for the 'export'
>>     consistency) and its own original package name reference (which should
>>     support the minified version) in the part of the accessor which does
>> the
>>     reassignment back to a simple value.
>>
>>     If you don't have time to look into this, I can explore it at some
>> point.
>>
>>
>>
>>     On Wed, Nov 6, 2019 at 10:52 AM Alex Harui <[email protected]>
>> wrote:
>>
>>     > Suggestions for better terminology and acronyms are welcome,
>> although I
>>     > don't think I agree on what is "optimized compiler output".
>>     >
>>     > You are correct that private statics won't be minified as well as
>> they
>>     > used to, but switching to getters solved a lot of other problems so
>> I'm
>>     > pushing these changes for now and we can try to do better for
>> private
>>     > statics later if it turns out there are lots of them.  There is
>> code in the
>>     > commit that tries to determine if the initialization expression
>> references
>>     > external dependencies.  That code could get smarter and further
>> reduce the
>>     > number of private statics that get converted to getter/setter.  In
>> a quick
>>     > search of the framework code, there are only a few static vars that
>>     > reference other classes.  Also, it is my understanding that the
>>     > defineProperties call where the variable/constant name is a key in
>> the
>>     > structure passed into defineProperties is what prevents renaming,
>> not the
>>     > string passed into defineProperty.
>>     >
>>     > My main concern about static code blocks is how well GCC handles
>> them.
>>     >
>>     > I'm not sure what you mean by "string name for a renamed member",
>> but if
>>     > you look at the modules examples they output the renaming map so
>> the module
>>     > can use the same renaming.
>>     >
>>     > Flash runs class verification and class initialization in the
>> runtime's
>>     > verifier at the first use of a class.  I have no idea how to
>> replicate that
>>     > in JS.  IOW, in JS, I don't know what line of code is going to be
>> the first
>>     > reference to a class.
>>     >
>>     > And if it really does become a problem, we might be able to do what
>> GCC
>>     > does and rename the private static ourselves since we know the only
>> places
>>     > that reference it are in the class we are compiling.
>>     >
>>     > My 2 cents,
>>     > -Alex
>>     >
>>     > On 11/5/19, 11:34 AM, "Greg Dove" <[email protected]> wrote:
>>     >
>>     >     Side comment: I actually prefer to limit the way I think of
>> 'PAYG' as
>>     >     enabling options for the user to compose incremental pieces of
>>     >     functionality together, instead of using it to describe
>> 'anything' that
>>     >     represents optimized compiler output. For me, PAYG is something
>> that
>>     > users
>>     >     actively 'do'.  The more I talk to new people about Royale the
>> more it
>>     >     becomes apparent that a lot of the terms and concepts are
>> confusing,
>>     > which
>>     >     is the only reason I am mentioning this. To me this is just
>> finding
>>     > ways to
>>     >     make compatible output that is optimized (presumably because
>> GCC can't
>>     >     optimize it itself).
>>     >
>>     >
>>     >     The approach described works well for public static const
>>     >
>>     >     For static vars, or for private static consts, using the string
>> value
>>     > to
>>     >     redefine the property does mean that the var name can now no
>> longer be
>>     >     minimified in these cases I think. That would be a small price
>> to pay
>>     > if it
>>     >     now works. I have looked in GCC/goog a few times to see if
>> there is
>>     > any way
>>     >     to get the string name for a renamed member, but I could not
>> find
>>     > anything
>>     >     (so far).
>>     >     The only way to keep things as they are there that I can think
>> of is to
>>     >     swap the private static consts for vars (so they can be
>> undefined at
>>     > class
>>     >     definition) and initialize them all in a static code block.
>> That could
>>     >     perhaps be achieved using something very similar to what you
>> described
>>     > at
>>     >     the class level if the class was determined to need it - the
>> first
>>     >     reference to the class would run the getter for the class
>> reference
>>     > itself,
>>     >     which would run static init code and then replace itself with
>> the
>>     > original
>>     >     class reference. That would essentially make it possible to
>> match the
>>     > way
>>     >     swf does it. Whether that plays nice with GCC or not I don't
>> know.
>>     >     I have not actually tried to use explicit static code blocks in
>> Royale
>>     > yet
>>     >     (I did not expect them to work, but perhaps they do already),
>> and only
>>     > used
>>     >     them rarely in as3 in the past in general. If these don't
>> currently
>>     > work
>>     >     then the same approach would allow us to do that. Things like:
>>     >
>>     >
>>     >     class Test {
>>     >
>>     >       public static const myConstArray:Array = [new OtherClass(),new
>>     >     OtherClass(), new OtherClass()];
>>     >
>>     >       {
>>     >           //explicit static init code
>>     >           for each(var other:OtherClass in myConstArray)
>>     >           {
>>     >               trace(other.toString());
>>     >           }
>>     >       }
>>     >
>>     >       //normal stuff
>>     >
>>     >     }
>>     >
>>     >     I think it might even be possible in normal as3 to have
>> multiple static
>>     >     code blocks like that. So running that code from inside a
>> 'class'
>>     > getter
>>     >     could perhaps solve that problem as well in a similar way. If
>> that is
>>     > being
>>     >     done though, it might as well initialize all the values. I
>> think the
>>     >     argument about lazy initialization for the individual items
>> could be
>>     > offset
>>     >     by avoiding extra code to support each individual lazy
>> initialization
>>     > as
>>     >     well, and in some cases also mean that minification is
>> maintained.
>>     >
>>     >
>>     >
>>     >     On Wed, Nov 6, 2019 at 7:06 AM Harbs <[email protected]>
>> wrote:
>>     >
>>     >     > Makes sense to me.
>>     >     >
>>     >     > > On Nov 5, 2019, at 7:41 PM, Alex Harui
>> <[email protected]>
>>     > wrote:
>>     >     > >
>>     >     > > FWIW, here is the pattern that appears to work in JSFiddle
>> for a
>>     > "static
>>     >     > var foo":
>>     >     > >
>>     >     > > o.get__foo = function() {
>>     >     > >   var value = <initializer expression>
>>     >     > >   Object.defineProperty(o, 'foo', {value : value, writable:
>> true});
>>     >     > >   return value;
>>     >     > > }
>>     >     > > o.set__foo = function(value) {
>>     >     > >    Object.defineProperty(o, 'foo', {value : value, writable:
>>     > true});
>>     >     > > }
>>     >     > > Object.defineProperties(o, { foo: { get: o.get__foo,set:
>>     > o.set__foo,
>>     >     > configurable: true}})
>>     >     > >
>>     >     > > We have to use Object.defineProperties in order to use an
>> @lends
>>     > JSDoc
>>     >     > annotation (not shown) for the minifier.
>>     >     > >
>>     >     > > A similar pattern will be used for "static const foo":
>>     >     > >
>>     >     > > o.get__foo = function() {
>>     >     > >   var value = <initializer expression>
>>     >     > >   Object.defineProperty(o, 'foo', {value : value, writable:
>>     > false});
>>     >     > >   return value;
>>     >     > > }
>>     >     > > Object.defineProperties(o, { foo: { get: o.get__foo,
>> configurable:
>>     >     > true}})
>>     >     > >
>>     >     > > Of course, I could be wrong...
>>     >     > >
>>     >     > > -Alex
>>     >     > >
>>     >     > > On 11/5/19, 8:56 AM, "Harbs" <[email protected]> wrote:
>>     >     > >
>>     >     > >    Good point on PAYG.
>>     >     > >
>>     >     > >    If we use #2 with one-time lazy evaluation, I think
>> that’s the
>>     > best
>>     >     > of both worlds.
>>     >     > >
>>     >     > >    Thanks,
>>     >     > >    Harbs
>>     >     > >
>>     >     > >> On Nov 5, 2019, at 6:44 PM, Alex Harui
>> <[email protected]>
>>     >     > wrote:
>>     >     > >>
>>     >     > >> Yeah, in my local branch I'm playing with various ways to
>> not run
>>     > the
>>     >     > initializer more than once.  We can tweak the pattern later.
>> It
>>     > involves
>>     >     > re-defining the property, but isn't  quite the patterns
>> offered
>>     > below.
>>     >     > >>
>>     >     > >> IMO, #2 is more PAYG than #1.  In #1, all initializers run
>>     > regardless
>>     >     > of whether your code uses that value or not.  In #2, the
>>     > initializers run
>>     >     > on demand, which is actually somewhat more like the Flash
>> runtime.
>>     > AIUI,
>>     >     > Flash does not run a class's static initializers until the
>> class is
>>     > about
>>     >     > to be accessed by code.  All initializers for a class then
>> run, but
>>     > if your
>>     >     > code never gets to the point where the verifier needs to
>> verify the
>>     > class,
>>     >     > the initializers are not run.
>>     >     > >>
>>     >     > >> -Alex
>>     >     > >>
>>     >     > >> On 11/4/19, 11:49 PM, "Greg Dove" <[email protected]>
>> wrote:
>>     >     > >>
>>     >     > >>   Yeah, in all cases where I had to do this manually I
>> used a
>>     > private
>>     >     > static
>>     >     > >>   backing var and populated it on first request similar to
>> what is
>>     >     > typically
>>     >     > >>   done for singleton-like get accessors. Otherwise it's not
>>     > really safe
>>     >     > >>   compared to the original (and as you say, could have
>> performance
>>     >     > issues
>>     >     > >>   too).
>>     >     > >>
>>     >     > >>   On Tue, 5 Nov 2019, 20:31 Harbs, <[email protected]>
>> wrote:
>>     >     > >>
>>     >     > >>> It seems to me that the getter approach can have an
>> impact on
>>     >     > performance.
>>     >     > >>> With approach #1, the static consts will only be
>> evaluated once,
>>     > while
>>     >     > with
>>     >     > >>> #2, it will be evaluated every time it’s accessed.
>>     >     > >>>
>>     >     > >>> Maybe we could use a hybrid approach where “bar” is
>> redefined as
>>     > the
>>     >     > >>> evaluated value the first time it’s accessed.
>>     >     > >>>
>>     >     > >>> Something like this:
>>     >     > >>>
>>     >     > >>> Foo.get__bar = function() {
>>     >     > >>> var val = ResourceManager.getInstance().getString("baz");
>>     >     > >>> delete Foo.bar;
>>     >     > >>> Foo.bar = val;
>>     >     > >>> return val;
>>     >     > >>> Object.defineProperty(Foo, "bar", {get: Foo.get__bar});
>>     >     > >>>
>>     >     > >>> or maybe this:
>>     >     > >>>
>>     >     > >>> Foo.get__bar = function() {
>>     >     > >>> var val = ResourceManager.getInstance().getString("baz");
>>     >     > >>> // is delete needed?
>>     >     > >>> delete Foo.bar;
>>     >     > >>> Object.defineProperty(Foo, "bar", {get: function(){return
>> val}});
>>     >     > >>> return val;
>>     >     > >>> }
>>     >     > >>> Object.defineProperty(Foo, "bar", {get: Foo.get__bar});
>>     >     > >>>
>>     >     > >>>
>>     >     > >>> Harbs
>>     >     > >>>
>>     >     > >>>> On Nov 5, 2019, at 2:52 AM, Alex Harui
>> <[email protected]
>>     > >
>>     >     > wrote:
>>     >     > >>>>
>>     >     > >>>> Hi,
>>     >     > >>>>
>>     >     > >>>> The issue of complex static initializers and dependency
>> order
>>     > keeps
>>     >     > >>> coming up.  In reviewing the past discussions, there were
>> a
>>     > couple of
>>     >     > >>> suggestions:
>>     >     > >>>> 1) separate static initializers into a block of code
>> that runs
>>     > after
>>     >     > the
>>     >     > >>> class is defined
>>     >     > >>>> 2) use getters
>>     >     > >>>>
>>     >     > >>>> I'm going to try #2.  I'm not convinced #1 will work
>> well with
>>     >     > minifiers
>>     >     > >>> or help us get the dependency order right.
>>     >     > >>>>
>>     >     > >>>> Thoughts?  Is there a case where getters won't work?
>>     >     > >>>>
>>     >     > >>>> For:
>>     >     > >>>>
>>     >     > >>>> public class Foo {
>>     >     > >>>> public static const bar:String =
>>     >     > >>> ResourceManager.getInstance().getString("baz");
>>     >     > >>>> }
>>     >     > >>>>
>>     >     > >>>> We currently generate:
>>     >     > >>>>
>>     >     > >>>> Foo.bar = ResourceManager.getInstance().getString("baz");
>>     >     > >>>>
>>     >     > >>>> And lots of other code tries to understand that the
>>     >     > >>> goog.require("ResourceManager") is more important than
>> other
>>     >     > goog.requires
>>     >     > >>> in the remove-circulars dependency calculation.
>>     >     > >>>>
>>     >     > >>>> But if we generate:
>>     >     > >>>> Foo.get__bar = function() { return
>>     >     > >>> ResourceManager.getInstance().getString("baz");};
>>     >     > >>>> Object.defineProperty(Foo, "bar", {get: Foo.get__bar});
>>     >     > >>>>
>>     >     > >>>> Then I think no statics will get evaluated at load time.
>>     >     > >>>>
>>     >     > >>>> Of course, I could be wrong...
>>     >     > >>>> -Alex
>>     >     > >>>>
>>     >     > >>>
>>     >     > >>>
>>     >     > >>
>>     >     > >>
>>     >     > >
>>     >     > >
>>     >     > >
>>     >     >
>>     >     >
>>     >
>>     >
>>     >
>>
>>
>>

Reply via email to