Skip to content

Commit c113993

Browse files
author
John Messerly
committed
fix #626, add AMD module format and make it default
R=nweiz@google.com, vsm@google.com Review URL: https://codereview.chromium.org/2249233002 .
1 parent 87577db commit c113993

36 files changed

+256662
-3692
lines changed

pkg/dev_compiler/.gitignore

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ doc/api/
1717
# Generated files go here.
1818
gen/
1919

20-
# Ignore generated summary.
21-
lib/runtime/dart_sdk.sum
20+
# Ignore generated SDK summary.
21+
lib/js/*/*.sum
2222

2323
# Created by ./tool/dependency_overrides.sh.
2424
dependency_overrides/

pkg/dev_compiler/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# dev_compiler changelog
22

3+
## next release
4+
- add support for AMD modules and make it the default.
5+
- precompile the SDK in AMD, CommonJS, and ES6 flavors.
6+
- legacy module format is deprecated.
7+
38
## 0.1.24
49
- workaround breaking change on requestAnimationFrame
510

pkg/dev_compiler/karma.conf.js

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,17 @@ module.exports = function(config) {
1313

1414
// list of files / patterns to load in the browser
1515
files: [
16-
'lib/runtime/dart_*.js',
17-
// {pattern: 'test/browser/*.js', included: false}
18-
'gen/codegen_output/pkg/*.js',
19-
'gen/codegen_output/language/**.js',
20-
'gen/codegen_output/language/**.err',
21-
'gen/codegen_output/corelib/**.js',
22-
'gen/codegen_output/corelib/**.err',
23-
'gen/codegen_output/lib/convert/**.js',
24-
'gen/codegen_output/lib/html/**.js',
25-
'gen/codegen_output/lib/math/**.js',
26-
'gen/codegen_output/lib/mirrors/**.js',
27-
'gen/codegen_output/lib/typed_data/**.js',
28-
'gen/codegen_output/lib/*/**.err',
29-
'test/browser/*.js',
16+
{pattern: 'lib/js/amd/dart_sdk.js', included: false},
17+
{pattern: 'gen/codegen_output/pkg/*.js', included: false},
18+
{pattern: 'gen/codegen_output/language/**/*.js', included: false},
19+
{pattern: 'gen/codegen_output/corelib/**/*.js', included: false},
20+
{pattern: 'gen/codegen_output/lib/**/*.js', included: false},
21+
{pattern: 'test/browser/*.js', included: false},
3022
'test-main.js',
3123
],
3224

3325
// list of files to exclude
34-
exclude: [
35-
],
26+
exclude: [],
3627

3728
// preprocess matching files before serving them to the browser
3829
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor

pkg/dev_compiler/lib/js/amd/dart_sdk.js

Lines changed: 84218 additions & 0 deletions
Large diffs are not rendered by default.

pkg/dev_compiler/lib/js/common/dart_sdk.js

Lines changed: 84216 additions & 0 deletions
Large diffs are not rendered by default.

pkg/dev_compiler/lib/js/es6/dart_sdk.js

Lines changed: 84182 additions & 0 deletions
Large diffs are not rendered by default.

pkg/dev_compiler/lib/runtime/dart_sdk.js renamed to pkg/dev_compiler/lib/js/legacy/dart_sdk.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1466,7 +1466,7 @@ dart_library.library('dart_sdk', null, /* Imports */[
14661466
let src = '';
14671467
for (let i = 2; i < dart.notNull(stack[dartx.length]); ++i) {
14681468
let frame = stack[dartx.get](i);
1469-
if (!dart.test(frame[dartx.contains]('dev_compiler/lib/runtime/dart_sdk.js'))) {
1469+
if (!dart.test(frame[dartx.contains]('dart_sdk.js'))) {
14701470
src = frame;
14711471
break;
14721472
}

pkg/dev_compiler/lib/src/compiler/code_generator.dart

Lines changed: 41 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,14 @@ import 'package:analyzer/src/summary/summarize_elements.dart'
2323
show PackageBundleAssembler;
2424
import 'package:analyzer/src/task/strong/ast_properties.dart'
2525
show isDynamicInvoke, setIsDynamicInvoke;
26-
import 'package:source_maps/source_maps.dart';
2726
import 'package:path/path.dart' show separator;
2827

2928
import '../closure/closure_annotator.dart' show ClosureAnnotator;
3029
import '../js_ast/js_ast.dart' as JS;
3130
import '../js_ast/js_ast.dart' show js;
3231
import 'ast_builder.dart' show AstBuilder;
3332
import 'compiler.dart'
34-
show BuildUnit, CompilerOptions, JSModuleFile, ModuleFormat;
33+
show BuildUnit, CompilerOptions, JSModuleFile;
3534
import 'element_helpers.dart';
3635
import 'element_loader.dart' show ElementLoader;
3736
import 'extension_types.dart' show ExtensionTypeSet;
@@ -40,12 +39,10 @@ import 'js_interop.dart';
4039
import 'js_metalet.dart' as JS;
4140
import 'js_names.dart' as JS;
4241
import 'js_typeref_codegen.dart' show JsTypeRefCodegen;
43-
import 'module_builder.dart'
44-
show LegacyModuleBuilder, NodeModuleBuilder, pathToJSIdentifier;
42+
import 'module_builder.dart' show pathToJSIdentifier;
4543
import 'nullable_type_inference.dart' show NullableTypeInference;
4644
import 'reify_coercions.dart' show CoercionReifier;
4745
import 'side_effect_analysis.dart' show ConstFieldVisitor, isStateless;
48-
import 'source_map_printer.dart' show SourceMapPrintingContext;
4946
import 'type_utilities.dart';
5047

5148
class CodeGenerator extends GeneralizingAstVisitor
@@ -173,46 +170,21 @@ class CodeGenerator extends GeneralizingAstVisitor
173170
_libraryRoot = '$_libraryRoot${separator}';
174171
}
175172

176-
var jsTree = _emitModule(compilationUnits);
177-
var codeAndSourceMap = _writeJSText(unit, jsTree);
173+
var module = _emitModule(compilationUnits);
174+
var dartApiSummary = _summarizeModule(compilationUnits);
178175

179-
List<int> summary;
180-
if (options.summarizeApi) {
181-
var assembler = new PackageBundleAssembler();
182-
compilationUnits
183-
.map((u) => u.element.library)
184-
.toSet()
185-
.forEach(assembler.serializeLibraryElement);
186-
summary = assembler.assemble().toBuffer();
187-
}
188-
189-
return new JSModuleFile(
190-
unit.name, errors, codeAndSourceMap.e0, codeAndSourceMap.e1, summary);
176+
return new JSModuleFile(unit.name, errors, options, module, dartApiSummary);
191177
}
192178

193-
Tuple2<String, Map> _writeJSText(BuildUnit unit, JS.Program jsTree) {
194-
var opts = new JS.JavaScriptPrintingOptions(
195-
emitTypes: options.closure,
196-
allowKeywordsInProperties: true,
197-
allowSingleLineIfStatements: true);
198-
JS.SimpleJavaScriptPrintingContext printer;
199-
SourceMapBuilder sourceMap;
200-
if (options.sourceMap) {
201-
var sourceMapContext = new SourceMapPrintingContext();
202-
sourceMap = sourceMapContext.sourceMap;
203-
printer = sourceMapContext;
204-
} else {
205-
printer = new JS.SimpleJavaScriptPrintingContext();
206-
}
207-
208-
jsTree.accept(new JS.Printer(opts, printer,
209-
localNamer: new JS.TemporaryNamer(jsTree)));
179+
List<int> _summarizeModule(List<CompilationUnit> compilationUnits) {
180+
if (!options.summarizeApi) return null;
210181

211-
if (options.sourceMap && options.sourceMapComment) {
212-
printer.emit('\n//# sourceMappingURL=${unit.name}.js.map\n');
213-
}
214-
215-
return new Tuple2(printer.getText(), sourceMap?.build(unit.name + '.js'));
182+
var assembler = new PackageBundleAssembler();
183+
compilationUnits
184+
.map((u) => u.element.library)
185+
.toSet()
186+
.forEach(assembler.serializeLibraryElement);
187+
return assembler.assemble().toBuffer();
216188
}
217189

218190
JS.Program _emitModule(List<CompilationUnit> compilationUnits) {
@@ -284,18 +256,7 @@ class CodeGenerator extends GeneralizingAstVisitor
284256
_copyAndFlattenBlocks(items, _moduleItems);
285257

286258
// Build the module.
287-
var module = new JS.Program(items, name: _buildUnit.name);
288-
289-
// Optional: lower module format. Otherwise just return it.
290-
switch (options.moduleFormat) {
291-
case ModuleFormat.legacy:
292-
return new LegacyModuleBuilder().build(module);
293-
case ModuleFormat.node:
294-
return new NodeModuleBuilder().build(module);
295-
case ModuleFormat.es6:
296-
return module;
297-
}
298-
return null; // unreachable. It is here to suppress a bogus Analyzer message
259+
return new JS.Program(items, name: _buildUnit.name);
299260
}
300261

301262
List<String> _getJSName(Element e) {
@@ -1750,6 +1711,7 @@ class CodeGenerator extends GeneralizingAstVisitor
17501711
var e = js.call('() => #', o);
17511712
return new JS.Property(_propertyName(name), e);
17521713
}
1714+
17531715
var sigFields = <JS.Property>[];
17541716
if (!tCtors.isEmpty) sigFields.add(build('constructors', tCtors));
17551717
if (!tMethods.isEmpty) sigFields.add(build('methods', tMethods));
@@ -3262,8 +3224,12 @@ class CodeGenerator extends GeneralizingAstVisitor
32623224
var vars = <JS.MetaLetVariable, JS.Expression>{};
32633225
var l = _visit(_bindValue(vars, 'l', target));
32643226
jsTarget = new JS.MetaLet(vars, [
3265-
js.call('(#[(#[dart._extensionType]) ? dartx[#] : #])',
3266-
[l, l, memberName, memberName,])
3227+
js.call('(#[(#[dart._extensionType]) ? dartx[#] : #])', [
3228+
l,
3229+
l,
3230+
memberName,
3231+
memberName,
3232+
])
32673233
]);
32683234
if (typeArgs != null) jsTarget = new JS.Call(jsTarget, typeArgs);
32693235
return new JS.Call(jsTarget, args);
@@ -3806,6 +3772,7 @@ class CodeGenerator extends GeneralizingAstVisitor
38063772
var args = _visit(argumentList) as List<JS.Expression>;
38073773
return isFactory ? new JS.Call(ctor, args) : new JS.New(ctor, args);
38083774
}
3775+
38093776
if (element != null && _isObjectLiteral(element.enclosingElement)) {
38103777
return _emitObjectLiteral(argumentList);
38113778
}
@@ -4047,6 +4014,7 @@ class CodeGenerator extends GeneralizingAstVisitor
40474014
}
40484015
return null;
40494016
}
4017+
40504018
if (expr is SimpleIdentifier) {
40514019
return finishIdentifier(expr);
40524020
} else if (expr is PrefixedIdentifier && !expr.isDeferred) {
@@ -4134,6 +4102,7 @@ class CodeGenerator extends GeneralizingAstVisitor
41344102
if (value != null) return value.bitLength;
41354103
return MAX;
41364104
}
4105+
41374106
return bitWidth(expr, 0) < 32;
41384107
}
41394108

@@ -4924,6 +4893,7 @@ class CodeGenerator extends GeneralizingAstVisitor
49244893
var name = js.string(node.components.join('.'), "'");
49254894
return js.call('#.new(#)', [_emitType(types.symbolType), name]);
49264895
}
4896+
49274897
return _emitConst(emitSymbol);
49284898
}
49294899

@@ -4952,6 +4922,7 @@ class CodeGenerator extends GeneralizingAstVisitor
49524922
}
49534923
return list;
49544924
}
4925+
49554926
if (isConst) return _cacheConst(emitList);
49564927
return emitList();
49574928
}
@@ -4990,6 +4961,7 @@ class CodeGenerator extends GeneralizingAstVisitor
49904961
}
49914962
return js.call('dart.map(#, #)', [mapArguments, types]);
49924963
}
4964+
49934965
if (node.constKeyword != null) return _emitConst(emitMap);
49944966
return emitMap();
49954967
}
@@ -5066,6 +5038,7 @@ class CodeGenerator extends GeneralizingAstVisitor
50665038
JS.Expression finish(JS.Expression result) {
50675039
return annotate(result, node);
50685040
}
5041+
50695042
if (node is PrefixExpression && node.operator.lexeme == '!') {
50705043
return finish(js.call('!#', _visitTest(node.operand)));
50715044
}
@@ -5077,6 +5050,7 @@ class CodeGenerator extends GeneralizingAstVisitor
50775050
return finish(js.call(code,
50785051
[_visitTest(node.leftOperand), _visitTest(node.rightOperand)]));
50795052
}
5053+
50805054
var op = node.operator.type.lexeme;
50815055
if (op == '&&') return shortCircuit('# && #');
50825056
if (op == '||') return shortCircuit('# || #');
@@ -5141,7 +5115,7 @@ class CodeGenerator extends GeneralizingAstVisitor
51415115
/// x.get('hi')
51425116
/// x.set('hi', 123)
51435117
///
5144-
/// This follows the same pattern as EcmaScript 6 Map:
5118+
/// This follows the same pattern as ECMAScript 6 Map:
51455119
/// <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map>
51465120
///
51475121
/// Unary minus looks like: `x['unary-']()`. Note that [unary] must be passed
@@ -5294,8 +5268,16 @@ class CodeGenerator extends GeneralizingAstVisitor
52945268
/// within the file.
52955269
///
52965270
/// If the value is null, the entire file is whitelisted.
5271+
///
5272+
// TODO(jmesserly): why is this here, and what can we do to remove it?
5273+
//
5274+
// Hard coded lists are completely unnecessary -- if a feature is needed,
5275+
// metadata, type system features, or command line options are the right way
5276+
// to express it.
5277+
//
5278+
// As it is this is completely unsound and unmaintainable.
52975279
static Map<String, List<String>> _uncheckedWhitelist = {
5298-
'dom_renderer.dart': ['moveNodesAfterSibling',],
5280+
'dom_renderer.dart': ['moveNodesAfterSibling'],
52995281
'template_ref.dart': ['createEmbeddedView'],
53005282
'ng_class.dart': ['_applyIterableChanges'],
53015283
'ng_for.dart': ['_bulkRemove', '_bulkInsert'],
@@ -5335,7 +5317,8 @@ class CodeGenerator extends GeneralizingAstVisitor
53355317
}
53365318
}
53375319

5338-
/// Choose a canonical name from the library element.
5320+
/// Choose a canonical name from the [library] element.
5321+
///
53395322
/// This never uses the library's name (the identifier in the `library`
53405323
/// declaration) as it doesn't have any meaningful rules enforced.
53415324
String jsLibraryName(String libraryRoot, LibraryElement library) {

pkg/dev_compiler/lib/src/compiler/command.dart

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5-
import 'dart:convert' show JSON;
65
import 'dart:io';
76
import 'package:analyzer/src/generated/source.dart' show Source;
87
import 'package:analyzer/src/summary/package_bundle_reader.dart'
@@ -11,14 +10,16 @@ import 'package:args/args.dart' show ArgParser, ArgResults;
1110
import 'package:args/command_runner.dart' show UsageException;
1211
import 'package:path/path.dart' as path;
1312

13+
import '../analyzer/context.dart' show AnalyzerOptions;
1414
import 'compiler.dart'
1515
show BuildUnit, CompilerOptions, JSModuleFile, ModuleCompiler;
16-
import '../analyzer/context.dart' show AnalyzerOptions;
16+
import 'module_builder.dart';
1717

1818
final ArgParser _argParser = () {
1919
var argParser = new ArgParser()
2020
..addFlag('help', abbr: 'h', help: 'Display this message.')
21-
..addOption('out', abbr: 'o', help: 'Output file (required).')
21+
..addOption('out',
22+
abbr: 'o', allowMultiple: true, help: 'Output file (required).')
2223
..addOption('module-root',
2324
help: 'Root module directory.\n'
2425
'Generated module paths are relative to this root.')
@@ -27,6 +28,7 @@ final ArgParser _argParser = () {
2728
'Generated library names are relative to this root.')
2829
..addOption('build-root',
2930
help: 'Deprecated in favor of --library-root', hide: true);
31+
addModuleFormatOptions(argParser, allowMultiple: true);
3032
AnalyzerOptions.addArguments(argParser);
3133
CompilerOptions.addArguments(argParser);
3234
return argParser;
@@ -88,13 +90,21 @@ void _compile(ArgResults argResults, void printFn(Object obj)) {
8890
printFn(_usageMessage);
8991
return;
9092
}
91-
var outPath = argResults['out'];
93+
var outPaths = argResults['out'] as List<String>;
94+
var moduleFormats = parseModuleFormatOption(argResults);
9295

93-
if (outPath == null) {
96+
if (outPaths.isEmpty) {
9497
_usageException('Please include the output file location. For example:\n'
9598
' -o PATH/TO/OUTPUT_FILE.js');
99+
} else if (outPaths.length != moduleFormats.length) {
100+
_usageException('Number of output files (${outPaths.length}) must match '
101+
'number of module formats (${moduleFormats.length}).');
96102
}
97103

104+
// TODO(jmesserly): for now the first one is special. This will go away once
105+
// we've removed the "root" and "module name" variables.
106+
var outPath = outPaths[0];
107+
98108
var libraryRoot = argResults['library-root'] as String;
99109
libraryRoot ??= argResults['build-root'] as String;
100110
if (libraryRoot != null) {
@@ -126,17 +136,15 @@ void _compile(ArgResults argResults, void printFn(Object obj)) {
126136
if (!module.isValid) throw new CompileErrorException();
127137

128138
// Write JS file, as well as source map and summary (if requested).
129-
new File(outPath).writeAsStringSync(module.code);
130-
if (module.sourceMap != null) {
131-
var mapPath = outPath + '.map';
132-
new File(mapPath)
133-
.writeAsStringSync(JSON.encode(module.placeSourceMap(mapPath)));
134-
}
135-
if (module.summaryBytes != null) {
136-
var summaryPath =
137-
path.withoutExtension(outPath) + '.${compilerOpts.summaryExtension}';
138-
new File(summaryPath).writeAsBytesSync(module.summaryBytes);
139+
for (var i = 0; i < outPaths.length; i++) {
140+
module.writeCodeSync(moduleFormats[i], outPaths[i]);
141+
if (module.summaryBytes != null) {
142+
var summaryPath =
143+
path.withoutExtension(outPath) + '.${compilerOpts.summaryExtension}';
144+
new File(summaryPath).writeAsBytesSync(module.summaryBytes);
145+
}
139146
}
147+
140148
}
141149

142150
String _moduleForLibrary(

0 commit comments

Comments
 (0)