IE11 JIT broken when using class properties only with the latest EDGE document mode

By design Issue #11312271

Details

Author
Jay S.
Created
Mar 17, 2017
Privacy
This issue is public.
Found in
  • Internet Explorer
Reports
Reported by 1 person

Sign in to watch or report this issue.

Steps to reproduce

This issue is broken only with IE11 EDGE doc mode, whereas rest of the doc mode <= 10 works exactly fine.

We know that MS is not working on IE11 fixes considering EDGE, but this is breaking the latest EDGE doc mode itself not the older doc modes in IE11 and we can’t live with it like that forever. It would have been okay to not fix if the issue was with the older doc modes like IE10/9, but here the issue is with the latest IE11 EDGE doc mode itself.

It’s disturbing as say the web page should be in the latest standards document mode like EDGE and its breaking in that document mode itself. Down-level doc modes were its not recommended works exactly fine, seems to be a regression with IE11.

Calling Function.name on Classes fails if it is called in the order of base class->child. If called in the child->base class order, it succeeds.

Simplified Repro, launch below URL and open F12 console section to observe the output.
https://jsfiddle.net/2so35uf3/1/

Actual:
console.log(Animal.name); // returns Animal in IE11 with EDGE doc mode
console.log(Snake.name); // returns Animal in IE11 with EDGE doc mode
console.log(Horse.name); // returns Animal in IE11 with EDGE doc mode
Actual Output:
Animal
Animal
Animal

Expected Output:
Animal
Snake
Horse

Now, just change the doc mode to IE10 and observe the console. It works as expected.

Based on walking the code I don’t think that is the problem. This appears to be a flaw in the IE11 JIT.

I’m looking for any advice on how to handle this besides (1) don’t use IE11 or (2) don’t use Function.name.

Sample:

// Typescript
class Animal {
hello(person: string) {
console.log(Hello ${person});
}
}

class Snake extends Animal {
hello(person: string) {
console.log(“I’m a snake”);
super.hello(person);
}
}

class Horse extends Animal {
get wow(): string {
return "wow";
}
}

console.log(Animal.name);
console.log(Snake.name);
console.log(Horse.name);

tsc -t ES2015 with produces this JavaScript:

class Animal {
hello(person) {
console.log(Hello ${person});
}
}
class Snake extends Animal {
hello(person) {
console.log(“I’m a snake”);
super.hello(person);
}
}
class Horse extends Animal {
get wow() {
return "wow";
}
}
console.log(Animal.name);
console.log(Snake.name);
console.log(Horse.name);

This issue is also reported in:
http://stackoverflow.com/questions/42470179/ie11-javascript-behavior-with-polyfilled-function-name
https://social.technet.microsoft.com/Forums/en-US/761d1195-bb1d-4129-a39d-420c304e5b15/ie11-jit-broken-when-using-class-properties?forum=ieitprocurrentver

Hope this is fixed sooner. Thanks.

Attachments

0 attachments

    Comments and activity

    • Microsoft Edge Team

      Changed Assigned To to “James M.”

      Changed Assigned To to “Ed M.”

      Changed Status to “By design”

    • IE doesn’t support ES6 class.  It looks like the sample is a polyfill trying create ES6 class semantic.

      The problem is actually with the JS code itself.  The problem is with this code
       if (needsPolyfill) {
              // For:
              //  * IE >=9 <12
              //  * Chrome >=5 <33
              if (canDefineProp) {
                  Object.defineProperty(Function.prototype, "name", {
                      get: function() {
                          var name = _name.call(this);
                          // Since named function definitions have immutable names, also memoize the
                          // output by defining the name property directly on this Function
                          // instance so that this polyfill will not need to be invoked again
                          if (this !== Function.prototype) {
                              Object.defineProperty(this, "name", {
                                  value: name,
                                  configurable: true
                              });

                          }
                          return name;
                      },
                      configurable: true
                  });
              }

      After you call the getter for “name” on Animal, you set it as a property of the function Animal.

      However, in function_inherits(), you set up the proto of Snake to Animal.
      So after Animal defines "name", it shadows the “name” getter on Function.prototype.

      That’s why if you do it in reverse order it works.

      Also IE10 doesn’t support proto, so function _inherits() doesn’t really set up the prototype chain for Snake and Horses.
      So no shadowing happens when “name” got defined on Animal.

    • The JS was created Typescript->ES6->Babel (with polyfills). The _inherits is a babel construct.

      The core issue I see is that the polyfill (https://github.com/JamesMGreene/Function.name) is memoizing the name with:
      if (this !== Function.prototype) {
      Object.defineProperty(this, "name", {
      value: name,
      configurable: true
      });
      }

      I found, that a simple tweak of:
      if (this !== Function.prototype) {
      Object.defineProperty(this.prototype, "name", {
      value: name,
      configurable: true
      });
      }

      allowed it to operate correctly.

      What do you think?

    • the code I posted is not working as I expected :-)

      For now, I’ve just the Object.define and and looking up the name every time it is asked for.

    You need to sign in to your Microsoft account to add a comment.

    Sign in