Skip to content

Commit

Permalink
Add missing spaces in certain statements and expressions to avoid inv…
Browse files Browse the repository at this point in the history
…alid code (#3173)

* Add missing spaces in certain statements and expressions to avoid invalid syntax

* Improve coverage
  • Loading branch information
lukastaegert committed Oct 18, 2019
1 parent 121a7f4 commit 91cb8f0
Show file tree
Hide file tree
Showing 10 changed files with 63 additions and 19 deletions.
27 changes: 12 additions & 15 deletions src/ast/nodes/AwaitExpression.ts
@@ -1,5 +1,3 @@
import MagicString from 'magic-string';
import { RenderOptions } from '../../utils/renderHelpers';
import { HasEffectsContext, InclusionContext } from '../ExecutionContext';
import ArrowFunctionExpression from './ArrowFunctionExpression';
import * as NodeType from './NodeType';
Expand All @@ -11,22 +9,21 @@ export default class AwaitExpression extends NodeBase {
type!: NodeType.tAwaitExpression;

hasEffects(context: HasEffectsContext) {
return super.hasEffects(context) || !context.ignore.returnAwaitYield;
return !context.ignore.returnAwaitYield || this.argument.hasEffects(context);
}

include(context: InclusionContext, includeChildrenRecursively: IncludeChildren) {
checkTopLevelAwait: if (!this.included && !this.context.usesTopLevelAwait) {
let parent = this.parent;
do {
if (parent instanceof FunctionNode || parent instanceof ArrowFunctionExpression)
break checkTopLevelAwait;
} while ((parent = (parent as Node).parent as Node));
this.context.usesTopLevelAwait = true;
if (!this.included) {
this.included = true;
checkTopLevelAwait: if (!this.context.usesTopLevelAwait) {
let parent = this.parent;
do {
if (parent instanceof FunctionNode || parent instanceof ArrowFunctionExpression)
break checkTopLevelAwait;
} while ((parent = (parent as Node).parent as Node));
this.context.usesTopLevelAwait = true;
}
}
super.include(context, includeChildrenRecursively);
}

render(code: MagicString, options: RenderOptions) {
super.render(code, options);
this.argument.include(context, includeChildrenRecursively);
}
}
4 changes: 4 additions & 0 deletions src/ast/nodes/ForInStatement.ts
Expand Up @@ -60,6 +60,10 @@ export default class ForInStatement extends StatementBase {
render(code: MagicString, options: RenderOptions) {
this.left.render(code, options, NO_SEMICOLON);
this.right.render(code, options, NO_SEMICOLON);
// handle no space between "in" and the right side
if (code.original.charCodeAt(this.right.start - 1) === 110 /* n */) {
code.prependLeft(this.right.start, ' ');
}
this.body.render(code, options);
}
}
4 changes: 4 additions & 0 deletions src/ast/nodes/ForOfStatement.ts
Expand Up @@ -45,6 +45,10 @@ export default class ForOfStatement extends StatementBase {
render(code: MagicString, options: RenderOptions) {
this.left.render(code, options, NO_SEMICOLON);
this.right.render(code, options, NO_SEMICOLON);
// handle no space between "of" and the right side
if (code.original.charCodeAt(this.right.start - 1) === 102 /* f */) {
code.prependLeft(this.right.start, ' ');
}
this.body.render(code, options);
}
}
3 changes: 3 additions & 0 deletions src/ast/nodes/ThrowStatement.ts
Expand Up @@ -20,5 +20,8 @@ export default class ThrowStatement extends StatementBase {

render(code: MagicString, options: RenderOptions) {
this.argument.render(code, options, { preventASI: true });
if (this.argument.start === this.start + 5 /* 'throw'.length */) {
code.prependLeft(this.start + 5, ' ');
}
}
}
3 changes: 1 addition & 2 deletions test/form/samples/side-effects-await/_config.js
@@ -1,5 +1,4 @@
module.exports = {
description:
'await statements should never be dropped if a function has other side-effects (#1584)',
options: { output: { name: 'myBundle' } }
'await statements should never be dropped if a function has other side-effects (#1584)'
};
2 changes: 2 additions & 0 deletions test/form/samples/top-level-await/_expected/es.js
@@ -1 +1,3 @@
await operation();

await retainedOperation();
2 changes: 2 additions & 0 deletions test/form/samples/top-level-await/_expected/system.js
Expand Up @@ -5,6 +5,8 @@ System.register([], function () {

await operation();

await retainedOperation();

}
};
});
4 changes: 2 additions & 2 deletions test/form/samples/top-level-await/main.js
@@ -1,4 +1,4 @@
await operation();

if (false)
await treeshakenOperation();
if (false) await treeshakenOperation();
else await retainedOperation();
@@ -0,0 +1,5 @@
module.exports = {
description:
'handle situations where the simplification of an expression can lead to issues due to missing white-space',
options: { treeshake: { tryCatchDeoptimization: false } }
};
28 changes: 28 additions & 0 deletions test/function/samples/missing-spaces-after-simplification/main.js
@@ -0,0 +1,28 @@
let result = '';

const a = { a: true };
for (const key in!0?a:a) result += key;

const b = ['b'];
for (const value of!0?b:b) result += value;

const c = 'c';
function testReturn() {
return!0?c:c;
}
result += testReturn();

const d = 'd';
function* testYield() {
yield!0?d:d;
}
for (const value of testYield()) result += value;

const e = 'e';
try {
throw!0?e:e;
} catch (err) {
result += err;
}

assert.strictEqual(result, 'abcde');

0 comments on commit 91cb8f0

Please sign in to comment.