Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

super() not calling parent's constructor on IE9 #133

Closed
jackismissing opened this issue Nov 1, 2015 · 16 comments
Closed

super() not calling parent's constructor on IE9 #133

jackismissing opened this issue Nov 1, 2015 · 16 comments

Comments

@jackismissing
Copy link

Hello,

After upgrading to babel@6.0.14, babelify@7.1.0 and babel-preset-es2015@ 6.0.14 it seems that on IE9, calling super() on a child class' constructor doesn't call the parent's constructor anymore.

The two classes live on different files and I import/export the whole using the ES2015 module syntax.

Like so:

// in myClassA.js
export class A {
    constructor() {
        console.log('I am your father');
    }

    init() {
        console.log('And I know who your sister is');
    }
}

// in myClassB.js
import {A} from './myClassA.js';

export class B extends A {
    constructor() {
        // Won't do anything
        super();
    }

    init() {
        // Will fire A.init() properly: 'And I know who your sister is' is logged
        super.init();
    }
}

// Wherever else
import {B} from './myClassB';

window.onload = () => {
    var B = new B();
}

And in my gulp task:

(...).transform(babel.configure({
    presets: ["es2015"],
    ignore: ["client/vendor"]
}));

It's working well on IE >= 10 but unfortunately not on IE9.
I'm opening the issue on the babelify repo since I'm using it but maybe it belongs to the babel one.

Reverting back to babel@5 and babelify@6 fixes the issue.

Thanks for the support and continue the good work guys !

@zertosh
Copy link
Member

zertosh commented Nov 1, 2015

Hmm. That's def not a babelify issue. I'm surprised it works with babel@5 because of https://github.com/babel/babel.github.io/blob/862b43d/docs/advanced/caveats.md#classes-10-and-below. Try using loose mode.

@mortterna
Copy link

I just stumbled on this exact issue. Super class constructor is never called with 'es2015' or 'es2015-loose' presets and with or without mentioned proto to assign plugin.

@zajca
Copy link

zajca commented Nov 25, 2015

I run into exact same issue. loose doesn't work.

I revert back to Babel5.

minimal code example: test is not printed on IE9,10 with babel6

class test {
    constructor() {
        console.log('test');
    }
}
​
class test2 extends test{
    constructor() {
        super();
        console.log('test2');
    }
}
​
new test2();

@zertosh
Copy link
Member

zertosh commented Nov 25, 2015

This issue should be moved to Babel

@karol-f
Copy link

karol-f commented Dec 3, 2015

In IE 10 I installed babel-plugin-transform-es2015-object-super and added it to .babelrc:

{
  "plugins": [
      "transform-es2015-object-super"
  ]
}

Hope it will help for IE9 too

@tolpit
Copy link

tolpit commented Dec 22, 2015

Object.setPrototypeOf is undefined on IE <= 11, and babel doesn't seem to handle this case. You could use a polyfill for the moment : https://gist.github.com/edoardocavazza/47246856759f2273e48b#file-object-setprototypeof-ie9-js

@miloszsobczak
Copy link

What about this issue? :(

@zertosh
Copy link
Member

zertosh commented Jan 17, 2016

For super calls to work in IE9, you must enable "loose" mode for the class transform. For inherited static properties to work in IE9, you must also add the babel-plugin-transform-proto-to-assign plugin.

This is the minimal set of transforms you need to get classes with super and inheritance working in IE9:

browserify('./index.js')
  .transform('babelify', {
    plugins: [
      'transform-es2015-block-scoping',
      ['transform-es2015-classes', {loose: true}],
      'transform-proto-to-assign',
    ],
  })
  .bundle()
  .pipe(fs.createWriteStream('out.js'));

@zertosh
Copy link
Member

zertosh commented Jan 17, 2016

Here is a fully working gist https://gist.github.com/zertosh/4f818163e4d68d58c0fa

@gajus
Copy link

gajus commented Jan 27, 2016

@jmlopez-rod
Copy link

@zertosh, thanks for the minimal set of transforms, this has gotten our project to work again in IE 9 after the update to babel 6. For reference, the previous solution was to use spec.protoToAssign as described in http://ricostacruz.com/til/babel-ie-class-inheritance.html.

So far this fixes our issues with IE 9 and everything still seems to work, my only concern is that I cannot use the transform-runtime to stop the code bloating as described in https://github.com/babel/babel-loader#babel-is-injecting-helpers-into-each-file-and-bloating-my-code. Any ideas how to add this to the minimal set?

@jmlopez-rod
Copy link

Documenting my findings for others with similar issues. This is my current babel configuration

  "babel": {
    "presets": [
      "es2015"
    ],
    "plugins": [
      ["transform-es2015-classes", { "loose": true }],
      "transform-runtime"
    ]
  },

This will still give the same problem, but if we use the transform-proto-to-assign plugin we can see that it defines the following function when babel runs:

function _defaults(obj, defaults) {
  var keys = Object.getOwnPropertyNames(defaults);
  for (var i = 0; i < keys.length; i++) {
    var key = keys[i];
    var value = Object.getOwnPropertyDescriptor(defaults, key);
    if (value && value.configurable && obj[key] === undefined) {
      Object.defineProperty(obj, key, value);
    }
  }
  return obj;
}

which is the same function found in babel-runtime/helpers/defaults.js.

The inherit function provided by the tranform-proto-to-assign plugins checks to see if Object.setPrototypeOf is defined, if it isn't then it uses _defaults. When we use the transform-runtime plugin we delegate the inherit function to the one provided by babel-runtime which does not define the _defaults function in case Object.setPrototypeOf isn't defined. Thus, if we wish to keep the same functionality while using babel-runtime we can either use the polyfill provided by @tolpit https://gist.github.com/edoardocavazza/47246856759f2273e48b#file-object-setprototypeof-ie9-js , or use the one provided by babel-runtime:

const key = 'setPrototypeOf';
if (typeof Object[key] === 'undefined') {
  Object[key] = require('babel-runtime/helpers/defaults.js').default;
}

NOTE: if you want to use typeof Object.setPrototypeOf instead we need to use transform-runtime with an option:

["transform-runtime", { "polyfill": false }]

For some reason using it by itself it replaces Object.setPrototypeOf by some other function which does not allow it to work on IE. I'm opting by the one I specified to keep the babel plugins to a minimum.

WARNING: when using the polyfill make sure to put it on its own file and then import it at the top of your main file. That is, don't use the polyfill like this:

const key = 'setPrototypeOf';
if (typeof Object[key] === 'undefined') {
  Object[key] = require('babel-runtime/helpers/defaults.js').default;
}

import 'myModule';
import 'otherModule';

This will make myModule and otherModule execute first. Instead do

import 'myPolyfills.js';
import 'myModule';
import 'otherModule';

where myPolyfills.js is a file containing the polyfill mentioned above.

@peternoordijk
Copy link

Is this still an issue? I tried to run a few tests and I didn't encounter any problems anymore on IE9. I used the es2015-loose preset without transform-proto-to-assign. My code is in here: https://jsfiddle.net/peternoordijk/ymtyud9y/

@rxaviers
Copy link

rxaviers commented Jun 7, 2016

Please, what's the final word on this? It seems like super doesn't work on <=IE10 except if using es2015-loose preset. Is that correct? Is that the suggested approach/workaround or is there a better solution that doesn't make use of the loose mode (e.g., inclusion of a polyfill?)? Should http://babeljs.io/docs/plugins/transform-es2015-object-super/ include a list of supported browsers? Thank you

@Pines-Cheng
Copy link

Pines-Cheng commented Aug 14, 2016

@zertosh I have tried your solution,my part of .babelrcis just like this:

{
  "plugins": [
    ["transform-es2015-classes", {"loose": true}],
    "transform-proto-to-assign",
    "transform-decorators-legacy"
  ],
  "presets": [
    "es2015",
    "react",
    "stage-0"
  ]
}

but I meet another trouble:

ERROR in ./js/kill/order/index.js
Module build failed: SyntaxError: C:/Users/Administrator/Desktop/ydh-qiang-web/src/main/webapp/pc/js/kill/order/index.js: Missing class properties transform.
  23 |     }
  24 |
> 25 |     state = {
     |     ^
  26 |         loading: false,

Do you have any idea?

@rickyblaha
Copy link

rickyblaha commented Aug 26, 2016

@Pines-Cheng the 3 plugins did not solve this issue for me either (using babel-core 6.13.2), but using preset es2015-loose did.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests