Update: Inspired by Erik’s suggestion to use @expose, I found that I can use @expose on the structure keys instead of having to create more prototype slots. So the pattern now is:
Object.defineProperties(org_apache_flex_utils_BinaryData.prototype, { /** @expose */ productService: { /** @this {org_apache_flex_utils_BinaryData} */ get: function() { return this.productService_; }, /** @this {org_apache_flex_utils_BinaryData} */ set: function(value) { this.productService_ = value + 10; } } }); Adding @expose was a simple enough change that I was able to implement it in a few hours. A few more fixes later and the release version is up and running! Google has deprecated @expose so this solution may stop working some day. I took a quick look at what the Closure Compiler does with @expose. It looks like it replaces all dot.path syntax with obj[‘prop’] syntax so other passes simply don’t rename the string literal. If @expose goes away, we might need to change FalconJX to do the same thing: replace dot.path with obj[‘prop]. We currently don’t visit all of the hand-written JS source we write, but we might some day for another related reason: right now we don’t want renaming of variables used in binding expressions, and we don’t have a way to support renaming of variables with MXML ids. If FlexJS apps turn out to be heavy with strings, we might consider making FalconJX smarter and have it inject the @expose tags for only the strings involved in binding expressions. Then if we’re visiting all of the source to do that, we could later implement @expose directly if it goes away. Anyway, I hope to check the defineProperties change in as soon as I can adjust the tests and merge the branch. Thanks again to Erik for his advice. -Alex On 4/6/15, 3:14 PM, "Alex Harui" <aha...@adobe.com> wrote: >Hi Erik, > >Well, this renaming issue is coming from an actual scenario that runs >correctly when not minified. I think what you are showing is that the >code-flow analyzer contributes to the renaming logic. In this actual test >case, someFunction is called from an event handler, so maybe the renaming >logic can’t follow the code-flow in those situations, especially because >lots of things are set up via the MXML data structure. > >However, if we can just prevent renaming, I think that will also work. >Having to define both a dummy prototype slot with @expose as well as the >defineProperties seems redundant to me, but I think that’s the route to >take, so thanks for finding that. I’ll see if I can get to the finish >line with that. > >One more question: Defining a slot without a value generates warnings >from GCC when called from FalconJX. IOW, adding this: > > /** > * @expose > */ > org_apache_flex_utils_BinaryData.prototype.productService; > >Will result in: > > > WARNING - Suspicious code. The result of the 'getprop' operator is not >being used. > > >I’m not sure why we get this warning in FalconJX but not in the GCC >Service UI or from the GCC command line. And also @expose is deprecated. >But if you’re ok with using @expose and finding a way to shut off those >warnings, I’ll go with that. > >Thanks for the help, >-Alex > >On 4/6/15, 2:33 PM, "Erik de Bruin" <e...@ixsoftware.nl> wrote: > >>Alex, >> >>I think what you're seeing is an artifact of the way you've set up >>your example... You don't instantiate the object and never reference >>the property outside of the class' internals. WIth such a minimal >>case, that basically doesn't execute, the compiler thinks it can be >>smart and 'optimize' away vital parts of the code... If I rework your >>example a bit to make it feel more 'real world' to the compiler: >> >> >> >>/** >> * @constructor >> */ >>var org_apache_flex_utils_BinaryData = function () { >> >> /** >> * @private {number} >> */ >> this.productService_; >> >>} >> >>org_apache_flex_utils_BinaryData.prototype.someFunction = function() { >> console.log(this.productService); >>}; >> >>Object.defineProperties(org_apache_flex_utils_BinaryData.prototype, { >> productService: { >> /** @this {org_apache_flex_utils_BinaryData} */ >> get: function() { >> return this.productService_; >> }, >> /** @this {org_apache_flex_utils_BinaryData} */ >> set: function(value) { >> this.productService_ = value + 10; >> } >> } >>}); >> >>var binaryData = new org_apache_flex_utils_BinaryData(); >> >>binaryData.productService = 100; >> >>binaryData.someFunction(); >> >> >> >>... You get, without errors or warnings: >> >> >> >>'use strict';function >>a(){}Object.defineProperties(a.prototype,{a:{get:function(){return >>this.b},set:function(c){this.b=c+10}}});var b=new >>a;b.a=100;console.log(b.a); >> >> >> >>This code does actually execute and it gives the expected 110, showing >>the setter is called and the 'defineProperties' is not simply ignored. >>You see the property is renamed to the same string 'everywhere', so >>the compiler knows what it is and how to handle it. >> >>In this example you can prevent the renaming by declaring the property >>with an @expose annotation on the object's prototype just before >>calling 'Object.defineProperties': >> >> >> >>/** >> * @expose >> */ >>org_apache_flex_utils_BinaryData.prototype.productService; >> >> >> >>Which, combined, gives a compiled output: >> >> >> >>'use strict';function >>a(){}Object.defineProperties(a.prototype,{productService:{get:function(){ >>r >>eturn >>this.a},set:function(c){this.a=c+10}}});var b=new >>a;b.productService=100;console.log(b.productService); >> >> >> >>Isn't that what you're looking for? >> >>EdB >> >> >> >>-- >>Ix Multimedia Software >> >>Jan Luykenstraat 27 >>3521 VB Utrecht >> >>T. 06-51952295 >>I. www.ixsoftware.nl >