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

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

Issue 2822633003: fix #29346, ensure all nodes are implemented by DDC's code generator (Closed)
Patch Set: fix Created 3 years, 8 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/sdk/ddc_sdk.sum ('k') | pkg/dev_compiler/lib/src/js_ast/nodes.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 2
3 // for details. All rights reserved. Use of this source code is governed by a 3 // for details. All rights reserved. Use of this source code is governed by a
4 // BSD-style license that can be found in the LICENSE file. 4 // BSD-style license that can be found in the LICENSE file.
5 5
6 import 'dart:collection' show HashMap, HashSet; 6 import 'dart:collection' show HashMap, HashSet;
7 import 'dart:math' show min, max; 7 import 'dart:math' show min, max;
8 8
9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; 9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator;
10 import 'package:analyzer/dart/ast/ast.dart'; 10 import 'package:analyzer/dart/ast/ast.dart';
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
46 import 'js_metalet.dart' as JS; 46 import 'js_metalet.dart' as JS;
47 import 'js_names.dart' as JS; 47 import 'js_names.dart' as JS;
48 import 'js_typeref_codegen.dart' show JsTypeRefCodegen; 48 import 'js_typeref_codegen.dart' show JsTypeRefCodegen;
49 import 'module_builder.dart' show pathToJSIdentifier; 49 import 'module_builder.dart' show pathToJSIdentifier;
50 import 'nullable_type_inference.dart' show NullableTypeInference; 50 import 'nullable_type_inference.dart' show NullableTypeInference;
51 import 'property_model.dart'; 51 import 'property_model.dart';
52 import 'reify_coercions.dart' show CoercionReifier; 52 import 'reify_coercions.dart' show CoercionReifier;
53 import 'side_effect_analysis.dart' show ConstFieldVisitor, isStateless; 53 import 'side_effect_analysis.dart' show ConstFieldVisitor, isStateless;
54 import 'type_utilities.dart'; 54 import 'type_utilities.dart';
55 55
56 class CodeGenerator extends GeneralizingAstVisitor 56 /// The code generator for Dart Dev Compiler.
57 with ClosureAnnotator, JsTypeRefCodegen, NullableTypeInference { 57 ///
58 /// Takes as input resolved Dart ASTs for every compilation unit in every
59 /// library in the module. Produces a single JavaScript AST for the module as
60 /// output, along with its source map.
61 ///
62 /// This class attempts to preserve identifier names and structure of the input
63 /// Dart code, whenever this is possible to do in the generated code.
64 //
65 // TODO(jmesserly): we should use separate visitors for statements and
66 // expressions. Declarations are handled directly, and many minor component
67 // AST nodes aren't visited, so the visitor pattern isn't helping except for
68 // expressions (which result in JS.Expression) and statements
69 // (which result in (JS.Statement).
70 class CodeGenerator extends Object
71 with ClosureAnnotator, JsTypeRefCodegen, NullableTypeInference
72 implements AstVisitor<JS.Node> {
58 final AnalysisContext context; 73 final AnalysisContext context;
59 final SummaryDataStore summaryData; 74 final SummaryDataStore summaryData;
60 75
61 final CompilerOptions options; 76 final CompilerOptions options;
62 final StrongTypeSystemImpl rules; 77 final StrongTypeSystemImpl rules;
63 78
64 /// The set of libraries we are currently compiling, and the temporaries used 79 /// The set of libraries we are currently compiling, and the temporaries used
65 /// to refer to them. 80 /// to refer to them.
66 /// 81 ///
67 /// We sometimes special case codegen for a single library, as it simplifies 82 /// We sometimes special case codegen for a single library, as it simplifies
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
232 null, 247 null,
233 sdk is SummaryBasedDartSdk 248 sdk is SummaryBasedDartSdk
234 ? sdk.bundle 249 ? sdk.bundle
235 : (sdk as FolderBasedDartSdk).getSummarySdkBundle(true)); 250 : (sdk as FolderBasedDartSdk).getSummarySdkBundle(true));
236 } 251 }
237 252
238 var assembler = new PackageBundleAssembler(); 253 var assembler = new PackageBundleAssembler();
239 assembler.recordDependencies(summaryData); 254 assembler.recordDependencies(summaryData);
240 255
241 var uriToUnit = new Map<String, UnlinkedUnit>.fromIterable(units, 256 var uriToUnit = new Map<String, UnlinkedUnit>.fromIterable(units,
242 key: (u) => u.element.source.uri.toString(), value: (unit) { 257 key: (u) => u.element.source.uri.toString(),
243 var unlinked = serializeAstUnlinked(unit); 258 value: (unit) {
244 assembler.addUnlinkedUnit(unit.element.source, unlinked); 259 var unlinked = serializeAstUnlinked(unit);
245 return unlinked; 260 assembler.addUnlinkedUnit(unit.element.source, unlinked);
246 }); 261 return unlinked;
262 });
247 263
248 summary_link 264 summary_link
249 .link( 265 .link(
250 uriToUnit.keys.toSet(), 266 uriToUnit.keys.toSet(),
251 (uri) => summaryData.linkedMap[uri], 267 (uri) => summaryData.linkedMap[uri],
252 (uri) => summaryData.unlinkedMap[uri] ?? uriToUnit[uri], 268 (uri) => summaryData.unlinkedMap[uri] ?? uriToUnit[uri],
253 context.declaredVariables.get, 269 context.declaredVariables.get,
254 true) 270 true)
255 .forEach(assembler.addLinkedLibrary); 271 .forEach(assembler.addLinkedLibrary);
256 272
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
322 } 338 }
323 339
324 // Add implicit dart:core dependency so it is first. 340 // Add implicit dart:core dependency so it is first.
325 emitLibraryName(dartCoreLibrary); 341 emitLibraryName(dartCoreLibrary);
326 342
327 // Visit each compilation unit and emit its code. 343 // Visit each compilation unit and emit its code.
328 // 344 //
329 // NOTE: declarations are not necessarily emitted in this order. 345 // NOTE: declarations are not necessarily emitted in this order.
330 // Order will be changed as needed so the resulting code can execute. 346 // Order will be changed as needed so the resulting code can execute.
331 // This is done by forward declaring items. 347 // This is done by forward declaring items.
332 compilationUnits.forEach(_emitCompilationUnit); 348 compilationUnits.forEach(visitCompilationUnit);
333 assert(_deferredProperties.isEmpty); 349 assert(_deferredProperties.isEmpty);
334 350
335 // Visit directives (for exports) 351 // Visit directives (for exports)
336 compilationUnits.forEach(_emitExportDirectives); 352 compilationUnits.forEach(_emitExportDirectives);
337 353
338 // Declare imports 354 // Declare imports
339 _finishImports(items); 355 _finishImports(items);
340 356
341 // Discharge the type table cache variables and 357 // Discharge the type table cache variables and
342 // hoisted definitions. 358 // hoisted definitions.
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after
558 void _declareBeforeUse(TypeDefiningElement e) { 574 void _declareBeforeUse(TypeDefiningElement e) {
559 if (e == null) return; 575 if (e == null) return;
560 576
561 var topLevel = _topLevelElements; 577 var topLevel = _topLevelElements;
562 if (topLevel.isNotEmpty && identical(currentElement, topLevel.last)) { 578 if (topLevel.isNotEmpty && identical(currentElement, topLevel.last)) {
563 // If the item is from our library, try to emit it now. 579 // If the item is from our library, try to emit it now.
564 _emitTypeDeclaration(e); 580 _emitTypeDeclaration(e);
565 } 581 }
566 } 582 }
567 583
568 void _emitCompilationUnit(CompilationUnit unit) { 584 @override
585 visitCompilationUnit(CompilationUnit unit) {
569 // NOTE: this method isn't the right place to initialize 586 // NOTE: this method isn't the right place to initialize
570 // per-compilation-unit state. Declarations can be visited out of order, 587 // per-compilation-unit state. Declarations can be visited out of order,
571 // this is only to catch things that haven't been emitted yet. 588 // this is only to catch things that haven't been emitted yet.
572 // 589 //
573 // See _emitTypeDeclaration. 590 // See _emitTypeDeclaration.
574 var library = unit.element.library; 591 var library = unit.element.library;
575 bool internalSdk = isSdkInternalRuntime(library); 592 bool internalSdk = isSdkInternalRuntime(library);
576 _currentElements.add(library); 593 _currentElements.add(library);
577 594
578 List<VariableDeclaration> fields; 595 List<VariableDeclaration> fields;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
614 631
615 void _emitExportDirectives(CompilationUnit unit) { 632 void _emitExportDirectives(CompilationUnit unit) {
616 for (var directive in unit.directives) { 633 for (var directive in unit.directives) {
617 _currentElements.add(directive.element); 634 _currentElements.add(directive.element);
618 directive.accept(this); 635 directive.accept(this);
619 _currentElements.removeLast(); 636 _currentElements.removeLast();
620 } 637 }
621 } 638 }
622 639
623 @override 640 @override
624 void visitLibraryDirective(LibraryDirective node) {} 641 visitLibraryDirective(LibraryDirective node) => null;
625 642
626 @override 643 @override
627 void visitImportDirective(ImportDirective node) { 644 visitImportDirective(ImportDirective node) {
628 // We don't handle imports here. 645 // We don't handle imports here.
629 // 646 //
630 // Instead, we collect imports whenever we need to generate a reference 647 // Instead, we collect imports whenever we need to generate a reference
631 // to another library. This has the effect of collecting the actually used 648 // to another library. This has the effect of collecting the actually used
632 // imports. 649 // imports.
633 // 650 //
634 // TODO(jmesserly): if this is a prefixed import, consider adding the prefix 651 // TODO(jmesserly): if this is a prefixed import, consider adding the prefix
635 // as an alias? 652 // as an alias?
653 return null;
636 } 654 }
637 655
638 @override 656 @override
639 void visitPartDirective(PartDirective node) {} 657 visitPartDirective(PartDirective node) => null;
640 658
641 @override 659 @override
642 void visitPartOfDirective(PartOfDirective node) {} 660 visitPartOfDirective(PartOfDirective node) => null;
643 661
644 @override 662 @override
645 void visitExportDirective(ExportDirective node) { 663 visitExportDirective(ExportDirective node) {
646 ExportElement element = node.element; 664 ExportElement element = node.element;
647 var currentLibrary = element.library; 665 var currentLibrary = element.library;
648 666
649 var currentNames = currentLibrary.publicNamespace.definedNames; 667 var currentNames = currentLibrary.publicNamespace.definedNames;
650 var exportedNames = 668 var exportedNames =
651 new NamespaceBuilder().createExportNamespaceForDirective(element); 669 new NamespaceBuilder().createExportNamespaceForDirective(element);
652 670
653 // We only need to export main as it is the only method part of the 671 // We only need to export main as it is the only method part of the
654 // publicly exposed JS API for a library. 672 // publicly exposed JS API for a library.
655 // TODO(jacobr): add a library level annotation indicating that all 673 // TODO(jacobr): add a library level annotation indicating that all
656 // contents of a library need to be exposed to JS. 674 // contents of a library need to be exposed to JS.
657 // https://github.com/dart-lang/sdk/issues/26368 675 // https://github.com/dart-lang/sdk/issues/26368
658 var export = exportedNames.get('main'); 676 var export = exportedNames.get('main');
659 677
660 if (export is FunctionElement) { 678 if (export is FunctionElement) {
661 // Don't allow redefining names from this library. 679 // Don't allow redefining names from this library.
662 if (currentNames.containsKey(export.name)) return; 680 if (currentNames.containsKey(export.name)) return null;
663 681
664 var name = _emitTopLevelName(export); 682 var name = _emitTopLevelName(export);
665 _moduleItems.add(js.statement( 683 _moduleItems.add(js.statement(
666 '#.# = #;', [emitLibraryName(currentLibrary), name.selector, name])); 684 '#.# = #;', [emitLibraryName(currentLibrary), name.selector, name]));
667 } 685 }
668 } 686 }
669 687
670 @override 688 @override
671 visitAsExpression(AsExpression node) { 689 visitAsExpression(AsExpression node) {
672 Expression fromExpr = node.expression; 690 Expression fromExpr = node.expression;
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
748 var typeFormals = element.typeParameters; 766 var typeFormals = element.typeParameters;
749 if (typeFormals.isNotEmpty) { 767 if (typeFormals.isNotEmpty) {
750 return _defineClassTypeArguments(element, typeFormals, 768 return _defineClassTypeArguments(element, typeFormals,
751 js.statement('const # = #;', [element.name, body])); 769 js.statement('const # = #;', [element.name, body]));
752 } else { 770 } else {
753 return js.statement('# = #;', [_emitTopLevelName(element), body]); 771 return js.statement('# = #;', [_emitTopLevelName(element), body]);
754 } 772 }
755 } 773 }
756 774
757 @override 775 @override
776 visitGenericTypeAlias(GenericTypeAlias node) {
777 throw new UnimplementedError('Generic type aliases are not implemented. '
778 'See https://github.com/dart-lang/sdk/issues/27971');
779 }
780
781 @override
758 JS.Expression visitTypeName(TypeName node) { 782 JS.Expression visitTypeName(TypeName node) {
759 if (node.type == null) { 783 if (node.type == null) {
760 // TODO(jmesserly): if the type fails to resolve, should we generate code 784 // TODO(jmesserly): if the type fails to resolve, should we generate code
761 // that throws instead? 785 // that throws instead?
762 assert(options.unsafeForceCompile || options.replCompile); 786 assert(options.unsafeForceCompile || options.replCompile);
763 return _callHelper('dynamic'); 787 return _callHelper('dynamic');
764 } 788 }
765 return _emitType(node.type); 789 return _emitType(node.type);
766 } 790 }
767 791
(...skipping 21 matching lines...) Expand all
789 [jsParams, _constructorName(parentCtor), jsParams]) as JS.Fun; 813 [jsParams, _constructorName(parentCtor), jsParams]) as JS.Fun;
790 methods.add(new JS.Method(_constructorName(ctor), fun)); 814 methods.add(new JS.Method(_constructorName(ctor), fun));
791 } 815 }
792 } 816 }
793 817
794 var typeFormals = element.typeParameters; 818 var typeFormals = element.typeParameters;
795 var isGeneric = typeFormals.isNotEmpty; 819 var isGeneric = typeFormals.isNotEmpty;
796 var className = isGeneric ? element.name : _emitTopLevelName(element); 820 var className = isGeneric ? element.name : _emitTopLevelName(element);
797 JS.Statement declareInterfaces(JS.Statement decl) { 821 JS.Statement declareInterfaces(JS.Statement decl) {
798 if (element.interfaces.isNotEmpty) { 822 if (element.interfaces.isNotEmpty) {
799 var body = [decl] 823 var body = [decl]..add(js.statement('#[#.implements] = () => #;', [
800 ..add(js.statement('#[#.implements] = () => #;', [
801 className, 824 className,
802 _runtimeModule, 825 _runtimeModule,
803 new JS.ArrayInitializer( 826 new JS.ArrayInitializer(
804 new List<JS.Expression>.from(element.interfaces.map(_emitType))) 827 new List<JS.Expression>.from(element.interfaces.map(_emitType)))
805 ])); 828 ]));
806 decl = _statement(body); 829 decl = _statement(body);
807 } 830 }
808 return decl; 831 return decl;
809 } 832 }
810 833
(...skipping 1255 matching lines...) Expand 10 before | Expand all | Expand 10 after
2066 var redirect = node.redirectedConstructor; 2089 var redirect = node.redirectedConstructor;
2067 if (redirect != null) { 2090 if (redirect != null) {
2068 var newKeyword = 2091 var newKeyword =
2069 resolutionMap.staticElementForConstructorReference(redirect).isFactory 2092 resolutionMap.staticElementForConstructorReference(redirect).isFactory
2070 ? '' 2093 ? ''
2071 : 'new'; 2094 : 'new';
2072 // Pass along all arguments verbatim, and let the callee handle them. 2095 // Pass along all arguments verbatim, and let the callee handle them.
2073 // TODO(jmesserly): we'll need something different once we have 2096 // TODO(jmesserly): we'll need something different once we have
2074 // rest/spread support, but this should work for now. 2097 // rest/spread support, but this should work for now.
2075 var params = 2098 var params =
2076 visitFormalParameterList(node.parameters, destructure: false); 2099 _emitFormalParameterList(node.parameters, destructure: false);
2077 2100
2078 var fun = new JS.Fun( 2101 var fun = new JS.Fun(
2079 params, 2102 params,
2080 js.statement('{ return $newKeyword #(#); }', 2103 js.statement(
2081 [_visit(redirect) as JS.Node, params]), 2104 '{ return $newKeyword #(#); }', [_visit(redirect), params]),
2082 returnType: returnType); 2105 returnType: returnType);
2083 return annotate( 2106 return annotate(
2084 new JS.Method(name, fun, isStatic: true), node, node.element); 2107 new JS.Method(name, fun, isStatic: true), node, node.element);
2085 } 2108 }
2086 2109
2087 var params = visitFormalParameterList(node.parameters); 2110 var params = _emitFormalParameterList(node.parameters);
2088 2111
2089 // Factory constructors are essentially static methods. 2112 // Factory constructors are essentially static methods.
2090 if (node.factoryKeyword != null) { 2113 if (node.factoryKeyword != null) {
2091 var body = <JS.Statement>[]; 2114 var body = <JS.Statement>[];
2092 var init = _emitArgumentInitializers(node, constructor: true); 2115 var init = _emitArgumentInitializers(node, constructor: true);
2093 if (init != null) body.add(init); 2116 if (init != null) body.add(init);
2094 body.add(_visit(node.body)); 2117 body.add(_visit(node.body));
2095 var fun = new JS.Fun(params, new JS.Block(body), returnType: returnType); 2118 var fun = new JS.Fun(params, new JS.Block(body), returnType: returnType);
2096 return annotate( 2119 return annotate(
2097 new JS.Method(name, fun, isStatic: true), node, node.element); 2120 new JS.Method(name, fun, isStatic: true), node, node.element);
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
2170 @override 2193 @override
2171 JS.Statement visitRedirectingConstructorInvocation( 2194 JS.Statement visitRedirectingConstructorInvocation(
2172 RedirectingConstructorInvocation node) { 2195 RedirectingConstructorInvocation node) {
2173 var ctor = resolutionMap.staticElementForConstructorReference(node); 2196 var ctor = resolutionMap.staticElementForConstructorReference(node);
2174 var cls = ctor.enclosingElement; 2197 var cls = ctor.enclosingElement;
2175 // We can't dispatch to the constructor with `this.new` as that might hit a 2198 // We can't dispatch to the constructor with `this.new` as that might hit a
2176 // derived class constructor with the same name. 2199 // derived class constructor with the same name.
2177 return js.statement('#.prototype.#.call(this, #);', [ 2200 return js.statement('#.prototype.#.call(this, #);', [
2178 new JS.Identifier(cls.name), 2201 new JS.Identifier(cls.name),
2179 _constructorName(ctor), 2202 _constructorName(ctor),
2180 _visit(node.argumentList) 2203 _emitArgumentList(node.argumentList)
2181 ]); 2204 ]);
2182 } 2205 }
2183 2206
2184 JS.Statement _superConstructorCall(ClassElement element, 2207 JS.Statement _superConstructorCall(ClassElement element,
2185 [SuperConstructorInvocation node]) { 2208 [SuperConstructorInvocation node]) {
2186 if (element.supertype == null) { 2209 if (element.supertype == null) {
2187 assert(element.type.isObject || options.unsafeForceCompile); 2210 assert(element.type.isObject || options.unsafeForceCompile);
2188 return null; 2211 return null;
2189 } 2212 }
2190 2213
(...skipping 11 matching lines...) Expand all
2202 // we don't have a default constructor in the supertype. 2225 // we don't have a default constructor in the supertype.
2203 assert(options.unsafeForceCompile); 2226 assert(options.unsafeForceCompile);
2204 return null; 2227 return null;
2205 } 2228 }
2206 2229
2207 if (superCtor.name == '' && !_hasUnnamedSuperConstructor(element)) { 2230 if (superCtor.name == '' && !_hasUnnamedSuperConstructor(element)) {
2208 return null; 2231 return null;
2209 } 2232 }
2210 2233
2211 var name = _constructorName(superCtor); 2234 var name = _constructorName(superCtor);
2212 var args = node != null ? _visit(node.argumentList) : []; 2235 var args = node != null ? _emitArgumentList(node.argumentList) : [];
2213 return annotate(js.statement('super.#(#);', [name, args]), node); 2236 return annotate(js.statement('super.#(#);', [name, args]), node);
2214 } 2237 }
2215 2238
2216 bool _hasUnnamedSuperConstructor(ClassElement e) { 2239 bool _hasUnnamedSuperConstructor(ClassElement e) {
2217 var supertype = e.supertype; 2240 var supertype = e.supertype;
2218 if (supertype == null) return false; 2241 if (supertype == null) return false;
2219 if (_hasUnnamedConstructor(supertype.element)) return true; 2242 if (_hasUnnamedConstructor(supertype.element)) return true;
2220 for (var mixin in e.mixins) { 2243 for (var mixin in e.mixins) {
2221 if (_hasUnnamedConstructor(mixin.element)) return true; 2244 if (_hasUnnamedConstructor(mixin.element)) return true;
2222 } 2245 }
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
2262 if (element is FieldFormalParameterElement) { 2285 if (element is FieldFormalParameterElement) {
2263 fields[element.field] = _emitSimpleIdentifier(p.identifier); 2286 fields[element.field] = _emitSimpleIdentifier(p.identifier);
2264 } 2287 }
2265 } 2288 }
2266 2289
2267 // Run constructor field initializers such as `: foo = bar.baz` 2290 // Run constructor field initializers such as `: foo = bar.baz`
2268 for (var init in ctor.initializers) { 2291 for (var init in ctor.initializers) {
2269 if (init is ConstructorFieldInitializer) { 2292 if (init is ConstructorFieldInitializer) {
2270 var element = init.fieldName.staticElement as FieldElement; 2293 var element = init.fieldName.staticElement as FieldElement;
2271 fields[element] = _visit(init.expression); 2294 fields[element] = _visit(init.expression);
2295 } else if (init is AssertInitializer) {
2296 throw new UnimplementedError(
2297 'Assert initializers are not implemented. '
2298 'See https://github.com/dart-lang/sdk/issues/27809');
2272 } 2299 }
2273 } 2300 }
2274 } 2301 }
2275 2302
2276 for (var f in fields.keys) unsetFields.remove(f); 2303 for (var f in fields.keys) unsetFields.remove(f);
2277 2304
2278 // Initialize all remaining fields 2305 // Initialize all remaining fields
2279 unsetFields.forEach((element, fieldNode) { 2306 unsetFields.forEach((element, fieldNode) {
2280 JS.Expression value; 2307 JS.Expression value;
2281 if (fieldNode.initializer != null) { 2308 if (fieldNode.initializer != null) {
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
2383 } 2410 }
2384 } 2411 }
2385 2412
2386 JS.Fun _emitNativeFunctionBody(MethodDeclaration node) { 2413 JS.Fun _emitNativeFunctionBody(MethodDeclaration node) {
2387 String name = 2414 String name =
2388 getAnnotationName(node.element, isJSAnnotation) ?? node.name.name; 2415 getAnnotationName(node.element, isJSAnnotation) ?? node.name.name;
2389 if (node.isGetter) { 2416 if (node.isGetter) {
2390 return new JS.Fun([], js.statement('{ return this.#; }', [name])); 2417 return new JS.Fun([], js.statement('{ return this.#; }', [name]));
2391 } else if (node.isSetter) { 2418 } else if (node.isSetter) {
2392 var params = 2419 var params =
2393 visitFormalParameterList(node.parameters, destructure: false); 2420 _emitFormalParameterList(node.parameters, destructure: false);
2394 return new JS.Fun( 2421 return new JS.Fun(
2395 params, js.statement('{ this.# = #; }', [name, params.last])); 2422 params, js.statement('{ this.# = #; }', [name, params.last]));
2396 } else { 2423 } else {
2397 return js.call( 2424 return js.call(
2398 'function (...args) { return this.#.apply(this, args); }', name); 2425 'function (...args) { return this.#.apply(this, args); }', name);
2399 } 2426 }
2400 } 2427 }
2401 2428
2402 JS.Method _emitMethodDeclaration(InterfaceType type, MethodDeclaration node) { 2429 JS.Method _emitMethodDeclaration(InterfaceType type, MethodDeclaration node) {
2403 if (node.isAbstract) { 2430 if (node.isAbstract) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
2443 if (JS.Return.foundIn(fn)) { 2470 if (JS.Return.foundIn(fn)) {
2444 // If a return is inside body, transform `(params) { body }` to 2471 // If a return is inside body, transform `(params) { body }` to
2445 // `(params) { (() => { body })(); return value; }`. 2472 // `(params) { (() => { body })(); return value; }`.
2446 // TODO(jmesserly): we could instead generate the return differently, 2473 // TODO(jmesserly): we could instead generate the return differently,
2447 // and avoid the immediately invoked function. 2474 // and avoid the immediately invoked function.
2448 body = new JS.Call(new JS.ArrowFun([], fn.body), []).toStatement(); 2475 body = new JS.Call(new JS.ArrowFun([], fn.body), []).toStatement();
2449 } 2476 }
2450 // Rewrite the function to include the return. 2477 // Rewrite the function to include the return.
2451 return new JS.Fun( 2478 return new JS.Fun(
2452 fn.params, new JS.Block([body, new JS.Return(fn.params.last)]), 2479 fn.params, new JS.Block([body, new JS.Return(fn.params.last)]),
2453 typeParams: fn.typeParams, 2480 typeParams: fn.typeParams, returnType: fn.returnType)
2454 returnType: fn.returnType)..sourceInformation = fn.sourceInformation; 2481 ..sourceInformation = fn.sourceInformation;
2455 } 2482 }
2456 2483
2457 @override 2484 @override
2458 JS.Statement visitFunctionDeclaration(FunctionDeclaration node) { 2485 JS.Statement visitFunctionDeclaration(FunctionDeclaration node) {
2459 assert(node.parent is CompilationUnit); 2486 assert(node.parent is CompilationUnit);
2460 2487
2461 if (_externalOrNative(node)) return null; 2488 if (_externalOrNative(node)) return null;
2462 2489
2463 if (node.isGetter || node.isSetter) { 2490 if (node.isGetter || node.isSetter) {
2464 PropertyAccessorElement element = node.element; 2491 PropertyAccessorElement element = node.element;
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
2649 var fn = _emitFunctionBody(node.element, node.parameters, node.body); 2676 var fn = _emitFunctionBody(node.element, node.parameters, node.body);
2650 return annotate(_makeGenericFunction(fn), node); 2677 return annotate(_makeGenericFunction(fn), node);
2651 } 2678 }
2652 2679
2653 JS.Fun _emitFunctionBody(ExecutableElement element, 2680 JS.Fun _emitFunctionBody(ExecutableElement element,
2654 FormalParameterList parameters, FunctionBody body) { 2681 FormalParameterList parameters, FunctionBody body) {
2655 FunctionType type = element.type; 2682 FunctionType type = element.type;
2656 2683
2657 // normal function (sync), vs (sync*, async, async*) 2684 // normal function (sync), vs (sync*, async, async*)
2658 var stdFn = !(element.isAsynchronous || element.isGenerator); 2685 var stdFn = !(element.isAsynchronous || element.isGenerator);
2659 var formals = visitFormalParameterList(parameters, destructure: stdFn); 2686 var formals = _emitFormalParameterList(parameters, destructure: stdFn);
2660 var code = (stdFn) 2687 var code = (stdFn)
2661 ? _visit(body) 2688 ? _visit(body)
2662 : new JS.Block( 2689 : new JS.Block(
2663 [_emitGeneratorFunctionBody(element, parameters, body).toReturn()]); 2690 [_emitGeneratorFunctionBody(element, parameters, body).toReturn()]);
2664 var typeFormals = _emitTypeFormals(type.typeFormals); 2691 var typeFormals = _emitTypeFormals(type.typeFormals);
2665 var returnType = emitTypeRef(type.returnType); 2692 var returnType = emitTypeRef(type.returnType);
2666 if (type.typeFormals.isNotEmpty) { 2693 if (type.typeFormals.isNotEmpty) {
2667 code = new JS.Block(<JS.Statement>[ 2694 code = new JS.Block(<JS.Statement>[
2668 new JS.Block(_typeTable.discharge(type.typeFormals)), 2695 new JS.Block(_typeTable.discharge(type.typeFormals)),
2669 code 2696 code
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
2702 // In the body of a `sync*` and `async`, `yield`/`await` are both generated 2729 // In the body of a `sync*` and `async`, `yield`/`await` are both generated
2703 // simply as `yield`. 2730 // simply as `yield`.
2704 // 2731 //
2705 // `async*` uses the `dart.asyncStar` helper, and also has an extra `stream` 2732 // `async*` uses the `dart.asyncStar` helper, and also has an extra `stream`
2706 // argument to the generator, which is used for passing values to the 2733 // argument to the generator, which is used for passing values to the
2707 // _AsyncStarStreamController implementation type. 2734 // _AsyncStarStreamController implementation type.
2708 // `yield` is specially generated inside `async*`, see visitYieldStatement. 2735 // `yield` is specially generated inside `async*`, see visitYieldStatement.
2709 // `await` is generated as `yield`. 2736 // `await` is generated as `yield`.
2710 // runtime/_generators.js has an example of what the code is generated as. 2737 // runtime/_generators.js has an example of what the code is generated as.
2711 var savedController = _asyncStarController; 2738 var savedController = _asyncStarController;
2712 var jsParams = visitFormalParameterList(parameters); 2739 var jsParams = _emitFormalParameterList(parameters);
2713 if (kind == 'asyncStar') { 2740 if (kind == 'asyncStar') {
2714 _asyncStarController = new JS.TemporaryId('stream'); 2741 _asyncStarController = new JS.TemporaryId('stream');
2715 jsParams.insert(0, _asyncStarController); 2742 jsParams.insert(0, _asyncStarController);
2716 } else { 2743 } else {
2717 _asyncStarController = null; 2744 _asyncStarController = null;
2718 } 2745 }
2719 var savedSuperAllowed = _superAllowed; 2746 var savedSuperAllowed = _superAllowed;
2720 _superAllowed = false; 2747 _superAllowed = false;
2721 // Visit the body with our async* controller set. 2748 // Visit the body with our async* controller set.
2722 var jsBody = _visit(body); 2749 var jsBody = _visit(body);
2723 _superAllowed = savedSuperAllowed; 2750 _superAllowed = savedSuperAllowed;
2724 _asyncStarController = savedController; 2751 _asyncStarController = savedController;
2725 2752
2726 DartType returnType = _getExpectedReturnType(element); 2753 DartType returnType = _getExpectedReturnType(element);
2727 JS.Expression gen = new JS.Fun(jsParams, jsBody, 2754 JS.Expression gen = new JS.Fun(jsParams, jsBody,
2728 isGenerator: true, returnType: emitTypeRef(returnType)); 2755 isGenerator: true, returnType: emitTypeRef(returnType));
2729 if (JS.This.foundIn(gen)) { 2756 if (JS.This.foundIn(gen)) {
2730 gen = js.call('#.bind(this)', gen); 2757 gen = js.call('#.bind(this)', gen);
2731 } 2758 }
2732 2759
2733 var T = _emitType(returnType); 2760 var T = _emitType(returnType);
2734 return _callHelper('#(#)', [ 2761 return _callHelper('#(#)', [
2735 kind, 2762 kind,
2736 [gen, T]..addAll(visitFormalParameterList(parameters, destructure: false)) 2763 [gen, T]..addAll(_emitFormalParameterList(parameters, destructure: false))
2737 ]); 2764 ]);
2738 } 2765 }
2739 2766
2740 @override 2767 @override
2741 JS.Statement visitFunctionDeclarationStatement( 2768 JS.Statement visitFunctionDeclarationStatement(
2742 FunctionDeclarationStatement node) { 2769 FunctionDeclarationStatement node) {
2743 var func = node.functionDeclaration; 2770 var func = node.functionDeclaration;
2744 if (func.isGetter || func.isSetter) { 2771 if (func.isGetter || func.isSetter) {
2745 return js.comment('Unimplemented function get/set statement: $node'); 2772 return js.comment('Unimplemented function get/set statement: $node');
2746 } 2773 }
(...skipping 627 matching lines...) Expand 10 before | Expand all | Expand 10 after
3374 JS.Expression target; 3401 JS.Expression target;
3375 if (element is TemporaryVariableElement) { 3402 if (element is TemporaryVariableElement) {
3376 // If this is one of our compiler's temporary variables, use its JS form. 3403 // If this is one of our compiler's temporary variables, use its JS form.
3377 target = element.jsVariable; 3404 target = element.jsVariable;
3378 } else if (element is ParameterElement) { 3405 } else if (element is ParameterElement) {
3379 target = _emitParameter(element); 3406 target = _emitParameter(element);
3380 } else { 3407 } else {
3381 target = new JS.Identifier(element.name); 3408 target = new JS.Identifier(element.name);
3382 } 3409 }
3383 3410
3384 return _visit(rhs).toAssignExpression(annotate(target, node)); 3411 return _visit<JS.Expression>(rhs)
3412 .toAssignExpression(annotate(target, node));
3385 } 3413 }
3386 3414
3387 /// Emits assignment to library scope element [element]. 3415 /// Emits assignment to library scope element [element].
3388 JS.Expression _emitSetTopLevel( 3416 JS.Expression _emitSetTopLevel(
3389 Expression lhs, Element element, Expression rhs) { 3417 Expression lhs, Element element, Expression rhs) {
3390 return _visit(rhs) 3418 return _visit<JS.Expression>(rhs)
3391 .toAssignExpression(annotate(_emitTopLevelName(element), lhs)); 3419 .toAssignExpression(annotate(_emitTopLevelName(element), lhs));
3392 } 3420 }
3393 3421
3394 /// Emits assignment to a static field element or property. 3422 /// Emits assignment to a static field element or property.
3395 JS.Expression _emitSetStaticProperty( 3423 JS.Expression _emitSetStaticProperty(
3396 Expression lhs, Element element, Expression rhs) { 3424 Expression lhs, Element element, Expression rhs) {
3397 // For static methods, we add the raw type name, without generics or 3425 // For static methods, we add the raw type name, without generics or
3398 // library prefix. We don't need those because static calls can't use 3426 // library prefix. We don't need those because static calls can't use
3399 // the generic type. 3427 // the generic type.
3400 ClassElement classElement = element.enclosingElement; 3428 ClassElement classElement = element.enclosingElement;
3401 var type = classElement.type; 3429 var type = classElement.type;
3402 var dynType = _emitStaticAccess(type); 3430 var dynType = _emitStaticAccess(type);
3403 var member = _emitMemberName(element.name, 3431 var member = _emitMemberName(element.name,
3404 isStatic: true, type: type, element: element); 3432 isStatic: true, type: type, element: element);
3405 return _visit(rhs).toAssignExpression( 3433 return _visit<JS.Expression>(rhs).toAssignExpression(
3406 annotate(new JS.PropertyAccess(dynType, member), lhs)); 3434 annotate(new JS.PropertyAccess(dynType, member), lhs));
3407 } 3435 }
3408 3436
3409 /// Emits an assignment to the [element] property of instance referenced by 3437 /// Emits an assignment to the [element] property of instance referenced by
3410 /// [jsTarget]. 3438 /// [jsTarget].
3411 JS.Expression _emitWriteInstanceProperty(Expression lhs, 3439 JS.Expression _emitWriteInstanceProperty(Expression lhs,
3412 JS.Expression jsTarget, Element element, JS.Expression value) { 3440 JS.Expression jsTarget, Element element, JS.Expression value) {
3413 String memberName = element.name; 3441 String memberName = element.name;
3414 var type = (element.enclosingElement as ClassElement).type; 3442 var type = (element.enclosingElement as ClassElement).type;
3415 var name = _emitMemberName(memberName, type: type, element: element); 3443 var name = _emitMemberName(memberName, type: type, element: element);
3416 return value.toAssignExpression( 3444 return value.toAssignExpression(
3417 annotate(new JS.PropertyAccess(jsTarget, name), lhs)); 3445 annotate(new JS.PropertyAccess(jsTarget, name), lhs));
3418 } 3446 }
3419 3447
3420 JS.Expression _emitSetSuper(Expression lhs, SuperExpression target, 3448 JS.Expression _emitSetSuper(Expression lhs, SuperExpression target,
3421 SimpleIdentifier id, Expression rhs) { 3449 SimpleIdentifier id, Expression rhs) {
3422 // TODO(sra): Determine whether and access helper is required for the 3450 // TODO(sra): Determine whether and access helper is required for the
3423 // setter. For now fall back on the r-value path. 3451 // setter. For now fall back on the r-value path.
3424 return _visit(rhs).toAssignExpression(_visit(lhs)); 3452 return _visit<JS.Expression>(rhs).toAssignExpression(_visit(lhs));
3425 } 3453 }
3426 3454
3427 JS.Expression _emitNullSafeSet(PropertyAccess node, Expression right) { 3455 JS.Expression _emitNullSafeSet(PropertyAccess node, Expression right) {
3428 // Emit `obj?.prop = expr` as: 3456 // Emit `obj?.prop = expr` as:
3429 // 3457 //
3430 // (_ => _ == null ? null : _.prop = expr)(obj). 3458 // (_ => _ == null ? null : _.prop = expr)(obj).
3431 // 3459 //
3432 // We could use a helper, e.g.: `nullSafeSet(e1, _ => _.v = e2)` 3460 // We could use a helper, e.g.: `nullSafeSet(e1, _ => _.v = e2)`
3433 // 3461 //
3434 // However with MetaLet, we get clean code in statement or void context, 3462 // However with MetaLet, we get clean code in statement or void context,
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
3491 } 3519 }
3492 if (node.methodName.name == 'call') { 3520 if (node.methodName.name == 'call') {
3493 var targetType = resolutionMap.staticTypeForExpression(target); 3521 var targetType = resolutionMap.staticTypeForExpression(target);
3494 if (targetType is FunctionType) { 3522 if (targetType is FunctionType) {
3495 // Call methods on function types should be handled as regular function 3523 // Call methods on function types should be handled as regular function
3496 // invocations. 3524 // invocations.
3497 return _emitFunctionCall(node, node.target); 3525 return _emitFunctionCall(node, node.target);
3498 } 3526 }
3499 if (targetType.isDartCoreFunction || targetType.isDynamic) { 3527 if (targetType.isDartCoreFunction || targetType.isDynamic) {
3500 // TODO(vsm): Can a call method take generic type parameters? 3528 // TODO(vsm): Can a call method take generic type parameters?
3501 return _emitDynamicInvoke(node, _visit(target), 3529 return _emitDynamicInvoke(
3502 _visit(node.argumentList) as List<JS.Expression>); 3530 node, _visit(target), _emitArgumentList(node.argumentList));
3503 } 3531 }
3504 } 3532 }
3505 3533
3506 return _emitMethodCall(target, node); 3534 return _emitMethodCall(target, node);
3507 } 3535 }
3508 3536
3509 JS.Expression _emitMethodCall(Expression target, MethodInvocation node) { 3537 JS.Expression _emitMethodCall(Expression target, MethodInvocation node) {
3510 var args = _visit(node.argumentList) as List<JS.Expression>; 3538 var args = _emitArgumentList(node.argumentList);
3511 var typeArgs = _emitInvokeTypeArguments(node); 3539 var typeArgs = _emitInvokeTypeArguments(node);
3512 3540
3513 if (target is SuperExpression && !_superAllowed) { 3541 if (target is SuperExpression && !_superAllowed) {
3514 return _emitSuperHelperCall(typeArgs, args, target, node); 3542 return _emitSuperHelperCall(typeArgs, args, target, node);
3515 } 3543 }
3516 3544
3517 return _emitMethodCallInternal(target, node, args, typeArgs); 3545 return _emitMethodCallInternal(target, node, args, typeArgs);
3518 } 3546 }
3519 3547
3520 JS.Expression _emitSuperHelperCall(List<JS.Expression> typeArgs, 3548 JS.Expression _emitSuperHelperCall(List<JS.Expression> typeArgs,
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
3640 } 3668 }
3641 3669
3642 /// Emits a function call, to a top-level function, local function, or 3670 /// Emits a function call, to a top-level function, local function, or
3643 /// an expression. 3671 /// an expression.
3644 JS.Expression _emitFunctionCall(InvocationExpression node, 3672 JS.Expression _emitFunctionCall(InvocationExpression node,
3645 [Expression function]) { 3673 [Expression function]) {
3646 if (function == null) { 3674 if (function == null) {
3647 function = node.function; 3675 function = node.function;
3648 } 3676 }
3649 var fn = _visit(function); 3677 var fn = _visit(function);
3650 var args = _visit(node.argumentList) as List<JS.Expression>; 3678 var args = _emitArgumentList(node.argumentList);
3651 if (isDynamicInvoke(function)) { 3679 if (isDynamicInvoke(function)) {
3652 return _emitDynamicInvoke(node, fn, args); 3680 return _emitDynamicInvoke(node, fn, args);
3653 } else { 3681 } else {
3654 return new JS.Call(_applyInvokeTypeArguments(fn, node), args); 3682 return new JS.Call(_applyInvokeTypeArguments(fn, node), args);
3655 } 3683 }
3656 } 3684 }
3657 3685
3658 JS.Expression _applyInvokeTypeArguments( 3686 JS.Expression _applyInvokeTypeArguments(
3659 JS.Expression target, InvocationExpression node) { 3687 JS.Expression target, InvocationExpression node) {
3660 var typeArgs = _emitInvokeTypeArguments(node); 3688 var typeArgs = _emitInvokeTypeArguments(node);
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
3789 } 3817 }
3790 return null; 3818 return null;
3791 } 3819 }
3792 3820
3793 @override 3821 @override
3794 JS.Expression visitFunctionExpressionInvocation( 3822 JS.Expression visitFunctionExpressionInvocation(
3795 FunctionExpressionInvocation node) => 3823 FunctionExpressionInvocation node) =>
3796 _emitFunctionCall(node); 3824 _emitFunctionCall(node);
3797 3825
3798 @override 3826 @override
3799 List<JS.Expression> visitArgumentList(ArgumentList node) { 3827 visitArgumentList(ArgumentList node) {
3828 assert(false);
vsm 2017/04/14 13:14:39 Should this just be in your unreachable list below
Jennifer Messerly 2017/04/14 17:03:58 yes! oops :) done
3829 }
3830
3831 List<JS.Expression> _emitArgumentList(ArgumentList node) {
3800 var args = <JS.Expression>[]; 3832 var args = <JS.Expression>[];
3801 var named = <JS.Property>[]; 3833 var named = <JS.Property>[];
3802 for (var arg in node.arguments) { 3834 for (var arg in node.arguments) {
3803 if (arg is NamedExpression) { 3835 if (arg is NamedExpression) {
3804 named.add(_visit(arg)); 3836 named.add(_visit(arg));
3805 } else if (arg is MethodInvocation && isJsSpreadInvocation(arg)) { 3837 } else if (arg is MethodInvocation && isJsSpreadInvocation(arg)) {
3806 args.add( 3838 args.add(
3807 new JS.RestParameter(_visit(arg.argumentList.arguments.single))); 3839 new JS.RestParameter(_visit(arg.argumentList.arguments.single)));
3808 } else { 3840 } else {
3809 args.add(_visit(arg)); 3841 args.add(_visit(arg));
3810 } 3842 }
3811 } 3843 }
3812 if (named.isNotEmpty) { 3844 if (named.isNotEmpty) {
3813 args.add(new JS.ObjectInitializer(named)); 3845 args.add(new JS.ObjectInitializer(named));
3814 } 3846 }
3815 return args; 3847 return args;
3816 } 3848 }
3817 3849
3818 @override 3850 @override
3819 JS.Property visitNamedExpression(NamedExpression node) { 3851 JS.Property visitNamedExpression(NamedExpression node) {
3820 assert(node.parent is ArgumentList); 3852 assert(node.parent is ArgumentList);
3821 return new JS.Property( 3853 return new JS.Property(
3822 _propertyName(node.name.label.name), _visit(node.expression)); 3854 _propertyName(node.name.label.name), _visit(node.expression));
3823 } 3855 }
3824 3856
3825 @override 3857 List<JS.Parameter> _emitFormalParameterList(FormalParameterList node,
3826 List<JS.Parameter> visitFormalParameterList(FormalParameterList node,
3827 {bool destructure: true}) { 3858 {bool destructure: true}) {
3828 if (node == null) return []; 3859 if (node == null) return [];
3829 3860
3830 destructure = destructure && options.destructureNamedParams; 3861 destructure = destructure && options.destructureNamedParams;
3831 3862
3832 var result = <JS.Parameter>[]; 3863 var result = <JS.Parameter>[];
3833 var namedVars = <JS.DestructuredVariable>[]; 3864 var namedVars = <JS.DestructuredVariable>[];
3834 var hasNamedArgsConflictingWithObjectProperties = false; 3865 var hasNamedArgsConflictingWithObjectProperties = false;
3835 var needsOpts = false; 3866 var needsOpts = false;
3836 3867
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
3973 JS.Statement visitVariableDeclarationStatement( 4004 JS.Statement visitVariableDeclarationStatement(
3974 VariableDeclarationStatement node) { 4005 VariableDeclarationStatement node) {
3975 // Special case a single variable with an initializer. 4006 // Special case a single variable with an initializer.
3976 // This helps emit cleaner code for things like: 4007 // This helps emit cleaner code for things like:
3977 // var result = []..add(1)..add(2); 4008 // var result = []..add(1)..add(2);
3978 var variables = node.variables.variables; 4009 var variables = node.variables.variables;
3979 if (variables.length == 1) { 4010 if (variables.length == 1) {
3980 var v = variables[0]; 4011 var v = variables[0];
3981 if (v.initializer != null) { 4012 if (v.initializer != null) {
3982 var name = new JS.Identifier(v.name.name); 4013 var name = new JS.Identifier(v.name.name);
3983 return _visit(v.initializer).toVariableDeclaration(name); 4014 return _visit<JS.Expression>(v.initializer).toVariableDeclaration(name);
3984 } 4015 }
3985 } 4016 }
3986 return _visit(node.variables).toStatement(); 4017 return _visit<JS.Expression>(node.variables).toStatement();
3987 } 4018 }
3988 4019
3989 @override 4020 @override
3990 visitVariableDeclarationList(VariableDeclarationList node) { 4021 visitVariableDeclarationList(VariableDeclarationList node) {
3991 return new JS.VariableDeclarationList( 4022 return new JS.VariableDeclarationList(
3992 'let', _visitList(node.variables) as List<JS.VariableInitialization>); 4023 'let', _visitList(node.variables) as List<JS.VariableInitialization>);
3993 } 4024 }
3994 4025
3995 @override 4026 @override
3996 visitVariableDeclaration(VariableDeclaration node) { 4027 visitVariableDeclaration(VariableDeclaration node) {
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
4115 hoistType: options.hoistInstanceCreation); 4146 hoistType: options.hoistInstanceCreation);
4116 if (name != null) { 4147 if (name != null) {
4117 ctor = new JS.PropertyAccess(ctor, _propertyName(name.name)); 4148 ctor = new JS.PropertyAccess(ctor, _propertyName(name.name));
4118 } 4149 }
4119 } else { 4150 } else {
4120 ctor = _emitConstructorName(element, type, name); 4151 ctor = _emitConstructorName(element, type, name);
4121 isFactory = element.isFactory; 4152 isFactory = element.isFactory;
4122 var classElem = element.enclosingElement; 4153 var classElem = element.enclosingElement;
4123 isNative = _isJSNative(classElem); 4154 isNative = _isJSNative(classElem);
4124 } 4155 }
4125 var args = _visit(argumentList) as List<JS.Expression>; 4156 var args = _emitArgumentList(argumentList);
4126 // Native factory constructors are JS constructors - use new here. 4157 // Native factory constructors are JS constructors - use new here.
4127 return isFactory && !isNative 4158 return isFactory && !isNative
4128 ? new JS.Call(ctor, args) 4159 ? new JS.Call(ctor, args)
4129 : new JS.New(ctor, args); 4160 : new JS.New(ctor, args);
4130 } 4161 }
4131 4162
4132 if (element != null && _isObjectLiteral(element.enclosingElement)) { 4163 if (element != null && _isObjectLiteral(element.enclosingElement)) {
4133 return _emitObjectLiteral(argumentList); 4164 return _emitObjectLiteral(argumentList);
4134 } 4165 }
4135 if (isConst) return _emitConst(emitNew); 4166 if (isConst) return _emitConst(emitNew);
4136 return emitNew(); 4167 return emitNew();
4137 } 4168 }
4138 4169
4139 bool _isObjectLiteral(ClassElement classElem) { 4170 bool _isObjectLiteral(ClassElement classElem) {
4140 return findAnnotation(classElem, isPublicJSAnnotation) != null && 4171 return findAnnotation(classElem, isPublicJSAnnotation) != null &&
4141 findAnnotation(classElem, isJSAnonymousAnnotation) != null; 4172 findAnnotation(classElem, isJSAnonymousAnnotation) != null;
4142 } 4173 }
4143 4174
4144 bool _isJSNative(ClassElement classElem) => 4175 bool _isJSNative(ClassElement classElem) =>
4145 findAnnotation(classElem, isPublicJSAnnotation) != null; 4176 findAnnotation(classElem, isPublicJSAnnotation) != null;
4146 4177
4147 JS.Expression _emitObjectLiteral(ArgumentList argumentList) { 4178 JS.Expression _emitObjectLiteral(ArgumentList argumentList) {
4148 var args = _visit(argumentList) as List<JS.Expression>; 4179 var args = _emitArgumentList(argumentList);
4149 if (args.isEmpty) { 4180 if (args.isEmpty) {
4150 return js.call('{}'); 4181 return js.call('{}');
4151 } 4182 }
4152 assert(args.single is JS.ObjectInitializer); 4183 assert(args.single is JS.ObjectInitializer);
4153 return args.single; 4184 return args.single;
4154 } 4185 }
4155 4186
4156 @override 4187 @override
4157 visitInstanceCreationExpression(InstanceCreationExpression node) { 4188 visitInstanceCreationExpression(InstanceCreationExpression node) {
4158 var element = resolutionMap.staticElementForConstructorReference(node); 4189 var element = resolutionMap.staticElementForConstructorReference(node);
(...skipping 576 matching lines...) Expand 10 before | Expand all | Expand 10 after
4735 var operatorName = op.lexeme; 4766 var operatorName = op.lexeme;
4736 // Use the name from the Dart spec. 4767 // Use the name from the Dart spec.
4737 if (operatorName == '-') operatorName = 'unary-'; 4768 if (operatorName == '-') operatorName = 'unary-';
4738 return _emitSend(expr, operatorName, []); 4769 return _emitSend(expr, operatorName, []);
4739 } 4770 }
4740 4771
4741 // Cascades can contain [IndexExpression], [MethodInvocation] and 4772 // Cascades can contain [IndexExpression], [MethodInvocation] and
4742 // [PropertyAccess]. The code generation for those is handled in their 4773 // [PropertyAccess]. The code generation for those is handled in their
4743 // respective visit methods. 4774 // respective visit methods.
4744 @override 4775 @override
4745 JS.Node visitCascadeExpression(CascadeExpression node) { 4776 visitCascadeExpression(CascadeExpression node) {
4746 var savedCascadeTemp = _cascadeTarget; 4777 var savedCascadeTemp = _cascadeTarget;
4747 4778
4748 var vars = <JS.MetaLetVariable, JS.Expression>{}; 4779 var vars = <JS.MetaLetVariable, JS.Expression>{};
4749 _cascadeTarget = _bindValue(vars, '_', node.target, context: node); 4780 _cascadeTarget = _bindValue(vars, '_', node.target, context: node);
4750 var sections = _visitList(node.cascadeSections) as List<JS.Expression>; 4781 var sections = _visitList(node.cascadeSections) as List<JS.Expression>;
4751 sections.add(_visit(_cascadeTarget)); 4782 sections.add(_visit(_cascadeTarget));
4752 var result = new JS.MetaLet(vars, sections, statelessResult: true); 4783 var result = new JS.MetaLet(vars, sections, statelessResult: true);
4753 _cascadeTarget = savedCascadeTemp; 4784 _cascadeTarget = savedCascadeTemp;
4754 return result; 4785 return result;
4755 } 4786 }
4756 4787
4757 @override 4788 @override
4758 visitParenthesizedExpression(ParenthesizedExpression node) => 4789 visitParenthesizedExpression(ParenthesizedExpression node) =>
4759 // The printer handles precedence so we don't need to. 4790 // The printer handles precedence so we don't need to.
4760 _visit(node.expression); 4791 _visit(node.expression);
4761 4792
4762 @override 4793 @override
4763 visitFormalParameter(FormalParameter node) { 4794 visitDefaultFormalParameter(DefaultFormalParameter node) {
4795 return _emitParameter(node.element, declaration: true);
4796 }
4797
4798 JS.Parameter _emitNormalFormalParameter(NormalFormalParameter node) {
4764 var id = _emitParameter(node.element, declaration: true); 4799 var id = _emitParameter(node.element, declaration: true);
4765 var isRestArg = findAnnotation(node.element, isJsRestAnnotation) != null; 4800 var isRestArg = findAnnotation(node.element, isJsRestAnnotation) != null;
4766 return isRestArg ? new JS.RestParameter(id) : id; 4801 return isRestArg ? new JS.RestParameter(id) : id;
4767 } 4802 }
4768 4803
4769 @override 4804 @override
4805 visitSimpleFormalParameter(SimpleFormalParameter node) =>
4806 _emitNormalFormalParameter(node);
4807
4808 @override
4809 visitFieldFormalParameter(FieldFormalParameter node) =>
4810 _emitNormalFormalParameter(node);
4811
4812 @override
4813 visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) =>
4814 _emitNormalFormalParameter(node);
4815
4816 @override
4770 JS.This visitThisExpression(ThisExpression node) => new JS.This(); 4817 JS.This visitThisExpression(ThisExpression node) => new JS.This();
4771 4818
4772 @override 4819 @override
4773 JS.Super visitSuperExpression(SuperExpression node) => new JS.Super(); 4820 JS.Super visitSuperExpression(SuperExpression node) => new JS.Super();
4774 4821
4775 @override 4822 @override
4776 visitPrefixedIdentifier(PrefixedIdentifier node) { 4823 visitPrefixedIdentifier(PrefixedIdentifier node) {
4777 if (_isDeferredLoadLibrary(node.prefix, node.identifier)) { 4824 if (_isDeferredLoadLibrary(node.prefix, node.identifier)) {
4778 // We are tearing off "loadLibrary" on a library prefix. 4825 // We are tearing off "loadLibrary" on a library prefix.
4779 return _callHelper('loadLibrary'); 4826 return _callHelper('loadLibrary');
(...skipping 627 matching lines...) Expand 10 before | Expand all | Expand 10 after
5407 @override 5454 @override
5408 JS.LiteralString visitSimpleStringLiteral(SimpleStringLiteral node) => 5455 JS.LiteralString visitSimpleStringLiteral(SimpleStringLiteral node) =>
5409 js.escapedString(node.value, node.isSingleQuoted ? "'" : '"'); 5456 js.escapedString(node.value, node.isSingleQuoted ? "'" : '"');
5410 5457
5411 @override 5458 @override
5412 JS.Expression visitAdjacentStrings(AdjacentStrings node) => 5459 JS.Expression visitAdjacentStrings(AdjacentStrings node) =>
5413 _visitListToBinary(node.strings, '+'); 5460 _visitListToBinary(node.strings, '+');
5414 5461
5415 @override 5462 @override
5416 JS.Expression visitStringInterpolation(StringInterpolation node) { 5463 JS.Expression visitStringInterpolation(StringInterpolation node) {
5464 var strings = <String>[];
5465 var interpolations = <JS.Expression>[];
5466
5467 var expectString = true;
5468 for (var e in node.elements) {
5469 if (e is InterpolationString) {
5470 assert(expectString);
5471 expectString = false;
5472
5473 // Escape the string as necessary for use in the eventual `` quotes.
5474 // TODO(jmesserly): this call adds quotes, and then we strip them off.
5475 var str = js.escapedString(e.value, '`').value;
5476 strings.add(str.substring(1, str.length - 1));
5477 } else {
5478 assert(!expectString);
5479 expectString = true;
5480 interpolations.add(_visit(e));
5481 }
5482 }
5417 return new JS.TaggedTemplate( 5483 return new JS.TaggedTemplate(
5418 _callHelper('str'), new JS.TemplateString(_visitList(node.elements))); 5484 _callHelper('str'), new JS.TemplateString(strings, interpolations));
5419 } 5485 }
5420 5486
5421 @override 5487 @override
5422 String visitInterpolationString(InterpolationString node) {
5423 // TODO(jmesserly): this call adds quotes, and then we strip them off.
5424 var str = js.escapedString(node.value, '`').value;
5425 return str.substring(1, str.length - 1);
5426 }
5427
5428 @override
5429 visitInterpolationExpression(InterpolationExpression node) => 5488 visitInterpolationExpression(InterpolationExpression node) =>
5430 _visit(node.expression); 5489 _visit(node.expression);
5431 5490
5432 @override 5491 @override
5433 visitBooleanLiteral(BooleanLiteral node) => js.boolean(node.value); 5492 visitBooleanLiteral(BooleanLiteral node) => js.boolean(node.value);
5434 5493
5435 @override 5494 T _visit<T extends JS.Node>(AstNode node) {
5436 JS.Expression visitExpression(Expression node) =>
5437 _unimplementedCall('Unimplemented ${node.runtimeType}: $node');
5438
5439 JS.Expression _unimplementedCall(String comment) {
5440 return _callHelper('throw(#)', [js.escapedString(comment)]);
5441 }
5442
5443 @override
5444 visitNode(AstNode node) {
5445 // TODO(jmesserly): verify this is unreachable.
5446 throw 'Unimplemented ${node.runtimeType}: $node';
5447 }
5448
5449 _visit(AstNode node) {
5450 if (node == null) return null; 5495 if (node == null) return null;
5451 var result = node.accept(this); 5496 var result = node.accept(this);
5452 return result is JS.Node ? annotate(result, node) : result; 5497 return result != null ? annotate(result, node) : null;
5453 } 5498 }
5454 5499
5455 // TODO(jmesserly): we should make sure this only returns JS AST nodes. 5500 // TODO(jmesserly): we should make sure this only returns JS AST nodes.
5456 List/*<R>*/ _visitList/*<T extends AstNode, R>*/(Iterable/*<T>*/ nodes) { 5501 List/*<R>*/ _visitList/*<T extends AstNode, R>*/(Iterable/*<T>*/ nodes) {
5457 if (nodes == null) return null; 5502 if (nodes == null) return null;
5458 var result = /*<R>*/ []; 5503 var result = /*<R>*/ [];
5459 for (var node in nodes) result.add(_visit(node) as dynamic/*=R*/); 5504 for (var node in nodes) result.add(_visit(node) as dynamic/*=R*/);
5460 return result; 5505 return result;
5461 } 5506 }
5462 5507
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
5603 useExtension = baseType is InterfaceType && 5648 useExtension = baseType is InterfaceType &&
5604 _isSymbolizedMember(baseType, name, alwaysSymbolizeNative); 5649 _isSymbolizedMember(baseType, name, alwaysSymbolizeNative);
5605 } 5650 }
5606 5651
5607 return useExtension 5652 return useExtension
5608 ? js.call('#.#', [_extensionSymbolsModule, result]) 5653 ? js.call('#.#', [_extensionSymbolsModule, result])
5609 : result; 5654 : result;
5610 } 5655 }
5611 5656
5612 var _forwardingCache = new HashMap<Element, Map<String, ExecutableElement>>(); 5657 var _forwardingCache = new HashMap<Element, Map<String, ExecutableElement>>();
5658
5613 Element _lookupForwardedMember(ClassElement element, String name) { 5659 Element _lookupForwardedMember(ClassElement element, String name) {
5614 // We only care about public methods. 5660 // We only care about public methods.
5615 if (name.startsWith('_')) return null; 5661 if (name.startsWith('_')) return null;
5616 5662
5617 var map = _forwardingCache.putIfAbsent(element, () => {}); 5663 var map = _forwardingCache.putIfAbsent(element, () => {});
5618 if (map.containsKey(name)) return map[name]; 5664 if (map.containsKey(name)) return map[name];
5619 5665
5620 // Note, for a public member, the library should not matter. 5666 // Note, for a public member, the library should not matter.
5621 var library = element.library; 5667 var library = element.library;
5622 var member = element.lookUpMethod(name, library) ?? 5668 var member = element.lookUpMethod(name, library) ??
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
5830 return whitelisted.contains(name); 5876 return whitelisted.contains(name);
5831 } 5877 }
5832 } 5878 }
5833 5879
5834 // Dynamic calls are less risky so there is no need to whitelist at the 5880 // Dynamic calls are less risky so there is no need to whitelist at the
5835 // method level. 5881 // method level.
5836 if (isCall && _uncheckedWhitelistCalls.contains(filename)) return true; 5882 if (isCall && _uncheckedWhitelistCalls.contains(filename)) return true;
5837 5883
5838 return path.endsWith(".template.dart"); 5884 return path.endsWith(".template.dart");
5839 } 5885 }
5886
5887 _unreachable(AstNode node) {
5888 throw new UnsupportedError(
5889 'tried to generate an unreachable node: `$node`');
5890 }
5891
5892 /// Unused, see methods for emitting declarations.
5893 @override
5894 visitAnnotation(node) => _unreachable(node);
5895
5896 /// Unused, see [_emitFieldInitializers].
5897 @override
5898 visitAssertInitializer(node) => _unreachable(node);
5899
5900 /// Not visited, but maybe they should be?
5901 /// See <https://github.com/dart-lang/sdk/issues/29347>
5902 @override
5903 visitComment(node) => _unreachable(node);
5904
5905 /// Not visited, but maybe they should be?
5906 /// See <https://github.com/dart-lang/sdk/issues/29347>
5907 @override
5908 visitCommentReference(node) => _unreachable(node);
5909
5910 /// Unused, handled by imports/exports.
5911 @override
5912 visitConfiguration(node) => _unreachable(node);
5913
5914 /// Unusued, see [_emitConstructor].
5915 @override
5916 visitConstructorDeclaration(node) => _unreachable(node);
5917
5918 /// Unusued, see [_emitFieldInitializers].
5919 @override
5920 visitConstructorFieldInitializer(node) => _unreachable(node);
5921
5922 /// Unusued. Handled in [visitForEachStatement].
5923 @override
5924 visitDeclaredIdentifier(node) => _unreachable(node);
5925
5926 /// Unused, handled by imports/exports.
5927 @override
5928 visitDottedName(node) => _unreachable(node);
5929
5930 /// Unused, handled by [visitEnumDeclaration].
5931 @override
5932 visitEnumConstantDeclaration(node) => _unreachable(node); // see
5933
5934 /// Unused, see [_emitClassHeritage].
5935 @override
5936 visitExtendsClause(node) => _unreachable(node);
5937
5938 /// Unused, see [_emitFormalParameterList].
5939 @override
5940 visitFormalParameterList(node) => _unreachable(node);
5941
5942 /// Unused, handled by imports/exports.
5943 @override
5944 visitShowCombinator(node) => _unreachable(node);
5945
5946 /// Unused, handled by imports/exports.
5947 @override
5948 visitHideCombinator(node) => _unreachable(node);
5949
5950 /// Unused, see [_emitClassHeritage].
5951 @override
5952 visitImplementsClause(node) => _unreachable(node);
5953
5954 /// Unused, handled by [visitStringInterpolation].
5955 @override
5956 visitInterpolationString(node) => _unreachable(node);
5957
5958 /// Unused, labels are handled by containing statements.
5959 @override
5960 visitLabel(node) => _unreachable(node);
5961
5962 /// Unused, handled by imports/exports.
5963 @override
5964 visitLibraryIdentifier(node) => _unreachable(node);
5965
5966 /// Unused, see [visitMapLiteral].
5967 @override
5968 visitMapLiteralEntry(node) => _unreachable(node);
5969
5970 /// Unused, see [_emitMethodDeclaration].
5971 @override
5972 visitMethodDeclaration(node) => _unreachable(node);
5973
5974 /// Unused, these are not visited.
5975 @override
5976 visitNativeClause(node) => _unreachable(node);
5977
5978 /// Unused, these are not visited.
5979 @override
5980 visitNativeFunctionBody(node) => _unreachable(node);
5981
5982 /// Unused, handled by [_emitConstructor].
5983 @override
5984 visitSuperConstructorInvocation(node) => _unreachable(node);
5985
5986 /// Unused, this can be handled when emitting the module if needed.
5987 @override
5988 visitScriptTag(node) => _unreachable(node);
5989
5990 /// Unused, see [_emitType].
5991 @override
5992 visitTypeArgumentList(node) => _unreachable(node);
5993
5994 /// Unused, see [_emitType].
5995 @override
5996 visitTypeParameter(node) => _unreachable(node);
5997
5998 /// Unused, see [_emitType].
5999 @override
6000 visitGenericFunctionType(node) => _unreachable(node);
6001
6002 /// Unused, see [_emitType].
6003 @override
6004 visitTypeParameterList(node) => _unreachable(node);
6005
6006 /// Unused, see [_emitClassHeritage].
6007 @override
6008 visitWithClause(node) => _unreachable(node);
5840 } 6009 }
5841 6010
5842 /// Choose a canonical name from the [library] element. 6011 /// Choose a canonical name from the [library] element.
5843 /// 6012 ///
5844 /// This never uses the library's name (the identifier in the `library` 6013 /// This never uses the library's name (the identifier in the `library`
5845 /// declaration) as it doesn't have any meaningful rules enforced. 6014 /// declaration) as it doesn't have any meaningful rules enforced.
5846 String jsLibraryName(String libraryRoot, LibraryElement library) { 6015 String jsLibraryName(String libraryRoot, LibraryElement library) {
5847 var uri = library.source.uri; 6016 var uri = library.source.uri;
5848 if (uri.scheme == 'dart') { 6017 if (uri.scheme == 'dart') {
5849 return uri.path; 6018 return uri.path;
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
5950 if (targetIdentifier.staticElement is! PrefixElement) return false; 6119 if (targetIdentifier.staticElement is! PrefixElement) return false;
5951 var prefix = targetIdentifier.staticElement as PrefixElement; 6120 var prefix = targetIdentifier.staticElement as PrefixElement;
5952 6121
5953 // The library the prefix is referring to must come from a deferred import. 6122 // The library the prefix is referring to must come from a deferred import.
5954 var containingLibrary = resolutionMap 6123 var containingLibrary = resolutionMap
5955 .elementDeclaredByCompilationUnit(target.root as CompilationUnit) 6124 .elementDeclaredByCompilationUnit(target.root as CompilationUnit)
5956 .library; 6125 .library;
5957 var imports = containingLibrary.getImportsWithPrefix(prefix); 6126 var imports = containingLibrary.getImportsWithPrefix(prefix);
5958 return imports.length == 1 && imports[0].isDeferred; 6127 return imports.length == 1 && imports[0].isDeferred;
5959 } 6128 }
OLDNEW
« no previous file with comments | « pkg/dev_compiler/lib/sdk/ddc_sdk.sum ('k') | pkg/dev_compiler/lib/src/js_ast/nodes.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698