Implement TDZ for ClassFieldDefinitionEvaluation (#6855)
* First implementation sketch and testcase * Use helper instead of inline IIFE's * minNodeVersion 6.0.0 * Hoisted visitor for subtraversal and fixed edgest case * Resolve merge conflicts in helpers * Remove duplicated helper from messing up Git
This commit is contained in:
parent
cdf420d4d8
commit
6330a152ce
@ -633,6 +633,12 @@ helpers.readOnlyError = defineHelper(`
|
||||
}
|
||||
`);
|
||||
|
||||
helpers.classNameTDZError = defineHelper(`
|
||||
export default function _classNameTDZError(name) {
|
||||
throw new Error("Class \\"" + name + "\\" cannot be referenced in computed property keys.");
|
||||
}
|
||||
`);
|
||||
|
||||
helpers.temporalUndefined = defineHelper(`
|
||||
export default {};
|
||||
`);
|
||||
|
||||
@ -25,6 +25,26 @@ export default function(api, options) {
|
||||
},
|
||||
};
|
||||
|
||||
const ClassFieldDefinitionEvaluationTDZVisitor = {
|
||||
Expression(path) {
|
||||
if (path === this.shouldSkip) {
|
||||
path.skip();
|
||||
}
|
||||
},
|
||||
|
||||
ReferencedIdentifier(path) {
|
||||
if (this.classRef === path.scope.getBinding(path.node.name)) {
|
||||
const classNameTDZError = this.file.addHelper("classNameTDZError");
|
||||
const throwNode = t.callExpression(classNameTDZError, [
|
||||
t.stringLiteral(path.node.name),
|
||||
]);
|
||||
|
||||
path.replaceWith(t.sequenceExpression([throwNode, path.node]));
|
||||
path.skip();
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
const buildClassPropertySpec = (ref, { key, value, computed }, scope) => {
|
||||
return template.statement`
|
||||
Object.defineProperty(REF, KEY, {
|
||||
@ -95,6 +115,11 @@ export default function(api, options) {
|
||||
// Make sure computed property names are only evaluated once (upon class definition)
|
||||
// and in the right order in combination with static properties
|
||||
if (!computedPath.get("key").isConstantExpression()) {
|
||||
computedPath.traverse(ClassFieldDefinitionEvaluationTDZVisitor, {
|
||||
classRef: path.scope.getBinding(ref.name),
|
||||
file: this.file,
|
||||
shouldSkip: computedPath.get("value"),
|
||||
});
|
||||
const ident = path.scope.generateUidIdentifierBasedOnNode(
|
||||
computedNode.key,
|
||||
);
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
class A {
|
||||
static [{ x: A || 0 }.x];
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||||
|
||||
function _classNameTDZError(name) { throw new Error("Class \"" + name + "\" cannot be referenced in computed property keys."); }
|
||||
|
||||
let A = function A() {
|
||||
_classCallCheck(this, A);
|
||||
};
|
||||
|
||||
var _x$x = {
|
||||
x: (_classNameTDZError("A"), A) || 0
|
||||
}.x;
|
||||
Object.defineProperty(A, _x$x, {
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
writable: true,
|
||||
value: void 0
|
||||
});
|
||||
@ -0,0 +1,3 @@
|
||||
class C {
|
||||
static [C + 3] = 3;
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
class C {
|
||||
static [C + 3] = 3;
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||||
|
||||
function _classNameTDZError(name) { throw new Error("Class \"" + name + "\" cannot be referenced in computed property keys."); }
|
||||
|
||||
let C = function C() {
|
||||
_classCallCheck(this, C);
|
||||
};
|
||||
|
||||
var _ref = (_classNameTDZError("C"), C) + 3;
|
||||
|
||||
Object.defineProperty(C, _ref, {
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
writable: true,
|
||||
value: 3
|
||||
});
|
||||
@ -0,0 +1,3 @@
|
||||
{
|
||||
"throws": "Class \"C\" cannot be referenced in computed property keys."
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
class C {
|
||||
static [C + 3] = 3;
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
class C {
|
||||
static [C + 3] = 3;
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
function _classNameTDZError(name) { throw new Error("Class \"" + name + "\" cannot be referenced in computed property keys."); }
|
||||
|
||||
class C {}
|
||||
|
||||
var _ref = (_classNameTDZError("C"), C) + 3;
|
||||
|
||||
C[_ref] = 3;
|
||||
@ -0,0 +1,4 @@
|
||||
{
|
||||
"throws": "Class \"C\" cannot be referenced in computed property keys.",
|
||||
"plugins": [["proposal-class-properties", {"loose": true}]]
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
{
|
||||
"plugins": ["proposal-class-properties", "transform-classes"],
|
||||
"minNodeVersion": "6.0.0"
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user