"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = transpileNamespace; var _core = require("@babel/core"); function transpileNamespace(path, allowNamespaces) { if (path.node.declare || path.node.id.type === "StringLiteral") { path.remove(); return; } if (!allowNamespaces) { throw path.get("id").buildCodeFrameError("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"); } const name = path.node.id.name; const value = handleNested(path, _core.types.cloneNode(path.node, true)); const bound = path.scope.hasOwnBinding(name); if (path.parent.type === "ExportNamedDeclaration") { if (!bound) { path.parentPath.insertAfter(value); path.replaceWith(getDeclaration(name)); path.scope.registerDeclaration(path.parentPath); } else { path.parentPath.replaceWith(value); } } else if (bound) { path.replaceWith(value); } else { path.scope.registerDeclaration(path.replaceWithMultiple([getDeclaration(name), value])[0]); } } function getDeclaration(name) { return _core.types.variableDeclaration("let", [_core.types.variableDeclarator(_core.types.identifier(name))]); } function getMemberExpression(name, itemName) { return _core.types.memberExpression(_core.types.identifier(name), _core.types.identifier(itemName)); } function handleVariableDeclaration(node, name, hub) { if (node.kind !== "const") { 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"); } const { declarations } = node; if (declarations.every(declarator => _core.types.isIdentifier(declarator.id))) { for (const declarator of declarations) { declarator.init = _core.types.assignmentExpression("=", getMemberExpression(name, declarator.id.name), declarator.init); } return [node]; } const bindingIdentifiers = _core.types.getBindingIdentifiers(node); const assignments = []; for (const idName in bindingIdentifiers) { assignments.push(_core.types.assignmentExpression("=", getMemberExpression(name, idName), _core.types.cloneNode(bindingIdentifiers[idName]))); } return [node, _core.types.expressionStatement(_core.types.sequenceExpression(assignments))]; } function buildNestedAmbiendModuleError(path, node) { throw path.hub.buildError(node, "Ambient modules cannot be nested in other modules or namespaces.", Error); } function handleNested(path, node, parentExport) { const names = new Set(); const realName = node.id; _core.types.assertIdentifier(realName); const name = path.scope.generateUid(realName.name); const namespaceTopLevel = _core.types.isTSModuleBlock(node.body) ? node.body.body : [_core.types.exportNamedDeclaration(node.body)]; for (let i = 0; i < namespaceTopLevel.length; i++) { const subNode = namespaceTopLevel[i]; switch (subNode.type) { case "TSModuleDeclaration": { if (!_core.types.isIdentifier(subNode.id)) { throw buildNestedAmbiendModuleError(path, subNode); } const transformed = handleNested(path, subNode); const moduleName = subNode.id.name; if (names.has(moduleName)) { namespaceTopLevel[i] = transformed; } else { names.add(moduleName); namespaceTopLevel.splice(i++, 1, getDeclaration(moduleName), transformed); } continue; } case "TSEnumDeclaration": case "FunctionDeclaration": case "ClassDeclaration": names.add(subNode.id.name); continue; case "VariableDeclaration": { for (const name in _core.types.getBindingIdentifiers(subNode)) { names.add(name); } continue; } default: continue; case "ExportNamedDeclaration": } switch (subNode.declaration.type) { case "TSEnumDeclaration": case "FunctionDeclaration": case "ClassDeclaration": { const itemName = subNode.declaration.id.name; names.add(itemName); namespaceTopLevel.splice(i++, 1, subNode.declaration, _core.types.expressionStatement(_core.types.assignmentExpression("=", getMemberExpression(name, itemName), _core.types.identifier(itemName)))); break; } case "VariableDeclaration": { const nodes = handleVariableDeclaration(subNode.declaration, name, path.hub); namespaceTopLevel.splice(i, nodes.length, ...nodes); i += nodes.length - 1; break; } case "TSModuleDeclaration": { if (!_core.types.isIdentifier(subNode.declaration.id)) { throw buildNestedAmbiendModuleError(path, subNode.declaration); } const transformed = handleNested(path, subNode.declaration, _core.types.identifier(name)); const moduleName = subNode.declaration.id.name; if (names.has(moduleName)) { namespaceTopLevel[i] = transformed; } else { names.add(moduleName); namespaceTopLevel.splice(i++, 1, getDeclaration(moduleName), transformed); } } } } let fallthroughValue = _core.types.objectExpression([]); if (parentExport) { const memberExpr = _core.types.memberExpression(parentExport, realName); fallthroughValue = _core.template.expression.ast` ${_core.types.cloneNode(memberExpr)} || (${_core.types.cloneNode(memberExpr)} = ${fallthroughValue}) `; } return _core.template.statement.ast` (function (${_core.types.identifier(name)}) { ${namespaceTopLevel} })(${realName} || (${_core.types.cloneNode(realName)} = ${fallthroughValue})); `; }