/** * Convert * let a = require('b'); * to * import a from 'b'; * * Any imported names are added to the collectedDefaultImportNames parameter. */ function rewriteSingleExportRequire( path: Path, module: Module, collectedDefaultImportNames: Array<string>): boolean { let { node } = path; if (!t.isVariableDeclaration(node)) { return false; } let { declarations } = node; let extractableDeclarations = []; declarations.forEach(declaration => { let { id, init } = declaration; if (!t.isIdentifier(id)) { return; } let pathNode = extractRequirePathNode(init); if (!pathNode) { return; } extractableDeclarations.push({ declaration, id, pathNode }); }); if (declarations.length === 0) { return false; } if (declarations.length !== extractableDeclarations.length) { // TODO: We have to replace only part of it. return false; } rewriteRequireAsImports( 'default-import', path, module, extractableDeclarations.map( ({ id, pathNode }) => ({ bindings: [new Binding(id.name, 'default')], pathNode }) ) ); path.replaceWithMultiple( extractableDeclarations.map(({ id, pathNode }) => t.importDeclaration( [t.importDefaultSpecifier(id)], pathNode )) ); collectedDefaultImportNames.push(...extractableDeclarations.map(d => d.id.name)); return true; }
function hasBinding(node, name) { if (Array.isArray(node)) { return node.some(ancestor => hasBinding(ancestor, name)); } else if ( types.isProgram(node) || types.isBlockStatement(node) || types.isBlock(node) ) { return node.body.some(statement => hasBinding(statement, name)); } else if ( types.isFunctionDeclaration(node) || types.isFunctionExpression(node) || types.isArrowFunctionExpression(node) ) { return ( (node.id && node.id.name === name) || node.params.some( param => types.isIdentifier(param) && param.name === name ) ); } else if (types.isVariableDeclaration(node)) { return node.declarations.some(declaration => declaration.id.name === name); } return false; }
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 extractSingleDeclaration(node: Node): ?Node { if (!t.isVariableDeclaration(node)) { return null; } if (node.declarations.length !== 1) { return null; } return node.declarations[0]; }
export default function(path, { getAsyncIterator }) { const { node, scope, parent } = path; const stepKey = scope.generateUidIdentifier("step"); const stepValue = scope.generateUidIdentifier("value"); const left = node.left; let declar; if (t.isIdentifier(left) || t.isPattern(left) || t.isMemberExpression(left)) { // for await (i of test), for await ({ i } of test) declar = t.expressionStatement( t.assignmentExpression("=", left, stepValue), ); } else if (t.isVariableDeclaration(left)) { // for await (let i of test) declar = t.variableDeclaration(left.kind, [ t.variableDeclarator(left.declarations[0].id, stepValue), ]); } let template = buildForAwait({ ITERATOR_HAD_ERROR_KEY: scope.generateUidIdentifier("didIteratorError"), ITERATOR_COMPLETION: scope.generateUidIdentifier( "iteratorNormalCompletion", ), ITERATOR_ERROR_KEY: scope.generateUidIdentifier("iteratorError"), ITERATOR_KEY: scope.generateUidIdentifier("iterator"), GET_ITERATOR: getAsyncIterator, OBJECT: node.right, STEP_VALUE: stepValue, STEP_KEY: stepKey, }); // remove async function wrapper template = template.body.body; const isLabeledParent = t.isLabeledStatement(parent); const tryBody = template[3].block.body; const loop = tryBody[0]; if (isLabeledParent) { tryBody[0] = t.labeledStatement(parent.label, loop); } return { replaceParent: isLabeledParent, node: template, declar, loop, }; }
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); });
/** * 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); }
if (left.isPattern() || left.isIdentifier()) { state.constantViolations.push(path); } }, ExportDeclaration: { exit(path) { const { node, scope } = path; const declar = node.declaration; if (t.isClassDeclaration(declar) || t.isFunctionDeclaration(declar)) { const id = declar.id; if (!id) return; const binding = scope.getBinding(id.name); if (binding) binding.reference(path); } else if (t.isVariableDeclaration(declar)) { for (const decl of (declar.declarations: Array<Object>)) { const ids = t.getBindingIdentifiers(decl); for (const name in ids) { const binding = scope.getBinding(name); if (binding) binding.reference(path); } } } }, }, LabeledStatement(path) { path.scope.getProgramParent().addGlobal(path.node); path.scope.getBlockParent().registerDeclaration(path); },
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 ""; }
wrapModule(asset, statements) { let body = []; let decls = []; let fns = []; for (let node of statements) { // Hoist all declarations out of the function wrapper // so that they can be referenced by other modules directly. if (t.isVariableDeclaration(node)) { for (let decl of node.declarations) { decls.push(t.variableDeclarator(decl.id)); if (decl.init) { body.push( t.expressionStatement( t.assignmentExpression( '=', t.identifier(decl.id.name), decl.init ) ) ); } } } else if (t.isFunctionDeclaration(node)) { // Function declarations can be hoisted out of the module initialization function fns.push(node); } else if (t.isClassDeclaration(node)) { // Class declarations are not hoisted. We declare a variable outside the // function convert to a class expression assignment. decls.push(t.variableDeclarator(t.identifier(node.id.name))); body.push( t.expressionStatement( t.assignmentExpression( '=', t.identifier(node.id.name), t.toExpression(node) ) ) ); } else { body.push(node); } } let executed = getName(asset, 'executed'); decls.push( t.variableDeclarator(t.identifier(executed), t.booleanLiteral(false)) ); let init = t.functionDeclaration( getIdentifier(asset, 'init'), [], t.blockStatement([ t.ifStatement(t.identifier(executed), t.returnStatement()), t.expressionStatement( t.assignmentExpression( '=', t.identifier(executed), t.booleanLiteral(true) ) ), ...body ]) ); return [t.variableDeclaration('var', decls), ...fns, init]; }
end: fromBabelLocation(node.loc.end, state.sourceId), }); parseDeclarator(node.param, scope, "var", "catch", node, state); } else if ( t.isBlockStatement(node) && // Function body's are handled in the function logic above. !t.isFunction(parentNode) && hasLexicalDeclaration(node, parentNode) ) { // Debugger will create new lexical environment for the block. pushTempScope(state, "block", "Block", { start: fromBabelLocation(node.loc.start, state.sourceId), end: fromBabelLocation(node.loc.end, state.sourceId), }); } else if ( t.isVariableDeclaration(node) && (node.kind === "var" || // Lexical declarations in for statements are handled above. !t.isForStatement(parentNode, { init: node }) || !t.isForXStatement(parentNode, { left: node })) ) { // Finds right lexical environment const hoistAt = !isLetOrConst(node) ? getVarScope(state.scope) : state.scope; node.declarations.forEach(declarator => { parseDeclarator( declarator.id, hoistAt, node.kind, node.kind,
return t.isMemberExpression(node) && t.isReferenced(node, parent); }, }; export const BindingIdentifier = { types: ["Identifier"], checkPath({ node, parent }: NodePath): boolean { return t.isIdentifier(node) && t.isBinding(node, parent); }, }; export const Statement = { types: ["Statement"], checkPath({ node, parent }: NodePath): boolean { if (t.isStatement(node)) { if (t.isVariableDeclaration(node)) { if (t.isForXStatement(parent, { left: node })) return false; if (t.isForStatement(parent, { init: node })) return false; } return true; } else { return false; } }, }; export const Expression = { types: ["Expression"], checkPath(path: NodePath): boolean { if (path.isIdentifier()) {