// Walk up the print stack to deterimine if our node can come first // in statement. function isFirstInStatement(printStack: Array<Object>): boolean { let i = printStack.length - 1; let node = printStack[i]; i--; let parent = printStack[i]; while (i > 0) { if (t.isExpressionStatement(parent, { expression: 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; }
export function replaceExpressionWithStatements(nodes: Array<Object>) { this.resync(); let toSequenceExpression = t.toSequenceExpression(nodes, this.scope); if (t.isSequenceExpression(toSequenceExpression)) { let exprs = toSequenceExpression.expressions; if (exprs.length >= 2 && this.parentPath.isExpressionStatement()) { this._maybePopFromStatements(exprs); } // could be just one element due to the previous maybe popping if (exprs.length === 1) { this.replaceWith(exprs[0]); } else { this.replaceWith(toSequenceExpression); } } else if (toSequenceExpression) { this.replaceWith(toSequenceExpression); } else { let container = t.functionExpression(null, [], t.blockStatement(nodes)); container.shadow = true; this.replaceWith(t.callExpression(container, [])); this.traverse(hoistVariablesVisitor); // add implicit returns to all ending expression statements let completionRecords: Array<NodePath> = this.get("callee").getCompletionRecords(); for (let path of completionRecords) { if (!path.isExpressionStatement()) continue; let loop = path.findParent((path) => path.isLoop()); if (loop) { let callee = this.get("callee"); let uid = callee.scope.generateDeclaredUidIdentifier("ret"); callee.get("body").pushContainer("body", t.returnStatement(uid)); path.get("expression").replaceWith( t.assignmentExpression("=", uid, path.node.expression) ); } else { path.replaceWith(t.returnStatement(path.node.expression)); } } return this.node; } }
// Walk up the print stack to deterimine 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 })) { return true; } if (considerDefaultExports && t.isExportDefaultDeclaration(parent, { declaration: node })) { return true; } if (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; }