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 <[email protected]> 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 <[email protected]> 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" <[email protected]> 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 <[email protected]> wrote:
>>>
>>> I have the following class:
>>> https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpaste.apache.org%2Fr7Ek&data=02%7C01%7Caharui%40adobe.com%7Cd50a81aaa8f8453ae0f408d5d45eb567%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636648425616368813&sdata=5Jz5bTTwhdwweaam%2BghkMCSwkM4WWyqnWHhr%2BrDpub8%3D&reserved=0
>>>
>>> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpaste.apache.org%2Fr7Ek&data=02%7C01%7Caharui%40adobe.com%7Cd50a81aaa8f8453ae0f408d5d45eb567%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636648425616368813&sdata=5Jz5bTTwhdwweaam%2BghkMCSwkM4WWyqnWHhr%2BrDpub8%3D&reserved=0>
>>>
>>> Which gets cross-compiled to:
>>> https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpaste.apache.org%2F3k1r&data=02%7C01%7Caharui%40adobe.com%7Cd50a81aaa8f8453ae0f408d5d45eb567%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636648425616378822&sdata=t50ucBXXnOezZW9mt%2BuMH5J5N%2BlJGGJBoBer7SkYU7I%3D&reserved=0
>>>
>>> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpaste.apache.org%2F3k1r&data=02%7C01%7Caharui%40adobe.com%7Cd50a81aaa8f8453ae0f408d5d45eb567%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636648425616378822&sdata=t50ucBXXnOezZW9mt%2BuMH5J5N%2BlJGGJBoBer7SkYU7I%3D&reserved=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
>>
>>
>>
>