I noticed and wondered if it was dialect. __

Just to try to dump related information into this thread so it is all here if 
you do get back to it:

In a Royale class's JS file, we used to set up the Object.definePropertles like 
this:

public class A {
  private var _foo:int = 0;
  public function get foo():int { return _foo }
}

Would be transpiled to:

A.prototype._foo = 0;
Object.defineProperties(A.prototype, { foo : get: function() { return this._foo 
}});

This worked in js-debug but when transpiled, GCC would give the two _foo 
different names, maybe like:

A.prototype.a = 0; // 'a'
Object.defineProperties(A.prototype, { foo : get: function() { return this.b 
}}); // 'b'

And this would not work.  GCC didn't think that the code in the 
Object.defineProperties structure was associated with the class A so it would 
use a different renaming scheme.
For that and some other reasons we currently generate all method bodies in the 
class pattern:

A.prototype._foo = 0;
A.prototype.get__foo = function() { return this._foo };
Object.defineProperties(A.prototype, { foo : get: A.prototype.get_foo }});

So when I say I have concerns about GCC and static init code, the concern is 
that GCC will not know that the static init code is referencing certain things 
in the class code.  But that might all work out as there is no 'this' in static 
init code.

-Alex

On 11/5/19, 4:15 PM, "Greg Dove" <[email protected]> wrote:

    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