Thanks, I will definitely come back to this as a reference when I look at
that.


On Wed, Nov 6, 2019 at 1:38 PM Alex Harui <[email protected]> wrote:

> 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