You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@flex.apache.org by Harbs <ha...@gmail.com> on 2016/07/17 18:48:18 UTC

[FalconJX] order of static members

The following code (from Base64):
		private static const _encodeChars:Vector.<int> = InitEncoreChar();  
		private static function InitEncoreChar():Vector.<int>  
		{  
			var encodeChars:Vector.<int> = new Vector.<int>(64, true);  
			
			// We could push the number directly  
			// but I think it's nice to see the characters (with no overhead on encode/decode)  
			var chars:String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";  
			for (var i:int = 0; i < 64; i++)  
			{  
				encodeChars[i] = chars.charCodeAt(i);  
			}  
			
			return encodeChars;  
		}  

compiles to:

/**
 * @private
 * @const
 * @type {Array}
 */
com.sociodox.utils.Base64._encodeChars = com.sociodox.utils.Base64.InitEncoreChar();

/**
 * @private
 * @return {Array}
 */
com.sociodox.utils.Base64.InitEncoreChar = function() {
  var /** @type {Array} */ encodeChars = new Array(64, true);
  var /** @type {string} */ chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  for (var /** @type {number} */ i = 0; i < 64; i++) {
    encodeChars[i] = chars.charCodeAt(i);
  }
  return encodeChars;
};

Trying to run this code in javascript will result in an error that com.sociodox.utils.Base64.InitEncoreChar is not defined. Of course this makes sense based on how the javascript is compiled. (There’s no difference between a private static and a public static other than the comments.)

It’s simple enough to fix this by placing functions before variable assignments.

However, the same code works in Flash no matter which order it’s declared. That’s probably because the code is analyzed before it’s actually run.

The thing is, that Javascript has the same functionality:

/**
 * @constructor
 */
com.sociodox.utils.Base64 = function() {
	com.sociodox.utils.Base64._encodeChars = InitEncoreChar();
	function InitEncoreChar(){
	  var /** @type {Array} */ encodeChars = new Array(64, true);
	  var /** @type {string} */ chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
	  for (var /** @type {number} */ i = 0; i < 64; i++) {
	    encodeChars[i] = chars.charCodeAt(i);
	  }
  return encodeChars;
		
        }
};

This will work no matter which order you declare the variable and the function because function declarations are evaluated before code is executed.

I don’t know a way to make this work in JS for public static functions, but for private static functions, this is likely a better pattern. It also makes the functions truly private…

Of course, I have no idea how much work it would be to make FalconJX be able to do this…

Thoughts?

Harbs

Re: Circular Dependencies (was [FalconJX] order of static members)

Posted by Harbs <ha...@gmail.com>.
A single file should work.

I’m not getting any errors when using the -remove-circulars argument and the XML processing seems to be working very well so far.

On Jul 20, 2016, at 8:38 PM, Alex Harui <ah...@adobe.com> wrote:

> Fun stuff, huh?
> 
> I think the (short-term) answer is to have the build merge XML.js and
> XMLList.js into a single file.  We might need to have the compiler special
> case the dependency calculation as well.
> 
> -Alex
> 
> On 7/20/16, 6:46 AM, "Harbs" <ha...@gmail.com> wrote:
> 
>> Also:
>> 
>> The signatures of XML functions have XMLList and XMLList has signatures
>> with XML.
>> 
>> On Jul 20, 2016, at 4:42 PM, Harbs <ha...@gmail.com> wrote:
>> 
>>> I have no idea how to even go about removing that dependency.
>>> 
>>> XMLList has a list of XML, so it needs to know about XML.
>>> 
>>> XML needs to build XMLLists of it’s children.
>>> 
>>> Even creating a factory doesn’t seem to me like it would solve this
>>> problem because XML needs to know about the factory and the factory
>>> needs to know about XML.
>>> 
>>> On Jul 20, 2016, at 4:35 PM, Harbs <ha...@gmail.com> wrote:
>>> 
>>>> I removed this, and now I’m getting an circular error of: XMLList ->
>>>> XML -> XMLList
>>>> 
>>>> That’s going to be hard to remove… :-(
>>>> 
>>>> On Jul 20, 2016, at 1:44 PM, Harbs <ha...@gmail.com> wrote:
>>>> 
>>>>> I tried removing the -remove-circulars option, and the only error I
>>>>> was was a circular dependency of: SEVERE: ERROR - Circular dependency
>>>>> detected: Namespace -> QName -> Namespace
>>>>> 
>>>> 
>>> 
>> 
> 


Re: Circular Dependencies (was [FalconJX] order of static members)

Posted by Alex Harui <ah...@adobe.com>.
Fun stuff, huh?

I think the (short-term) answer is to have the build merge XML.js and
XMLList.js into a single file.  We might need to have the compiler special
case the dependency calculation as well.

-Alex

On 7/20/16, 6:46 AM, "Harbs" <ha...@gmail.com> wrote:

>Also:
>
>The signatures of XML functions have XMLList and XMLList has signatures
>with XML.
>
>On Jul 20, 2016, at 4:42 PM, Harbs <ha...@gmail.com> wrote:
>
>> I have no idea how to even go about removing that dependency.
>> 
>> XMLList has a list of XML, so it needs to know about XML.
>> 
>> XML needs to build XMLLists of it’s children.
>> 
>> Even creating a factory doesn’t seem to me like it would solve this
>>problem because XML needs to know about the factory and the factory
>>needs to know about XML.
>> 
>> On Jul 20, 2016, at 4:35 PM, Harbs <ha...@gmail.com> wrote:
>> 
>>> I removed this, and now I’m getting an circular error of: XMLList ->
>>>XML -> XMLList
>>> 
>>> That’s going to be hard to remove… :-(
>>> 
>>> On Jul 20, 2016, at 1:44 PM, Harbs <ha...@gmail.com> wrote:
>>> 
>>>> I tried removing the -remove-circulars option, and the only error I
>>>>was was a circular dependency of: SEVERE: ERROR - Circular dependency
>>>>detected: Namespace -> QName -> Namespace
>>>> 
>>> 
>> 
>


Re: Circular Dependencies (was [FalconJX] order of static members)

Posted by Harbs <ha...@gmail.com>.
Also:

The signatures of XML functions have XMLList and XMLList has signatures with XML.

On Jul 20, 2016, at 4:42 PM, Harbs <ha...@gmail.com> wrote:

> I have no idea how to even go about removing that dependency.
> 
> XMLList has a list of XML, so it needs to know about XML.
> 
> XML needs to build XMLLists of it’s children.
> 
> Even creating a factory doesn’t seem to me like it would solve this problem because XML needs to know about the factory and the factory needs to know about XML.
> 
> On Jul 20, 2016, at 4:35 PM, Harbs <ha...@gmail.com> wrote:
> 
>> I removed this, and now I’m getting an circular error of: XMLList -> XML -> XMLList
>> 
>> That’s going to be hard to remove… :-(
>> 
>> On Jul 20, 2016, at 1:44 PM, Harbs <ha...@gmail.com> wrote:
>> 
>>> I tried removing the -remove-circulars option, and the only error I was was a circular dependency of: SEVERE: ERROR - Circular dependency detected: Namespace -> QName -> Namespace
>>> 
>> 
> 


Re: Circular Dependencies (was [FalconJX] order of static members)

Posted by Harbs <ha...@gmail.com>.
I have no idea how to even go about removing that dependency.

XMLList has a list of XML, so it needs to know about XML.

XML needs to build XMLLists of it’s children.

Even creating a factory doesn’t seem to me like it would solve this problem because XML needs to know about the factory and the factory needs to know about XML.

On Jul 20, 2016, at 4:35 PM, Harbs <ha...@gmail.com> wrote:

> I removed this, and now I’m getting an circular error of: XMLList -> XML -> XMLList
> 
> That’s going to be hard to remove… :-(
> 
> On Jul 20, 2016, at 1:44 PM, Harbs <ha...@gmail.com> wrote:
> 
>> I tried removing the -remove-circulars option, and the only error I was was a circular dependency of: SEVERE: ERROR - Circular dependency detected: Namespace -> QName -> Namespace
>> 
> 


Re: Circular Dependencies (was [FalconJX] order of static members)

Posted by Harbs <ha...@gmail.com>.
I removed this, and now I’m getting an circular error of: XMLList -> XML -> XMLList

That’s going to be hard to remove… :-(

On Jul 20, 2016, at 1:44 PM, Harbs <ha...@gmail.com> wrote:

> I tried removing the -remove-circulars option, and the only error I was was a circular dependency of: SEVERE: ERROR - Circular dependency detected: Namespace -> QName -> Namespace
> 


Re: Circular Dependencies (was [FalconJX] order of static members)

Posted by Harbs <ha...@gmail.com>.
I was waiting until I got my app to run before I responded to this, so my response would be more intelligent.

On Jul 19, 2016, at 7:13 PM, Alex Harui <ah...@adobe.com> wrote:

> 
> FWIW, Google doesn't call it a limitation.  They think they are enforcing
> good design principles.  We could generate different code, but it will be
> a bunch of work and I don't know if it will have side-effects and GCC will
> have trouble optimizing it.

Now that I have worked through my code, I tend to agree with this statement. Being forced to work through circularities helped clean up my code.

> Technically, all circularities cause problems.

That’s not what I’m seeing.
With -remove-circulars enabled I ran into the following issues:
1. A super-class could not reference a sub-class at all. I had one case where I had such a reference to work around an obscure bug. It would have been difficult to work around this in a more “accepted” way. (I worked-around this pretty easily by using a string representation of the type name rather than using “is".)
2. A static variable of class A could no reference a class B which somewhere downstream class B (or its references) have a reference to class A. Changing the static variable in Class A to in instance variable made this problem go away.
3. Even a private instance variable in class A which references class B using “as” causes problems when class B has a downstream reference to class A. Using -js-output-optimization=skipAsCoercions fixed this issue.

That was it. I have plenty of cross-references between two classes both as public and private getters and none of them caused problems. I’m actually surprised and impressed that I did not have more issues. Once I wrapped my head around the issues involved, fixing the few issues I had was pretty straight-foward.

I tried removing the -remove-circulars option, and the only error I was was a circular dependency of: SEVERE: ERROR - Circular dependency detected: Namespace -> QName -> Namespace

I don’t know if there were others that were not reported because I did not try to fix that one.

> IMO, there should be a overridable method where the subclass takes care of
> whatever set up it needs.  The Base should not know about the Subs as that
> makes Base a candidate for updating if a new Sub is needed in the future.

Right. That’s the general pattern I use. However, the sub-classes call super.doStuff() as well to run generic code. My case was a specific problem deep in the generic code (which should not have happened at all). Trying to extract that logic would have caused a lot of code duplication. Just excluding the specific sub-class was a simpler ad-hoc solution. Using string class “names” is what I think is the accepted solution to this situation when overriding is not palatable.

> AIUI, that is
> the Factory pattern and that code should be moved to a Factory class and
> that should break the circularity and not be too much effort.

I use factories when necessary, but I’m not a big fan of factories when they’re not. I like to keep indirection down to a minimum.

> AIUI, the recommended pattern is that interfaces should not have
> references to non-interfaces.  And while you can still create
> circularities that way, I think the argument is that you can always define
> one more interface to break the circularity and that is a better design.
> And, FWIW, having no non-interfaces in interfaces and more interfaces
> would have helped Flex immensely around the mixing of different versions
> of code (the Marshall Plan), so doing this now for FlexJS is a good bet
> for our long term future.

This is a good point, and one I’ll try to keep in mind.

Re: Circular Dependencies (was [FalconJX] order of static members)

Posted by Alex Harui <ah...@adobe.com>.

On 7/19/16, 1:54 AM, "Harbs" <ha...@gmail.com> wrote:

>It’s taken me a bit of time to wrap my head around the issues here, but I
>think I have it clear enough to articulate the issues I’m bumping into
>and possibly propose some solutions.
>
>There are two different scenarios related to circulars; debug builds and
>release builds.
>
>Debug Builds:
>I’ve run into two situations where I’ve had errors in the debug build due
>to circularities:
>
>Snip...
>
>As I understand it, the problem with my suggestion is that it does not
>address limitations in the Google Closure Compiler. This brings us to
>release builds.

FWIW, Google doesn't call it a limitation.  They think they are enforcing
good design principles.  We could generate different code, but it will be
a bunch of work and I don't know if it will have side-effects and GCC will
have trouble optimizing it.

>
>Release Builds:
>There’s many kinds of circularities, I’m I’m not clear on which ones
>cause problems. 

Technically, all circularities cause problems.  GCC wants to understand
every reference in your source files when optimizing and expects the
goog.requires to define some of the references.  And then if the
references are circular, it complains.  And while we've provided options
in the compiler to not generate some references, if your code still makes
such a reference without a goog.require for it, you will likely get an
error as well and the optimizer will not generate a release version.

>Alex wrote an explanation on the wiki,[1] which is a good starting point,
>but there’s still questions I have. I will list the ones that I’ve
>thought of:
>
>1. A extends B and B extends A. This is not supported by ActionScript, so
>it’s a non-issue.
>2. Super classes which have a reference to the sub class as mentioned in
>the wiki.
>3. Classes which are unrelated in hierarchy, but reference each other.
>4. A circular chain of class references. (i.e. a uses b which uses c
>which used d which uses a)
>3. public static variables
>4. private static variables
>5. public variables
>6. private variables
>7. function parameters of all four types
>8. function return types.
>9. interfaces.

Apparently, computer scientists have defined patterns for eliminating
circularities.  I am not an expert on these patterns since we could get
away with them in Flex/Flash, but below is how I think of the scenarios.


>
>To make this a bit more concrete, I have a number of known circularities
>in my code:
>
>1. I have a sub class which calls a super method to take care of most if
>the object setup. This setup is identical for all sub classes with the
>exception of on piece which should be not done for a specific sub, so in
>the super class I have a line of code if(this is Sub){//don’t do it}.
>Getting rid of this line of code is doable, but would require indirection
>which I’d rather avoid. (but not too big a deal)

IMO, there should be a overridable method where the subclass takes care of
whatever set up it needs.  The Base should not know about the Subs as that
makes Base a candidate for updating if a new Sub is needed in the future.

>2. I have a “page” class which keeps track of all objects that it
>contains. The object classes each have a reference to their containing
>pages which is needed to do all kinds of calculations. I think this is a
>totally valid design, and doing it any other way would be very messy and
>make it very difficult to follow the code flow. This exact situation is
>mentioned in the closure lib Google Group.[2]

You can keep track of instances created, but the Page class should only
think of them as Pages and not subclasses of Pages.  When I took a look at
your code, I thought I saw the circular reference caused by the base class
taking information and deciding which subclass to create.  AIUI, that is
the Factory pattern and that code should be moved to a Factory class and
that should break the circularity and not be too much effort.

>3. I probably have lots of chained dependencies — especially with regard
>to ApplicationFacade.
>
>I don’t know the best way to fix my problems with things as they stand.
>There were two suggestions to problem #2 on the Google Group.[3] One way
>to put the classes in the same file, and the second was to use
>interfaces. My question is whether interfaces would solve the problem:

AIUI, the recommended pattern is that interfaces should not have
references to non-interfaces.  And while you can still create
circularities that way, I think the argument is that you can always define
one more interface to break the circularity and that is a better design.
And, FWIW, having no non-interfaces in interfaces and more interfaces
would have helped Flex immensely around the mixing of different versions
of code (the Marshall Plan), so doing this now for FlexJS is a good bet
for our long term future.

HTH,
-Alex


Re: Circular Dependencies (was [FalconJX] order of static members)

Posted by Josh Tynjala <jo...@gmail.com>.
For the release build, the Closure compiler does exactly as you describe.
It combines everything into one monolithic file (and does some other
things, like minifying and optimizing the JS), so that nothing needs to be
loaded at runtime. goog.provide() and goog.require() calls are stripped
out, but as I understand it, they are still used to determine the order of
the combined files.

To do better than the Closure compiler does now, we'd need to figure out a
different way to order the files. I suspect we'd need to split classes into
multiple parts and set up everything in phases to avoid circular
dependencies.

- Josh

On Tue, Jul 19, 2016 at 1:54 AM, Harbs <ha...@gmail.com> wrote:

> It’s taken me a bit of time to wrap my head around the issues here, but I
> think I have it clear enough to articulate the issues I’m bumping into and
> possibly propose some solutions.
>
> There are two different scenarios related to circulars; debug builds and
> release builds.
>
> Debug Builds:
> I’ve run into two situations where I’ve had errors in the debug build due
> to circularities:
>
> 1. I’m using PureMVC (which ports to FlexJS as-is without a hitch by
> including the source). PureMVC has a Facade class which is a Singleton that
> is used as a go-between to get Proxies and Mediators as well a notification
> hub. In a number of places in my code I had some code which looks like
> this: private static var myProxy:SomeProxy =
> ApplicationFacade.getInstance().retrieveProxy(SomeProxy.NAME) as SomeProxy;
> The class which calls this is being loaded before ApplicationFacade.js, so
> ApplicationFacade is undefined when the above code is run.
>
> 2. I have a situation where the goog.requires are such that three of my
> sub-classes are being loaded before their super-classes. I’m not completely
> sure on exactly which circularity is causing this (more on that later), but
> the symptom of this problem is that when goog.inherits(MySubClass,
> MySuperClass); is called, MySuperClass is not yet defined.
>
> I resolved situation #1 (at least for the debug), by removing “static”.
> This moves the definition into the constructor, so it’s only evaluated when
> the class is instantiated — at which time, ApplicationFacade is already
> loaded.
>
> If we only need to deal with debug builds, both of these issues could be
> handled with initialization functions. Instead of this:
>
> /**
>  * @constructor
>  * @extends {Super}
>  * @param {Holder} page
>  */
> Sub = function(page) {
>   com.printui.model.vos.TextFrameVO._init_();
>   //do stuff...
>   Sub.base(this, 'constructor', page);
> };
>
> goog.inherits(Sub, Super);
>
> Sub.proxy = org.apache.flex.utils.Language.as(ApplicationFacade.getInstance().retrieveProxy(SomeProxy.NAME),
> SomeProxy);
>
> We could do this:
> /**
>  * @constructor
>  * @extends {Super}
>  * @param {Holder} page
>  */
> Sub = function(page) {
>   Sub._init_();
>   //do stuff...
>   Sub.base(this, 'constructor', page);
> };
>
> Sub._init_ = function(){
>   goog.inherits(Sub, Super);
>   Sub.proxy = org.apache.flex.utils.Language.as(ApplicationFacade.getInstance().retrieveProxy(SomeProxy.NAME),
> SomeProxy);
>   Sub._init_ = function(){}
> }
>
> This would cause class variables and inheritance setup to run the first
> time a class is instantiated and not when the script is first evaluated.
> Sub._init_ = function(){} at the end of the function redefines the function
> to do nothing after the first time it’s run, so class initialization would
> only happen once no matter how many times you instantiate the class.
>
> After writing this, I realized that the above suggestion is actually
> flawed for static classes which are not instantiated because the init
> function would never be called. I think the goog.inherits should be fine
> because inheritance only matters on classes which are instantiated.
> However, a better solution would probably be to call init() on all classes
> after they are loaded.
>
> As I understand it, the problem with my suggestion is that it does not
> address limitations in the Google Closure Compiler. This brings us to
> release builds.
>
> Release Builds:
> There’s many kinds of circularities, I’m I’m not clear on which ones cause
> problems. Alex wrote an explanation on the wiki,[1] which is a good
> starting point, but there’s still questions I have. I will list the ones
> that I’ve thought of:
>
> 1. A extends B and B extends A. This is not supported by ActionScript, so
> it’s a non-issue.
> 2. Super classes which have a reference to the sub class as mentioned in
> the wiki.
> 3. Classes which are unrelated in hierarchy, but reference each other.
> 4. A circular chain of class references. (i.e. a uses b which uses c which
> used d which uses a)
> 3. public static variables
> 4. private static variables
> 5. public variables
> 6. private variables
> 7. function parameters of all four types
> 8. function return types.
> 9. interfaces.
>
> To make this a bit more concrete, I have a number of known circularities
> in my code:
>
> 1. I have a sub class which calls a super method to take care of most if
> the object setup. This setup is identical for all sub classes with the
> exception of on piece which should be not done for a specific sub, so in
> the super class I have a line of code if(this is Sub){//don’t do it}.
> Getting rid of this line of code is doable, but would require indirection
> which I’d rather avoid. (but not too big a deal)
> 2. I have a “page” class which keeps track of all objects that it
> contains. The object classes each have a reference to their containing
> pages which is needed to do all kinds of calculations. I think this is a
> totally valid design, and doing it any other way would be very messy and
> make it very difficult to follow the code flow. This exact situation is
> mentioned in the closure lib Google Group.[2]
> 3. I probably have lots of chained dependencies — especially with regard
> to ApplicationFacade.
>
> I don’t know the best way to fix my problems with things as they stand.
> There were two suggestions to problem #2 on the Google Group.[3] One way to
> put the classes in the same file, and the second was to use interfaces. My
> question is whether interfaces would solve the problem:
>
> public interface IPage{
>   function get backgroundObject():PageItem;
> }
> public class Page implements IPage{
>   var pageItems:Vector.<PageItem> = new Vector.<PageItem>();
>   pageItems.push(new PageItem());
>   pageItems.push(new PageItem());
>   public function get backgroundObject():PageItem{
>     return pageItems[0];
>   }
> }
> public class PageItem{
>   private var _page:IPage;
>   public function PageItem(page:IPage){
>     _page = page;
>   }
>   public function get background():PageItem{
>     return _page.backgroundObject;
>   }
> }
>
> Page needs the interface IPage (or does it?) which needs PageItem, which
> needs IPage which needs PageItem ad infinitum.
>
> A bigger question I have is related to the first suggestion (i.e.
> including them in the same file). That makes me question whether we need
> good.provide and goog.require at all for the release build. For debug, we
> definitely want the files separated to identify code during debug. But for
> release, it seems to me that Falcon can simply combine all the required
> files into a single monolithic file containing everything. That should
> eliminate the need to use goog.provide and goog.require being that they are
> only used (AIUI) for goog to know which files to load. I see two ways this
> could be accomplished:
> 1. It could strip out all good.provides and good.requires fro the debug
> build and combine the files.
> 2. It could rebuild from source without goo.provide and goog.require at
> all. (It is possible that I’m not understanding what goog.provide does and
> it’s still needed, but I’m pretty sure I’m right about goog.require.)
>
> Wow. This was a long email, but I think this is an important topic.
>
> Thoughts?
> Harbs
>
>
> [1] https://cwiki.apache.org/confluence/display/FLEX/Circular+Dependencies
> [2]
> https://groups.google.com/d/msg/closure-library-discuss/ZfC1xKIs-NA/vjnhA4llbZsJ
> [3]
> https://groups.google.com/d/msg/closure-library-discuss/ZfC1xKIs-NA/BtEzF7Ow4R4J
>
> On Jul 18, 2016, at 9:30 PM, Alex Harui <ah...@adobe.com> wrote:
>
> >
> >
> > On 7/17/16, 11:45 PM, "Harbs" <ha...@gmail.com> wrote:
> >
> >> The issue should be clear.
> >>
> >> If MySuperClass.js has not yet been loaded when MySubClass.js is loaded,
> >> goog.inherits(MySubClass, MySuperClass); which is in MySubClass.js will
> >> cause an error.
> >
> > Harbs, if our code normally had problems loading subclasses before base
> > classes, I doubt any of our examples would run.  There should be a
> > goog.require for the base class at the top of the subclass's file and
> that
> > should load the base class before the goog.inherit runs.  There is
> > something unique about your scenario.  We need a test case in order to
> > determine what it is.
> >
> >>
> >> This code is being added to the JS file right after the constructor is
> >> being defined, but it’s not wrapped in an initializer function so it’s
> >> evaluated as soon as the JS file is loaded.
> >>
> >> If it would be wrapped in an init function, it could be evaluated only
> >> after all files are loaded, so all classes would be defined.
> >>
> >> We’ve been spending the better part of the last day trying to distill
> >> this down to a test case which causes the compiler to load the classes
> in
> >> the wrong order. We’re getting closer, but we’re not there yet. Even if
> >> we find the specific root cause in my case for the files to be loaded in
> >> the wrong order, I still think it’s a design flaw which should be fixed.
> >> The order of loading files should not matter.
> >
> > The order of loading files currently matters.  IMO, it would not be worth
> > it to make it not matter.  Google thinks it should matter otherwise they
> > wouldn't have created the goog.require system and deps.js.
> >
> > Thanks,
> > -Alex
> >
>
>

Circular Dependencies (was [FalconJX] order of static members)

Posted by Harbs <ha...@gmail.com>.
It’s taken me a bit of time to wrap my head around the issues here, but I think I have it clear enough to articulate the issues I’m bumping into and possibly propose some solutions.

There are two different scenarios related to circulars; debug builds and release builds.

Debug Builds:
I’ve run into two situations where I’ve had errors in the debug build due to circularities:

1. I’m using PureMVC (which ports to FlexJS as-is without a hitch by including the source). PureMVC has a Facade class which is a Singleton that is used as a go-between to get Proxies and Mediators as well a notification hub. In a number of places in my code I had some code which looks like this: private static var myProxy:SomeProxy = ApplicationFacade.getInstance().retrieveProxy(SomeProxy.NAME) as SomeProxy; The class which calls this is being loaded before ApplicationFacade.js, so ApplicationFacade is undefined when the above code is run.

2. I have a situation where the goog.requires are such that three of my sub-classes are being loaded before their super-classes. I’m not completely sure on exactly which circularity is causing this (more on that later), but the symptom of this problem is that when goog.inherits(MySubClass, MySuperClass); is called, MySuperClass is not yet defined.

I resolved situation #1 (at least for the debug), by removing “static”. This moves the definition into the constructor, so it’s only evaluated when the class is instantiated — at which time, ApplicationFacade is already loaded.

If we only need to deal with debug builds, both of these issues could be handled with initialization functions. Instead of this:

/**
 * @constructor
 * @extends {Super}
 * @param {Holder} page
 */
Sub = function(page) {
  com.printui.model.vos.TextFrameVO._init_();
  //do stuff...
  Sub.base(this, 'constructor', page);
};

goog.inherits(Sub, Super);

Sub.proxy = org.apache.flex.utils.Language.as(ApplicationFacade.getInstance().retrieveProxy(SomeProxy.NAME), SomeProxy);

We could do this:
/**
 * @constructor
 * @extends {Super}
 * @param {Holder} page
 */
Sub = function(page) {
  Sub._init_();
  //do stuff...
  Sub.base(this, 'constructor', page);
};

Sub._init_ = function(){
  goog.inherits(Sub, Super);
  Sub.proxy = org.apache.flex.utils.Language.as(ApplicationFacade.getInstance().retrieveProxy(SomeProxy.NAME), SomeProxy);
  Sub._init_ = function(){}
}

This would cause class variables and inheritance setup to run the first time a class is instantiated and not when the script is first evaluated. Sub._init_ = function(){} at the end of the function redefines the function to do nothing after the first time it’s run, so class initialization would only happen once no matter how many times you instantiate the class.

After writing this, I realized that the above suggestion is actually flawed for static classes which are not instantiated because the init function would never be called. I think the goog.inherits should be fine because inheritance only matters on classes which are instantiated. However, a better solution would probably be to call init() on all classes after they are loaded.

As I understand it, the problem with my suggestion is that it does not address limitations in the Google Closure Compiler. This brings us to release builds.

Release Builds:
There’s many kinds of circularities, I’m I’m not clear on which ones cause problems. Alex wrote an explanation on the wiki,[1] which is a good starting point, but there’s still questions I have. I will list the ones that I’ve thought of:

1. A extends B and B extends A. This is not supported by ActionScript, so it’s a non-issue.
2. Super classes which have a reference to the sub class as mentioned in the wiki.
3. Classes which are unrelated in hierarchy, but reference each other.
4. A circular chain of class references. (i.e. a uses b which uses c which used d which uses a)
3. public static variables
4. private static variables
5. public variables
6. private variables
7. function parameters of all four types
8. function return types.
9. interfaces.

To make this a bit more concrete, I have a number of known circularities in my code:

1. I have a sub class which calls a super method to take care of most if the object setup. This setup is identical for all sub classes with the exception of on piece which should be not done for a specific sub, so in the super class I have a line of code if(this is Sub){//don’t do it}. Getting rid of this line of code is doable, but would require indirection which I’d rather avoid. (but not too big a deal)
2. I have a “page” class which keeps track of all objects that it contains. The object classes each have a reference to their containing pages which is needed to do all kinds of calculations. I think this is a totally valid design, and doing it any other way would be very messy and make it very difficult to follow the code flow. This exact situation is mentioned in the closure lib Google Group.[2]
3. I probably have lots of chained dependencies — especially with regard to ApplicationFacade.

I don’t know the best way to fix my problems with things as they stand. There were two suggestions to problem #2 on the Google Group.[3] One way to put the classes in the same file, and the second was to use interfaces. My question is whether interfaces would solve the problem:

public interface IPage{
  function get backgroundObject():PageItem;
}
public class Page implements IPage{
  var pageItems:Vector.<PageItem> = new Vector.<PageItem>();
  pageItems.push(new PageItem());
  pageItems.push(new PageItem());
  public function get backgroundObject():PageItem{
    return pageItems[0];
  }
}
public class PageItem{
  private var _page:IPage;
  public function PageItem(page:IPage){
    _page = page;
  }
  public function get background():PageItem{
    return _page.backgroundObject;
  }
}

Page needs the interface IPage (or does it?) which needs PageItem, which needs IPage which needs PageItem ad infinitum.

A bigger question I have is related to the first suggestion (i.e. including them in the same file). That makes me question whether we need good.provide and goog.require at all for the release build. For debug, we definitely want the files separated to identify code during debug. But for release, it seems to me that Falcon can simply combine all the required files into a single monolithic file containing everything. That should eliminate the need to use goog.provide and goog.require being that they are only used (AIUI) for goog to know which files to load. I see two ways this could be accomplished:
1. It could strip out all good.provides and good.requires fro the debug build and combine the files.
2. It could rebuild from source without goo.provide and goog.require at all. (It is possible that I’m not understanding what goog.provide does and it’s still needed, but I’m pretty sure I’m right about goog.require.)

Wow. This was a long email, but I think this is an important topic.

Thoughts?
Harbs


[1] https://cwiki.apache.org/confluence/display/FLEX/Circular+Dependencies
[2]https://groups.google.com/d/msg/closure-library-discuss/ZfC1xKIs-NA/vjnhA4llbZsJ
[3]https://groups.google.com/d/msg/closure-library-discuss/ZfC1xKIs-NA/BtEzF7Ow4R4J

On Jul 18, 2016, at 9:30 PM, Alex Harui <ah...@adobe.com> wrote:

> 
> 
> On 7/17/16, 11:45 PM, "Harbs" <ha...@gmail.com> wrote:
> 
>> The issue should be clear.
>> 
>> If MySuperClass.js has not yet been loaded when MySubClass.js is loaded,
>> goog.inherits(MySubClass, MySuperClass); which is in MySubClass.js will
>> cause an error.
> 
> Harbs, if our code normally had problems loading subclasses before base
> classes, I doubt any of our examples would run.  There should be a
> goog.require for the base class at the top of the subclass's file and that
> should load the base class before the goog.inherit runs.  There is
> something unique about your scenario.  We need a test case in order to
> determine what it is.
> 
>> 
>> This code is being added to the JS file right after the constructor is
>> being defined, but it’s not wrapped in an initializer function so it’s
>> evaluated as soon as the JS file is loaded.
>> 
>> If it would be wrapped in an init function, it could be evaluated only
>> after all files are loaded, so all classes would be defined.
>> 
>> We’ve been spending the better part of the last day trying to distill
>> this down to a test case which causes the compiler to load the classes in
>> the wrong order. We’re getting closer, but we’re not there yet. Even if
>> we find the specific root cause in my case for the files to be loaded in
>> the wrong order, I still think it’s a design flaw which should be fixed.
>> The order of loading files should not matter.
> 
> The order of loading files currently matters.  IMO, it would not be worth
> it to make it not matter.  Google thinks it should matter otherwise they
> wouldn't have created the goog.require system and deps.js.
> 
> Thanks,
> -Alex
> 


Re: [FalconJX] order of static members

Posted by Alex Harui <ah...@adobe.com>.

On 7/17/16, 11:45 PM, "Harbs" <ha...@gmail.com> wrote:

>The issue should be clear.
>
>If MySuperClass.js has not yet been loaded when MySubClass.js is loaded,
>goog.inherits(MySubClass, MySuperClass); which is in MySubClass.js will
>cause an error.

Harbs, if our code normally had problems loading subclasses before base
classes, I doubt any of our examples would run.  There should be a
goog.require for the base class at the top of the subclass's file and that
should load the base class before the goog.inherit runs.  There is
something unique about your scenario.  We need a test case in order to
determine what it is.

>
>This code is being added to the JS file right after the constructor is
>being defined, but it’s not wrapped in an initializer function so it’s
>evaluated as soon as the JS file is loaded.
>
>If it would be wrapped in an init function, it could be evaluated only
>after all files are loaded, so all classes would be defined.
>
>We’ve been spending the better part of the last day trying to distill
>this down to a test case which causes the compiler to load the classes in
>the wrong order. We’re getting closer, but we’re not there yet. Even if
>we find the specific root cause in my case for the files to be loaded in
>the wrong order, I still think it’s a design flaw which should be fixed.
>The order of loading files should not matter.

The order of loading files currently matters.  IMO, it would not be worth
it to make it not matter.  Google thinks it should matter otherwise they
wouldn't have created the goog.require system and deps.js.

Thanks,
-Alex


Re: [FalconJX] order of static members

Posted by Harbs <ha...@gmail.com>.
The issue should be clear.

If MySuperClass.js has not yet been loaded when MySubClass.js is loaded, goog.inherits(MySubClass, MySuperClass); which is in MySubClass.js will cause an error.

This code is being added to the JS file right after the constructor is being defined, but it’s not wrapped in an initializer function so it’s evaluated as soon as the JS file is loaded.

If it would be wrapped in an init function, it could be evaluated only after all files are loaded, so all classes would be defined.

We’ve been spending the better part of the last day trying to distill this down to a test case which causes the compiler to load the classes in the wrong order. We’re getting closer, but we’re not there yet. Even if we find the specific root cause in my case for the files to be loaded in the wrong order, I still think it’s a design flaw which should be fixed. The order of loading files should not matter.

On Jul 18, 2016, at 9:38 AM, Alex Harui <ah...@adobe.com> wrote:

> A simple test case might help us understand the issue better.
> 
> -Alex
> 
> On 7/17/16, 11:35 PM, "Harbs" <ha...@gmail.com> wrote:
> 
>> To be clear:
>> 
>> I’m currently struggling with goog.inherits(MySubClass, MySuperClass);
>> For some reason (which I’m not totally clear on) MySubClass is being
>> loaded first, and MySuperClass is not yet defined when this code is
>> called.
>> 
>> If goog.inherits was mored to an initializer which is lazy-evaluated, I
>> believe this error would go away.
>> 
>> On Jul 18, 2016, at 9:25 AM, Harbs <ha...@gmail.com> wrote:
>> 
>>> I’m also not sure how the prototype is being setup.
>>> 
>>> It could be you’ve already solved my concerns there, but it looks like
>>> a lot of the prototype is being setup outside the constructor.
>>> 
>>> On Jul 18, 2016, at 9:10 AM, Alex Harui <ah...@adobe.com> wrote:
>>> 
>>>> 
>>>> 
>>>> On 7/17/16, 11:02 PM, "Harbs" <ha...@gmail.com> wrote:
>>>> 
>>>>> Well, I guess the question is where the init functions would be
>>>>> called.
>>>>> 
>>>>> My idea was that the “instance init function call would be added to
>>>>> the
>>>>> constructor as the first thing that happens (with the exception of
>>>>> calling init on the super-class first).
>>>> 
>>>> Right now, instance initialization happens in the constructor.  I can't
>>>> immediately think of a a scenario where that isn't sufficient.
>>>> 
>>>>> 
>>>>> The class initializers is more of a question. I figured that might
>>>>> need
>>>>> to be added into whatever code loads the js files.
>>>> 
>>>> I think I would end each .js file with:
>>>> 
>>>> SomeClass.cinit = function()
>>>> {
>>>> // all class initializer code
>>>> }
>>>> SomeClass.cinit();
>>>> 
>>>> 
>>>> Maybe I'm not thinking of some scenario where more is needed.
>>>> 
>>>> -Alex
>>>> 
>>> 
>> 
> 


Re: [FalconJX] order of static members

Posted by Alex Harui <ah...@adobe.com>.
A simple test case might help us understand the issue better.

-Alex

On 7/17/16, 11:35 PM, "Harbs" <ha...@gmail.com> wrote:

>To be clear:
>
>I’m currently struggling with goog.inherits(MySubClass, MySuperClass);
>For some reason (which I’m not totally clear on) MySubClass is being
>loaded first, and MySuperClass is not yet defined when this code is
>called.
>
>If goog.inherits was mored to an initializer which is lazy-evaluated, I
>believe this error would go away.
>
>On Jul 18, 2016, at 9:25 AM, Harbs <ha...@gmail.com> wrote:
>
>> I’m also not sure how the prototype is being setup.
>> 
>> It could be you’ve already solved my concerns there, but it looks like
>>a lot of the prototype is being setup outside the constructor.
>> 
>> On Jul 18, 2016, at 9:10 AM, Alex Harui <ah...@adobe.com> wrote:
>> 
>>> 
>>> 
>>> On 7/17/16, 11:02 PM, "Harbs" <ha...@gmail.com> wrote:
>>> 
>>>> Well, I guess the question is where the init functions would be
>>>>called.
>>>> 
>>>> My idea was that the “instance init function call would be added to
>>>>the
>>>> constructor as the first thing that happens (with the exception of
>>>> calling init on the super-class first).
>>> 
>>> Right now, instance initialization happens in the constructor.  I can't
>>> immediately think of a a scenario where that isn't sufficient.
>>> 
>>>> 
>>>> The class initializers is more of a question. I figured that might
>>>>need
>>>> to be added into whatever code loads the js files.
>>> 
>>> I think I would end each .js file with:
>>> 
>>> SomeClass.cinit = function()
>>> {
>>> // all class initializer code
>>> }
>>> SomeClass.cinit();
>>> 
>>> 
>>> Maybe I'm not thinking of some scenario where more is needed.
>>> 
>>> -Alex
>>> 
>> 
>


Re: [FalconJX] order of static members

Posted by Harbs <ha...@gmail.com>.
To be clear:

I’m currently struggling with goog.inherits(MySubClass, MySuperClass); For some reason (which I’m not totally clear on) MySubClass is being loaded first, and MySuperClass is not yet defined when this code is called.

If goog.inherits was mored to an initializer which is lazy-evaluated, I believe this error would go away.

On Jul 18, 2016, at 9:25 AM, Harbs <ha...@gmail.com> wrote:

> I’m also not sure how the prototype is being setup.
> 
> It could be you’ve already solved my concerns there, but it looks like a lot of the prototype is being setup outside the constructor.
> 
> On Jul 18, 2016, at 9:10 AM, Alex Harui <ah...@adobe.com> wrote:
> 
>> 
>> 
>> On 7/17/16, 11:02 PM, "Harbs" <ha...@gmail.com> wrote:
>> 
>>> Well, I guess the question is where the init functions would be called.
>>> 
>>> My idea was that the “instance init function call would be added to the
>>> constructor as the first thing that happens (with the exception of
>>> calling init on the super-class first).
>> 
>> Right now, instance initialization happens in the constructor.  I can't
>> immediately think of a a scenario where that isn't sufficient.
>> 
>>> 
>>> The class initializers is more of a question. I figured that might need
>>> to be added into whatever code loads the js files.
>> 
>> I think I would end each .js file with:
>> 
>> SomeClass.cinit = function()
>> {
>> // all class initializer code
>> }
>> SomeClass.cinit();
>> 
>> 
>> Maybe I'm not thinking of some scenario where more is needed.
>> 
>> -Alex
>> 
> 


Re: [FalconJX] order of static members

Posted by Alex Harui <ah...@adobe.com>.

On 7/17/16, 11:25 PM, "Harbs" <ha...@gmail.com> wrote:

>I’m also not sure how the prototype is being setup.
>
>It could be you’ve already solved my concerns there, but it looks like a
>lot of the prototype is being setup outside the constructor.

Scalar prototype initializers are set on the prototype property:

Source:

Class A {
  Var foo:int = 10;
}

Generates:

A.prototype.foo = 10;

Complex prototype initializers are set in the constructor.

Source:

Class A {
  Var foo:Array = [];
}

Generates:

Function A()
{
  foo = [];
}


Re: [FalconJX] order of static members

Posted by Harbs <ha...@gmail.com>.
I’m also not sure how the prototype is being setup.

It could be you’ve already solved my concerns there, but it looks like a lot of the prototype is being setup outside the constructor.

On Jul 18, 2016, at 9:10 AM, Alex Harui <ah...@adobe.com> wrote:

> 
> 
> On 7/17/16, 11:02 PM, "Harbs" <ha...@gmail.com> wrote:
> 
>> Well, I guess the question is where the init functions would be called.
>> 
>> My idea was that the “instance init function call would be added to the
>> constructor as the first thing that happens (with the exception of
>> calling init on the super-class first).
> 
> Right now, instance initialization happens in the constructor.  I can't
> immediately think of a a scenario where that isn't sufficient.
> 
>> 
>> The class initializers is more of a question. I figured that might need
>> to be added into whatever code loads the js files.
> 
> I think I would end each .js file with:
> 
> SomeClass.cinit = function()
> {
>  // all class initializer code
> }
> SomeClass.cinit();
> 
> 
> Maybe I'm not thinking of some scenario where more is needed.
> 
> -Alex
> 


Re: [FalconJX] order of static members

Posted by Harbs <ha...@gmail.com>.
This still does not address the issue where a class is relying on another class in a static variable.

MyClassA.myB:MyClassB = MyClassB.getInstance();
If MyClassA is loaded before MyClassB, this code will fail.

If however, both classes are first loaded and only then, the initializers are called (for constants and variables), the above code would be fine.

On Jul 18, 2016, at 9:10 AM, Alex Harui <ah...@adobe.com> wrote:

> 
> 
> On 7/17/16, 11:02 PM, "Harbs" <ha...@gmail.com> wrote:
> 
>> Well, I guess the question is where the init functions would be called.
>> 
>> My idea was that the “instance init function call would be added to the
>> constructor as the first thing that happens (with the exception of
>> calling init on the super-class first).
> 
> Right now, instance initialization happens in the constructor.  I can't
> immediately think of a a scenario where that isn't sufficient.
> 
>> 
>> The class initializers is more of a question. I figured that might need
>> to be added into whatever code loads the js files.
> 
> I think I would end each .js file with:
> 
> SomeClass.cinit = function()
> {
>  // all class initializer code
> }
> SomeClass.cinit();
> 
> 
> Maybe I'm not thinking of some scenario where more is needed.
> 
> -Alex
> 


Re: [FalconJX] order of static members

Posted by Alex Harui <ah...@adobe.com>.

On 7/17/16, 11:02 PM, "Harbs" <ha...@gmail.com> wrote:

>Well, I guess the question is where the init functions would be called.
>
>My idea was that the “instance init function call would be added to the
>constructor as the first thing that happens (with the exception of
>calling init on the super-class first).

Right now, instance initialization happens in the constructor.  I can't
immediately think of a a scenario where that isn't sufficient.

>
>The class initializers is more of a question. I figured that might need
>to be added into whatever code loads the js files.

I think I would end each .js file with:

SomeClass.cinit = function()
{
  // all class initializer code
}
SomeClass.cinit();


Maybe I'm not thinking of some scenario where more is needed.

-Alex


Re: [FalconJX] order of static members

Posted by Harbs <ha...@gmail.com>.
Well, I guess the question is where the init functions would be called.

My idea was that the “instance init function call would be added to the constructor as the first thing that happens (with the exception of calling init on the super-class first).

The class initializers is more of a question. I figured that might need to be added into whatever code loads the js files.

On Jul 18, 2016, at 8:59 AM, Alex Harui <ah...@adobe.com> wrote:

> 
> 
> On 7/17/16, 10:51 PM, "Harbs" <ha...@gmail.com> wrote:
> 
>> A number of reasons:
>> 1. performance
>> 2. If the code does calculations which might change later on
>> 3. If it needs to always reference the same object, you don’t want it
>> reassigned.
> 
> But who would call it more than once?
> 
>> 
>> For instance initialization, you need to setup your prototype only once,
>> or bad things could happen — and the bas class’ prototype needs to be
>> setup first.
> 
> IMO, the prototype is not the instance.
> 
>> 
>> As far as initializing vs constructor goes:
>> 
>> The prototype of the superclass needs to be defined first, but
>> initialization code in the super-class' constructor might need to be run
>> second.
> 
> I think I would need to see actual code examples for these scenarios in
> order to understand when the order of constructors needs to be controlled.
> 
> -Alex
> 


Re: [FalconJX] order of static members

Posted by Alex Harui <ah...@adobe.com>.

On 7/17/16, 10:51 PM, "Harbs" <ha...@gmail.com> wrote:

>A number of reasons:
>1. performance
>2. If the code does calculations which might change later on
>3. If it needs to always reference the same object, you don’t want it
>reassigned.

But who would call it more than once?

>
>For instance initialization, you need to setup your prototype only once,
>or bad things could happen — and the bas class’ prototype needs to be
>setup first.

IMO, the prototype is not the instance.

>
>As far as initializing vs constructor goes:
>
>The prototype of the superclass needs to be defined first, but
>initialization code in the super-class' constructor might need to be run
>second.

I think I would need to see actual code examples for these scenarios in
order to understand when the order of constructors needs to be controlled.

-Alex


Re: [FalconJX] order of static members

Posted by Harbs <ha...@gmail.com>.
A number of reasons:
1. performance
2. If the code does calculations which might change later on
3. If it needs to always reference the same object, you don’t want it reassigned.

For instance initialization, you need to setup your prototype only once, or bad things could happen — and the bas class’ prototype needs to be setup first.

As far as initializing vs constructor goes:

The prototype of the superclass needs to be defined first, but initialization code in the super-class' constructor might need to be run second.

On Jul 18, 2016, at 8:43 AM, Alex Harui <ah...@adobe.com> wrote:

> Maybe I'm missing something, but why are you worried about it being called
> more than once?
> 
> What scenario requires an instance initializer instead of code in the
> constructor?
> 
> -Alex
> 
> On 7/17/16, 9:59 PM, "Harbs" <ha...@gmail.com> wrote:
> 
>> Well, one simple fix might be to move all functions before variables.
>> This should work because functions are not evaluated until they are run.
>> 
>> I think there is a bigger issue which I’m running into in other classes:
>> I’m getting all kinds of errors which I think are due to the order of
>> classes being loaded. During class initialization, I’m getting errors
>> that other classes are not found.
>> 
>> While thinking abut this, I came to the conclusion that class
>> initializers and instance initializers are probably the way to go. The
>> initializer functions can reassign themselves to do nothing to ensure
>> they are only run once.
>> 
>> Something like this:
>> 
>> MyClass._init_class_ = function(){
>> //Do class initialization stuff including variable and constant assignment
>> 	console.log("running init");
>> 	MyClass._init_class_ = function(){
>> 		// do nothing
>> 	}
>> }
>> MyClass(){
>> 	MyClass._init_instance_();
>> }
>> MyClass._init_instance_ = function(){
>> // call _init_instance_ on super
>> // assign the prototype
>> MyClass._init_instance_ = function(){
>> }
>> 
>> }
>> 
>> I’m not positive, but I’m pretty sure that this would eliminate almost
>> all my issues.
>> 
>> On Jul 18, 2016, at 7:27 AM, Alex Harui <ah...@adobe.com> wrote:
>> 
>>> 
>>> 
>>> On 7/17/16, 11:48 AM, "Harbs" <ha...@gmail.com> wrote:
>>> 
>>>> The following code (from Base64):
>>>> 		private static const _encodeChars:Vector.<int> = InitEncoreChar();
>>>> 		private static function InitEncoreChar():Vector.<int>
>>>> 		{  
>>>> 		}  
>>>> 
>>>> Trying to run this code in javascript will result in an error that
>>>> com.sociodox.utils.Base64.InitEncoreChar is not defined. Of course this
>>>> makes sense based on how the javascript is compiled. (There’s no
>>>> difference between a private static and a public static other than the
>>>> comments.)
>>>> 
>>>> It’s simple enough to fix this by placing functions before variable
>>>> assignments.
>>>> 
>>>> However, the same code works in Flash no matter which order it’s
>>>> declared. That’s probably because the code is analyzed before it’s
>>>> actually run.
>>> 
>>> I think it is because functions/methods are created in the class traits,
>>> which run before the class initializer.
>>> 
>>>> 
>>>> The thing is, that Javascript has the same functionality:
>>>> 
>>>> /**
>>>> * @constructor
>>>> */
>>>> com.sociodox.utils.Base64 = function() {
>>>> 	com.sociodox.utils.Base64._encodeChars = InitEncoreChar();
>>>> 	function InitEncoreChar(){
>>>> 	  var /** @type {Array} */ encodeChars = new Array(64, true);
>>>> 	  var /** @type {string} */ chars =
>>>> "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
>>>> 	  for (var /** @type {number} */ i = 0; i < 64; i++) {
>>>> 	    encodeChars[i] = chars.charCodeAt(i);
>>>> 	  }
>>>> return encodeChars;
>>>> 		
>>>>      }
>>>> };
>>>> 
>>>> This will work no matter which order you declare the variable and the
>>>> function because function declarations are evaluated before code is
>>>> executed.
>>>> 
>>>> I don’t know a way to make this work in JS for public static functions,
>>>> but for private static functions, this is likely a better pattern. It
>>>> also makes the functions truly private…
>>>> 
>>>> Of course, I have no idea how much work it would be to make FalconJX be
>>>> able to do this…
>>> 
>>> I'm not sure it is worth generating this fancier output, but folks are
>>> welcome to create an emitter that does.
>>> 
>>>> 
>>>> Thoughts?
>>> 
>>> We should fix this someday (probably by creating a class initializer
>>> function), but since the workaround is simple enough, I'd say file a bug
>>> but defer it to a future release.
>>> 
>>> -Alex
>>> 
>> 
> 


Re: [FalconJX] order of static members

Posted by Alex Harui <ah...@adobe.com>.
Maybe I'm missing something, but why are you worried about it being called
more than once?

What scenario requires an instance initializer instead of code in the
constructor?

-Alex

On 7/17/16, 9:59 PM, "Harbs" <ha...@gmail.com> wrote:

>Well, one simple fix might be to move all functions before variables.
>This should work because functions are not evaluated until they are run.
>
>I think there is a bigger issue which I’m running into in other classes:
>I’m getting all kinds of errors which I think are due to the order of
>classes being loaded. During class initialization, I’m getting errors
>that other classes are not found.
>
>While thinking abut this, I came to the conclusion that class
>initializers and instance initializers are probably the way to go. The
>initializer functions can reassign themselves to do nothing to ensure
>they are only run once.
>
>Something like this:
>
>MyClass._init_class_ = function(){
>//Do class initialization stuff including variable and constant assignment
>	console.log("running init");
>	MyClass._init_class_ = function(){
>		// do nothing
>	}
>}
>MyClass(){
>	MyClass._init_instance_();
>}
>MyClass._init_instance_ = function(){
>// call _init_instance_ on super
>// assign the prototype
>MyClass._init_instance_ = function(){
>}
>
>}
>
>I’m not positive, but I’m pretty sure that this would eliminate almost
>all my issues.
>
>On Jul 18, 2016, at 7:27 AM, Alex Harui <ah...@adobe.com> wrote:
>
>> 
>> 
>> On 7/17/16, 11:48 AM, "Harbs" <ha...@gmail.com> wrote:
>> 
>>> The following code (from Base64):
>>> 		private static const _encodeChars:Vector.<int> = InitEncoreChar();
>>> 		private static function InitEncoreChar():Vector.<int>
>>> 		{  
>>> 		}  
>>> 
>>> Trying to run this code in javascript will result in an error that
>>> com.sociodox.utils.Base64.InitEncoreChar is not defined. Of course this
>>> makes sense based on how the javascript is compiled. (There’s no
>>> difference between a private static and a public static other than the
>>> comments.)
>>> 
>>> It’s simple enough to fix this by placing functions before variable
>>> assignments.
>>> 
>>> However, the same code works in Flash no matter which order it’s
>>> declared. That’s probably because the code is analyzed before it’s
>>> actually run.
>> 
>> I think it is because functions/methods are created in the class traits,
>> which run before the class initializer.
>> 
>>> 
>>> The thing is, that Javascript has the same functionality:
>>> 
>>> /**
>>> * @constructor
>>> */
>>> com.sociodox.utils.Base64 = function() {
>>> 	com.sociodox.utils.Base64._encodeChars = InitEncoreChar();
>>> 	function InitEncoreChar(){
>>> 	  var /** @type {Array} */ encodeChars = new Array(64, true);
>>> 	  var /** @type {string} */ chars =
>>> "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
>>> 	  for (var /** @type {number} */ i = 0; i < 64; i++) {
>>> 	    encodeChars[i] = chars.charCodeAt(i);
>>> 	  }
>>> return encodeChars;
>>> 		
>>>       }
>>> };
>>> 
>>> This will work no matter which order you declare the variable and the
>>> function because function declarations are evaluated before code is
>>> executed.
>>> 
>>> I don’t know a way to make this work in JS for public static functions,
>>> but for private static functions, this is likely a better pattern. It
>>> also makes the functions truly private…
>>> 
>>> Of course, I have no idea how much work it would be to make FalconJX be
>>> able to do this…
>> 
>> I'm not sure it is worth generating this fancier output, but folks are
>> welcome to create an emitter that does.
>> 
>>> 
>>> Thoughts?
>> 
>> We should fix this someday (probably by creating a class initializer
>> function), but since the workaround is simple enough, I'd say file a bug
>> but defer it to a future release.
>> 
>> -Alex
>> 
>


Re: [FalconJX] order of static members

Posted by Harbs <ha...@gmail.com>.
Well, one simple fix might be to move all functions before variables. This should work because functions are not evaluated until they are run.

I think there is a bigger issue which I’m running into in other classes: I’m getting all kinds of errors which I think are due to the order of classes being loaded. During class initialization, I’m getting errors that other classes are not found.

While thinking abut this, I came to the conclusion that class initializers and instance initializers are probably the way to go. The initializer functions can reassign themselves to do nothing to ensure they are only run once.

Something like this:

MyClass._init_class_ = function(){
//Do class initialization stuff including variable and constant assignment
	console.log("running init");
	MyClass._init_class_ = function(){
		// do nothing
	}
}
MyClass(){
	MyClass._init_instance_();
}
MyClass._init_instance_ = function(){
// call _init_instance_ on super
// assign the prototype
MyClass._init_instance_ = function(){
}

}

I’m not positive, but I’m pretty sure that this would eliminate almost all my issues.

On Jul 18, 2016, at 7:27 AM, Alex Harui <ah...@adobe.com> wrote:

> 
> 
> On 7/17/16, 11:48 AM, "Harbs" <ha...@gmail.com> wrote:
> 
>> The following code (from Base64):
>> 		private static const _encodeChars:Vector.<int> = InitEncoreChar();
>> 		private static function InitEncoreChar():Vector.<int>
>> 		{  
>> 		}  
>> 
>> Trying to run this code in javascript will result in an error that
>> com.sociodox.utils.Base64.InitEncoreChar is not defined. Of course this
>> makes sense based on how the javascript is compiled. (There’s no
>> difference between a private static and a public static other than the
>> comments.)
>> 
>> It’s simple enough to fix this by placing functions before variable
>> assignments.
>> 
>> However, the same code works in Flash no matter which order it’s
>> declared. That’s probably because the code is analyzed before it’s
>> actually run.
> 
> I think it is because functions/methods are created in the class traits,
> which run before the class initializer.
> 
>> 
>> The thing is, that Javascript has the same functionality:
>> 
>> /**
>> * @constructor
>> */
>> com.sociodox.utils.Base64 = function() {
>> 	com.sociodox.utils.Base64._encodeChars = InitEncoreChar();
>> 	function InitEncoreChar(){
>> 	  var /** @type {Array} */ encodeChars = new Array(64, true);
>> 	  var /** @type {string} */ chars =
>> "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
>> 	  for (var /** @type {number} */ i = 0; i < 64; i++) {
>> 	    encodeChars[i] = chars.charCodeAt(i);
>> 	  }
>> return encodeChars;
>> 		
>>       }
>> };
>> 
>> This will work no matter which order you declare the variable and the
>> function because function declarations are evaluated before code is
>> executed.
>> 
>> I don’t know a way to make this work in JS for public static functions,
>> but for private static functions, this is likely a better pattern. It
>> also makes the functions truly private…
>> 
>> Of course, I have no idea how much work it would be to make FalconJX be
>> able to do this…
> 
> I'm not sure it is worth generating this fancier output, but folks are
> welcome to create an emitter that does.
> 
>> 
>> Thoughts?
> 
> We should fix this someday (probably by creating a class initializer
> function), but since the workaround is simple enough, I'd say file a bug
> but defer it to a future release.
> 
> -Alex
> 


Re: [FalconJX] order of static members

Posted by Alex Harui <ah...@adobe.com>.

On 7/17/16, 11:48 AM, "Harbs" <ha...@gmail.com> wrote:

>The following code (from Base64):
>		private static const _encodeChars:Vector.<int> = InitEncoreChar();
>		private static function InitEncoreChar():Vector.<int>
>		{  
>		}  
>
>Trying to run this code in javascript will result in an error that
>com.sociodox.utils.Base64.InitEncoreChar is not defined. Of course this
>makes sense based on how the javascript is compiled. (There’s no
>difference between a private static and a public static other than the
>comments.)
>
>It’s simple enough to fix this by placing functions before variable
>assignments.
>
>However, the same code works in Flash no matter which order it’s
>declared. That’s probably because the code is analyzed before it’s
>actually run.

I think it is because functions/methods are created in the class traits,
which run before the class initializer.

>
>The thing is, that Javascript has the same functionality:
>
>/**
> * @constructor
> */
>com.sociodox.utils.Base64 = function() {
>	com.sociodox.utils.Base64._encodeChars = InitEncoreChar();
>	function InitEncoreChar(){
>	  var /** @type {Array} */ encodeChars = new Array(64, true);
>	  var /** @type {string} */ chars =
>"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
>	  for (var /** @type {number} */ i = 0; i < 64; i++) {
>	    encodeChars[i] = chars.charCodeAt(i);
>	  }
>  return encodeChars;
>		
>        }
>};
>
>This will work no matter which order you declare the variable and the
>function because function declarations are evaluated before code is
>executed.
>
>I don’t know a way to make this work in JS for public static functions,
>but for private static functions, this is likely a better pattern. It
>also makes the functions truly private…
>
>Of course, I have no idea how much work it would be to make FalconJX be
>able to do this…

I'm not sure it is worth generating this fancier output, but folks are
welcome to create an emitter that does.

>
>Thoughts?

We should fix this someday (probably by creating a class initializer
function), but since the workaround is simple enough, I'd say file a bug
but defer it to a future release.

-Alex