1 | "use strict";
|
2 |
|
3 | Object.defineProperty(exports, "__esModule", {
|
4 | value: true
|
5 | });
|
6 | exports.default = transpileNamespace;
|
7 |
|
8 | var _core = require("@babel/core");
|
9 |
|
10 | function transpileNamespace(path, t, allowNamespaces) {
|
11 | if (path.node.declare || path.node.id.type === "StringLiteral") {
|
12 | path.remove();
|
13 | return;
|
14 | }
|
15 |
|
16 | if (!allowNamespaces) {
|
17 | throw path.hub.file.buildCodeFrameError(path.node.id, "Namespace not marked type-only declare." + " Non-declarative namespaces are only supported experimentally in Babel." + " To enable and review caveats see:" + " https://babeljs.io/docs/en/babel-plugin-transform-typescript");
|
18 | }
|
19 |
|
20 | const name = path.node.id.name;
|
21 | const value = handleNested(path, t, t.cloneDeep(path.node));
|
22 | const bound = path.scope.hasOwnBinding(name);
|
23 |
|
24 | if (path.parent.type === "ExportNamedDeclaration") {
|
25 | if (!bound) {
|
26 | path.parentPath.insertAfter(value);
|
27 | path.replaceWith(getDeclaration(t, name));
|
28 | path.scope.registerDeclaration(path.parentPath);
|
29 | } else {
|
30 | path.parentPath.replaceWith(value);
|
31 | }
|
32 | } else if (bound) {
|
33 | path.replaceWith(value);
|
34 | } else {
|
35 | path.scope.registerDeclaration(path.replaceWithMultiple([getDeclaration(t, name), value])[0]);
|
36 | }
|
37 | }
|
38 |
|
39 | function getDeclaration(t, name) {
|
40 | return t.variableDeclaration("let", [t.variableDeclarator(t.identifier(name))]);
|
41 | }
|
42 |
|
43 | function getMemberExpression(t, name, itemName) {
|
44 | return t.memberExpression(t.identifier(name), t.identifier(itemName));
|
45 | }
|
46 |
|
47 | function handleVariableDeclaration(node, name, hub) {
|
48 | if (node.kind !== "const") {
|
49 | throw hub.file.buildCodeFrameError(node, "Namespaces exporting non-const are not supported by Babel." + " Change to const or see:" + " https://babeljs.io/docs/en/babel-plugin-transform-typescript");
|
50 | }
|
51 |
|
52 | const {
|
53 | declarations
|
54 | } = node;
|
55 |
|
56 | if (declarations.every(declarator => _core.types.isIdentifier(declarator.id))) {
|
57 | for (const declarator of node.declarations) {
|
58 | declarator.init = _core.types.assignmentExpression("=", getMemberExpression(_core.types, name, declarator.id.name), declarator.init);
|
59 | }
|
60 |
|
61 | return [node];
|
62 | }
|
63 |
|
64 | const bindingIdentifiers = _core.types.getBindingIdentifiers(node);
|
65 |
|
66 | const assignments = [];
|
67 |
|
68 | for (const idName in bindingIdentifiers) {
|
69 | assignments.push(_core.types.assignmentExpression("=", getMemberExpression(_core.types, name, idName), _core.types.cloneNode(bindingIdentifiers[idName])));
|
70 | }
|
71 |
|
72 | return [node, _core.types.expressionStatement(_core.types.sequenceExpression(assignments))];
|
73 | }
|
74 |
|
75 | function handleNested(path, t, node, parentExport) {
|
76 | const names = new Set();
|
77 | const realName = node.id;
|
78 | const name = path.scope.generateUid(realName.name);
|
79 | const namespaceTopLevel = node.body.body;
|
80 |
|
81 | for (let i = 0; i < namespaceTopLevel.length; i++) {
|
82 | const subNode = namespaceTopLevel[i];
|
83 |
|
84 | switch (subNode.type) {
|
85 | case "TSModuleDeclaration":
|
86 | {
|
87 | const transformed = handleNested(path, t, subNode);
|
88 | const moduleName = subNode.id.name;
|
89 |
|
90 | if (names.has(moduleName)) {
|
91 | namespaceTopLevel[i] = transformed;
|
92 | } else {
|
93 | names.add(moduleName);
|
94 | namespaceTopLevel.splice(i++, 1, getDeclaration(t, moduleName), transformed);
|
95 | }
|
96 |
|
97 | continue;
|
98 | }
|
99 |
|
100 | case "TSEnumDeclaration":
|
101 | case "FunctionDeclaration":
|
102 | case "ClassDeclaration":
|
103 | names.add(subNode.id.name);
|
104 | continue;
|
105 |
|
106 | case "VariableDeclaration":
|
107 | {
|
108 | for (const name in t.getBindingIdentifiers(subNode)) {
|
109 | names.add(name);
|
110 | }
|
111 |
|
112 | continue;
|
113 | }
|
114 |
|
115 | default:
|
116 | continue;
|
117 |
|
118 | case "ExportNamedDeclaration":
|
119 | }
|
120 |
|
121 | switch (subNode.declaration.type) {
|
122 | case "TSEnumDeclaration":
|
123 | case "FunctionDeclaration":
|
124 | case "ClassDeclaration":
|
125 | {
|
126 | const itemName = subNode.declaration.id.name;
|
127 | names.add(itemName);
|
128 | namespaceTopLevel.splice(i++, 1, subNode.declaration, t.expressionStatement(t.assignmentExpression("=", getMemberExpression(t, name, itemName), t.identifier(itemName))));
|
129 | break;
|
130 | }
|
131 |
|
132 | case "VariableDeclaration":
|
133 | {
|
134 | const nodes = handleVariableDeclaration(subNode.declaration, name, path.hub);
|
135 | namespaceTopLevel.splice(i, nodes.length, ...nodes);
|
136 | i += nodes.length - 1;
|
137 | break;
|
138 | }
|
139 |
|
140 | case "TSModuleDeclaration":
|
141 | {
|
142 | const transformed = handleNested(path, t, subNode.declaration, t.identifier(name));
|
143 | const moduleName = subNode.declaration.id.name;
|
144 |
|
145 | if (names.has(moduleName)) {
|
146 | namespaceTopLevel[i] = transformed;
|
147 | } else {
|
148 | names.add(moduleName);
|
149 | namespaceTopLevel.splice(i++, 1, getDeclaration(t, moduleName), transformed);
|
150 | }
|
151 | }
|
152 | }
|
153 | }
|
154 |
|
155 | let fallthroughValue = t.objectExpression([]);
|
156 |
|
157 | if (parentExport) {
|
158 | const memberExpr = t.memberExpression(parentExport, realName);
|
159 | fallthroughValue = _core.template.expression.ast`
|
160 | ${t.cloneNode(memberExpr)} ||
|
161 | (${t.cloneNode(memberExpr)} = ${fallthroughValue})
|
162 | `;
|
163 | }
|
164 |
|
165 | return _core.template.statement.ast`
|
166 | (function (${t.identifier(name)}) {
|
167 | ${namespaceTopLevel}
|
168 | })(${realName} || (${t.cloneNode(realName)} = ${fallthroughValue}));
|
169 | `;
|
170 | } |
\ | No newline at end of file |