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

Side by Side Diff: lib/src/codegen/js_codegen.dart

Issue 1020043002: Replace dart_core.js with actual compiled SDK (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: merge Created 5 years, 9 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 | « lib/runtime/dart_runtime.js ('k') | lib/src/dependency_graph.dart » ('j') | 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 library dev_compiler.src.codegen.js_codegen; 5 library dev_compiler.src.codegen.js_codegen;
6 6
7 import 'dart:collection' show HashSet, HashMap; 7 import 'dart:collection' show HashSet, HashMap;
8 import 'dart:io' show Directory, File; 8 import 'dart:io' show Directory, File;
9 9
10 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; 10 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator;
(...skipping 13 matching lines...) Expand all
24 import 'package:dev_compiler/src/js/js_ast.dart' as JS; 24 import 'package:dev_compiler/src/js/js_ast.dart' as JS;
25 import 'package:dev_compiler/src/js/js_ast.dart' show js; 25 import 'package:dev_compiler/src/js/js_ast.dart' show js;
26 26
27 import 'package:dev_compiler/src/checker/rules.dart'; 27 import 'package:dev_compiler/src/checker/rules.dart';
28 import 'package:dev_compiler/src/info.dart'; 28 import 'package:dev_compiler/src/info.dart';
29 import 'package:dev_compiler/src/options.dart'; 29 import 'package:dev_compiler/src/options.dart';
30 import 'package:dev_compiler/src/report.dart'; 30 import 'package:dev_compiler/src/report.dart';
31 import 'package:dev_compiler/src/utils.dart'; 31 import 'package:dev_compiler/src/utils.dart';
32 import 'code_generator.dart'; 32 import 'code_generator.dart';
33 33
34 // This must match the optional parameter name used in runtime.js
35 const String _jsNamedParameterName = r'opt$';
36
37 bool _isAnnotationType(Annotation m, String name) => m.name.name == name; 34 bool _isAnnotationType(Annotation m, String name) => m.name.name == name;
38 35
39 Annotation _getAnnotation(AnnotatedNode node, String name) => node.metadata 36 Annotation _getAnnotation(AnnotatedNode node, String name) => node.metadata
40 .firstWhere((annotation) => _isAnnotationType(annotation, name), 37 .firstWhere((annotation) => _isAnnotationType(annotation, name),
41 orElse: () => null); 38 orElse: () => null);
42 39
43 Annotation _getJsNameAnnotation(AnnotatedNode node) => 40 Annotation _getJsNameAnnotation(AnnotatedNode node) =>
44 _getAnnotation(node, "JsName"); 41 _getAnnotation(node, "JsName");
45 42
46 class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor { 43 class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
123 120
124 var defaultValue = js.call(jsDefaultValue); 121 var defaultValue = js.call(jsDefaultValue);
125 return new JS.Program([ 122 return new JS.Program([
126 js.statement('var #;', name), 123 js.statement('var #;', name),
127 js.statement("(function($_EXPORTS) { 'use strict'; #; })(# || (# = #));", 124 js.statement("(function($_EXPORTS) { 'use strict'; #; })(# || (# = #));",
128 [body, name, name, defaultValue]) 125 [body, name, name, defaultValue])
129 ]); 126 ]);
130 } 127 }
131 128
132 JS.Statement _initPrivateSymbol(String name) => 129 JS.Statement _initPrivateSymbol(String name) =>
133 js.statement('let # = Symbol(#);', [name, js.string(name, "'")]); 130 js.statement('let # = $_SYMBOL(#);', [name, js.string(name, "'")]);
131
132 // TODO(jmesserly): this is a temporary workaround for `Symbol` in core,
133 // until we have better name tracking.
134 String get _SYMBOL => currentLibrary.isDartCore ? 'dart.JsSymbol' : 'Symbol';
134 135
135 @override 136 @override
136 JS.Statement visitCompilationUnit(CompilationUnit node) { 137 JS.Statement visitCompilationUnit(CompilationUnit node) {
137 var source = node.element.source; 138 var source = node.element.source;
138 139
139 _constEvaluator = new ConstantEvaluator(source, rules.provider); 140 _constEvaluator = new ConstantEvaluator(source, rules.provider);
140 _checkerReporter.enterSource(source); 141 _checkerReporter.enterSource(source);
141 142
142 // TODO(jmesserly): scriptTag, directives. 143 // TODO(jmesserly): scriptTag, directives.
143 var body = <JS.Statement>[]; 144 var body = <JS.Statement>[];
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
252 JS.Statement visitClassTypeAlias(ClassTypeAlias node) { 253 JS.Statement visitClassTypeAlias(ClassTypeAlias node) {
253 // If we've already emitted this class, skip it. 254 // If we've already emitted this class, skip it.
254 var classElem = node.element; 255 var classElem = node.element;
255 if (_pendingClasses.remove(classElem) == null) return null; 256 if (_pendingClasses.remove(classElem) == null) return null;
256 257
257 var name = node.name.name; 258 var name = node.name.name;
258 var heritage = 259 var heritage =
259 js.call('dart.mixin(#)', [_visitList(node.withClause.mixinTypes)]); 260 js.call('dart.mixin(#)', [_visitList(node.withClause.mixinTypes)]);
260 var classDecl = new JS.ClassDeclaration( 261 var classDecl = new JS.ClassDeclaration(
261 new JS.ClassExpression(new JS.VariableDeclaration(name), heritage, [])); 262 new JS.ClassExpression(new JS.VariableDeclaration(name), heritage, []));
262 if (isPublic(name)) _exports.add(name);
263 263
264 return _finishClassDef(classElem, classDecl); 264 return _finishClassDef(classElem, classDecl);
265 } 265 }
266 266
267 @override 267 @override
268 JS.Statement visitClassDeclaration(ClassDeclaration node) { 268 JS.Statement visitClassDeclaration(ClassDeclaration node) {
269 // If we've already emitted this class, skip it. 269 // If we've already emitted this class, skip it.
270 var classElem = node.element; 270 var classElem = node.element;
271 if (_pendingClasses.remove(classElem) == null) return null; 271 if (_pendingClasses.remove(classElem) == null) return null;
272 if (_getJsNameAnnotation(node) != null) return null; 272 if (_getJsNameAnnotation(node) != null) return null;
273 273
274 currentClass = node; 274 currentClass = node;
275 275
276 var name = classElem.name; 276 var name = classElem.name;
277 if (isPublic(name)) _exports.add(name);
278 277
279 var ctors = <ConstructorDeclaration>[]; 278 var ctors = <ConstructorDeclaration>[];
280 var fields = <FieldDeclaration>[]; 279 var fields = <FieldDeclaration>[];
281 var staticFields = <FieldDeclaration>[]; 280 var staticFields = <FieldDeclaration>[];
282 for (var member in node.members) { 281 for (var member in node.members) {
283 if (member is ConstructorDeclaration) { 282 if (member is ConstructorDeclaration) {
284 ctors.add(member); 283 ctors.add(member);
285 } else if (member is FieldDeclaration) { 284 } else if (member is FieldDeclaration) {
286 (member.isStatic ? staticFields : fields).add(member); 285 (member.isStatic ? staticFields : fields).add(member);
287 } 286 }
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 333
335 return js.statement( 334 return js.statement(
336 'dart.defineLazyClass(#, { get #() { #; return #; } });', [ 335 'dart.defineLazyClass(#, { get #() { #; return #; } });', [
337 _EXPORTS, 336 _EXPORTS,
338 name, 337 name,
339 body, 338 body,
340 name 339 name
341 ]); 340 ]);
342 } 341 }
343 342
343 if (isPublic(name)) _exports.add(name);
344
344 if (genericDef != null) { 345 if (genericDef != null) {
345 body = js.statement('{ #; let # = #; }', [genericDef, name, genericInst]); 346 body = js.statement('{ #; let # = #; }', [genericDef, name, genericInst]);
347 if (isPublic(name)) _exports.add(genericName);
346 } 348 }
347 349
348 if (classElem.type.isObject) return body; 350 if (classElem.type.isObject) return body;
349 351
350 // If we're not lazy, we still need to ensure our dependencies are 352 // If we're not lazy, we still need to ensure our dependencies are
351 // generated first. 353 // generated first.
352 var classDefs = <JS.Statement>[]; 354 var classDefs = <JS.Statement>[];
353 _emitClassIfNeeded(classDefs, classElem.supertype.element); 355 _emitClassIfNeeded(classDefs, classElem.supertype.element);
354 for (var m in classElem.mixins) { 356 for (var m in classElem.mixins) {
355 _emitClassIfNeeded(classDefs, m.element); 357 _emitClassIfNeeded(classDefs, m.element);
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
450 if (result) break; 452 if (result) break;
451 result = _inLibraryCycle(e.exportedLibrary); 453 result = _inLibraryCycle(e.exportedLibrary);
452 } 454 }
453 return _libraryCycleMemo[library] = result; 455 return _libraryCycleMemo[library] = result;
454 } 456 }
455 457
456 JS.Statement _emitGenericClassDef(ClassElement cls, JS.Statement body) { 458 JS.Statement _emitGenericClassDef(ClassElement cls, JS.Statement body) {
457 var name = cls.name; 459 var name = cls.name;
458 var genericName = '$name\$'; 460 var genericName = '$name\$';
459 var typeParams = cls.typeParameters.map((p) => new JS.Parameter(p.name)); 461 var typeParams = cls.typeParameters.map((p) => new JS.Parameter(p.name));
460 // TODO(jmesserly): is it worth exporting both names? Alternatively we could
461 // put the generic type constructor on the <dynamic> instance.
462 if (isPublic(name)) _exports.add(genericName);
463 return js.statement('let # = dart.generic(function(#) { #; return #; });', [ 462 return js.statement('let # = dart.generic(function(#) { #; return #; });', [
464 genericName, 463 genericName,
465 typeParams, 464 typeParams,
466 body, 465 body,
467 name 466 name
468 ]); 467 ]);
469 } 468 }
470 469
471 JS.Expression _classHeritage(ClassDeclaration node) { 470 JS.Expression _classHeritage(ClassDeclaration node) {
472 if (node.element.type.isObject) return null; 471 if (node.element.type.isObject) return null;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
514 if (element.library.isDartCore && element.name == 'Iterable') { 513 if (element.library.isDartCore && element.name == 'Iterable') {
515 JS.Fun body = js.call('''function() { 514 JS.Fun body = js.call('''function() {
516 var iterator = this.iterator; 515 var iterator = this.iterator;
517 return { 516 return {
518 next() { 517 next() {
519 var done = iterator.moveNext(); 518 var done = iterator.moveNext();
520 return { done: done, current: done ? void 0 : iterator.current }; 519 return { done: done, current: done ? void 0 : iterator.current };
521 } 520 }
522 }; 521 };
523 }'''); 522 }''');
524 jsMethods.add(new JS.Method(js.call('Symbol.iterator'), body)); 523 jsMethods.add(new JS.Method(js.call('$_SYMBOL.iterator'), body));
525 } 524 }
526 return jsMethods.where((m) => m != null).toList(growable: false); 525 return jsMethods.where((m) => m != null).toList(growable: false);
527 } 526 }
528 527
529 /// Emit class members that need to come after the class declaration, such 528 /// Emit class members that need to come after the class declaration, such
530 /// as static fields. See [_emitClassMethods] for things that are emitted 529 /// as static fields. See [_emitClassMethods] for things that are emitted
531 /// insite the ES6 `class { ... }` node. 530 /// insite the ES6 `class { ... }` node.
532 JS.Statement _finishClassMembers(String name, JS.ClassExpression cls, 531 JS.Statement _finishClassMembers(String name, JS.ClassExpression cls,
533 List<ConstructorDeclaration> ctors, List<FieldDeclaration> staticFields) { 532 List<ConstructorDeclaration> ctors, List<FieldDeclaration> staticFields) {
534 var body = <JS.Statement>[]; 533 var body = <JS.Statement>[];
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
591 node.name == null) { 590 node.name == null) {
592 // Implements Dart constructor behavior. Because of V8 `super` 591 // Implements Dart constructor behavior. Because of V8 `super`
593 // [constructor restrictions] 592 // [constructor restrictions]
594 // (https://code.google.com/p/v8/issues/detail?id=3330#c65) 593 // (https://code.google.com/p/v8/issues/detail?id=3330#c65)
595 // we cannot currently emit actual ES6 constructors with super calls. 594 // we cannot currently emit actual ES6 constructors with super calls.
596 // Instead we use the same trick as named constructors, and do them as 595 // Instead we use the same trick as named constructors, and do them as
597 // instance methods that perform initialization. 596 // instance methods that perform initialization.
598 // TODO(jmesserly): we'll need to rethink this once the ES6 spec and V8 597 // TODO(jmesserly): we'll need to rethink this once the ES6 spec and V8
599 // settles. See <https://github.com/dart-lang/dev_compiler/issues/51>. 598 // settles. See <https://github.com/dart-lang/dev_compiler/issues/51>.
600 // Performance of this pattern is likely to be bad. 599 // Performance of this pattern is likely to be bad.
600 name = 'constructor';
601 body = js.statement('''{ 601 body = js.statement('''{
602 // Get the class name for this instance. 602 // Get the class name for this instance.
603 var name = this.constructor.name; 603 var name = this.constructor.name;
604 // Call the default constructor. 604 // Call the default constructor.
605 var init = this[name]; 605 var init = this[name];
606 var result = void 0; 606 var result = void 0;
607 if (init) result = init.apply(this, arguments); 607 if (init) result = init.apply(this, arguments);
608 return result === void 0 ? this : result; 608 return result === void 0 ? this : result;
609 }'''); 609 }''');
610 } else { 610 } else {
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
790 if (parameters == null || !_hasArgumentInitializers(parameters)) { 790 if (parameters == null || !_hasArgumentInitializers(parameters)) {
791 return null; 791 return null;
792 } 792 }
793 793
794 var body = []; 794 var body = [];
795 for (var param in parameters.parameters) { 795 for (var param in parameters.parameters) {
796 // TODO(justinfagnani): rename identifier if necessary 796 // TODO(justinfagnani): rename identifier if necessary
797 var name = param.identifier.name; 797 var name = param.identifier.name;
798 798
799 if (param.kind == ParameterKind.NAMED) { 799 if (param.kind == ParameterKind.NAMED) {
800 body.add(js.statement('let # = opt\$.# === void 0 ? # : opt\$.#;', [ 800 body.add(js.statement('let # = opt\$ && # in opt\$ ? opt\$.# : #;', [
801 name, 801 name,
802 js.string(name, "'"),
802 name, 803 name,
803 _defaultParamValue(param), 804 _defaultParamValue(param),
804 name
805 ])); 805 ]));
806 } else if (param.kind == ParameterKind.POSITIONAL) { 806 } else if (param.kind == ParameterKind.POSITIONAL) {
807 body.add(js.statement('if (# === void 0) # = #;', [ 807 body.add(js.statement('if (# === void 0) # = #;', [
808 name, 808 name,
809 name, 809 name,
810 _defaultParamValue(param) 810 _defaultParamValue(param)
811 ])); 811 ]));
812 } 812 }
813 } 813 }
814 return _statement(body); 814 return _statement(body);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
858 858
859 body.add(new JS.FunctionDeclaration( 859 body.add(new JS.FunctionDeclaration(
860 new JS.VariableDeclaration(name), _visit(node.functionExpression))); 860 new JS.VariableDeclaration(name), _visit(node.functionExpression)));
861 861
862 if (isPublic(name)) _exports.add(name); 862 if (isPublic(name)) _exports.add(name);
863 return _statement(body); 863 return _statement(body);
864 } 864 }
865 865
866 JS.Method _emitTopLevelProperty(FunctionDeclaration node) { 866 JS.Method _emitTopLevelProperty(FunctionDeclaration node) {
867 var name = node.name.name; 867 var name = node.name.name;
868 if (isPublic(name)) _exports.add(name);
869 return new JS.Method( 868 return new JS.Method(
870 new JS.PropertyName(name), _visit(node.functionExpression), 869 new JS.PropertyName(name), _visit(node.functionExpression),
871 isGetter: node.isGetter, isSetter: node.isSetter); 870 isGetter: node.isGetter, isSetter: node.isSetter);
872 } 871 }
873 872
874 @override 873 @override
875 JS.Expression visitFunctionExpression(FunctionExpression node) { 874 JS.Expression visitFunctionExpression(FunctionExpression node) {
876 var params = _visit(node.parameters); 875 var params = _visit(node.parameters);
877 if (params == null) params = []; 876 if (params == null) params = [];
878 877
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after
1153 assert(node.parent is ArgumentList); 1152 assert(node.parent is ArgumentList);
1154 return new JS.Property( 1153 return new JS.Property(
1155 new JS.PropertyName(node.name.label.name), _visit(node.expression)); 1154 new JS.PropertyName(node.name.label.name), _visit(node.expression));
1156 } 1155 }
1157 1156
1158 @override 1157 @override
1159 List<JS.Parameter> visitFormalParameterList(FormalParameterList node) { 1158 List<JS.Parameter> visitFormalParameterList(FormalParameterList node) {
1160 var result = <JS.Parameter>[]; 1159 var result = <JS.Parameter>[];
1161 for (FormalParameter param in node.parameters) { 1160 for (FormalParameter param in node.parameters) {
1162 if (param.kind == ParameterKind.NAMED) { 1161 if (param.kind == ParameterKind.NAMED) {
1163 result.add(new JS.Parameter(_jsNamedParameterName)); 1162 result.add(new JS.Parameter(r'opt$'));
1164 break; 1163 break;
1165 } 1164 }
1166 result.add(_visit(param)); 1165 result.add(_visit(param));
1167 } 1166 }
1168 return result; 1167 return result;
1169 } 1168 }
1170 1169
1171 @override 1170 @override
1172 JS.Statement visitExpressionStatement(ExpressionStatement node) => 1171 JS.Statement visitExpressionStatement(ExpressionStatement node) =>
1173 _expressionStatement(_visit(node.expression)); 1172 _expressionStatement(_visit(node.expression));
(...skipping 1127 matching lines...) Expand 10 before | Expand all | Expand 10 after
2301 2300
2302 // TODO(jmesserly): in many cases marking the end will be unncessary. 2301 // TODO(jmesserly): in many cases marking the end will be unncessary.
2303 printer.mark(_location(node.end)); 2302 printer.mark(_location(node.end));
2304 } 2303 }
2305 2304
2306 String _getIdentifier(AstNode node) { 2305 String _getIdentifier(AstNode node) {
2307 if (node is SimpleIdentifier) return node.name; 2306 if (node is SimpleIdentifier) return node.name;
2308 return null; 2307 return null;
2309 } 2308 }
2310 } 2309 }
OLDNEW
« no previous file with comments | « lib/runtime/dart_runtime.js ('k') | lib/src/dependency_graph.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698