Skip to content

Commit 8956b31

Browse files
Only process an export once to avoid duplication of exported names
1 parent e1c11ee commit 8956b31

File tree

13 files changed

+57
-62
lines changed

13 files changed

+57
-62
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@
8282
"verbose": true
8383
},
8484
"prettier": {
85-
"printWidth": 100,
85+
"printWidth": 120,
8686
"trailingComma": "all",
8787
"parser": "typescript",
8888
"singleQuote": true

src/acorn.ts

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -29,25 +29,14 @@ import {
2929
ClassDeclaration,
3030
ExportSpecifier,
3131
} from 'estree';
32-
// import { DYNAMIC_IMPORT_DECLARATION } from './types';
3332
import * as acorn from 'acorn';
34-
// const acorn = require('acorn');
33+
import { log } from './debug';
34+
import { writeTempFile } from './temp-file';
3535
const acornWalk = require('acorn-walk');
36-
// const dynamicImport = require('acorn-dynamic-import');
37-
38-
// const DYNAMIC_IMPORT_BASEVISITOR = Object.assign({}, acornWalk.base, {
39-
// [DYNAMIC_IMPORT_DECLARATION]: () => {},
40-
// });
4136

4237
export const walk = {
4338
simple: acornWalk.simple,
4439
ancestor: acornWalk.ancestor,
45-
// simple(node: Program, visitors: any): void {
46-
// acornWalk.simple(node, visitors, DYNAMIC_IMPORT_BASEVISITOR);
47-
// },
48-
// ancestor(node: Program, visitors: any): void {
49-
// acornWalk.ancestor(node, visitors, DYNAMIC_IMPORT_BASEVISITOR);
50-
// },
5140
};
5241

5342
const DEFAULT_ACORN_OPTIONS = {
@@ -57,9 +46,13 @@ const DEFAULT_ACORN_OPTIONS = {
5746
ranges: true,
5847
};
5948

60-
export function parse(source: string): Program {
61-
return (acorn.parse(source, DEFAULT_ACORN_OPTIONS) as unknown) as Program;
62-
// return acorn.Parser.extend(dynamicImport.default).parse(source, DEFAULT_ACORN_OPTIONS);
49+
export async function parse(fileName: string, source: string): Promise<Program> {
50+
try {
51+
return (acorn.parse(source, DEFAULT_ACORN_OPTIONS) as unknown) as Program;
52+
} catch (e) {
53+
log(`parse exception in ${fileName}`, `file://${await writeTempFile(source, '.js')}`);
54+
throw e;
55+
}
6356
}
6457

6558
export function isIdentifier(node: BaseNode): node is Identifier {

src/transform.ts

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,11 @@ export class ChunkTransform extends Transform {
6565
return null;
6666
}
6767

68-
public async pre(source: MagicString): Promise<MagicString> {
68+
public async pre(fileName: string, source: MagicString): Promise<MagicString> {
6969
return source;
7070
}
7171

72-
public async post(source: MagicString): Promise<MagicString> {
72+
public async post(fileName: string, source: MagicString): Promise<MagicString> {
7373
return source;
7474
}
7575
}
@@ -84,16 +84,24 @@ export async function chunkLifecycle(
8484
const log: Array<[string, string]> = [];
8585
const sourcemaps: Array<RemappingDecodedSourceMap> = [];
8686
let source = new MagicString(code);
87+
let finalSource: string = '';
8788

8889
log.push(['before', code]);
89-
for (const transform of transforms) {
90-
const transformed = await transform[method](source);
91-
const transformedSource = transformed.toString();
92-
sourcemaps.push(createDecodedSourceMap(transformed, fileName));
93-
source = new MagicString(transformedSource);
94-
log.push([transform.name, transformedSource]);
90+
try {
91+
for (const transform of transforms) {
92+
const transformed = await transform[method](fileName, source);
93+
const transformedSource = transformed.toString();
94+
sourcemaps.push(createDecodedSourceMap(transformed, fileName));
95+
source = new MagicString(transformedSource);
96+
log.push([transform.name, transformedSource]);
97+
}
98+
finalSource = source.toString();
99+
} catch (e) {
100+
log.push(['after', finalSource]);
101+
await logTransformChain(fileName, printableName, log);
102+
103+
throw e;
95104
}
96-
const finalSource = source.toString();
97105

98106
log.push(['after', finalSource]);
99107
await logTransformChain(fileName, printableName, log);

src/transformers/chunk/asi.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ export default class ASITransform extends ChunkTransform {
2626
* Small reduction in semi-colons, removing from end of block statements.
2727
* @param source source following closure compiler minification
2828
*/
29-
public async post(source: MagicString): Promise<MagicString> {
29+
public async post(fileName: string, source: MagicString): Promise<MagicString> {
3030
const code = source.toString();
31-
const program = parse(code);
31+
const program = await parse(fileName, code);
3232

3333
if (program.body) {
3434
const lastStatement = program.body[program.body.length - 1];

src/transformers/chunk/const.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ export default class ConstTransform extends ChunkTransform {
2929
* @param code source following closure compiler minification
3030
* @return code after removing the strict mode declaration (when safe to do so)
3131
*/
32-
public async pre(source: MagicString): Promise<MagicString> {
32+
public async pre(fileName: string, source: MagicString): Promise<MagicString> {
3333
const code = source.toString();
34-
const program = parse(code);
34+
const program = await parse(fileName, code);
3535

3636
walk.simple(program, {
3737
VariableDeclaration(node: VariableDeclaration) {

src/transformers/chunk/exports.ts

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,8 @@ export default class ExportTransform extends ChunkTransform implements Transform
8484
return collected;
8585
}
8686

87-
private async deriveExports(code: string): Promise<void> {
88-
const program = parse(code);
87+
private async deriveExports(fileName: string, code: string): Promise<void> {
88+
const program = await parse(fileName, code);
8989

9090
walk.simple(program, {
9191
ExportNamedDeclaration: (node: ExportNamedDeclaration) => {
@@ -97,9 +97,7 @@ export default class ExportTransform extends ChunkTransform implements Transform
9797
ExportAllDeclaration: () => {
9898
// TODO(KB): This case `export * from "./import"` is not currently supported.
9999
this.context.error(
100-
new Error(
101-
`Rollup Plugin Closure Compiler does not support export all syntax for externals.`,
102-
),
100+
new Error(`Rollup Plugin Closure Compiler does not support export all syntax for externals.`),
103101
);
104102
},
105103
});
@@ -130,13 +128,13 @@ export default class ExportTransform extends ChunkTransform implements Transform
130128
* @param id Rollup id reference to the source
131129
* @return modified input source with window scoped references.
132130
*/
133-
public async pre(source: MagicString): Promise<MagicString> {
131+
public async pre(fileName: string, source: MagicString): Promise<MagicString> {
134132
if (!isESMFormat(this.outputOptions)) {
135-
return super.pre(source);
133+
return super.pre(fileName, source);
136134
}
137135

138136
const code = source.toString();
139-
await this.deriveExports(code);
137+
await this.deriveExports(fileName, code);
140138

141139
for (const key of this.originalExports.keys()) {
142140
const value: ExportDetails = this.originalExports.get(key) as ExportDetails;
@@ -162,13 +160,13 @@ export default class ExportTransform extends ChunkTransform implements Transform
162160
* @param code source post Closure Compiler Compilation
163161
* @return Promise containing the repaired source
164162
*/
165-
public async post(source: MagicString): Promise<MagicString> {
163+
public async post(fileName: string, source: MagicString): Promise<MagicString> {
166164
if (!isESMFormat(this.outputOptions)) {
167-
return super.post(source);
165+
return super.post(fileName, source);
168166
}
169167

170168
const code = source.toString();
171-
const program = parse(code);
169+
const program = await parse(fileName, code);
172170
let collectedExportsToAppend: Map<string | null, Array<string>> = new Map();
173171

174172
source.trimEnd();
@@ -192,9 +190,7 @@ export default class ExportTransform extends ChunkTransform implements Transform
192190
const exportName: string | null = PreservedExportName(left);
193191

194192
if (exportName !== null && this.originalExports.get(exportName)) {
195-
const exportDetails: ExportDetails = this.originalExports.get(
196-
exportName,
197-
) as ExportDetails;
193+
const exportDetails: ExportDetails = this.originalExports.get(exportName) as ExportDetails;
198194
const exportIsLocal: boolean = exportDetails.source === null;
199195
const exportInline: boolean =
200196
(exportIsLocal &&
@@ -227,6 +223,9 @@ export default class ExportTransform extends ChunkTransform implements Transform
227223
const { 1: ancestorEnd } = ancestor.range as Range;
228224
source.remove(leftStart, ancestorEnd);
229225
}
226+
227+
// An Export can only be processed once.
228+
this.originalExports.delete(exportName);
230229
}
231230
}
232231
},

src/transformers/chunk/hashbang-apply.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export default class HashbangApplyTransform extends ChunkTransform implements Tr
2929
/**
3030
* @param source MagicString of source to process post Closure Compilation.
3131
*/
32-
public async post(source: MagicString): Promise<MagicString> {
32+
public async post(fileName: string, source: MagicString): Promise<MagicString> {
3333
if (this.memory.hashbang === null) {
3434
return source;
3535
}

src/transformers/chunk/hashbang-remove.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export default class HashbangRemoveTransform extends ChunkTransform implements T
2929
/**
3030
* @param source MagicString of source to process post Closure Compilation.
3131
*/
32-
public async pre(source: MagicString): Promise<MagicString> {
32+
public async pre(fileName: string, source: MagicString): Promise<MagicString> {
3333
const stringified = source.trim().toString();
3434
const match = /^#!.*/.exec(stringified);
3535

src/transformers/chunk/imports.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,9 @@ window['${DYNAMIC_IMPORT_REPLACEMENT}'] = ${DYNAMIC_IMPORT_REPLACEMENT};`;
8686
* @param code source to parse, and modify
8787
* @return modified input source with external imports removed.
8888
*/
89-
public pre = async (source: MagicString): Promise<MagicString> => {
89+
public pre = async (fileName: string, source: MagicString): Promise<MagicString> => {
9090
const code = source.toString();
91-
let program = parse(code);
91+
let program = await parse(fileName, code);
9292
let dynamicImportPresent: boolean = false;
9393
let { mangler, importedExternalsSyntax, importedExternalsLocalNames } = this;
9494

@@ -154,9 +154,9 @@ window['${DYNAMIC_IMPORT_REPLACEMENT}'] = ${DYNAMIC_IMPORT_REPLACEMENT};`;
154154
* @param code source post Closure Compiler Compilation
155155
* @return Promise containing the repaired source
156156
*/
157-
public async post(source: MagicString): Promise<MagicString> {
157+
public async post(fileName: string, source: MagicString): Promise<MagicString> {
158158
const code = source.toString();
159-
const program = parse(code);
159+
const program = await parse(fileName, code);
160160

161161
for (const importedExternalSyntax of Object.values(this.importedExternalsSyntax)) {
162162
source.prepend(importedExternalSyntax);

src/transformers/chunk/literal-computed-keys.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ export default class LiteralComputedKeys extends ChunkTransform implements Trans
3434
* @param code source to parse, and modify
3535
* @return modified input source with computed literal keys
3636
*/
37-
public async post(source: MagicString): Promise<MagicString> {
38-
const program = parse(source.toString());
37+
public async post(fileName: string, source: MagicString): Promise<MagicString> {
38+
const program = await parse(fileName, source.toString());
3939

4040
walk.simple(program, {
4141
ObjectExpression(node: ObjectExpression) {

0 commit comments

Comments
 (0)