Skip to content

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

@nicodotcomputer

Description

@nicodotcomputer

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 !

Activity

zertosh

zertosh commented on Nov 1, 2015

@zertosh
Member

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

mortterna commented on Nov 24, 2015

@mortterna

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

zajca commented on Nov 25, 2015

@zajca

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

zertosh commented on Nov 25, 2015

@zertosh
Member

This issue should be moved to Babel

karol-f

karol-f commented on Dec 3, 2015

@karol-f

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

tolpit commented on Dec 22, 2015

@tolpit

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

miloszsobczak commented on Jan 17, 2016

@miloszsobczak

What about this issue? :(

zertosh

zertosh commented on Jan 17, 2016

@zertosh
Member

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

zertosh commented on Jan 17, 2016

@zertosh
Member
jmlopez-rod

jmlopez-rod commented on Feb 24, 2016

@jmlopez-rod

@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

jmlopez-rod commented on Mar 12, 2016

@jmlopez-rod

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

peternoordijk commented on Apr 20, 2016

@peternoordijk

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

rxaviers commented on Jun 7, 2016

@rxaviers

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

Pines-Cheng commented on Aug 14, 2016

@Pines-Cheng

@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

rickyblaha commented on Aug 26, 2016

@rickyblaha

@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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @zajca@rickyblaha@zertosh@karol-f@rxaviers

        Issue actions

          super() not calling parent's constructor on IE9 · Issue #133 · babel/babelify