| 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 |