Skip to content

Commit 1d9c841

Browse files
Fixed tests + added post compilation transform to ensure single argument arrow functions are not wrapped in parenthesis for their singular argument. (#169)
1 parent 98066d1 commit 1d9c841

File tree

11 files changed

+81
-14
lines changed

11 files changed

+81
-14
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
"acorn": "6.1.1",
3131
"acorn-dynamic-import": "4.0.0",
3232
"acorn-walk": "6.1.1",
33-
"google-closure-compiler": "20190215.0.1",
33+
"google-closure-compiler": "20190325.0.0",
3434
"magic-string": "0.25.2",
3535
"temp-write": "3.4.0"
3636
},

src/transformers/arrow-function.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/**
2+
* Copyright 2019 The AMP HTML Authors. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS-IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import { Transform, Range, TransformInterface } from '../types';
18+
import { TransformSourceDescription } from 'rollup';
19+
import MagicString from 'magic-string';
20+
import { ArrowFunctionExpression } from 'estree';
21+
import { parse, walk } from '../acorn';
22+
23+
/**
24+
* Closure Compiler will occasionally wrap ArrowFunctionExpression Parameters with additional parenthesis.
25+
* e.g (a)=>a.foo() => a=>a.foo()
26+
*
27+
* @see https://astexplorer.net/#/gist/20d7fbe32292c6c9f303c1d9643885ec/6c97fabca987814cced795b8d3d078094e642264
28+
*/
29+
export default class ArrowFunctionTransform extends Transform implements TransformInterface {
30+
/**
31+
* @param code source to parse, and modify
32+
* @return modified input source with computed literal keys
33+
*/
34+
public async postCompilation(code: string): Promise<TransformSourceDescription> {
35+
const source = new MagicString(code);
36+
const program = parse(code);
37+
38+
walk.simple(program, {
39+
ArrowFunctionExpression(arrowFunction: ArrowFunctionExpression) {
40+
const functionRange: Range = arrowFunction.range as Range;
41+
const params = arrowFunction.params;
42+
if (params.length === 1) {
43+
const identifier = params[0];
44+
if ('name' in identifier) {
45+
const paramRange: Range = params[0].range as Range;
46+
if (functionRange[0] !== paramRange[0]) {
47+
const bodyRange = arrowFunction.body.range as Range;
48+
source.overwrite(functionRange[0], bodyRange[0], `${identifier.name}=>`);
49+
}
50+
}
51+
}
52+
},
53+
});
54+
55+
return {
56+
code: source.toString(),
57+
map: source.generateMap().mappings,
58+
};
59+
}
60+
}

src/transformers/imports.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
import { Transform } from '../types';
17+
import { Transform, Range } from '../types';
1818
import { literalName, importLocalNames } from './parsing-utilities';
1919
import { TransformSourceDescription } from 'rollup';
2020
import MagicString from 'magic-string';
@@ -33,7 +33,7 @@ const HEADER = `/**
3333

3434
interface RangedImport {
3535
type: string;
36-
range: [number, number];
36+
range: Range;
3737
}
3838

3939
export default class ImportTransform extends Transform {
@@ -83,7 +83,7 @@ window['${DYNAMIC_IMPORT_REPLACEMENT}'] = ${DYNAMIC_IMPORT_REPLACEMENT};`;
8383
walk.simple(program, {
8484
async ImportDeclaration(node: ImportDeclaration) {
8585
const name = literalName(self.context, node.source);
86-
const range: [number, number] = node.range ? [node.range[0], node.range[1]] : [0, 0];
86+
const range: Range = node.range ? [node.range[0], node.range[1]] : [0, 0];
8787
self.importedExternalsSyntax[name] = code.slice(range[0], range[1]);
8888
source.remove(range[0], range[1]);
8989

@@ -127,7 +127,7 @@ window['${DYNAMIC_IMPORT_REPLACEMENT}'] = ${DYNAMIC_IMPORT_REPLACEMENT};`;
127127
walk.simple(program, {
128128
Identifier(node: Identifier) {
129129
if (node.name === DYNAMIC_IMPORT_REPLACEMENT) {
130-
const range: [number, number] = node.range ? [node.range[0], node.range[1]] : [0, 0];
130+
const range: Range = node.range ? [node.range[0], node.range[1]] : [0, 0];
131131
source.overwrite(range[0], range[1], DYNAMIC_IMPORT_KEYWORD);
132132
}
133133
},

src/transforms.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import ExportTransform from './transformers/exports';
2222
import ImportTransform from './transformers/imports';
2323
import StrictTransform from './transformers/strict';
2424
import ConstTransform from './transformers/const';
25+
import ArrowFunctionTransform from './transformers/arrow-function';
2526
import { logSource } from './debug';
2627

2728
/**
@@ -41,6 +42,7 @@ export const createTransforms = (
4142
new StrictTransform(context, options),
4243
new ExportTransform(context, options),
4344
new ImportTransform(context, options),
45+
new ArrowFunctionTransform(context, options),
4446
];
4547
};
4648

src/types.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ export const ALL_EXPORT_DECLARATIONS = [
4242
EXPORT_ALL_DECLARATION,
4343
];
4444

45+
export type Range = [number, number];
46+
4547
export enum ExportClosureMapping {
4648
NAMED_FUNCTION = 0,
4749
NAMED_CLASS = 1,
@@ -58,7 +60,7 @@ export interface ExportNameToClosureMapping {
5860
[key: string]: {
5961
alias: string | null;
6062
type: ExportClosureMapping;
61-
range: [number, number];
63+
range: Range;
6264
};
6365
}
6466

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
var b=Symbol.for("smth");var isSmth=(a)=>a&&!!a[b];export{isSmth};
1+
var b=Symbol.for("smth");var isSmth=a=>a&&!!a[b];export{isSmth};
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
var b=Symbol.for("smth");var isSmth=(a)=>a&&!!a[b];export{isSmth};
1+
var b=Symbol.for("smth");var isSmth=a=>a&&!!a[b];export{isSmth};

test/export-transpilation/fixtures/named-constant.esm.es5.js

Lines changed: 4 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/generator.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,9 @@ function generate(shouldFail, category, name, codeSplit, formats, closureFlags)
116116
const output = await compile(optionKey, format);
117117

118118
t.plan(output.length);
119-
output.forEach(result => t.is(result.code, result.minified));
119+
for (result of output) {
120+
t.is(result.code, result.minified)
121+
}
120122
},
121123
);
122124
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
'use strict';var wrapper=function(a){a.a=function(a){document.body.innerHTML="hello "+a};return a}({});
1+
'use strict';var wrapper=function(a){a.a=function(b){document.body.innerHTML="hello "+b};return a}({});

0 commit comments

Comments
 (0)