-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Description
I propose we add a new helper to assist with class instance construction runtime semantics when extending ES6 built-in classes while compiling with --target ES5
.
Background
Our current emit for classes for --target ES5
assumes that the superclass follows the same runtime semantics as the classes we emit. Generally this means that the constructor can be called as a function via call()
or apply()
. However, a number of ES6 built-in classes are specified to throw when not used as a constructor (i.e. Promise
, Map
, etc.), and other ES6 built-in classes return a value when called, ignoring the this
value provided to call()
or apply()
(i.e. Error
, Array
, etc.).
Previously we provided guidance for possible workarounds for this to support the latter scenario, but we do not currently have a solution for the former scenario.
Proposal
The following code listing describes a new __construct
helper that we would need to emit for any file that contains an explicit (or implicit, for property declarations) super()
call:
class MyPromise extends Promise {
constructor(executor) {
super(executor);
}
}
// becomes...
var __extends = ...;
var __construct = (this && this.__construct) || (typeof Reflect !== "undefined" && Reflect.construct
? function (s, t, a, n) { return t !== null ? Reflect.construct(t, a, n) : s; }
: function (s, t, a) { return t !== null && t.apply(s, a) || s; });
var MyPromise = (function (_super) {
__extends(MyPromise, _super);
function MyPromise(executor) {
var _this = this;
var _newTarget = this.constructor;
_this = __construct(this, _super, [executor], _newTarget);
return _this;
}
return MyPromise;
})(Promise);
Benefits
- Allows down-level class emit to extend ES6 built-ins if running in an ES6 host by feature detecting
Reflect.construct
. - Falls back to the existing behavior when running in an ES5 host.
- Handles
extends null
andextends x
whenx
isnull
in the same way as existing behavior. - Handles custom return values from
super
in the same way as existing behavior.
Drawbacks
- Larger helper footprint
- Subclassing a built-in in an ES5 host has different runtime semantics than subclassing a built-in in an ES6 host:
- In ES5, subclassing
Array
orError
will not have the correct prototype chain. The only solution is to explicitly set the prototype chain using the non-standard__proto__
property as per established guidance.
- In ES5, subclassing