javascriptrequirejsecmascript-6babeljstypeof

Babel/RequireJS + typeof "RangeError: Maximum call stack size exceeded"


I have a very basic JS error and I'm quite ashamed to not be able to solve it...

I'm developping with ES6 and Babel and I'm making some experiments. Please note I'm using these arguments with Babel:

--presets es2015 --plugins transform-es2015-modules-amd

I have a simple module:

"use strict";

export default class Inspector {
    static inspect() {
        console.log(this.prototype.myMethod);
        console.log(typeof this.prototype.myMethod);
    }
}

I use this module like that:

"use strict";

import Inspector from "inspector";

class Child extends Inspector {
    myMethod() {
        console.log(`Hello from ${this.name}`);
    }
}

Child.inspect();

The goal here is really dumb: simply check how the prototype is populated with ES6 inheritance.

The first console.log from inspect() method displays, as expected:

function myMethod() { console.log("Hello from " + this.name); }

Inheritances has worked as expected, hourray! But the funny part is the second console.log (console.log(typeof this.prototype.myMethod);) which triggers an error:

require.js:19 RangeError: Maximum call stack size exceeded(…)

I was expecting something more like "function", but hey, I suppose I'm quite naive...

This error seems to be related to requirejs modules, but I have no clues why I can log the function but not its type.

Please also note that I can call this method in the inspect method:

static inspect() {
        this.prototype.myMethod();
}

This displays "Hello from undefined" (I was expected "Hello from Child" but since it's not a static method, it's normal. Anyway, the call is correctly performed!).

So, my question here: why can I log and call a method but I can't run typeof on it?

Thanks in advance!

EDIT: you can see below the transpiled files:

inspector.js

define(["exports"], function (exports) {
    "use strict";

    Object.defineProperty(exports, "__esModule", {
        value: true
    });

    function _typeof(obj) {
        return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj === "undefined" ? "undefined" : _typeof(obj);
    }

    function _classCallCheck(instance, Constructor) {
        if (!(instance instanceof Constructor)) {
            throw new TypeError("Cannot call a class as a function");
        }
    }

    var _createClass = (function () {
        function defineProperties(target, props) {
            for (var i = 0; i < props.length; i++) {
                var descriptor = props[i];
                descriptor.enumerable = descriptor.enumerable || false;
                descriptor.configurable = true;
                if ("value" in descriptor) descriptor.writable = true;
                Object.defineProperty(target, descriptor.key, descriptor);
            }
        }

        return function (Constructor, protoProps, staticProps) {
            if (protoProps) defineProperties(Constructor.prototype, protoProps);
            if (staticProps) defineProperties(Constructor, staticProps);
            return Constructor;
        };
    })();

    var Inspector = (function () {
        function Inspector() {
            _classCallCheck(this, Inspector);
        }

        _createClass(Inspector, null, [{
            key: "inspect",
            value: function inspect() {
                this.prototype.myMethod();
                console.log(this.prototype.myMethod);
                console.log(_typeof(this.prototype.myMethod));
            }
        }]);

        return Inspector;
    })();

    exports.default = Inspector;
});

child.js

function _typeof(obj) { return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj; }

define(["inspector"], function (_inspector) {
    "use strict";

    var _inspector2 = _interopRequireDefault(_inspector);

    function _interopRequireDefault(obj) {
        return obj && obj.__esModule ? obj : {
            default: obj
        };
    }

    function _classCallCheck(instance, Constructor) {
        if (!(instance instanceof Constructor)) {
            throw new TypeError("Cannot call a class as a function");
        }
    }

    var _createClass = (function () {
        function defineProperties(target, props) {
            for (var i = 0; i < props.length; i++) {
                var descriptor = props[i];
                descriptor.enumerable = descriptor.enumerable || false;
                descriptor.configurable = true;
                if ("value" in descriptor) descriptor.writable = true;
                Object.defineProperty(target, descriptor.key, descriptor);
            }
        }

        return function (Constructor, protoProps, staticProps) {
            if (protoProps) defineProperties(Constructor.prototype, protoProps);
            if (staticProps) defineProperties(Constructor, staticProps);
            return Constructor;
        };
    })();

    function _possibleConstructorReturn(self, call) {
        if (!self) {
            throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
        }

        return call && ((typeof call === "undefined" ? "undefined" : _typeof(call)) === "object" || typeof call === "function") ? call : self;
    }

    function _inherits(subClass, superClass) {
        if (typeof superClass !== "function" && superClass !== null) {
            throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
        }

        subClass.prototype = Object.create(superClass && superClass.prototype, {
            constructor: {
                value: subClass,
                enumerable: false,
                writable: true,
                configurable: true
            }
        });
        if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
    }

    var Child = (function (_Inspector) {
        _inherits(Child, _Inspector);

        function Child() {
            _classCallCheck(this, Child);

            return _possibleConstructorReturn(this, Object.getPrototypeOf(Child).apply(this, arguments));
        }

        _createClass(Child, [{
            key: "myMethod",
            value: function myMethod() {
                console.log("Hello from " + this.name);
            }
        }]);

        return Child;
    })(_inspector2.default);

    Child.inspect();
});

Exception stracktrace is not very helpful unfortunately :

ea.check @ require.js:19

(anonymous function) @ require.js:23

(anonymous function) @ require.js:8

(anonymous function) @ require.js:24

x @ require.js:7

ea.emit @ require.js:24

ea.check @ require.js:20 ea.enable @ require.js:24

ea.init @ require.js:17 J @ require.js:14

h.completeLoad @ require.js:29

h.onScriptLoad @ require.js:30

EDIT2: By looking at the transpiled files, it seems that my typeof is replaced with method _typeOf from Babel. And this function is looping infinitely...

Is it a bug with Babel? Did I miss any arguments for the compilation?


Solution

  • Looks like a babel bug, it might be exactly this one: https://phabricator.babeljs.io/T6777