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