Skip to content

Commit 2d4f237

Browse files
Export CJS auto generate extern (#235)
1 parent a5df548 commit 2d4f237

File tree

3 files changed

+77
-7
lines changed

3 files changed

+77
-7
lines changed

src/transformers/exports.ts

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import {
2222
Node,
2323
ClassDeclaration,
2424
} from 'estree';
25-
import { TransformSourceDescription } from 'rollup';
25+
import { TransformSourceDescription, OutputOptions } from 'rollup';
2626
import { NamedDeclaration, DefaultDeclaration } from './parsing-utilities';
2727
import { isESMFormat } from '../options';
2828
import {
@@ -34,6 +34,20 @@ import {
3434
import MagicString from 'magic-string';
3535
import { parse, walk } from '../acorn';
3636

37+
const CJS_EXTERN = `/**
38+
* @fileoverview Externs built via derived configuration from Rollup or input code.
39+
* This extern contains the export global object so Closure doesn't get confused by its presence.
40+
* @externs
41+
*/
42+
43+
/**
44+
* @typedef {{
45+
* __esModule: boolean,
46+
* }}
47+
*/
48+
let exports;
49+
`;
50+
3751
/**
3852
* This Transform will apply only if the Rollup configuration is for 'esm' output.
3953
*
@@ -76,6 +90,14 @@ export default class ExportTransform extends Transform implements TransformInter
7690
return originalExports;
7791
}
7892

93+
public extern(options: OutputOptions): string {
94+
if (options.format === 'cjs') {
95+
return CJS_EXTERN;
96+
}
97+
98+
return '';
99+
}
100+
79101
/**
80102
* Before Closure Compiler modifies the source, we need to ensure it has window scoped
81103
* references to the named exports. This prevents Closure from mangling their names.
@@ -225,9 +247,7 @@ export default class ExportTransform extends Transform implements TransformInter
225247

226248
if (originalExports[exportName].alias !== null) {
227249
collectedExportsToAppend.push(
228-
`${ancestor.expression.left.property.name} as ${
229-
originalExports[exportName].alias
230-
}`,
250+
`${ancestor.expression.left.property.name} as ${originalExports[exportName].alias}`,
231251
);
232252
} else {
233253
collectedExportsToAppend.push(ancestor.expression.left.property.name);
@@ -250,9 +270,7 @@ export default class ExportTransform extends Transform implements TransformInter
250270

251271
if (ancestor.expression.right.type === 'Identifier') {
252272
collectedExportsToAppend.push(
253-
`${ancestor.expression.right.name} as ${
254-
ancestor.expression.left.property.name
255-
}`,
273+
`${ancestor.expression.right.name} as ${ancestor.expression.left.property.name}`,
256274
);
257275
}
258276
break;
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
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 test from 'ava';
18+
import { createTransforms } from '../../transpile/transforms';
19+
import { defaults } from '../../transpile/options';
20+
import * as fs from 'fs';
21+
import { promisify } from 'util';
22+
23+
const readFile = promisify(fs.readFile);
24+
25+
test('generate extern for cjs export pattern', async t => {
26+
const externFixtureContent = await readFile('test/export-cjs/fixtures/export.extern.js', 'utf8');
27+
const outputOptions = {
28+
format: 'cjs',
29+
};
30+
31+
const transforms = createTransforms({});
32+
const options = defaults(outputOptions, [], transforms);
33+
34+
const contentMatch = options.externs.some(async externFilePath => {
35+
const fileContent = await readFile(externFilePath, 'utf8');
36+
return fileContent === externFixtureContent;
37+
});
38+
39+
t.is(contentMatch, true);
40+
});
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/**
2+
* @fileoverview Externs built via derived configuration from Rollup or input code.
3+
* This extern contains the export global object so Closure doesn't get confused by its presence.
4+
* @externs
5+
*/
6+
7+
/**
8+
* @typedef {{
9+
* __esModule: boolean,
10+
* }}
11+
*/
12+
let exports;

0 commit comments

Comments
 (0)