
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = rewriteLiveReferences;
var _assert = require("assert");
var _t = require("@babel/types");
var _template = require("@babel/template");
var _helperSimpleAccess = require("@babel/helper-simple-access");
const {
assignmentExpression,
callExpression,
cloneNode,
expressionStatement,
getOuterBindingIdentifiers,
identifier,
isMemberExpression,
isVariableDeclaration,
jsxIdentifier,
jsxMemberExpression,
memberExpression,
numericLiteral,
sequenceExpression,
stringLiteral,
variableDeclaration,
variableDeclarator
} = _t;
function isInType(path) {
do {
switch (path.parent.type) {
case "TSTypeAnnotation":
case "TSTypeAliasDeclaration":
case "TSTypeReference":
case "TypeAnnotation":
case "TypeAlias":
return true;
case "ExportSpecifier":
return path.parentPath.parent.exportKind === "type";
default:
if (path.parentPath.isStatement() || path.parentPath.isExpression()) {
return false;
}
}
} while (path = path.parentPath);
}
function rewriteLiveReferences(programPath, metadata) {
const imported = new Map();
const exported = new Map();
const requeueInParent = path => {
programPath.requeue(path);
};
for (const [source, data] of metadata.source) {
for (const [localName, importName] of data.imports) {
imported.set(localName, [source, importName, null]);
}
for (const localName of data.importsNamespace) {
imported.set(localName, [source, null, localName]);
}
}
for (const [local, data] of metadata.local) {
let exportMeta = exported.get(local);
if (!exportMeta) {
exportMeta = [];
exported.set(local, exportMeta);
}
exportMeta.push(...data.names);
}
const rewriteBindingInitVisitorState = {
metadata,
requeueInParent,
scope: programPath.scope,
exported
};
programPath.traverse(rewriteBindingInitVisitor, rewriteBindingInitVisitorState);
(0, _helperSimpleAccess.default)(programPath, new Set([...Array.from(imported.keys()), ...Array.from(exported.keys())]), false);
const rewriteReferencesVisitorState = {
seen: new WeakSet(),
metadata,
requeueInParent,
scope: programPath.scope,
imported,
exported,
buildImportReference: ([source, importName, localName], identNode) => {
const meta = metadata.source.get(source);
if (localName) {
if (meta.lazy) {
identNode = callExpression(identNode, []);
}
return identNode;
}
let namespace = identifier(meta.name);
if (meta.lazy) namespace = callExpression(namespace, []);
if (importName === "default" && meta.interop === "node-default") {
return namespace;
}
const computed = metadata.stringSpecifiers.has(importName);
return memberExpression(namespace, computed ? stringLiteral(importName) : identifier(importName), computed);
}
};
programPath.traverse(rewriteReferencesVisitor, rewriteReferencesVisitorState);
}
const rewriteBindingInitVisitor = {
Scope(path) {
path.skip();
},
ClassDeclaration(path) {
const {
requeueInParent,
exported,
metadata
} = this;
const {
id
} = path.node;
if (!id) throw new Error("Expected class to have a name");
const localName = id.name;
const exportNames = exported.get(localName) || [];
if (exportNames.length > 0) {
const statement = expressionStatement(buildBindingExportAssignmentExpression(metadata, exportNames, identifier(localName), path.scope));
statement._blockHoist = path.node._blockHoist;
requeueInParent(path.insertAfter(statement)[0]);
}
},
VariableDeclaration(path) {
const {
requeueInParent,
exported,
metadata
} = this;
Object.keys(path.getOuterBindingIdentifiers()).forEach(localName => {
const exportNames = exported.get(localName) || [];
if (exportNames.length > 0) {
const statement = expressionStatement(buildBindingExportAssignmentExpression(metadata, exportNames, identifier(localName), path.scope));
statement._blockHoist = path.node._blockHoist;
requeueInParent(path.insertAfter(statement)[0]);
}
});
}
};
const buildBindingExportAssignmentExpression = (metadata, exportNames, localExpr, scope) => {
const exportsObjectName = metadata.exportName;
for (let currentScope = scope; currentScope != null; currentScope = currentScope.parent) {
if (currentScope.hasOwnBinding(exportsObjectName)) {
currentScope.rename(exportsObjectName);
}
}
return (exportNames || []).reduce((expr, exportName) => {
const {
stringSpecifiers
} = metadata;
const computed = stringSpecifiers.has(exportName);
return assignmentExpression("=", memberExpression(identifier(exportsObjectName), computed ? stringLiteral(exportName) : identifier(exportName), computed), expr);
}, localExpr);
};
const buildImportThrow = localName => {
return _template.default.expression.ast`
(function() {
throw new Error('"' + '${localName}' + '" is read-only.');
})()
`;
};
const rewriteReferencesVisitor = {
ReferencedIdentifier(path) {
const {
seen,
buildImportReference,
scope,
imported,
requeueInParent
} = this;
if (seen.has(path.node)) return;
seen.add(path.node);
const localName = path.node.name;
const importData = imported.get(localName);
if (importData) {
if (isInType(path)) {
throw path.buildCodeFrameError(`Cannot transform the imported binding "${localName}" since it's also used in a type annotation. ` + `Please strip type annotations using @babel/preset-typescript or @babel/preset-flow.`);
}
const localBinding = path.scope.getBinding(localName);
const rootBinding = scope.getBinding(localName);
if (rootBinding !== localBinding) return;
const ref = buildImportReference(importData, path.node);
ref.loc = path.node.loc;
if ((path.parentPath.isCallExpression({
callee: path.node
}) || path.parentPath.isOptionalCallExpression({
callee: path.node
}) || path.parentPath.isTaggedTemplateExpression({
tag: path.node
})) && isMemberExpression(ref)) {
path.replaceWith(sequenceExpression([numericLiteral(0), ref]));
} else if (path.isJSXIdentifier() && isMemberExpression(ref)) {
const {
object,
property
} = ref;
path.replaceWith(jsxMemberExpression(jsxIdentifier(object.name), jsxIdentifier(property.name)));
} else {
path.replaceWith(ref);
}
requeueInParent(path);
path.skip();
}
},
UpdateExpression(path) {
const {
scope,
seen,
imported,
exported,
requeueInParent,
buildImportReference
} = this;
if (seen.has(path.node)) return;
seen.add(path.node);
const arg = path.get("argument");
if (arg.isMemberExpression()) return;
const update = path.node;
if (arg.isIdentifier()) {
const localName = arg.node.name;
if (scope.getBinding(localName) !== path.scope.getBinding(localName)) {
return;
}
const exportedNames = exported.get(localName);
const importData = imported.get(localName);
if ((exportedNames == null ? void 0 : exportedNames.length) > 0 || importData) {
if (importData) {
path.replaceWith(assignmentExpression(update.operator[0] + "=", buildImportReference(importData, arg.node), buildImportThrow(localName)));
} else if (update.prefix) {
path.replaceWith(buildBindingExportAssignmentExpression(this.metadata, exportedNames, cloneNode(update), path.scope));
} else {
const ref = scope.generateDeclaredUidIdentifier(localName);
path.replaceWith(sequenceExpression([assignmentExpression("=", cloneNode(ref), cloneNode(update)), buildBindingExportAssignmentExpression(this.metadata, exportedNames, identifier(localName), path.scope), cloneNode(ref)]));
}
}
}
requeueInParent(path);
path.skip();
},
AssignmentExpression: {
exit(path) {
const {
scope,
seen,
imported,
exported,
requeueInParent,
buildImportReference
} = this;
if (seen.has(path.node)) return;
seen.add(path.node);
const left = path.get("left");
if (left.isMemberExpression()) return;
if (left.isIdentifier()) {
const localName = left.node.name;
if (scope.getBinding(localName) !== path.scope.getBinding(localName)) {
return;
}
const exportedNames = exported.get(localName);
const importData = imported.get(localName);
if ((exportedNames == null ? void 0 : exportedNames.length) > 0 || importData) {
_assert(path.node.operator === "=", "Path was not simplified");
const assignment = path.node;
if (importData) {
assignment.left = buildImportReference(importData, left.node);
assignment.right = sequenceExpression([assignment.right, buildImportThrow(localName)]);
}
path.replaceWith(buildBindingExportAssignmentExpression(this.metadata, exportedNames, assignment, path.scope));
requeueInParent(path);
}
} else {
const ids = left.getOuterBindingIdentifiers();
const programScopeIds = Object.keys(ids).filter(localName => scope.getBinding(localName) === path.scope.getBinding(localName));
const id = programScopeIds.find(localName => imported.has(localName));
if (id) {
path.node.right = sequenceExpression([path.node.right, buildImportThrow(id)]);
}
const items = [];
programScopeIds.forEach(localName => {
const exportedNames = exported.get(localName) || [];
if (exportedNames.length > 0) {
items.push(buildBindingExportAssignmentExpression(this.metadata, exportedNames, identifier(localName), path.scope));
}
});
if (items.length > 0) {
let node = sequenceExpression(items);
if (path.parentPath.isExpressionStatement()) {
node = expressionStatement(node);
node._blockHoist = path.parentPath.node._blockHoist;
}
const statement = path.insertAfter(node)[0];
requeueInParent(statement);
}
}
}
},
"ForOfStatement|ForInStatement"(path) {
const {
scope,
node
} = path;
const {
left
} = node;
const {
exported,
imported,
scope: programScope
} = this;
if (!isVariableDeclaration(left)) {
let didTransformExport = false,
importConstViolationName;
const loopBodyScope = path.get("body").scope;
for (const name of Object.keys(getOuterBindingIdentifiers(left))) {
if (programScope.getBinding(name) === scope.getBinding(name)) {
if (exported.has(name)) {
didTransformExport = true;
if (loopBodyScope.hasOwnBinding(name)) {
loopBodyScope.rename(name);
}
}
if (imported.has(name) && !importConstViolationName) {
importConstViolationName = name;
}
}
}
if (!didTransformExport && !importConstViolationName) {
return;
}
path.ensureBlock();
const bodyPath = path.get("body");
const newLoopId = scope.generateUidIdentifierBasedOnNode(left);
path.get("left").replaceWith(variableDeclaration("let", [variableDeclarator(cloneNode(newLoopId))]));
scope.registerDeclaration(path.get("left"));
if (didTransformExport) {
bodyPath.unshiftContainer("body", expressionStatement(assignmentExpression("=", left, newLoopId)));
}
if (importConstViolationName) {
bodyPath.unshiftContainer("body", expressionStatement(buildImportThrow(importConstViolationName)));
}
}
}
};
//# sourceMappingURL=rewrite-live-references.js.map