Skip to content

Commit

Permalink
Fix exit tracking when the argument expression of an early return sta…
Browse files Browse the repository at this point in the history
…tement throws (closes #53)
  • Loading branch information
rpetrich committed Nov 19, 2021
1 parent 504a1d9 commit 65791b9
Show file tree
Hide file tree
Showing 9 changed files with 57 additions and 11 deletions.
48 changes: 40 additions & 8 deletions async-to-promises.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2786,6 +2786,14 @@ export default function ({
);
}

function expressionNeverThrows(expression: Expression): boolean {
return (
isValueLiteral(expression) ||
types.isIdentifier(expression) ||
(types.isUnaryExpression(expression) && isValueLiteral(expression.argument))
);
}

// Visitor that replaces all returns and breaks with updates to the appropriate break/exit bookkeeping variables
const replaceReturnsAndBreaksVisitor: Visitor<{
pluginState: PluginState;
Expand All @@ -2797,19 +2805,43 @@ export default function ({
ReturnStatement(path) {
if (!skipNodeSet.has(path.node) && this.exitIdentifier) {
const minify = readConfigKey(this.pluginState.opts, "minify");
if (minify && path.node.argument && extractLooseBooleanValue(path.node.argument) === true) {
path.replaceWith(
returnStatement(
types.assignmentExpression("=", this.exitIdentifier, path.node.argument),
path.node
)
);
if (path.node.argument) {
if (minify && extractLooseBooleanValue(path.node.argument) === true) {
// assign _exit using a truthy return value
path.replaceWith(
returnStatement(
types.assignmentExpression("=", this.exitIdentifier, path.node.argument),
path.node
)
);
} else if (expressionNeverThrows(path.node.argument)) {
// path cannot throw, assign _exit first
path.replaceWithMultiple([
types.expressionStatement(
types.assignmentExpression("=", this.exitIdentifier, booleanLiteral(true, minify))
),
returnStatement(path.node.argument, path.node),
]);
} else {
// path might throw, evaluate it and assign to a temporary before assigning _exit
const tempIdentifier = path.scope.generateUidIdentifierBasedOnNode(path.node.argument, "temp");
path.replaceWithMultiple([
types.variableDeclaration("const", [
types.variableDeclarator(tempIdentifier, path.node.argument),
]),
types.expressionStatement(
types.assignmentExpression("=", this.exitIdentifier, booleanLiteral(true, minify))
),
returnStatement(tempIdentifier, path.node),
]);
}
} else {
// empty return, assign _exit before returning
path.replaceWithMultiple([
types.expressionStatement(
types.assignmentExpression("=", this.exitIdentifier, booleanLiteral(true, minify))
),
returnStatement(path.node.argument || undefined, path.node),
returnStatement(undefined, path.node),
]);
}
}
Expand Down
2 changes: 1 addition & 1 deletion tests/await logical statement if/hoisted.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion tests/await logical statement if/inlined.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion tests/await logical statement if/output.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions tests/throwing early exit/hoisted.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions tests/throwing early exit/inlined.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions tests/throwing early exit/input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
async function(arg) {
try {
const value = await arg;
return value.missing;
} catch (e) {
}
return "fallback";
}
3 changes: 3 additions & 0 deletions tests/throwing early exit/options.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"supportedBabels": ["babel 7"]
}
1 change: 1 addition & 0 deletions tests/throwing early exit/output.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 65791b9

Please sign in to comment.