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
>

Reply via email to