Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(496)

Side by Side Diff: pkg/dev_compiler/lib/src/compiler/module_builder.dart

Issue 2337213003: Support generating inlined source maps and wrapping module contents within a JavaScript eval block … (Closed)
Patch Set: Refactor based on John's offline comments. Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « pkg/dev_compiler/lib/src/compiler/compiler.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 28 matching lines...) Expand all
39 if (format is String) { 39 if (format is String) {
40 return [parseModuleFormat(format)]; 40 return [parseModuleFormat(format)];
41 } 41 }
42 return (format as List<String>).map(parseModuleFormat).toList(); 42 return (format as List<String>).map(parseModuleFormat).toList();
43 } 43 }
44 44
45 /// Adds an option to the [argParser] for choosing the module format, optionally 45 /// Adds an option to the [argParser] for choosing the module format, optionally
46 /// [allowMultiple] formats to be specified, with each emitted into a separate 46 /// [allowMultiple] formats to be specified, with each emitted into a separate
47 /// file. 47 /// file.
48 void addModuleFormatOptions(ArgParser argParser, {bool allowMultiple: false}) { 48 void addModuleFormatOptions(ArgParser argParser, {bool allowMultiple: false}) {
49 argParser.addOption('modules', 49 argParser
50 help: 'module pattern to emit', 50 ..addOption('modules',
51 allowed: [ 51 help: 'module pattern to emit',
52 'es6', 52 allowed: [
53 'common', 53 'es6',
54 'amd', 54 'common',
55 'legacy', // deprecated 55 'amd',
56 'node', // renamed to commonjs 56 'legacy', // deprecated
57 'all' // to emit all flavors for the SDK 57 'node', // renamed to commonjs
58 ], 58 'all' // to emit all flavors for the SDK
59 allowedHelp: { 59 ],
60 'es6': 'ECMAScript 6 modules', 60 allowedHelp: {
61 'common': 'CommonJS/Node.js modules', 61 'es6': 'ECMAScript 6 modules',
62 'amd': 'AMD/RequireJS modules' 62 'common': 'CommonJS/Node.js modules',
63 }, 63 'amd': 'AMD/RequireJS modules'
64 allowMultiple: allowMultiple, 64 },
65 defaultsTo: 'amd'); 65 allowMultiple: allowMultiple,
66 defaultsTo: 'amd')
67 ..addFlag('single-out-file',
68 help: 'emit output so that libraries can be concatenated together into '
69 'a single file. Only compatible with legacy and amd module formats.' ,
70 defaultsTo: false);
66 } 71 }
67 72
68 /// Transforms an ES6 [module] into a given module [format]. 73 /// Transforms an ES6 [module] into a given module [format].
69 /// 74 ///
70 /// If the format is [ModuleFormat.es6] this will return [module] unchanged. 75 /// If the format is [ModuleFormat.es6] this will return [module] unchanged.
71 /// 76 ///
72 /// Because JS ASTs are immutable the resulting module will share as much 77 /// Because JS ASTs are immutable the resulting module will share as much
73 /// structure as possible with the original. The transformation is a shallow one 78 /// structure as possible with the original. The transformation is a shallow one
74 /// that affects the top-level module items, especially [ImportDeclaration]s and 79 /// that affects the top-level module items, especially [ImportDeclaration]s and
75 /// [ExportDeclaration]s. 80 /// [ExportDeclaration]s.
76 Program transformModuleFormat(ModuleFormat format, Program module) { 81 Program transformModuleFormat(
82 ModuleFormat format, bool singleOutFile, Program module) {
77 switch (format) { 83 switch (format) {
78 case ModuleFormat.legacy: 84 case ModuleFormat.legacy:
79 return new LegacyModuleBuilder().build(module); 85 return new LegacyModuleBuilder(singleOutFile).build(module);
80 case ModuleFormat.common: 86 case ModuleFormat.common:
81 return new CommonJSModuleBuilder().build(module); 87 return new CommonJSModuleBuilder(singleOutFile).build(module);
82 case ModuleFormat.amd: 88 case ModuleFormat.amd:
83 return new AmdModuleBuilder().build(module); 89 return new AmdModuleBuilder(singleOutFile).build(module);
84 case ModuleFormat.es6: 90 case ModuleFormat.es6:
91 assert(singleOutFile == false);
85 return module; 92 return module;
86 } 93 }
87 return null; // unreachable. suppresses a bogus analyzer message 94 return null; // unreachable. suppresses a bogus analyzer message
88 } 95 }
89 96
90 /// Base class for compiling ES6 modules into various ES5 module patterns. 97 /// Base class for compiling ES6 modules into various ES5 module patterns.
91 /// 98 ///
92 /// This is a helper class for utilities and state that is shared by several 99 /// This is a helper class for utilities and state that is shared by several
93 /// module transformers. 100 /// module transformers.
94 // TODO(jmesserly): "module transformer" might be a better name than builder. 101 // TODO(jmesserly): "module transformer" might be a better name than builder.
(...skipping 28 matching lines...) Expand all
123 } 130 }
124 131
125 visitStatement(Statement node) { 132 visitStatement(Statement node) {
126 statements.add(node); 133 statements.add(node);
127 } 134 }
128 } 135 }
129 136
130 /// Generates modules for with our legacy `dart_library.js` loading mechanism. 137 /// Generates modules for with our legacy `dart_library.js` loading mechanism.
131 // TODO(jmesserly): remove this and replace with something that interoperates. 138 // TODO(jmesserly): remove this and replace with something that interoperates.
132 class LegacyModuleBuilder extends _ModuleBuilder { 139 class LegacyModuleBuilder extends _ModuleBuilder {
140 /// The legacy module format always generates output compatible with a single
141 /// file mode.
142 LegacyModuleBuilder(bool singleOutFile);
143
133 Program build(Program module) { 144 Program build(Program module) {
134 // Collect imports/exports/statements. 145 // Collect imports/exports/statements.
135 visitProgram(module); 146 visitProgram(module);
136 147
137 // Build import parameters. 148 // Build import parameters.
138 var exportsVar = new TemporaryId('exports'); 149 var exportsVar = new TemporaryId('exports');
139 var parameters = <TemporaryId>[exportsVar]; 150 var parameters = <TemporaryId>[exportsVar];
140 var importNames = <Expression>[]; 151 var importNames = <Expression>[];
141 var importStatements = <Statement>[]; 152 var importStatements = <Statement>[];
142 for (var import in imports) { 153 for (var import in imports) {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 js.commentExpression( 191 js.commentExpression(
181 "Imports", new ArrayInitializer(importNames, multiline: true)), 192 "Imports", new ArrayInitializer(importNames, multiline: true)),
182 resultModule 193 resultModule
183 ]); 194 ]);
184 return new Program(<ModuleItem>[moduleDef]); 195 return new Program(<ModuleItem>[moduleDef]);
185 } 196 }
186 } 197 }
187 198
188 /// Generates CommonJS modules (used by Node.js). 199 /// Generates CommonJS modules (used by Node.js).
189 class CommonJSModuleBuilder extends _ModuleBuilder { 200 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
190 Program build(Program module) { 209 Program build(Program module) {
191 var importStatements = <Statement>[]; 210 var importStatements = <Statement>[];
192 211
193 // Collect imports/exports/statements. 212 // Collect imports/exports/statements.
194 visitProgram(module); 213 visitProgram(module);
195 214
196 for (var import in imports) { 215 for (var import in imports) {
197 // TODO(jmesserly): we could use destructuring here. 216 // TODO(jmesserly): we could use destructuring here.
198 var moduleVar = 217 var moduleVar =
199 new TemporaryId(pathToJSIdentifier(import.from.valueWithoutQuotes)); 218 new TemporaryId(pathToJSIdentifier(import.from.valueWithoutQuotes));
(...skipping 29 matching lines...) Expand all
229 // This extra level of indirection should be unnecessary. 248 // This extra level of indirection should be unnecessary.
230 var block = 249 var block =
231 js.statement("(function() { 'use strict'; #; })()", [statements]); 250 js.statement("(function() { 'use strict'; #; })()", [statements]);
232 251
233 return new Program([block]); 252 return new Program([block]);
234 } 253 }
235 } 254 }
236 255
237 /// Generates AMD modules (used in browsers with RequireJS). 256 /// Generates AMD modules (used in browsers with RequireJS).
238 class AmdModuleBuilder extends _ModuleBuilder { 257 class AmdModuleBuilder extends _ModuleBuilder {
258 final bool singleOutFile;
259
260 AmdModuleBuilder(this.singleOutFile);
261
239 Program build(Program module) { 262 Program build(Program module) {
240 var importStatements = <Statement>[]; 263 var importStatements = <Statement>[];
241 264
242 // Collect imports/exports/statements. 265 // Collect imports/exports/statements.
243 visitProgram(module); 266 visitProgram(module);
244 267
245 var dependencies = <LiteralString>[]; 268 var dependencies = <LiteralString>[];
246 var fnParams = <Parameter>[]; 269 var fnParams = <Parameter>[];
247 for (var import in imports) { 270 for (var import in imports) {
248 // TODO(jmesserly): we could use destructuring once Atom supports it. 271 // TODO(jmesserly): we could use destructuring once Atom supports it.
(...skipping 21 matching lines...) Expand all
270 assert(names != null); 293 assert(names != null);
271 for (var name in names) { 294 for (var name in names) {
272 exportedProps.add(new Property(js.string(name.name), name)); 295 exportedProps.add(new Property(js.string(name.name), name));
273 } 296 }
274 } 297 }
275 statements.add(js.comment('Exports:')); 298 statements.add(js.comment('Exports:'));
276 statements.add( 299 statements.add(
277 new Return(new ObjectInitializer(exportedProps, multiline: true))); 300 new Return(new ObjectInitializer(exportedProps, multiline: true)));
278 } 301 }
279 302
280 var block = js.statement("define(#, function(#) { 'use strict'; #; });", 303 var block = singleOutFile
281 [new ArrayInitializer(dependencies), fnParams, statements]); 304 ? js.statement("define(#, #, function(#) { 'use strict'; #; });", [
305 js.string(module.name, "'"),
306 new ArrayInitializer(dependencies),
307 fnParams,
308 statements
309 ])
310 : js.statement("define(#, function(#) { 'use strict'; #; });",
311 [new ArrayInitializer(dependencies), fnParams, statements]);
282 312
283 return new Program([block]); 313 return new Program([block]);
284 } 314 }
285 } 315 }
286 316
287 /// Escape [name] to make it into a valid identifier. 317 /// Escape [name] to make it into a valid identifier.
288 String pathToJSIdentifier(String name) { 318 String pathToJSIdentifier(String name) {
289 return toJSIdentifier(path.basenameWithoutExtension(name)); 319 return toJSIdentifier(path.basenameWithoutExtension(name));
290 } 320 }
291 321
(...skipping 18 matching lines...) Expand all
310 // Ensure the identifier first character is not numeric and that the whole 340 // Ensure the identifier first character is not numeric and that the whole
311 // identifier is not a keyword. 341 // identifier is not a keyword.
312 if (result.startsWith(new RegExp('[0-9]')) || invalidVariableName(result)) { 342 if (result.startsWith(new RegExp('[0-9]')) || invalidVariableName(result)) {
313 return '\$$result'; 343 return '\$$result';
314 } 344 }
315 return result; 345 return result;
316 } 346 }
317 347
318 // Invalid characters for identifiers, which would need to be escaped. 348 // Invalid characters for identifiers, which would need to be escaped.
319 final _invalidCharInIdentifier = new RegExp(r'[^A-Za-z_$0-9]'); 349 final _invalidCharInIdentifier = new RegExp(r'[^A-Za-z_$0-9]');
OLDNEW
« no previous file with comments | « pkg/dev_compiler/lib/src/compiler/compiler.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698