t.traverse(ast, (node, ancestors) => { const parent = ancestors[ancestors.length - 1]; if (t.isWithStatement(node)) { shouldUpdate = false; return; } if (!isTopLevel(ancestors)) { return; } if (t.isAssignmentExpression(node)) { if (t.isIdentifier(node.left) || t.isPattern(node.left)) { const newNode = globalizeAssignment(node, bindings); isMapped = true; return replaceNode(ancestors, newNode); } return; } if (!t.isVariableDeclaration(node)) { return; } if (!t.isForStatement(parent.node)) { const newNodes = globalizeDeclaration(node, bindings); isMapped = true; replaceNode(ancestors, newNodes); } });
function rewriteAsExport(path: Path, module: Module): boolean { let { node } = path; if (!t.isExpressionStatement(node)) { return false; } let { expression } = node; if (!t.isAssignmentExpression(expression)) { return false; } let { left, right } = expression; if (isExportsObject(path.get('expression.left'))) { return rewriteSingleExportAsDefaultExport(path, module); } else if (t.isMemberExpression(left) && !left.computed) { if (!isExportsObject(path.get('expression.left.object'))) { return false; } if (t.isFunctionExpression(right)) { return rewriteNamedFunctionExpressionExport(path, module); } else if (t.isIdentifier(right)) { return rewriteNamedIdentifierExport(path, module); } else { return rewriteNamedValueExport(path, module); } } else { return false; } }
export default function getPluginReplaceProcess(target: 'browser' | 'node') { return { visitor: { MemberExpression(path: Object) { const name = getName(path.node, ['process'], 3) if (name === null || t.isAssignmentExpression(path.parent)) return let modified = false if (name === 'process.browser' && target === 'browser') { // NOTE: Leaving unchanged for node envs on purpose modified = true path.replaceWith(t.booleanLiteral(true)) } if (name === 'process.env.NODE_ENV') { modified = true path.replaceWith(t.stringLiteral(process.env.NODE_ENV || 'development')) } if (modified && path.parentPath.isBinaryExpression()) { const evaluated = path.parentPath.evaluate() if (evaluated.confident) { path.parentPath.replaceWith(t.valueToNode(evaluated.value)) } } }, }, } }
function leftRightOfAssignment(node: Object): ?{ left: Object, right: Object } { if (t.isVariableDeclarator(node)) { return { left: node.id, right: node.init }; } else if (t.isAssignmentExpression(node) && node.operator === '=') { return { left: node.left, right: node.right }; } else { return null; } }
enterExpressionStatement(node) { if (!babel.isAssignmentExpression(node.expression) && !babel.isMemberExpression(node.expression)) { return; } const jsdocAnn = jsdoc.parseJsdoc(esutil.getAttachedComment(node) || ''); if (!jsdoc.hasTag(jsdocAnn, 'memberof')) { return; } const memberofTag = jsdoc.getTag(jsdocAnn, 'memberof'); const namespaceName = memberofTag && memberofTag.description; let prop = undefined; let namespacedIdentifier; if (!namespaceName || !this.namespaces.has(namespaceName)) { return; } if (babel.isAssignmentExpression(node.expression)) { if (babel.isFunctionExpression(node.expression.right)) { return; } namespacedIdentifier = ast_value_1.getIdentifierName(node.expression.left); } else if (babel.isMemberExpression(node.expression)) { namespacedIdentifier = ast_value_1.getIdentifierName(node.expression); } if (!namespacedIdentifier || namespacedIdentifier.indexOf('.prototype.') !== -1) { return; } const namespace = this.namespaces.get(namespaceName); const name = namespacedIdentifier.substring(namespacedIdentifier.lastIndexOf('.') + 1); prop = this._createPropertyFromExpression(name, node.expression, jsdocAnn); if (prop) { namespace.properties.set(name, prop); } }
generateUidBasedOnNode(parent: Object, defaultName?: String) { let node = parent; if (t.isAssignmentExpression(parent)) { node = parent.left; } else if (t.isVariableDeclarator(parent)) { node = parent.id; } else if (t.isObjectProperty(node) || t.isObjectMethod(node)) { node = node.key; } const parts = []; gatherNodeParts(node, parts); let id = parts.join("$"); id = id.replace(/^_/, "") || defaultName || "ref"; return this.generateUid(id.slice(0, 20)); }
t.traverse(ast, (node, ancestors) => { const parent = ancestors[ancestors.length - 1]; if ( t.isWithStatement(node) || !isTopLevel(ancestors) || t.isAssignmentExpression(node) || !t.isVariableDeclaration(node) || t.isForStatement(parent.node) || !Array.isArray(node.declarations) || node.declarations.length === 0 ) { return; } const newNodes = translateDeclarationIntoAssignment(node); replaceNode(ancestors, newNodes); declarations.push(node); });
/** * Rewrites the exports for a file, intentionally converting to a default export * with the same value as the previous module.exports. */ function rewriteStatementsAsDefaultExport(programPath: Path, module: Module) { let exportPaths = []; programPath.traverse({ 'MemberExpression|Identifier|ThisExpression'(path: Path) { if (isExportsObject(path)) { exportPaths.push(path); path.skip(); } } }); if (exportPaths.length === 0) { return; } // Turn a unique `module.exports` line into a single `export default` statement. if (exportPaths.length === 1) { let exportPath = exportPaths[0]; let enclosingStatement = getEnclosingStatement(exportPath); if (t.isExpressionStatement(enclosingStatement.node) && t.isAssignmentExpression(enclosingStatement.node.expression) && enclosingStatement.node.expression.left === exportPath.node) { rewriteAssignmentToDefaultExport(enclosingStatement, module); return; } } let exportsIdentifier = claim(programPath.scope, 'defaultExport'); let exportsVarName = exportsIdentifier.name; let firstStatement = getEnclosingStatement(exportPaths[0]); let lastStatement = getEnclosingStatement(exportPaths[exportPaths.length - 1]); module.magicString.appendLeft(firstStatement.node.start, `let ${exportsVarName} = {};\n`); for (let exportPath of exportPaths) { module.magicString.overwrite(exportPath.node.start, exportPath.node.end, exportsVarName); exportPath.replaceWith(exportsIdentifier); } module.magicString.appendLeft(lastStatement.node.end, `\nexport default ${exportsVarName};`); }
_createPropertyFromExpression(name, node, jsdocAnn) { let description; let type; let readOnly = false; const privacy = esutil.getOrInferPrivacy(name, jsdocAnn); const sourceRange = this.document.sourceRangeForNode(node); const warnings = []; if (jsdocAnn) { description = jsdoc.getDescription(jsdocAnn); readOnly = jsdoc.hasTag(jsdocAnn, 'readonly'); } let detectedType; if (babel.isAssignmentExpression(node)) { detectedType = esutil.getClosureType(node.right, jsdocAnn, sourceRange, this.document); } else { detectedType = esutil.getClosureType(node, jsdocAnn, sourceRange, this.document); } if (detectedType.successful) { type = detectedType.value; } else { warnings.push(detectedType.error); type = '?'; } return { name, astNode: { language: 'js', node, containingDocument: this.document }, type, jsdoc: jsdocAnn, sourceRange, description, privacy, warnings, readOnly, }; }
/** * Extracts properties from a given namespace node. */ function getNamespaceProperties(node, document) { const properties = new Map(); let child; if (babel.isVariableDeclaration(node)) { if (node.declarations.length !== 1) { return properties; } const declaration = node.declarations[0].init; if (!babel.isObjectExpression(declaration)) { return properties; } child = declaration; } else if (babel.isExpressionStatement(node) && babel.isAssignmentExpression(node.expression) && babel.isObjectExpression(node.expression.right)) { child = node.expression.right; } else { return properties; } return esutil.extractPropertiesFromClassOrObjectBody(child, document); }
// Walk up the print stack to determine if our node can come first // in statement. function isFirstInStatement( printStack: Array<Object>, { considerArrow = false, considerDefaultExports = false } = {}, ): boolean { let i = printStack.length - 1; let node = printStack[i]; i--; let parent = printStack[i]; while (i > 0) { if ( t.isExpressionStatement(parent, { expression: node }) || t.isTaggedTemplateExpression(parent) || (considerDefaultExports && t.isExportDefaultDeclaration(parent, { declaration: node })) || (considerArrow && t.isArrowFunctionExpression(parent, { body: node })) ) { return true; } if ( t.isCallExpression(parent, { callee: node }) || (t.isSequenceExpression(parent) && parent.expressions[0] === node) || t.isMemberExpression(parent, { object: node }) || t.isConditional(parent, { test: node }) || t.isBinary(parent, { left: node }) || t.isAssignmentExpression(parent, { left: node }) ) { node = parent; i--; parent = printStack[i]; } else { return false; } } return false; }
specHandle(path: NodePath) { let property; let computed; let args; const parent = path.parent; const node = path.node; if (isIllegalBareSuper(node, parent)) { throw path.buildCodeFrameError("Illegal use of bare super"); } if (t.isCallExpression(node)) { const callee = node.callee; if (t.isSuper(callee)) { return; } else if (isMemberExpressionSuper(callee)) { // super.test(); // to // _get(Object.getPrototypeOf(objectRef.prototype), "test", this).call(this); property = callee.property; computed = callee.computed; args = node.arguments; } } else if (t.isMemberExpression(node) && t.isSuper(node.object)) { // super.name; // to // _get(Object.getPrototypeOf(objectRef.prototype), "name", this); property = node.property; computed = node.computed; } else if ( t.isUpdateExpression(node) && isMemberExpressionSuper(node.argument) ) { const binary = t.assignmentExpression( node.operator[0] + "=", node.argument, t.numericLiteral(1), ); if (node.prefix) { // ++super.foo; // to // super.foo += 1; return this.specHandleAssignmentExpression(null, path, binary); } else { // super.foo++; // to // let _ref = super.foo; super.foo = _ref + 1; const ref = path.scope.generateUidIdentifier("ref"); return this.specHandleAssignmentExpression(ref, path, binary).concat( t.expressionStatement(ref), ); } } else if ( t.isAssignmentExpression(node) && isMemberExpressionSuper(node.left) ) { return this.specHandleAssignmentExpression(null, path, node); } if (!property) return; const superProperty = this.getSuperProperty(property, computed); if (args) { return this.optimiseCall(superProperty, args); } else { return superProperty; } }
function getSnippet( path: SimplePath | null, prevPath?: SimplePath, expression?: string = "" ): string { if (!path) { return expression; } if (t.isVariableDeclaration(path)) { const node = path.node.declarations[0]; const name = node.id.name; return extendSnippet(name, expression, path, prevPath); } if (t.isVariableDeclarator(path)) { const node = path.node.id; if (t.isObjectPattern(node)) { return expression; } const name = node.name; const prop = extendSnippet(name, expression, path, prevPath); return prop; } if (t.isAssignmentExpression(path)) { const node = path.node.left; const name = t.isMemberExpression(node) ? getMemberSnippet(node) : node.name; const prop = extendSnippet(name, expression, path, prevPath); return prop; } if (isFunction(path)) { return expression; } if (t.isIdentifier(path)) { const node = path.node; return `${node.name}.${expression}`; } if (t.isObjectProperty(path)) { return getObjectSnippet(path, prevPath, expression); } if (t.isObjectExpression(path)) { const parentPath = prevPath && prevPath.parentPath; return getObjectSnippet(parentPath, prevPath, expression); } if (t.isMemberExpression(path)) { return getMemberSnippet(path.node, expression); } if (t.isArrayExpression(path)) { if (!prevPath) { throw new Error("Assertion failure - path should exist"); } return getArraySnippet(path, prevPath, expression); } return ""; }