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

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

Issue 2015753002: Angular template workarounds (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 4 years, 6 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 | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 import 'dart:collection' show HashMap, HashSet; 5 import 'dart:collection' show HashMap, HashSet;
6 import 'dart:math' show min, max; 6 import 'dart:math' show min, max;
7 7
8 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; 8 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator;
9 import 'package:analyzer/dart/ast/ast.dart'; 9 import 'package:analyzer/dart/ast/ast.dart';
10 import 'package:analyzer/dart/ast/token.dart' show Token, TokenType; 10 import 'package:analyzer/dart/ast/token.dart' show Token, TokenType;
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
119 /// Helper class for emitting elements in the proper order to allow 119 /// Helper class for emitting elements in the proper order to allow
120 /// JS to load the module. 120 /// JS to load the module.
121 ElementLoader _loader; 121 ElementLoader _loader;
122 122
123 BuildUnit _buildUnit; 123 BuildUnit _buildUnit;
124 124
125 String _buildRoot; 125 String _buildRoot;
126 126
127 bool _superAllowed = true; 127 bool _superAllowed = true;
128 128
129 bool _inAngularTemplate = false;
130
129 List<JS.TemporaryId> _superHelperSymbols = <JS.TemporaryId>[]; 131 List<JS.TemporaryId> _superHelperSymbols = <JS.TemporaryId>[];
130 List<JS.Method> _superHelpers = <JS.Method>[]; 132 List<JS.Method> _superHelpers = <JS.Method>[];
131 133
132 List<TypeParameterType> _typeParamInConst = null; 134 List<TypeParameterType> _typeParamInConst = null;
133 135
134 /// Whether we are currently generating code for the body of a `JS()` call. 136 /// Whether we are currently generating code for the body of a `JS()` call.
135 bool _isInForeignJS = false; 137 bool _isInForeignJS = false;
136 138
137 CodeGenerator(AnalysisContext c, this.options, this._extensionTypes) 139 CodeGenerator(AnalysisContext c, this.options, this._extensionTypes)
138 : context = c, 140 : context = c,
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after
417 419
418 if (item != null) _moduleItems.add(item); 420 if (item != null) _moduleItems.add(item);
419 } 421 }
420 422
421 void _declareBeforeUse(Element e) { 423 void _declareBeforeUse(Element e) {
422 _loader.declareBeforeUse(e, _emitDeclaration); 424 _loader.declareBeforeUse(e, _emitDeclaration);
423 } 425 }
424 426
425 @override 427 @override
426 void visitCompilationUnit(CompilationUnit unit) { 428 void visitCompilationUnit(CompilationUnit unit) {
429 _inAngularTemplate =
Jennifer Messerly 2016/05/26 18:19:02 can we have this guarded by a compile flag please?
430 unit.element.source.fullName.endsWith(".template.dart");
Jennifer Messerly 2016/05/26 18:19:02 So, this doesn't work... I should put a comment on
431
427 _constField = new ConstFieldVisitor(types, unit.element.source); 432 _constField = new ConstFieldVisitor(types, unit.element.source);
428 433
429 for (var declaration in unit.declarations) { 434 for (var declaration in unit.declarations) {
430 var element = declaration.element; 435 var element = declaration.element;
431 if (element != null) { 436 if (element != null) {
432 _emitDeclaration(element); 437 _emitDeclaration(element);
433 } else { 438 } else {
434 declaration.accept(this); 439 declaration.accept(this);
435 } 440 }
436 } 441 }
437 for (var directive in unit.directives) { 442 for (var directive in unit.directives) {
438 directive.accept(this); 443 directive.accept(this);
439 } 444 }
445 _inAngularTemplate = false;
440 } 446 }
441 447
442 @override 448 @override
443 void visitLibraryDirective(LibraryDirective node) {} 449 void visitLibraryDirective(LibraryDirective node) {}
444 450
445 @override 451 @override
446 void visitImportDirective(ImportDirective node) { 452 void visitImportDirective(ImportDirective node) {
447 // We don't handle imports here. 453 // We don't handle imports here.
448 // 454 //
449 // Instead, we collect imports whenever we need to generate a reference 455 // Instead, we collect imports whenever we need to generate a reference
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
535 return js.call('dart.asInt(#)', jsFrom); 541 return js.call('dart.asInt(#)', jsFrom);
536 } 542 }
537 543
538 // A no-op in JavaScript. 544 // A no-op in JavaScript.
539 return jsFrom; 545 return jsFrom;
540 } 546 }
541 547
542 var type = _emitType(to, 548 var type = _emitType(to,
543 nameType: options.nameTypeTests || options.hoistTypeTests, 549 nameType: options.nameTypeTests || options.hoistTypeTests,
544 hoistType: options.hoistTypeTests); 550 hoistType: options.hoistTypeTests);
551 if (_inAngularTemplate) return jsFrom;
545 return js.call('dart.as(#, #)', [jsFrom, type]); 552 return js.call('dart.as(#, #)', [jsFrom, type]);
546 } 553 }
547 554
548 @override 555 @override
549 visitIsExpression(IsExpression node) { 556 visitIsExpression(IsExpression node) {
550 // Generate `is` as `dart.is` or `typeof` depending on the RHS type. 557 // Generate `is` as `dart.is` or `typeof` depending on the RHS type.
551 JS.Expression result; 558 JS.Expression result;
552 var type = node.type.type; 559 var type = node.type.type;
553 var lhs = _visit(node.expression); 560 var lhs = _visit(node.expression);
554 var typeofName = _jsTypeofName(type); 561 var typeofName = _jsTypeofName(type);
(...skipping 1158 matching lines...) Expand 10 before | Expand all | Expand 10 after
1713 } 1720 }
1714 } 1721 }
1715 1722
1716 // TODO(jmesserly): various problems here, see: 1723 // TODO(jmesserly): various problems here, see:
1717 // https://github.com/dart-lang/dev_compiler/issues/116 1724 // https://github.com/dart-lang/dev_compiler/issues/116
1718 var paramType = param.element.type; 1725 var paramType = param.element.type;
1719 if (node is MethodDeclaration && _unsoundCovariant(paramType, true)) { 1726 if (node is MethodDeclaration && _unsoundCovariant(paramType, true)) {
1720 var castType = _emitType(paramType, 1727 var castType = _emitType(paramType,
1721 nameType: options.nameTypeTests || options.hoistTypeTests, 1728 nameType: options.nameTypeTests || options.hoistTypeTests,
1722 hoistType: options.hoistTypeTests); 1729 hoistType: options.hoistTypeTests);
1723 body.add(js.statement('dart.as(#, #);', [jsParam, castType])); 1730 if (!_inAngularTemplate) {
1731 body.add(js.statement('dart.as(#, #);', [jsParam, castType]));
1732 }
1724 } 1733 }
1725 } 1734 }
1726 return body.isEmpty ? null : _statement(body); 1735 return body.isEmpty ? null : _statement(body);
1727 } 1736 }
1728 1737
1729 /// Given a type [t], return whether or not t is unsoundly covariant. 1738 /// Given a type [t], return whether or not t is unsoundly covariant.
1730 /// If [contravariant] is true, then t appears in a contravariant 1739 /// If [contravariant] is true, then t appears in a contravariant
1731 /// position. 1740 /// position.
1732 bool _unsoundCovariant(DartType t, bool contravariant) { 1741 bool _unsoundCovariant(DartType t, bool contravariant) {
1733 if (t is TypeParameterType) { 1742 if (t is TypeParameterType) {
(...skipping 776 matching lines...) Expand 10 before | Expand all | Expand 10 after
2510 } 2519 }
2511 2520
2512 target = _getTarget(lhs); 2521 target = _getTarget(lhs);
2513 id = lhs.propertyName; 2522 id = lhs.propertyName;
2514 } else if (lhs is PrefixedIdentifier) { 2523 } else if (lhs is PrefixedIdentifier) {
2515 target = lhs.prefix; 2524 target = lhs.prefix;
2516 id = lhs.identifier; 2525 id = lhs.identifier;
2517 } 2526 }
2518 2527
2519 if (target != null && DynamicInvoke.get(target)) { 2528 if (target != null && DynamicInvoke.get(target)) {
2529 if (_inAngularTemplate) {
2530 return _visit(rhs).toAssignExpression(_visit(lhs));
2531 }
2520 return js.call('dart.dput(#, #, #)', 2532 return js.call('dart.dput(#, #, #)',
2521 [_visit(target), _emitMemberName(id.name), _visit(rhs)]); 2533 [_visit(target), _emitMemberName(id.name), _visit(rhs)]);
2522 } 2534 }
2523 2535
2524 return _visit(rhs).toAssignExpression(_visit(lhs)); 2536 return _visit(rhs).toAssignExpression(_visit(lhs));
2525 } 2537 }
2526 2538
2527 JS.Expression _emitNullSafeSet(PropertyAccess node, Expression right) { 2539 JS.Expression _emitNullSafeSet(PropertyAccess node, Expression right) {
2528 // Emit `obj?.prop = expr` as: 2540 // Emit `obj?.prop = expr` as:
2529 // 2541 //
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
2640 List<JS.Expression> args, 2652 List<JS.Expression> args,
2641 List<JS.Expression> typeArgs) { 2653 List<JS.Expression> typeArgs) {
2642 var type = getStaticType(target); 2654 var type = getStaticType(target);
2643 var name = node.methodName.name; 2655 var name = node.methodName.name;
2644 var element = node.methodName.staticElement; 2656 var element = node.methodName.staticElement;
2645 bool isStatic = element is ExecutableElement && element.isStatic; 2657 bool isStatic = element is ExecutableElement && element.isStatic;
2646 var memberName = _emitMemberName(name, type: type, isStatic: isStatic); 2658 var memberName = _emitMemberName(name, type: type, isStatic: isStatic);
2647 2659
2648 JS.Expression jsTarget = _visit(target); 2660 JS.Expression jsTarget = _visit(target);
2649 if (DynamicInvoke.get(target) || DynamicInvoke.get(node.methodName)) { 2661 if (DynamicInvoke.get(target) || DynamicInvoke.get(node.methodName)) {
2662 if (_inAngularTemplate) {
2663 jsTarget = new JS.PropertyAccess(jsTarget, memberName);
2664 if (typeArgs != null) jsTarget = new JS.Call(jsTarget, typeArgs);
2665 return new JS.Call(jsTarget, args);
2666 }
2650 if (typeArgs != null) { 2667 if (typeArgs != null) {
2651 return js.call('dart.dgsend(#, #, #, #)', 2668 return js.call('dart.dgsend(#, #, #, #)',
2652 [jsTarget, new JS.ArrayInitializer(typeArgs), memberName, args]); 2669 [jsTarget, new JS.ArrayInitializer(typeArgs), memberName, args]);
2653 } else { 2670 } else {
2654 return js.call('dart.dsend(#, #, #)', [jsTarget, memberName, args]); 2671 return js.call('dart.dsend(#, #, #)', [jsTarget, memberName, args]);
2655 } 2672 }
2656 } 2673 }
2657 if (_isObjectMemberCall(target, name)) { 2674 if (_isObjectMemberCall(target, name)) {
2658 assert(typeArgs == null); // Object methods don't take type args. 2675 assert(typeArgs == null); // Object methods don't take type args.
2659 return js.call('dart.#(#, #)', [name, jsTarget, args]); 2676 return js.call('dart.#(#, #)', [name, jsTarget, args]);
2660 } 2677 }
2661 2678
2662 jsTarget = new JS.PropertyAccess(jsTarget, memberName); 2679 jsTarget = new JS.PropertyAccess(jsTarget, memberName);
2663 if (typeArgs != null) jsTarget = new JS.Call(jsTarget, typeArgs); 2680 if (typeArgs != null) jsTarget = new JS.Call(jsTarget, typeArgs);
2664 2681
2665 return new JS.Call(jsTarget, args); 2682 return new JS.Call(jsTarget, args);
2666 } 2683 }
2667 2684
2668 /// Emits a function call, to a top-level function, local function, or 2685 /// Emits a function call, to a top-level function, local function, or
2669 /// an expression. 2686 /// an expression.
2670 JS.Expression _emitFunctionCall(InvocationExpression node) { 2687 JS.Expression _emitFunctionCall(InvocationExpression node) {
2671 var fn = _visit(node.function); 2688 var fn = _visit(node.function);
2672 var args = _visit(node.argumentList); 2689 var args = _visit(node.argumentList);
2673 if (DynamicInvoke.get(node.function)) { 2690 if (DynamicInvoke.get(node.function)) {
2674 var typeArgs = _emitInvokeTypeArguments(node); 2691 var typeArgs = _emitInvokeTypeArguments(node);
2675 if (typeArgs != null) { 2692 if (typeArgs != null) {
2676 return js.call('dart.dgcall(#, #, #)', 2693 return js.call('dart.dgcall(#, #, #)',
2677 [fn, new JS.ArrayInitializer(typeArgs), args]); 2694 [fn, new JS.ArrayInitializer(typeArgs), args]);
2678 } else { 2695 } else {
2696 if (_inAngularTemplate) {
2697 return new JS.Call(fn, args);
2698 }
2679 return js.call('dart.dcall(#, #)', [fn, args]); 2699 return js.call('dart.dcall(#, #)', [fn, args]);
2680 } 2700 }
2681 } else { 2701 } else {
2682 return new JS.Call(_applyInvokeTypeArguments(fn, node), args); 2702 return new JS.Call(_applyInvokeTypeArguments(fn, node), args);
2683 } 2703 }
2684 } 2704 }
2685 2705
2686 JS.Expression _applyInvokeTypeArguments( 2706 JS.Expression _applyInvokeTypeArguments(
2687 JS.Expression target, InvocationExpression node) { 2707 JS.Expression target, InvocationExpression node) {
2688 var typeArgs = _emitInvokeTypeArguments(node); 2708 var typeArgs = _emitInvokeTypeArguments(node);
(...skipping 1158 matching lines...) Expand 10 before | Expand all | Expand 10 after
3847 if (type == null) return null; 3867 if (type == null) return null;
3848 return _emitFunctionTypeArguments(type, instantiated); 3868 return _emitFunctionTypeArguments(type, instantiated);
3849 } 3869 }
3850 3870
3851 JS.Expression _emitAccessInternal(Expression target, Element member, 3871 JS.Expression _emitAccessInternal(Expression target, Element member,
3852 String memberName, List<JS.Expression> typeArgs) { 3872 String memberName, List<JS.Expression> typeArgs) {
3853 bool isStatic = member is ClassMemberElement && member.isStatic; 3873 bool isStatic = member is ClassMemberElement && member.isStatic;
3854 var name = _emitMemberName(memberName, 3874 var name = _emitMemberName(memberName,
3855 type: getStaticType(target), isStatic: isStatic); 3875 type: getStaticType(target), isStatic: isStatic);
3856 if (DynamicInvoke.get(target)) { 3876 if (DynamicInvoke.get(target)) {
3877 if (_inAngularTemplate) {
3878 return js.call('#.#', [_visit(target), name]);
3879 }
3857 return js.call('dart.dload(#, #)', [_visit(target), name]); 3880 return js.call('dart.dload(#, #)', [_visit(target), name]);
3858 } 3881 }
3859 3882
3860 var jsTarget = _visit(target); 3883 var jsTarget = _visit(target);
3861 bool isSuper = jsTarget is JS.Super; 3884 bool isSuper = jsTarget is JS.Super;
3862 3885
3863 if (isSuper && member is FieldElement && !member.isSynthetic) { 3886 if (isSuper && member is FieldElement && !member.isSynthetic) {
3864 // If super.x is actually a field, then x is an instance property since 3887 // If super.x is actually a field, then x is an instance property since
3865 // subclasses cannot override x. 3888 // subclasses cannot override x.
3866 jsTarget = new JS.This(); 3889 jsTarget = new JS.This();
(...skipping 30 matching lines...) Expand all
3897 Expression target, String name, List<Expression> args) { 3920 Expression target, String name, List<Expression> args) {
3898 var type = getStaticType(target); 3921 var type = getStaticType(target);
3899 var memberName = _emitMemberName(name, unary: args.isEmpty, type: type); 3922 var memberName = _emitMemberName(name, unary: args.isEmpty, type: type);
3900 if (DynamicInvoke.get(target)) { 3923 if (DynamicInvoke.get(target)) {
3901 // dynamic dispatch 3924 // dynamic dispatch
3902 var dynamicHelper = const {'[]': 'dindex', '[]=': 'dsetindex'}[name]; 3925 var dynamicHelper = const {'[]': 'dindex', '[]=': 'dsetindex'}[name];
3903 if (dynamicHelper != null) { 3926 if (dynamicHelper != null) {
3904 return js.call( 3927 return js.call(
3905 'dart.$dynamicHelper(#, #)', [_visit(target), _visitList(args)]); 3928 'dart.$dynamicHelper(#, #)', [_visit(target), _visitList(args)]);
3906 } 3929 }
3907 return js.call('dart.dsend(#, #, #)', 3930 if (_inAngularTemplate) {
3908 [_visit(target), memberName, _visitList(args)]); 3931 return js
3932 .call('#.#(#)', [_visit(target), memberName, _visitList(args)]);
3933 } else {
3934 return js.call('dart.dsend(#, #, #)',
3935 [_visit(target), memberName, _visitList(args)]);
3936 }
3909 } 3937 }
3910 3938
3911 // Generic dispatch to a statically known method. 3939 // Generic dispatch to a statically known method.
3912 return js.call('#.#(#)', [_visit(target), memberName, _visitList(args)]); 3940 return js.call('#.#(#)', [_visit(target), memberName, _visitList(args)]);
3913 } 3941 }
3914 3942
3915 @override 3943 @override
3916 visitIndexExpression(IndexExpression node) { 3944 visitIndexExpression(IndexExpression node) {
3917 var target = _getTarget(node); 3945 var target = _getTarget(node);
3918 if (_useNativeJsIndexer(target.staticType)) { 3946 if (_useNativeJsIndexer(target.staticType)) {
(...skipping 713 matching lines...) Expand 10 before | Expand all | Expand 10 after
4632 } 4660 }
4633 4661
4634 bool isLibraryPrefix(Expression node) => 4662 bool isLibraryPrefix(Expression node) =>
4635 node is SimpleIdentifier && node.staticElement is PrefixElement; 4663 node is SimpleIdentifier && node.staticElement is PrefixElement;
4636 4664
4637 LibraryElement _getLibrary(AnalysisContext c, String uri) => 4665 LibraryElement _getLibrary(AnalysisContext c, String uri) =>
4638 c.computeLibraryElement(c.sourceFactory.forUri(uri)); 4666 c.computeLibraryElement(c.sourceFactory.forUri(uri));
4639 4667
4640 bool _isDartRuntime(LibraryElement l) => 4668 bool _isDartRuntime(LibraryElement l) =>
4641 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; 4669 l.isInSdk && l.source.uri.toString() == 'dart:_runtime';
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698