Here’s the short version:

All the files are loaded in order of the dependency declarations. Calculating 
the correct order is very difficult and sometimes impossible.

The way the circular dependencies are resolved is by simply declaring them all 
in the main class. Declaring them in subclasses can cause goog to try and load 
files before they are a actually loaded. The exact order ends up being a bit of 
a crapshoot. Statics are evaluated when the file is first loaded, so 
initializing anything other than native (or externally loaded) objects can 
cause an error.

My proposed solution is to extract all non-native costs and initialized vars 
into a separate file and load that file last in the dependency list. That 
ensures all the classes are already loaded. Unfortunately no-one has worked on 
resolving this problem yet. Earlier versions of the compiler tried to be 
smarter about order, but that turned out to not always work…

Alex could give you the longer version… ;-)

What I do for cases where static custom classes are needed is something like 
this:

private static var _myFoo:Foo;
public static function get FOO():Foo{
        if(!_myFoo){
                _myFoo = new Foo();
        }
        return _myFoo;
}

There’s slightly more overhead than a const, but at least it works…

Harbs

> On Jul 19, 2018, at 4:39 PM, Frost, Andrew <andrew.fr...@harman.com> wrote:
> 
> Hi
> 
>> If it’s in the big list, it should be initialized correctly.
> .. but depending on the order of the big list, things will be initialised in 
> different orders...
> 
>> Are you initializing a BinaryData as a static const (or preinitialized var)?
> Yes
>> i.e. public static const DATA:BinaryData = new BinaryData() is a no-no.
> So - why is this a no-no? I'm trying to convert an ActionScript class that 
> Adobe wrote a long time ago, which has the equivalent using ByteArray. Are 
> you saying that it's not possible to do certain things with ActionScript in 
> Royale that are fine when you're targeting Flash?
> I know it's not a great practice to have this sort of thing but I would hope 
> that there is some level of parity between the ActionScript code that you can 
> write for each of the targets; plus, as I've found, all that's needed for 
> this construct to work 100% of the time is if we could specify the correct 
> dependencies for the BinaryData class.
> 
>> I’d really like to have the compiler delay loading of static consts and var 
>> to the very end of the loading. That would allow this pattern…
> True, and possibly that could work, but surely it would also be allowed if we 
> generated the line:
> goog.addDependency('../../../org/apache/royale/utils/BinaryData.js',
>  ['org.apache.royale.utils.BinaryData'], [ 'org.apache.royale.utils.Endian', 
>  'org.apache.royale.utils.IBinaryDataInput', 
> 'org.apache.royale.utils.IBinaryDataOutput']);
> 
> So regardless of all the discussion, I would quite like to find out why the 
> 'Endian' isn't listed as a dependency when all this html/JS stuff is 
> generated... likewise some of the other constructs where something depends on 
> something else (e.g. "is" is being used in the Namespace constructor, but I'm 
> creating a Namespace prior to the Language.js file being loaded..)
> 
> I guess we can't actually wait until the end of loading everything until we 
> start to initialise things, unless we change how the JS code is output (i.e. 
> to have a single static initialiser for the class which is run after 
> everything is loaded, rather than declaring all the static properties with 
> initialisation in-place..)
> 
> Interesting problem!
> 
> thanks
> 
>   Andrew
> 
> 
> -----Original Message-----
> From: Harbs [mailto:harbs.li...@gmail.com] 
> Sent: 19 July 2018 14:19
> To: dev@royale.apache.org
> Subject: [EXTERNAL] Re: Query on Royale dependency generation
> 
> If it’s in the big list, it should be initialized correctly.
> 
> Are you initializing a BinaryData as a static const (or preinitialized var)?
> 
> i.e. public static const DATA:BinaryData = new BinaryData() is a no-no.
> 
> I’d really like to have the compiler delay loading of static consts and var 
> to the very end of the loading. That would allow this pattern…
> 
>> On Jul 19, 2018, at 4:06 PM, Frost, Andrew <andrew.fr...@harman.com> wrote:
>> 
>> Hi
>> 
>> Yes (it's weird!) - okay so I just set the -remove-circulars option to true 
>> explicitly but still no change (from the default).
>> 
>> If you look in your html file, do you get just:
>> goog.addDependency('../../../org/apache/royale/utils/BinaryData.js', 
>> ['org.apache.royale.utils.BinaryData'], 
>> ['org.apache.royale.utils.IBinaryDataInput', 
>> 'org.apache.royale.utils.IBinaryDataOutput']);
>> for the dependencies of it?
>> 
>> In the big list of dependencies at the start, then yes Endian is showing up 
>> there. BinaryData isn't in that big list, because this is a dependency of 
>> another of my classes (which is in the list). It's constructor is being 
>> called because there's a static property being initialised i.e.
>> static private var _bytes : BinaryData = new BinaryData();
>> 
>> 
>> From a bit more digging, the issue (whether it happens or not) seems to be 
>> due to the order in which the files are loaded; there can be a specific 
>> order be applied in terms of ensuring that the dependencies are loaded 
>> before the classes that require them, but there isn't a dependency link 
>> between BinaryData and Endian (as you can see from your compiled .js files). 
>> So without this dependency, it seems like luck? as to which order these go 
>> in?
>> 
>> I've just created another project and this one works fine, but in the 
>> network info I can that Endian.js is being loaded prior to BinaryData.js. I 
>> can't see why this would be: it seems to just be down to the order that the 
>> big dependency list at the start of the html script is written. And I can't 
>> actually see why with one project, I'm ending up with one of our own classes 
>> early on in that list ... which means I currently have two solutions for 
>> fixing this: (a) add the endian dependency to the binarydata line in the 
>> html; (b) reorder the main list of dependencies at the top of the html to 
>> make endian appear earlier on. Neither of these are a good solution when 
>> this file is generated on every build!!
>> 
>> So: am I right in thinking that the dependency list for the BinaryData.js 
>> should include the Endian one? i.e. this is wrong:
>> goog.addDependency('../../../org/apache/royale/utils/BinaryData.js', 
>> ['org.apache.royale.utils.BinaryData'], 
>> ['org.apache.royale.utils.IBinaryDataInput', 
>> 'org.apache.royale.utils.IBinaryDataOutput']);
>> 
>> If so, then that needs to change (somehow) and it would then solve my 
>> problem...
>> 
>> thanks
>> 
>>  Andrew
>> 
>> 
>> -----Original Message-----
>> From: Harbs [mailto:harbs.li...@gmail.com]
>> Sent: 19 July 2018 13:32
>> To: dev@royale.apache.org
>> Subject: [EXTERNAL] Re: Query on Royale dependency generation
>> 
>> The Endian dependency should be added to the main application dependency. 
>> The entire list should be included there. (I have 872 dependencies listed.) 
>> ‘org.apache.royale.utils.Endian’ is one of them.
>> 
>> I am also using URLStream and URLBinaryLoader which list Endian as a 
>> dependency, so it’s possible it’s being pulled from there. I’m not sure I 
>> have an application which uses BinaryData without one of those.
>> 
>>> On Jul 19, 2018, at 3:19 PM, Harbs <harbs.li...@gmail.com> wrote:
>>> 
>>> That’s weird. I believe the default is false (although I think the default 
>>> should be true).
>>> 
>>> Try setting -remove-circulars to true. I think that should resolve it.
>>> 
>>> Yes. I’m using BinaryData extensively.
>>> 
>>>> On Jul 19, 2018, at 3:15 PM, Frost, Andrew <andrew.fr...@harman.com> wrote:
>>>> 
>>>> Hi
>>>> 
>>>> I'm not using it on my build command line, i.e. it's set as the default 
>>>> 'true'.
>>>> 
>>>> If I do set it to 'false' then I get what I would expect from the code, 
>>>> i.e. it ignores the interfaces and just outputs the discovered 
>>>> dependencies - including the google one:
>>>> goog.addDependency('../../../org/apache/royale/utils/BinaryData.js',
>>>> ['org.apache.royale.utils.BinaryData'], ['goog.DEBUG', 
>>>> 'org.apache.royale.utils.Endian']);
>>>> 
>>>> But now I get hundreds of errors from the browser's JS engine e.g. 
>>>> IStatesObject.js:42 Uncaught TypeError: Cannot read property 
>>>> 'IEventDispatcher' of undefined  at IStatesObject.js:42
>>>> (anonymous) @ IStatesObject.js:42
>>>> IUIBase.js:58 Uncaught TypeError: Cannot read property 
>>>> 'IEventDispatcher' of undefined  at IUIBase.js:58
>>>> (anonymous) @ IUIBase.js:58
>>>> IBeadModel.js:38 Uncaught TypeError: Cannot read property 
>>>> 'IEventDispatcher' of undefined  at IBeadModel.js:38
>>>> (anonymous) @ IBeadModel.js:38
>>>> Event.js:33 Uncaught TypeError: Cannot read property 'Event' of 
>>>> undefined  at Event.js:33
>>>> (anonymous) @ Event.js:33
>>>> base.js:2484 Uncaught TypeError: Cannot read property 'prototype' of 
>>>> undefined  at Object.goog.inherits (base.js:2484)  at UIBase.js:44 
>>>> goog.inherits @ base.js:2484
>>>> (anonymous) @ UIBase.js:44
>>>> base.js:2484 Uncaught TypeError: Cannot read property 'prototype' of 
>>>> undefined  at Object.goog.inherits (base.js:2484)  at 
>>>> eventtarget.js:96 goog.inherits @ base.js:2484
>>>> (anonymous) @ eventtarget.js:96
>>>> base.js:2484 Uncaught TypeError: Cannot read property 'prototype' of 
>>>> undefined  at Object.goog.inherits (base.js:2484)  at 
>>>> HTMLElementWrapper.js:28 .....
>>>> 
>>>> 
>>>> I'm assuming I'm not meant to be editing the html dependency list manually 
>>>> (there's another one to change, Namespace.js has a dependency on 
>>>> Language.js due to the use of "is") so unless something here is 
>>>> project-specific that's changing how it's outputting/parsing the 
>>>> dependencies, I'm not sure what's up.
>>>> 
>>>> If anyone has a project that uses BinaryData, are they able to check 
>>>> what they see in the generated HTML for that one, to see whether 
>>>> it's just me who doesn't have the Endian dependency added..? FWIW 
>>>> I've been trying both with 0.9.2 downloaded via NPM, and the latest 
>>>> develop branch (well perhaps a week out of date now..)
>>>> 
>>>> thanks
>>>> 
>>>> Andrew
>>>> 
>>>> 
>>>> -----Original Message-----
>>>> From: Harbs [mailto:harbs.li...@gmail.com]
>>>> Sent: 19 July 2018 12:18
>>>> To: dev@royale.apache.org
>>>> Subject: [EXTERNAL] Re: Query on Royale dependency generation
>>>> 
>>>> Are you using the -remove-circulars compiler option?
>>>> 
>>>>> On Jul 19, 2018, at 1:05 PM, Frost, Andrew <andrew.fr...@harman.com> 
>>>>> wrote:
>>>>> 
>>>>> Hi guys
>>>>> 
>>>>> I'd been getting an error when running a simple Royale application:
>>>>> Uncaught TypeError: Cannot read property 'BIG_ENDIAN' of undefined 
>>>>> at new org.apache.royale.utils.BinaryData (BinaryData.js:28)
>>>>> 
>>>>> the line in question is from the constructor:
>>>>> org.apache.royale.utils.BinaryData = function(bytes) {  bytes = 
>>>>> typeof bytes !== 'undefined' ? bytes : null;  this._endian = 
>>>>> org.apache.royale.utils.Endian.BIG_ENDIAN;
>>>>> and "Endian" is undefined.
>>>>> 
>>>>> After a little digging I found this is because the BinaryData object is 
>>>>> being constructed without the JS engine having knowledge of the "Endian" 
>>>>> class: something went wrong with the google dependency thing. In my 
>>>>> generated html page I have a line:
>>>>> goog.addDependency('../../../org/apache/royale/utils/BinaryData.js'
>>>>> , ['org.apache.royale.utils.BinaryData'],
>>>>> ['org.apache.royale.utils.IBinaryDataInput',
>>>>> 'org.apache.royale.utils.IBinaryDataOutput']);
>>>>> and if I change this to:
>>>>> goog.addDependency('../../../org/apache/royale/utils/BinaryData.js'
>>>>> , ['org.apache.royale.utils.BinaryData'],
>>>>> ['org.apache.royale.utils.IBinaryDataInput',
>>>>> 'org.apache.royale.utils.IBinaryDataOutput',
>>>>> 'org.apache.royale.utils.Endian']);
>>>>> then it works.
>>>>> 
>>>>> Looking at where this comes from in the compiler:
>>>>> compiler-jx/src/main/java/org/apache/royale/compiler/internal/graph
>>>>> / Go ogleDepsWriter.java function "generateDeps" is creating these 
>>>>> lists, and if the "removeCirculars" value is true (which it is by 
>>>>> default unless changed on the command-line) then we add dependencies for 
>>>>> the interfaces that we implement (gd.fileInfo.impls) and any static 
>>>>> dependencies (gd.fileInfo.staticDeps) but we don't add the actual 
>>>>> dependencies that were calculated (gd.deps or gd.fileInfo.deps - both of 
>>>>> these contain the Endian definition).
>>>>> 
>>>>> So I can fix my project by updating the compiler to do:
>>>>>  if (gd.fileInfo.deps != null)
>>>>>        deps.addAll(gd.fileInfo.deps); and then it works: the 
>>>>> generated line though is:
>>>>> goog.addDependency('../../../org/apache/royale/utils/BinaryData.js'
>>>>> , ['org.apache.royale.utils.BinaryData'], ['goog.DEBUG', 
>>>>> 'org.apache.royale.utils.Endian', 
>>>>> 'org.apache.royale.utils.IBinaryDataInput',
>>>>> 'org.apache.royale.utils.IBinaryDataOutput']);
>>>>> 
>>>>> 
>>>>> So my questions:
>>>>> 
>>>>> 1.  where is the fault here? Am I right in thinking that there's a 
>>>>> missing set of dependencies that need to also be added per the above 
>>>>> snippet, or should the Endian definition be listed as a dependency in the 
>>>>> gd.fileInfo.staticDeps list (which is null for me)  2.  presumably we 
>>>>> don't want "goog.DEBUG" to end up in the dependency list: is there a 
>>>>> sensible way of getting rid of this (or should we just manually filter 
>>>>> out anything starting "goog.")?
>>>>> 3.  if we should be adding these dependencies separately, is there a 
>>>>> preference for "gd.deps" vs "gd.fileInfo.deps"?
>>>>> 
>>>>> thanks
>>>>> 
>>>>> Andrew
>>>>> 
>>>>> 
>>>> 
>>> 
>> 
> 

Reply via email to