Re: Problem with "this" inside static method

2018-06-19 Thread Alex Harui


On 6/19/18, 4:03 AM, "Harbs"  wrote:


I can rewrite the cases I keep bumping into with these problems, but it 
seems to me like this is something we really need to fix.

Makes sense.  Go for it. Good luck.

I looked at the compiler code, but I don’t see any comments on why this is 
happening. I’m not sure what you mean about ES5 strict mode. The only 
limitation is that function statements (i.e. named functions) need to be at the 
top level of a script or function. This should not effect anonymous functions 
at all. I think we should leave top-level functions alone as well.

I tried to follow the logic on how it removes function blocks, and I had 
trouble doing so…

That may be why it isn't outputting the right thing.  I think functions have 
classifications as Local or not.  I think any local function gets hoisted right 
now.  I suspect the solution will involve understanding the node patterns that 
distinguish local functions that must be hoisted vs those that don't, plus also 
making closures and assigning them instead of assigning just functions.

My 2 cents,
-Alex

Harbs

> On Jun 18, 2018, at 7:44 AM, Harbs  wrote:
> 
>> I'm unclear as to what the desired JS output really should be.  Would it 
really work in JS if the function was directly assigned to a slot on the 
instance instead of a temporary variable first?  If so why?
> 
> Yes. Because it’s a reference to an instance variable function “cal"l can 
replace “this” in that case.
> 
>> I'm also surprised that in JS, a function call can't have its 'this' 
pointer reassigned by Function.call.  What is the actual JS that is running?
> 
> Struct.prototype.decode = function(stream, parent, length) {
>  var res, _ref;
>  if (length == null) {
>length = 0;
>  }
>  res = this._setup(stream, parent, length);
>  this._parseFields(stream, res, this.fields);
>  if ((_ref = this.process) != null) {
>_ref.call(res, stream);
>  }
>  return res;
> };
> 
> _ref.call(res, stream) did not work because despite res being passed into 
the function, “this” remained the global this in the static function.
> 
> I’m really not sure why passing in this does not work on static 
functions. I was surprised myself.
> 
> FWIW, I rewrote the code to avoid using “this”, but it’s probably not a 
bad idea to fix this if possible…
> 
> Harbs
> 
>> On Jun 18, 2018, at 7:09 AM, Alex Harui  wrote:
>> 
>> Without actually looking at the compiler, I think that functions that 
are not methods are pulled out and declared early for ES5 (strict?) reasons.  
I'm not sure there is a good distinction between a "local function" and 
assigning a function to something.
>> 
>> IIRC, "assigning" some functions like in a function as a parameter like 
addEventListener is supposed to generate Language.closure wrappers to make a 
"closure" and bind the 'this' pointer to the method.
>> 
>> I'm unclear as to what the desired JS output really should be.  Would it 
really work in JS if the function was directly assigned to a slot on the 
instance instead of a temporary variable first?  If so why?
>> 
>> I'm also surprised that in JS, a function call can't have its 'this' 
pointer reassigned by Function.call.  What is the actual JS that is running?
>> 
>> -Alex
>> 
>> On 6/17/18, 7:29 AM, "Harbs"  wrote:
>> 
>>   An additional related problem:
>> 
>>   Using “call” with a different “this” will not work with the aliased 
functions either.
>> 
>>   This is proving to be a challenge for me…
>> 
>>   Harbs
>> 
>>> On Jun 17, 2018, at 12:02 PM, Harbs  wrote:
>>> 
>>> I have the following class:
>>> 
https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpaste.apache.org%2Fr7Ek=02%7C01%7Caharui%40adobe.com%7Cd50a81aaa8f8453ae0f408d5d45eb567%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636648425616368813=5Jz5bTTwhdwweaam%2BghkMCSwkM4WWyqnWHhr%2BrDpub8%3D=0
 

>>> 
>>> Which gets cross-compiled to:
>>> 
https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpaste.apache.org%2F3k1r=02%7C01%7Caharui%40adobe.com%7Cd50a81aaa8f8453ae0f408d5d45eb567%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636648425616378822=t50ucBXXnOezZW9mt%2BuMH5J5N%2BlJGGJBoBer7SkYU7I%3D=0
 

>>> 
>>> The problem 

Re: Problem with "this" inside static method

2018-06-19 Thread Harbs
I’m pretty sure this is not a problem with static functions per se. It seems to 
be a general functional problem. Here’s another place I ran into issues:

I have some code inside a public function:

this.glyphInfos = glyphRun.glyphs.map(function(glyph):GlyphInfo{return new 
GlyphInfo(this.font, glyph.id, glyph.codePoints.slice())});

This gets cross-compiled into:

var /** @type {Function} */ __localFn0__ = function(glyph) {
return new com.printui.fontkit.opentype.GlyphInfo(this.font, glyph.id, 
glyph.codePoints.slice());
}
this.glyphInfos = glyphRun.glyphs.map(__localFn0__);

When the function is inline, “this” refers to the class instance.

After being pulled out into a local variable, “this” refers to the global 
Window object.

I can rewrite the cases I keep bumping into with these problems, but it seems 
to me like this is something we really need to fix.

I looked at the compiler code, but I don’t see any comments on why this is 
happening. I’m not sure what you mean about ES5 strict mode. The only 
limitation is that function statements (i.e. named functions) need to be at the 
top level of a script or function. This should not effect anonymous functions 
at all. I think we should leave top-level functions alone as well.

I tried to follow the logic on how it removes function blocks, and I had 
trouble doing so…

Harbs

> On Jun 18, 2018, at 7:44 AM, Harbs  wrote:
> 
>> I'm unclear as to what the desired JS output really should be.  Would it 
>> really work in JS if the function was directly assigned to a slot on the 
>> instance instead of a temporary variable first?  If so why?
> 
> Yes. Because it’s a reference to an instance variable function “cal"l can 
> replace “this” in that case.
> 
>> I'm also surprised that in JS, a function call can't have its 'this' pointer 
>> reassigned by Function.call.  What is the actual JS that is running?
> 
> Struct.prototype.decode = function(stream, parent, length) {
>  var res, _ref;
>  if (length == null) {
>length = 0;
>  }
>  res = this._setup(stream, parent, length);
>  this._parseFields(stream, res, this.fields);
>  if ((_ref = this.process) != null) {
>_ref.call(res, stream);
>  }
>  return res;
> };
> 
> _ref.call(res, stream) did not work because despite res being passed into the 
> function, “this” remained the global this in the static function.
> 
> I’m really not sure why passing in this does not work on static functions. I 
> was surprised myself.
> 
> FWIW, I rewrote the code to avoid using “this”, but it’s probably not a bad 
> idea to fix this if possible…
> 
> Harbs
> 
>> On Jun 18, 2018, at 7:09 AM, Alex Harui  wrote:
>> 
>> Without actually looking at the compiler, I think that functions that are 
>> not methods are pulled out and declared early for ES5 (strict?) reasons.  
>> I'm not sure there is a good distinction between a "local function" and 
>> assigning a function to something.
>> 
>> IIRC, "assigning" some functions like in a function as a parameter like 
>> addEventListener is supposed to generate Language.closure wrappers to make a 
>> "closure" and bind the 'this' pointer to the method.
>> 
>> I'm unclear as to what the desired JS output really should be.  Would it 
>> really work in JS if the function was directly assigned to a slot on the 
>> instance instead of a temporary variable first?  If so why?
>> 
>> I'm also surprised that in JS, a function call can't have its 'this' pointer 
>> reassigned by Function.call.  What is the actual JS that is running?
>> 
>> -Alex
>> 
>> On 6/17/18, 7:29 AM, "Harbs"  wrote:
>> 
>>   An additional related problem:
>> 
>>   Using “call” with a different “this” will not work with the aliased 
>> functions either.
>> 
>>   This is proving to be a challenge for me…
>> 
>>   Harbs
>> 
>>> On Jun 17, 2018, at 12:02 PM, Harbs  wrote:
>>> 
>>> I have the following class:
>>> https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpaste.apache.org%2Fr7Ek=02%7C01%7Caharui%40adobe.com%7Cd50a81aaa8f8453ae0f408d5d45eb567%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636648425616368813=5Jz5bTTwhdwweaam%2BghkMCSwkM4WWyqnWHhr%2BrDpub8%3D=0
>>>  
>>> 
>>> 
>>> Which gets cross-compiled to:
>>> https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpaste.apache.org%2F3k1r=02%7C01%7Caharui%40adobe.com%7Cd50a81aaa8f8453ae0f408d5d45eb567%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636648425616378822=t50ucBXXnOezZW9mt%2BuMH5J5N%2BlJGGJBoBer7SkYU7I%3D=0
>>>  
>>> 

Re: Problem with "this" inside static method

2018-06-17 Thread Harbs
> I'm unclear as to what the desired JS output really should be.  Would it 
> really work in JS if the function was directly assigned to a slot on the 
> instance instead of a temporary variable first?  If so why?

Yes. Because it’s a reference to an instance variable function “cal"l can 
replace “this” in that case.

> I'm also surprised that in JS, a function call can't have its 'this' pointer 
> reassigned by Function.call.  What is the actual JS that is running?

Struct.prototype.decode = function(stream, parent, length) {
  var res, _ref;
  if (length == null) {
length = 0;
  }
  res = this._setup(stream, parent, length);
  this._parseFields(stream, res, this.fields);
  if ((_ref = this.process) != null) {
_ref.call(res, stream);
  }
  return res;
};

_ref.call(res, stream) did not work because despite res being passed into the 
function, “this” remained the global this in the static function.

I’m really not sure why passing in this does not work on static functions. I 
was surprised myself.

FWIW, I rewrote the code to avoid using “this”, but it’s probably not a bad 
idea to fix this if possible…

Harbs

> On Jun 18, 2018, at 7:09 AM, Alex Harui  wrote:
> 
> Without actually looking at the compiler, I think that functions that are not 
> methods are pulled out and declared early for ES5 (strict?) reasons.  I'm not 
> sure there is a good distinction between a "local function" and assigning a 
> function to something.
> 
> IIRC, "assigning" some functions like in a function as a parameter like 
> addEventListener is supposed to generate Language.closure wrappers to make a 
> "closure" and bind the 'this' pointer to the method.
> 
> I'm unclear as to what the desired JS output really should be.  Would it 
> really work in JS if the function was directly assigned to a slot on the 
> instance instead of a temporary variable first?  If so why?
> 
> I'm also surprised that in JS, a function call can't have its 'this' pointer 
> reassigned by Function.call.  What is the actual JS that is running?
> 
> -Alex
> 
> On 6/17/18, 7:29 AM, "Harbs"  wrote:
> 
>An additional related problem:
> 
>Using “call” with a different “this” will not work with the aliased 
> functions either.
> 
>This is proving to be a challenge for me…
> 
>Harbs
> 
>> On Jun 17, 2018, at 12:02 PM, Harbs  wrote:
>> 
>> I have the following class:
>> https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpaste.apache.org%2Fr7Ek=02%7C01%7Caharui%40adobe.com%7Cd50a81aaa8f8453ae0f408d5d45eb567%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636648425616368813=5Jz5bTTwhdwweaam%2BghkMCSwkM4WWyqnWHhr%2BrDpub8%3D=0
>>  
>> 
>> 
>> Which gets cross-compiled to:
>> https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpaste.apache.org%2F3k1r=02%7C01%7Caharui%40adobe.com%7Cd50a81aaa8f8453ae0f408d5d45eb567%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636648425616378822=t50ucBXXnOezZW9mt%2BuMH5J5N%2BlJGGJBoBer7SkYU7I%3D=0
>>  
>> 
>> 
>> The problem is here:
>> struct.process = function():void {
>>if (this.version === 0) {
>>for (var i:int = 0; i < this.offsets.length; i++) {
>>this.offsets[i] <<= 1;
>>}
>>}
>> };
>> 
>> In this case, “this” refers to the “struct” VersionedStruct instance. (At 
>> least in Javascript. Am I correct in assuming that’s the case in 
>> ActionScript as well?)
>> 
>> However, it gets cross-compiled to the following where “this" is the global 
>> this:
>> 
>> var /** @type {Function} */ __localFn0__ = function() {
>>  if (this.version === 0) {
>>for (var /** @type {number} */ i = 0; i < this.offsets.length; i++) {
>>  this.offsets[i] <<= 1;
>>}
>>  }
>> }
>> com.printui.fontkit.tables.loca.struct.process = __localFn0__;
>> 
>> What is the purpose of pulling the inline function out?
>> 
>> Harbs
> 
> 
> 



Problem with "this" inside static method

2018-06-17 Thread Harbs
I have the following class:
https://paste.apache.org/r7Ek 

Which gets cross-compiled to:
https://paste.apache.org/3k1r 

The problem is here:
struct.process = function():void {
if (this.version === 0) {
for (var i:int = 0; i < this.offsets.length; i++) {
this.offsets[i] <<= 1;
}
}
};

In this case, “this” refers to the “struct” VersionedStruct instance. (At least 
in Javascript. Am I correct in assuming that’s the case in ActionScript as 
well?)

However, it gets cross-compiled to the following where “this" is the global 
this:

var /** @type {Function} */ __localFn0__ = function() {
  if (this.version === 0) {
for (var /** @type {number} */ i = 0; i < this.offsets.length; i++) {
  this.offsets[i] <<= 1;
}
  }
}
com.printui.fontkit.tables.loca.struct.process = __localFn0__;

What is the purpose of pulling the inline function out?

Harbs