-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
Mixed es5/es2015 code with mixin classes causes runtime errors #17088
Comments
I suspect this got lost in the shuffle. Ping @DanielRosenwasser |
🎤 tap tap is this thing on? 😁 /cc @mhegazy |
Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed. |
We would need to add a helper to facilitate marshalling var __construct = (this && this.__construct) || (typeof Reflect !== "undefined" && Reflect.construct
? function (self, target, args) { return target !== null && Reflect.construct(target, args, self.constructor) || self; }
: function (self, target, args) { return target !== null && target.apply(self, args) || self; }); Which would then be used like this: function Tagged(Base) {
return (function (_super) {
__extends(class_1, _super);
function class_1() {
var _this = __construct(this, _super, arguments);
_this._tag = '';
return _this;
}
return class_1;
}(Base));
} |
We are currently running into this issue where we still emit most part of our codebase to es5 but only some are being migrated to es2015. Are there any plans to change the emitted es5 code like the example you posted? @rbuckton |
This continues to be an issue, making it impossible to subclass built-ins like Promises or EventTarget while targeting ES5 output I've resorted to hand-transpiling some subclasses to use the |
This is very problematic because it means my library (which rely on this) published in es5 cannot be consumed by JavaScript directly at all. |
I just stumbled upon this. I'm not sure what more feedback is required, this bug basically breaks exporting class decorators in es5 and using them in es6+. I had to resort to |
I think if someone wants to take a swing at an implementation, then we would be willing to discuss at a meeting and pull in the changes. |
Looks like this works with Babel, because it creates a function around the super class ( "use strict";
// the untranspiled chunk
class A {}
// transpiled class B extends A {} with babel
function _instanceof(left, right) { if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) { return !!right[Symbol.hasInstance](left); } else { return left instanceof right; } }
function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
function _classCallCheck(instance, Constructor) { if (!_instanceof(instance, Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function () { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
var B = /*#__PURE__*/function (_A) {
_inherits(B, _A);
var _super = _createSuper(B);
function B() {
_classCallCheck(this, B);
return _super.apply(this, arguments);
}
return B;
}(A); and TS uses "use strict";
// the untranspiled chunk
class A {}
// transpiled class B extends A {} with TS
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var B = /** @class */ (function (_super) {
__extends(B, _super);
function B() {
return _super !== null && _super.apply(this, arguments) || this;
}
return B;
}(A));
new B() // fails!
/*
Uncaught TypeError: Class constructor A cannot be invoked without 'new'
at new B (<anonymous>:18:42)
at <anonymous>:1:1
B @ VM714:18
(anonymous) @ VM738:1
*/ Because this fails: class C {}
C.apply({}, []) // Uncaught TypeError: Class constructor C cannot be invoked without 'new' |
This issue still exists, but as more and more projects move to targeting ES2015 and higher I'm not sure it is a high enough priority to be fixed as the chances of running afoul of this are smaller and smaller. I expected the largest cause of this comes from extending builtins like @DanielRosenwasser do we want to close this, or take a fix? I put together a fix for this, but it requires adding the Alternatively, we could fix this behind a flag for the rare cases where this happens. |
And this is how it fails: https://stackblitz.com/edit/js-svplky?file=index.js I flag would be awesome. |
TypeScript Version: 2.4.1 (but likely anything since 2.2)
When utilising code targeted at ES5 mixed with code targeted at ES6 causes a runtime error when using mixin classes. The real world use case was using a library that was targeted at ES5 for distribution compatibility reasons while downstream code is being targeted at ES2017 because of running in a known limited environment.
Code
Tagged.ts
TaggedExample.ts
Expected behavior:
No run-time errors.
Actual behavior:
A runtime error of
Uncaught TypeError: Class constructor Example cannot be invoked without 'new'
.The text was updated successfully, but these errors were encountered: