OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 import 'package:args/args.dart' show ArgParser, ArgResults; | 5 import 'package:args/args.dart' show ArgParser, ArgResults; |
6 import 'package:path/path.dart' as path; | 6 import 'package:path/path.dart' as path; |
7 | 7 |
8 import '../js_ast/js_ast.dart'; | 8 import '../js_ast/js_ast.dart'; |
9 import 'js_names.dart'; | 9 import 'js_names.dart'; |
10 | 10 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 'all' // to emit all flavors for the SDK | 58 'all' // to emit all flavors for the SDK |
59 ], | 59 ], |
60 allowedHelp: { | 60 allowedHelp: { |
61 'es6': 'ECMAScript 6 modules', | 61 'es6': 'ECMAScript 6 modules', |
62 'common': 'CommonJS/Node.js modules', | 62 'common': 'CommonJS/Node.js modules', |
63 'amd': 'AMD/RequireJS modules' | 63 'amd': 'AMD/RequireJS modules' |
64 }, | 64 }, |
65 allowMultiple: allowMultiple, | 65 allowMultiple: allowMultiple, |
66 defaultsTo: 'amd') | 66 defaultsTo: 'amd') |
67 ..addFlag('single-out-file', | 67 ..addFlag('single-out-file', |
68 help: 'emit output so that libraries can be concatenated together into ' | 68 help: 'emit modules that can be concatenated into one file.\n' |
69 'a single file. Only compatible with legacy and amd module formats.'
, | 69 'Only compatible with legacy and amd module formats.', |
70 defaultsTo: false); | 70 defaultsTo: false, |
| 71 hide: true); |
71 } | 72 } |
72 | 73 |
73 /// Transforms an ES6 [module] into a given module [format]. | 74 /// Transforms an ES6 [module] into a given module [format]. |
74 /// | 75 /// |
75 /// If the format is [ModuleFormat.es6] this will return [module] unchanged. | 76 /// If the format is [ModuleFormat.es6] this will return [module] unchanged. |
76 /// | 77 /// |
77 /// Because JS ASTs are immutable the resulting module will share as much | 78 /// Because JS ASTs are immutable the resulting module will share as much |
78 /// structure as possible with the original. The transformation is a shallow one | 79 /// structure as possible with the original. The transformation is a shallow one |
79 /// that affects the top-level module items, especially [ImportDeclaration]s and | 80 /// that affects the top-level module items, especially [ImportDeclaration]s and |
80 /// [ExportDeclaration]s. | 81 /// [ExportDeclaration]s. |
81 Program transformModuleFormat( | 82 Program transformModuleFormat( |
82 ModuleFormat format, bool singleOutFile, Program module) { | 83 ModuleFormat format, Program module, {bool singleOutFile: false}) { |
83 switch (format) { | 84 switch (format) { |
84 case ModuleFormat.legacy: | 85 case ModuleFormat.legacy: |
85 return new LegacyModuleBuilder(singleOutFile).build(module); | 86 // Legacy format always generates output compatible with single file mode. |
| 87 return new LegacyModuleBuilder().build(module); |
86 case ModuleFormat.common: | 88 case ModuleFormat.common: |
87 return new CommonJSModuleBuilder(singleOutFile).build(module); | 89 assert(!singleOutFile); |
| 90 return new CommonJSModuleBuilder().build(module); |
88 case ModuleFormat.amd: | 91 case ModuleFormat.amd: |
89 return new AmdModuleBuilder(singleOutFile).build(module); | 92 // TODO(jmesserly): encode singleOutFile as a module format? |
| 93 // Since it's irrelevant except for AMD. |
| 94 return new AmdModuleBuilder(singleOutFile: singleOutFile).build(module); |
90 case ModuleFormat.es6: | 95 case ModuleFormat.es6: |
91 assert(singleOutFile == false); | 96 assert(!singleOutFile); |
92 return module; | 97 return module; |
93 } | 98 } |
94 return null; // unreachable. suppresses a bogus analyzer message | 99 return null; // unreachable. suppresses a bogus analyzer message |
95 } | 100 } |
96 | 101 |
97 /// Base class for compiling ES6 modules into various ES5 module patterns. | 102 /// Base class for compiling ES6 modules into various ES5 module patterns. |
98 /// | 103 /// |
99 /// This is a helper class for utilities and state that is shared by several | 104 /// This is a helper class for utilities and state that is shared by several |
100 /// module transformers. | 105 /// module transformers. |
101 // TODO(jmesserly): "module transformer" might be a better name than builder. | 106 // TODO(jmesserly): "module transformer" might be a better name than builder. |
(...skipping 28 matching lines...) Expand all Loading... |
130 } | 135 } |
131 | 136 |
132 visitStatement(Statement node) { | 137 visitStatement(Statement node) { |
133 statements.add(node); | 138 statements.add(node); |
134 } | 139 } |
135 } | 140 } |
136 | 141 |
137 /// Generates modules for with our legacy `dart_library.js` loading mechanism. | 142 /// Generates modules for with our legacy `dart_library.js` loading mechanism. |
138 // TODO(jmesserly): remove this and replace with something that interoperates. | 143 // TODO(jmesserly): remove this and replace with something that interoperates. |
139 class LegacyModuleBuilder extends _ModuleBuilder { | 144 class LegacyModuleBuilder extends _ModuleBuilder { |
140 /// The legacy module format always generates output compatible with a single | |
141 /// file mode. | |
142 LegacyModuleBuilder(bool singleOutFile); | |
143 | 145 |
144 Program build(Program module) { | 146 Program build(Program module) { |
145 // Collect imports/exports/statements. | 147 // Collect imports/exports/statements. |
146 visitProgram(module); | 148 visitProgram(module); |
147 | 149 |
148 // Build import parameters. | 150 // Build import parameters. |
149 var exportsVar = new TemporaryId('exports'); | 151 var exportsVar = new TemporaryId('exports'); |
150 var parameters = <TemporaryId>[exportsVar]; | 152 var parameters = <TemporaryId>[exportsVar]; |
151 var importNames = <Expression>[]; | 153 var importNames = <Expression>[]; |
152 var importStatements = <Statement>[]; | 154 var importStatements = <Statement>[]; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 js.commentExpression( | 193 js.commentExpression( |
192 "Imports", new ArrayInitializer(importNames, multiline: true)), | 194 "Imports", new ArrayInitializer(importNames, multiline: true)), |
193 resultModule | 195 resultModule |
194 ]); | 196 ]); |
195 return new Program(<ModuleItem>[moduleDef]); | 197 return new Program(<ModuleItem>[moduleDef]); |
196 } | 198 } |
197 } | 199 } |
198 | 200 |
199 /// Generates CommonJS modules (used by Node.js). | 201 /// Generates CommonJS modules (used by Node.js). |
200 class CommonJSModuleBuilder extends _ModuleBuilder { | 202 class CommonJSModuleBuilder extends _ModuleBuilder { |
201 final bool singleOutFile; | |
202 | |
203 CommonJSModuleBuilder(this.singleOutFile) { | |
204 // singleOutFile mode is not currently supported by the CommonJS module | |
205 // builder. | |
206 assert(singleOutFile == false); | |
207 } | |
208 | |
209 Program build(Program module) { | 203 Program build(Program module) { |
210 var importStatements = <Statement>[]; | 204 var importStatements = <Statement>[]; |
211 | 205 |
212 // Collect imports/exports/statements. | 206 // Collect imports/exports/statements. |
213 visitProgram(module); | 207 visitProgram(module); |
214 | 208 |
215 for (var import in imports) { | 209 for (var import in imports) { |
216 // TODO(jmesserly): we could use destructuring here. | 210 // TODO(jmesserly): we could use destructuring here. |
217 var moduleVar = | 211 var moduleVar = |
218 new TemporaryId(pathToJSIdentifier(import.from.valueWithoutQuotes)); | 212 new TemporaryId(pathToJSIdentifier(import.from.valueWithoutQuotes)); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
250 js.statement("(function() { 'use strict'; #; })()", [statements]); | 244 js.statement("(function() { 'use strict'; #; })()", [statements]); |
251 | 245 |
252 return new Program([block]); | 246 return new Program([block]); |
253 } | 247 } |
254 } | 248 } |
255 | 249 |
256 /// Generates AMD modules (used in browsers with RequireJS). | 250 /// Generates AMD modules (used in browsers with RequireJS). |
257 class AmdModuleBuilder extends _ModuleBuilder { | 251 class AmdModuleBuilder extends _ModuleBuilder { |
258 final bool singleOutFile; | 252 final bool singleOutFile; |
259 | 253 |
260 AmdModuleBuilder(this.singleOutFile); | 254 AmdModuleBuilder({this.singleOutFile: false}); |
261 | 255 |
262 Program build(Program module) { | 256 Program build(Program module) { |
263 var importStatements = <Statement>[]; | 257 var importStatements = <Statement>[]; |
264 | 258 |
265 // Collect imports/exports/statements. | 259 // Collect imports/exports/statements. |
266 visitProgram(module); | 260 visitProgram(module); |
267 | 261 |
268 var dependencies = <LiteralString>[]; | 262 var dependencies = <LiteralString>[]; |
269 var fnParams = <Parameter>[]; | 263 var fnParams = <Parameter>[]; |
270 for (var import in imports) { | 264 for (var import in imports) { |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
340 // Ensure the identifier first character is not numeric and that the whole | 334 // Ensure the identifier first character is not numeric and that the whole |
341 // identifier is not a keyword. | 335 // identifier is not a keyword. |
342 if (result.startsWith(new RegExp('[0-9]')) || invalidVariableName(result)) { | 336 if (result.startsWith(new RegExp('[0-9]')) || invalidVariableName(result)) { |
343 return '\$$result'; | 337 return '\$$result'; |
344 } | 338 } |
345 return result; | 339 return result; |
346 } | 340 } |
347 | 341 |
348 // Invalid characters for identifiers, which would need to be escaped. | 342 // Invalid characters for identifiers, which would need to be escaped. |
349 final _invalidCharInIdentifier = new RegExp(r'[^A-Za-z_$0-9]'); | 343 final _invalidCharInIdentifier = new RegExp(r'[^A-Za-z_$0-9]'); |
OLD | NEW |