1313// limitations under the License.
1414
1515import { ModuleTransformer } from './ModuleTransformer.js' ;
16- import {
17- CALL_EXPRESSION ,
18- GET_ACCESSOR ,
19- OBJECT_LITERAL ,
20- PROPERTY_NAME_ASSIGNMENT ,
21- RETURN_STATEMENT
22- } from '../syntax/trees/ParseTreeType.js' ;
23- import {
24- ArgumentList ,
25- CallExpression ,
26- ExpressionStatement
27- } from '../syntax/trees/ParseTrees.js' ;
28- import { assert } from '../util/assert.js' ;
29- import globalThis from './globalThis.js' ;
16+ import { NAMED_EXPORT } from '../syntax/trees/ParseTreeType.js' ;
17+ import { AnonBlock } from '../syntax/trees/ParseTrees.js' ;
3018import {
3119 parseExpression ,
3220 parsePropertyDefinition ,
33- parseStatements
21+ parseStatement ,
3422} from './PlaceholderParser.js' ;
3523import {
36- createEmptyParameterList ,
37- createFunctionExpression ,
38- createIdentifierExpression ,
24+ createExpressionStatement ,
3925 createObjectLiteral ,
26+ createObjectLiteralForDescriptor ,
4027 createPropertyNameAssignment ,
41- createVariableStatement ,
42- createVariableDeclaration ,
43- createVariableDeclarationList
4428} from './ParseTreeFactory.js' ;
45- import { VAR } from '../syntax/TokenType.js' ;
29+ import { prependStatements } from './PrependStatements.js' ;
30+ import { FindVisitor } from './FindVisitor.js' ;
4631
4732export class CommonJsModuleTransformer extends ModuleTransformer {
48-
4933 constructor ( identifierGenerator , reporter , options = undefined ) {
5034 super ( identifierGenerator , reporter , options ) ;
51- this . moduleVars_ = [ ] ;
5235 this . anonymousModule =
5336 options && ! options . bundle && options . moduleName !== true ;
37+ this . namedExportsWithModuleSpecifiers_ = [ ] ;
38+ this . isImportingDefault_ = false ;
39+ this . needsInteropRequire_ = false ;
5440 }
5541
5642 getModuleName ( tree ) {
@@ -59,106 +45,105 @@ export class CommonJsModuleTransformer extends ModuleTransformer {
5945 return tree . moduleName ;
6046 }
6147
62- moduleProlog ( ) {
63- let statements = super . moduleProlog ( ) ;
64-
65- // declare temp vars in prolog
66- if ( this . moduleVars_ . length ) {
67- let tmpVarDeclarations = createVariableStatement ( createVariableDeclarationList ( VAR ,
68- this . moduleVars_ . map ( ( varName ) => createVariableDeclaration ( varName , null ) ) ) ) ;
69-
70- statements . push ( tmpVarDeclarations ) ;
48+ wrapModule ( statements ) {
49+ if ( this . needsInteropRequire_ ) {
50+ const req = parseStatement `function $__interopRequire(id) {
51+ id = require(id);
52+ return id && id.__esModule && id || {default: id};
53+ }` ;
54+ return prependStatements ( statements , req ) ;
7155 }
72-
7356 return statements ;
7457 }
7558
76- wrapModule ( statements ) {
77- let last = statements [ statements . length - 1 ] ;
78- statements = statements . slice ( 0 , - 1 ) ;
79- assert ( last . type === RETURN_STATEMENT ) ;
80- let exportExpression = last . expression ;
81-
82- // If the module doesn't use any export statements, nor global "this", it
83- // might be because it wants to make its own changes to "exports" or
84- // "module.exports", so we don't append "module.exports = {}" to the output.
85- if ( this . hasExports ( ) ) {
86- let exportStatement =
87- this . transformExportExpressionToModuleExport ( exportExpression ) ;
88- statements = statements . concat ( exportStatement ) ;
59+ addExportStatement ( statements ) {
60+ if ( ! this . hasExports ( ) ) {
61+ return statements ;
8962 }
90- return statements ;
91- }
9263
93- transformExportExpressionToModuleExport ( tree ) {
94- let expression ;
95-
96- // $traceurRuntime.exportStar({}, ...)
97- if ( tree . type === CALL_EXPRESSION ) {
98- let descriptors =
99- this . transformObjectLiteralToDescriptors ( tree . args . args [ 0 ] ) ;
100- let object = parseExpression
101- `Object.defineProperties(module.exports, ${ descriptors } )` ;
102- let newArgs = new ArgumentList ( tree . args . location ,
103- [ object , ...tree . args . args . slice ( 1 ) ] )
104- expression = new CallExpression ( tree . location , tree . operand , newArgs ) ;
105- } else {
106- let descriptors = this . transformObjectLiteralToDescriptors ( tree ) ;
107- expression = parseExpression
108- `Object.defineProperties(module.exports, ${ descriptors } )` ;
64+ const descr = this . getExportDescriptors ( ) ;
65+ let exportObject = parseExpression
66+ `Object.defineProperties(module.exports, ${ descr } )` ;
67+ if ( this . hasStarExports ( ) ) {
68+ exportObject = this . getExportStar ( exportObject ) ;
10969 }
11070
111- return new ExpressionStatement ( expression . location , expression ) ;
71+ // Mutate module.exports immediately after all the export star are
72+ // imported, before any module code is executed, to allow some cyclic
73+ // dependencies to work.
74+ return prependStatements ( statements ,
75+ ...this . namedExportsWithModuleSpecifiers_ ,
76+ createExpressionStatement ( exportObject ) ) ;
11277 }
11378
114- transformObjectLiteralToDescriptors ( literalTree ) {
115- assert ( literalTree . type === OBJECT_LITERAL ) ;
116-
117- let props = literalTree . propertyNameAndValues . map ( ( exp ) => {
118- let descriptor ;
119-
120- switch ( exp . type ) {
121- case GET_ACCESSOR : {
122- let getterFunction =
123- createFunctionExpression ( createEmptyParameterList ( ) , exp . body ) ;
124- descriptor =
125- parseExpression `{get: ${ getterFunction } , enumerable: true}` ;
126- break ;
127- }
79+ getExportDescriptors ( ) {
80+ // {
81+ // x: {
82+ // enumerable: true,
83+ // get: function() { ... },
84+ // },
85+ // ...
86+ // }
87+
88+ const properties = this . exportVisitor . getNonTypeNamedExports ( ) . map ( exp => {
89+ const f = parseExpression `function() { return ${
90+ this . getGetterExportReturnExpression ( exp )
91+ } ; }`;
92+ return createPropertyNameAssignment ( exp . name ,
93+ createObjectLiteralForDescriptor ( { enumerable : true , get : f } ) ) ;
94+ } ) ;
95+ properties . unshift ( parsePropertyDefinition `__esModule: {value: true}` ) ;
96+ return createObjectLiteral ( properties ) ;
97+ }
12898
129- case PROPERTY_NAME_ASSIGNMENT :
130- descriptor = parseExpression `{value: ${ exp . value } }` ;
131- break ;
99+ transformExportDeclaration ( tree ) {
100+ this . checkForDefaultImport_ ( tree ) ;
101+ this . exportVisitor . visitAny ( tree ) ;
102+ const transformed = this . transformAny ( tree . declaration ) ;
103+
104+ // Need to output the require for export ? from moduleSpecifier before
105+ // the call to exportStar.
106+ if ( tree . declaration . type == NAMED_EXPORT &&
107+ tree . declaration . moduleSpecifier !== null ) {
108+ this . namedExportsWithModuleSpecifiers_ . push ( transformed ) ;
109+ return new AnonBlock ( null , [ ] ) ;
110+ }
132111
133- default :
134- throw new Error ( `Unexpected property type ${ exp . type } ` ) ;
135- }
112+ return transformed ;
113+ }
136114
137- return createPropertyNameAssignment ( exp . name , descriptor ) ;
138- } ) ;
115+ transformImportDeclaration ( tree ) {
116+ this . checkForDefaultImport_ ( tree ) ;
117+ return super . transformImportDeclaration ( tree ) ;
118+ }
139119
140- return createObjectLiteral ( props ) ;
120+ checkForDefaultImport_ ( tree ) {
121+ const finder = new FindDefault ( ) ;
122+ finder . visitAny ( tree ) ;
123+ this . isImportingDefault_ = finder . found ;
141124 }
142125
143126 transformModuleSpecifier ( tree ) {
144127 let moduleName = tree . token . processedValue ;
145- let tmpVar = this . getTempVarNameForModuleSpecifier ( tree ) ;
146- this . moduleVars_ . push ( tmpVar ) ;
147- let tvId = createIdentifierExpression ( tmpVar ) ;
148-
149- // require the module, if it is not marked as an ES6 module, treat it as { default: module }
150- // this allows for an unlinked CommonJS / ES6 interop
151- // note that future implementations should also check for native Module with
152- // Reflect.isModule or similar
153- return parseExpression `(${ tvId } = require(${ moduleName } ),
154- ${ tvId } && ${ tvId } .__esModule && ${ tvId } || {default: ${ tvId } })` ;
128+ if ( this . isImportingDefault_ ) {
129+ this . needsInteropRequire_ = true ;
130+ return parseExpression `$__interopRequire(${ moduleName } )` ;
131+ }
132+ return parseExpression `require(${ moduleName } )` ;
155133 }
134+ }
156135
157- getExportProperties ( ) {
158- let properties = super . getExportProperties ( ) ;
159-
160- if ( this . exportVisitor_ . hasExports ( ) )
161- properties . push ( parsePropertyDefinition `__esModule: true` ) ;
162- return properties ;
136+ class FindDefault extends FindVisitor {
137+ visitImportSpecifier ( tree ) {
138+ this . found = tree . name !== null && tree . name . value === 'default' ;
139+ }
140+ visitNameSpaceImport ( tree ) {
141+ this . found = true ;
142+ }
143+ visitNameSpaceExport ( tree ) {
144+ this . found = true ;
145+ }
146+ visitExportSpecifier ( tree ) {
147+ this . found = tree . lhs !== null && tree . lhs . value === 'default' ;
163148 }
164149}
0 commit comments