UNPKG

8.54 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.default = void 0;
7var _core = require("@babel/core");
8const buildClassDecorator = _core.template.statement(`
9 DECORATOR(CLASS_REF = INNER) || CLASS_REF;
10`);
11const buildClassPrototype = (0, _core.template)(`
12 CLASS_REF.prototype;
13`);
14const buildGetDescriptor = (0, _core.template)(`
15 Object.getOwnPropertyDescriptor(TARGET, PROPERTY);
16`);
17const buildGetObjectInitializer = (0, _core.template)(`
18 (TEMP = Object.getOwnPropertyDescriptor(TARGET, PROPERTY), (TEMP = TEMP ? TEMP.value : undefined), {
19 enumerable: true,
20 configurable: true,
21 writable: true,
22 initializer: function(){
23 return TEMP;
24 }
25 })
26`);
27const WARNING_CALLS = new WeakSet();
28function applyEnsureOrdering(path) {
29 const decorators = (path.isClass() ? [path, ...path.get("body.body")] : path.get("properties")).reduce((acc, prop) => acc.concat(prop.node.decorators || []), []);
30 const identDecorators = decorators.filter(decorator => !_core.types.isIdentifier(decorator.expression));
31 if (identDecorators.length === 0) return;
32 return _core.types.sequenceExpression(identDecorators.map(decorator => {
33 const expression = decorator.expression;
34 const id = decorator.expression = path.scope.generateDeclaredUidIdentifier("dec");
35 return _core.types.assignmentExpression("=", id, expression);
36 }).concat([path.node]));
37}
38function applyClassDecorators(classPath) {
39 if (!hasClassDecorators(classPath.node)) return;
40 const decorators = classPath.node.decorators || [];
41 classPath.node.decorators = null;
42 const name = classPath.scope.generateDeclaredUidIdentifier("class");
43 return decorators.map(dec => dec.expression).reverse().reduce(function (acc, decorator) {
44 return buildClassDecorator({
45 CLASS_REF: _core.types.cloneNode(name),
46 DECORATOR: _core.types.cloneNode(decorator),
47 INNER: acc
48 }).expression;
49 }, classPath.node);
50}
51function hasClassDecorators(classNode) {
52 var _classNode$decorators;
53 return !!((_classNode$decorators = classNode.decorators) != null && _classNode$decorators.length);
54}
55function applyMethodDecorators(path, state) {
56 if (!hasMethodDecorators(path.node.body.body)) return;
57 return applyTargetDecorators(path, state, path.node.body.body);
58}
59function hasMethodDecorators(body) {
60 return body.some(node => {
61 var _node$decorators;
62 return (_node$decorators = node.decorators) == null ? void 0 : _node$decorators.length;
63 });
64}
65function applyObjectDecorators(path, state) {
66 if (!hasMethodDecorators(path.node.properties)) return;
67 return applyTargetDecorators(path, state, path.node.properties.filter(prop => prop.type !== "SpreadElement"));
68}
69function applyTargetDecorators(path, state, decoratedProps) {
70 const name = path.scope.generateDeclaredUidIdentifier(path.isClass() ? "class" : "obj");
71 const exprs = decoratedProps.reduce(function (acc, node) {
72 let decorators = [];
73 if (node.decorators != null) {
74 decorators = node.decorators;
75 node.decorators = null;
76 }
77 if (decorators.length === 0) return acc;
78 if (node.computed) {
79 throw path.buildCodeFrameError("Computed method/property decorators are not yet supported.");
80 }
81 const property = _core.types.isLiteral(node.key) ? node.key : _core.types.stringLiteral(node.key.name);
82 const target = path.isClass() && !node.static ? buildClassPrototype({
83 CLASS_REF: name
84 }).expression : name;
85 if (_core.types.isClassProperty(node, {
86 static: false
87 })) {
88 const descriptor = path.scope.generateDeclaredUidIdentifier("descriptor");
89 const initializer = node.value ? _core.types.functionExpression(null, [], _core.types.blockStatement([_core.types.returnStatement(node.value)])) : _core.types.nullLiteral();
90 node.value = _core.types.callExpression(state.addHelper("initializerWarningHelper"), [descriptor, _core.types.thisExpression()]);
91 WARNING_CALLS.add(node.value);
92 acc.push(_core.types.assignmentExpression("=", _core.types.cloneNode(descriptor), _core.types.callExpression(state.addHelper("applyDecoratedDescriptor"), [_core.types.cloneNode(target), _core.types.cloneNode(property), _core.types.arrayExpression(decorators.map(dec => _core.types.cloneNode(dec.expression))), _core.types.objectExpression([_core.types.objectProperty(_core.types.identifier("configurable"), _core.types.booleanLiteral(true)), _core.types.objectProperty(_core.types.identifier("enumerable"), _core.types.booleanLiteral(true)), _core.types.objectProperty(_core.types.identifier("writable"), _core.types.booleanLiteral(true)), _core.types.objectProperty(_core.types.identifier("initializer"), initializer)])])));
93 } else {
94 acc.push(_core.types.callExpression(state.addHelper("applyDecoratedDescriptor"), [_core.types.cloneNode(target), _core.types.cloneNode(property), _core.types.arrayExpression(decorators.map(dec => _core.types.cloneNode(dec.expression))), _core.types.isObjectProperty(node) || _core.types.isClassProperty(node, {
95 static: true
96 }) ? buildGetObjectInitializer({
97 TEMP: path.scope.generateDeclaredUidIdentifier("init"),
98 TARGET: _core.types.cloneNode(target),
99 PROPERTY: _core.types.cloneNode(property)
100 }).expression : buildGetDescriptor({
101 TARGET: _core.types.cloneNode(target),
102 PROPERTY: _core.types.cloneNode(property)
103 }).expression, _core.types.cloneNode(target)]));
104 }
105 return acc;
106 }, []);
107 return _core.types.sequenceExpression([_core.types.assignmentExpression("=", _core.types.cloneNode(name), path.node), _core.types.sequenceExpression(exprs), _core.types.cloneNode(name)]);
108}
109function decoratedClassToExpression({
110 node,
111 scope
112}) {
113 if (!hasClassDecorators(node) && !hasMethodDecorators(node.body.body)) {
114 return;
115 }
116 const ref = node.id ? _core.types.cloneNode(node.id) : scope.generateUidIdentifier("class");
117 return _core.types.variableDeclaration("let", [_core.types.variableDeclarator(ref, _core.types.toExpression(node))]);
118}
119const visitor = {
120 ExportDefaultDeclaration(path) {
121 const decl = path.get("declaration");
122 if (!decl.isClassDeclaration()) return;
123 const replacement = decoratedClassToExpression(decl);
124 if (replacement) {
125 const [varDeclPath] = path.replaceWithMultiple([replacement, _core.types.exportNamedDeclaration(null, [_core.types.exportSpecifier(_core.types.cloneNode(replacement.declarations[0].id), _core.types.identifier("default"))])]);
126 if (!decl.node.id) {
127 path.scope.registerDeclaration(varDeclPath);
128 }
129 }
130 },
131 ClassDeclaration(path) {
132 const replacement = decoratedClassToExpression(path);
133 if (replacement) {
134 const [newPath] = path.replaceWith(replacement);
135 const decl = newPath.get("declarations.0");
136 const id = decl.node.id;
137 const binding = path.scope.getOwnBinding(id.name);
138 binding.identifier = id;
139 binding.path = decl;
140 }
141 },
142 ClassExpression(path, state) {
143 const decoratedClass = applyEnsureOrdering(path) || applyClassDecorators(path) || applyMethodDecorators(path, state);
144 if (decoratedClass) path.replaceWith(decoratedClass);
145 },
146 ObjectExpression(path, state) {
147 const decoratedObject = applyEnsureOrdering(path) || applyObjectDecorators(path, state);
148 if (decoratedObject) path.replaceWith(decoratedObject);
149 },
150 AssignmentExpression(path, state) {
151 if (!WARNING_CALLS.has(path.node.right)) return;
152 path.replaceWith(_core.types.callExpression(state.addHelper("initializerDefineProperty"), [_core.types.cloneNode(path.get("left.object").node), _core.types.stringLiteral(path.get("left.property").node.name || path.get("left.property").node.value), _core.types.cloneNode(path.get("right.arguments")[0].node), _core.types.cloneNode(path.get("right.arguments")[1].node)]));
153 },
154 CallExpression(path, state) {
155 if (path.node.arguments.length !== 3) return;
156 if (!WARNING_CALLS.has(path.node.arguments[2])) return;
157 if (path.node.callee.name !== state.addHelper("defineProperty").name) {
158 return;
159 }
160 path.replaceWith(_core.types.callExpression(state.addHelper("initializerDefineProperty"), [_core.types.cloneNode(path.get("arguments")[0].node), _core.types.cloneNode(path.get("arguments")[1].node), _core.types.cloneNode(path.get("arguments.2.arguments")[0].node), _core.types.cloneNode(path.get("arguments.2.arguments")[1].node)]));
161 }
162};
163var _default = exports.default = visitor;
164
165//# sourceMappingURL=transformer-legacy.js.map