add legacy decorators support to strict class fields (#10616)
This PR allows legacy decorators to work with strict class fields, which are now stage 3 and have shipped in a number of browsers. Allowing this will allow users of the legacy transform (which is currently recommended by the champions of the decorator proposal) to use the proper class field semantics for non-decorated fields, which should help prevent breakage later on. This change is not a breaking change, since users had to explicitly opt into loose mode in class fields before. This just gives them the option to remove that opt-in.
This commit is contained in:
parent
bea1b0d0af
commit
5c0d8a9de7
@ -1040,9 +1040,7 @@ helpers.initializerWarningHelper = helper("7.0.0-beta.0")`
|
||||
export default function _initializerWarningHelper(descriptor, context){
|
||||
throw new Error(
|
||||
'Decorating class property failed. Please ensure that ' +
|
||||
'proposal-class-properties is enabled and set to use loose mode. ' +
|
||||
'To use proposal-class-properties in spec mode with decorators, wait for ' +
|
||||
'the next major version of decorators in stage 2.'
|
||||
'proposal-class-properties is enabled and runs after the decorators transform.'
|
||||
);
|
||||
}
|
||||
`;
|
||||
|
||||
@ -0,0 +1,12 @@
|
||||
function dec() {}
|
||||
|
||||
// Create a local function binding so babel has to change the name of the helper
|
||||
function _defineProperty() {}
|
||||
|
||||
class A {
|
||||
@dec a;
|
||||
|
||||
@dec b = 123;
|
||||
|
||||
c = 456;
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
{
|
||||
"plugins": [
|
||||
["proposal-decorators", { "legacy": true }],
|
||||
["proposal-class-properties"],
|
||||
"transform-classes"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
var _class, _descriptor, _descriptor2, _temp;
|
||||
|
||||
function _initializerDefineProperty(target, property, descriptor, context) { if (!descriptor) return; Object.defineProperty(target, property, { enumerable: descriptor.enumerable, configurable: descriptor.configurable, writable: descriptor.writable, value: descriptor.initializer ? descriptor.initializer.call(context) : void 0 }); }
|
||||
|
||||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||||
|
||||
function _defineProperty2(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
||||
|
||||
function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) { var desc = {}; Object.keys(descriptor).forEach(function (key) { desc[key] = descriptor[key]; }); desc.enumerable = !!desc.enumerable; desc.configurable = !!desc.configurable; if ('value' in desc || desc.initializer) { desc.writable = true; } desc = decorators.slice().reverse().reduce(function (desc, decorator) { return decorator(target, property, desc) || desc; }, desc); if (context && desc.initializer !== void 0) { desc.value = desc.initializer ? desc.initializer.call(context) : void 0; desc.initializer = undefined; } if (desc.initializer === void 0) { Object.defineProperty(target, property, desc); desc = null; } return desc; }
|
||||
|
||||
function _initializerWarningHelper(descriptor, context) { throw new Error('Decorating class property failed. Please ensure that ' + 'proposal-class-properties is enabled and runs after the decorators transform.'); }
|
||||
|
||||
function dec() {} // Create a local function binding so babel has to change the name of the helper
|
||||
|
||||
|
||||
function _defineProperty() {}
|
||||
|
||||
let A = (_class = (_temp = function A() {
|
||||
"use strict";
|
||||
|
||||
_classCallCheck(this, A);
|
||||
|
||||
_initializerDefineProperty(this, "a", _descriptor, this);
|
||||
|
||||
_initializerDefineProperty(this, "b", _descriptor2, this);
|
||||
|
||||
_defineProperty2(this, "c", 456);
|
||||
}, _temp), (_descriptor = _applyDecoratedDescriptor(_class.prototype, "a", [dec], {
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
writable: true,
|
||||
initializer: null
|
||||
}), _descriptor2 = _applyDecoratedDescriptor(_class.prototype, "b", [dec], {
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
writable: true,
|
||||
initializer: function () {
|
||||
return 123;
|
||||
}
|
||||
})), _class);
|
||||
@ -0,0 +1,9 @@
|
||||
function dec() {}
|
||||
|
||||
class A {
|
||||
@dec a;
|
||||
|
||||
@dec b = 123;
|
||||
|
||||
c = 456;
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
{
|
||||
"plugins": [
|
||||
["proposal-decorators", { "legacy": true }],
|
||||
["proposal-class-properties", { "loose": true }],
|
||||
"transform-classes"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
var _class, _descriptor, _descriptor2, _temp;
|
||||
|
||||
function _initializerDefineProperty(target, property, descriptor, context) { if (!descriptor) return; Object.defineProperty(target, property, { enumerable: descriptor.enumerable, configurable: descriptor.configurable, writable: descriptor.writable, value: descriptor.initializer ? descriptor.initializer.call(context) : void 0 }); }
|
||||
|
||||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||||
|
||||
function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) { var desc = {}; Object.keys(descriptor).forEach(function (key) { desc[key] = descriptor[key]; }); desc.enumerable = !!desc.enumerable; desc.configurable = !!desc.configurable; if ('value' in desc || desc.initializer) { desc.writable = true; } desc = decorators.slice().reverse().reduce(function (desc, decorator) { return decorator(target, property, desc) || desc; }, desc); if (context && desc.initializer !== void 0) { desc.value = desc.initializer ? desc.initializer.call(context) : void 0; desc.initializer = undefined; } if (desc.initializer === void 0) { Object.defineProperty(target, property, desc); desc = null; } return desc; }
|
||||
|
||||
function _initializerWarningHelper(descriptor, context) { throw new Error('Decorating class property failed. Please ensure that ' + 'proposal-class-properties is enabled and runs after the decorators transform.'); }
|
||||
|
||||
function dec() {}
|
||||
|
||||
let A = (_class = (_temp = function A() {
|
||||
"use strict";
|
||||
|
||||
_classCallCheck(this, A);
|
||||
|
||||
_initializerDefineProperty(this, "a", _descriptor, this);
|
||||
|
||||
_initializerDefineProperty(this, "b", _descriptor2, this);
|
||||
|
||||
this.c = 456;
|
||||
}, _temp), (_descriptor = _applyDecoratedDescriptor(_class.prototype, "a", [dec], {
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
writable: true,
|
||||
initializer: null
|
||||
}), _descriptor2 = _applyDecoratedDescriptor(_class.prototype, "b", [dec], {
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
writable: true,
|
||||
initializer: function () {
|
||||
return 123;
|
||||
}
|
||||
})), _class);
|
||||
@ -0,0 +1,9 @@
|
||||
function dec() {}
|
||||
|
||||
class A {
|
||||
@dec a;
|
||||
|
||||
@dec b = 123;
|
||||
|
||||
c = 456;
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
{
|
||||
"plugins": [
|
||||
["proposal-decorators", { "legacy": true }],
|
||||
["proposal-class-properties"],
|
||||
"transform-classes"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
var _class, _descriptor, _descriptor2, _temp;
|
||||
|
||||
function _initializerDefineProperty(target, property, descriptor, context) { if (!descriptor) return; Object.defineProperty(target, property, { enumerable: descriptor.enumerable, configurable: descriptor.configurable, writable: descriptor.writable, value: descriptor.initializer ? descriptor.initializer.call(context) : void 0 }); }
|
||||
|
||||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||||
|
||||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
||||
|
||||
function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) { var desc = {}; Object.keys(descriptor).forEach(function (key) { desc[key] = descriptor[key]; }); desc.enumerable = !!desc.enumerable; desc.configurable = !!desc.configurable; if ('value' in desc || desc.initializer) { desc.writable = true; } desc = decorators.slice().reverse().reduce(function (desc, decorator) { return decorator(target, property, desc) || desc; }, desc); if (context && desc.initializer !== void 0) { desc.value = desc.initializer ? desc.initializer.call(context) : void 0; desc.initializer = undefined; } if (desc.initializer === void 0) { Object.defineProperty(target, property, desc); desc = null; } return desc; }
|
||||
|
||||
function _initializerWarningHelper(descriptor, context) { throw new Error('Decorating class property failed. Please ensure that ' + 'proposal-class-properties is enabled and runs after the decorators transform.'); }
|
||||
|
||||
function dec() {}
|
||||
|
||||
let A = (_class = (_temp = function A() {
|
||||
"use strict";
|
||||
|
||||
_classCallCheck(this, A);
|
||||
|
||||
_initializerDefineProperty(this, "a", _descriptor, this);
|
||||
|
||||
_initializerDefineProperty(this, "b", _descriptor2, this);
|
||||
|
||||
_defineProperty(this, "c", 456);
|
||||
}, _temp), (_descriptor = _applyDecoratedDescriptor(_class.prototype, "a", [dec], {
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
writable: true,
|
||||
initializer: null
|
||||
}), _descriptor2 = _applyDecoratedDescriptor(_class.prototype, "b", [dec], {
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
writable: true,
|
||||
initializer: function () {
|
||||
return 123;
|
||||
}
|
||||
})), _class);
|
||||
@ -12,7 +12,7 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
|
||||
|
||||
function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) { var desc = {}; Object.keys(descriptor).forEach(function (key) { desc[key] = descriptor[key]; }); desc.enumerable = !!desc.enumerable; desc.configurable = !!desc.configurable; if ('value' in desc || desc.initializer) { desc.writable = true; } desc = decorators.slice().reverse().reduce(function (desc, decorator) { return decorator(target, property, desc) || desc; }, desc); if (context && desc.initializer !== void 0) { desc.value = desc.initializer ? desc.initializer.call(context) : void 0; desc.initializer = undefined; } if (desc.initializer === void 0) { Object.defineProperty(target, property, desc); desc = null; } return desc; }
|
||||
|
||||
function _initializerWarningHelper(descriptor, context) { throw new Error('Decorating class property failed. Please ensure that ' + 'proposal-class-properties is enabled and set to use loose mode. ' + 'To use proposal-class-properties in spec mode with decorators, wait for ' + 'the next major version of decorators in stage 2.'); }
|
||||
function _initializerWarningHelper(descriptor, context) { throw new Error('Decorating class property failed. Please ensure that ' + 'proposal-class-properties is enabled and runs after the decorators transform.'); }
|
||||
|
||||
function dec() {}
|
||||
|
||||
|
||||
@ -290,4 +290,24 @@ export default {
|
||||
]),
|
||||
);
|
||||
},
|
||||
|
||||
CallExpression(path, state) {
|
||||
if (path.node.arguments.length !== 3) return;
|
||||
if (!WARNING_CALLS.has(path.node.arguments[2])) return;
|
||||
|
||||
// If the class properties plugin isn't enabled, this line will add an unused helper
|
||||
// to the code. It's not ideal, but it's ok since the configuration is not valid anyway.
|
||||
if (path.node.callee.name !== state.addHelper("defineProperty").name) {
|
||||
return;
|
||||
}
|
||||
|
||||
path.replaceWith(
|
||||
t.callExpression(state.addHelper("initializerDefineProperty"), [
|
||||
t.cloneNode(path.get("arguments")[0].node),
|
||||
t.cloneNode(path.get("arguments")[1].node),
|
||||
t.cloneNode(path.get("arguments.2.arguments")[0].node),
|
||||
t.cloneNode(path.get("arguments.2.arguments")[1].node),
|
||||
]),
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
@ -2,7 +2,7 @@ var _class, _descriptor;
|
||||
|
||||
function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) { var desc = {}; Object.keys(descriptor).forEach(function (key) { desc[key] = descriptor[key]; }); desc.enumerable = !!desc.enumerable; desc.configurable = !!desc.configurable; if ('value' in desc || desc.initializer) { desc.writable = true; } desc = decorators.slice().reverse().reduce(function (desc, decorator) { return decorator(target, property, desc) || desc; }, desc); if (context && desc.initializer !== void 0) { desc.value = desc.initializer ? desc.initializer.call(context) : void 0; desc.initializer = undefined; } if (desc.initializer === void 0) { Object.defineProperty(target, property, desc); desc = null; } return desc; }
|
||||
|
||||
function _initializerWarningHelper(descriptor, context) { throw new Error('Decorating class property failed. Please ensure that ' + 'proposal-class-properties is enabled and set to use loose mode. ' + 'To use proposal-class-properties in spec mode with decorators, wait for ' + 'the next major version of decorators in stage 2.'); }
|
||||
function _initializerWarningHelper(descriptor, context) { throw new Error('Decorating class property failed. Please ensure that ' + 'proposal-class-properties is enabled and runs after the decorators transform.'); }
|
||||
|
||||
import { observable } from 'mobx';
|
||||
let Foo = (_class = class Foo {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user