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

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

Issue 2928483002: fix #27255, remove angular whitelist hack (Closed)
Patch Set: rebase Created 3 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 | pkg/dev_compiler/lib/src/compiler/compiler.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 672 matching lines...) Expand 10 before | Expand all | Expand 10 after
683 } 683 }
684 } 684 }
685 685
686 @override 686 @override
687 visitAsExpression(AsExpression node) { 687 visitAsExpression(AsExpression node) {
688 Expression fromExpr = node.expression; 688 Expression fromExpr = node.expression;
689 var from = getStaticType(fromExpr); 689 var from = getStaticType(fromExpr);
690 var to = node.type.type; 690 var to = node.type.type;
691 691
692 JS.Expression jsFrom = _visit(fromExpr); 692 JS.Expression jsFrom = _visit(fromExpr);
693 if (_inWhitelistCode(node)) return jsFrom;
694 693
695 // Skip the cast if it's not needed. 694 // Skip the cast if it's not needed.
696 if (rules.isSubtypeOf(from, to)) return jsFrom; 695 if (rules.isSubtypeOf(from, to)) return jsFrom;
697 696
698 // All Dart number types map to a JS double. 697 // All Dart number types map to a JS double.
699 if (_isNumberInJS(from) && _isNumberInJS(to)) { 698 if (_isNumberInJS(from) && _isNumberInJS(to)) {
700 // Make sure to check when converting to int. 699 // Make sure to check when converting to int.
701 if (from != types.intType && to == types.intType) { 700 if (from != types.intType && to == types.intType) {
702 // TODO(jmesserly): fuse this with notNull check. 701 // TODO(jmesserly): fuse this with notNull check.
703 return _callHelper('asInt(#)', jsFrom); 702 return _callHelper('asInt(#)', jsFrom);
(...skipping 1667 matching lines...) Expand 10 before | Expand all | Expand 10 after
2371 [jsParam, jsParam, _defaultParamValue(param)])); 2370 [jsParam, jsParam, _defaultParamValue(param)]));
2372 } 2371 }
2373 } 2372 }
2374 2373
2375 // TODO(jmesserly): various problems here, see: 2374 // TODO(jmesserly): various problems here, see:
2376 // https://github.com/dart-lang/sdk/issues/27259 2375 // https://github.com/dart-lang/sdk/issues/27259
2377 var paramType = 2376 var paramType =
2378 resolutionMap.elementDeclaredByFormalParameter(param).type; 2377 resolutionMap.elementDeclaredByFormalParameter(param).type;
2379 if (node is MethodDeclaration && 2378 if (node is MethodDeclaration &&
2380 (resolutionMap.elementDeclaredByFormalParameter(param).isCovariant || 2379 (resolutionMap.elementDeclaredByFormalParameter(param).isCovariant ||
2381 _unsoundCovariant(paramType, true)) && 2380 _unsoundCovariant(paramType, true))) {
2382 !_inWhitelistCode(node)) {
2383 var castType = _emitType(paramType, 2381 var castType = _emitType(paramType,
2384 nameType: options.nameTypeTests || options.hoistTypeTests, 2382 nameType: options.nameTypeTests || options.hoistTypeTests,
2385 hoistType: options.hoistTypeTests); 2383 hoistType: options.hoistTypeTests);
2386 body.add(js.statement('#._check(#);', [castType, jsParam])); 2384 body.add(js.statement('#._check(#);', [castType, jsParam]));
2387 } 2385 }
2388 } 2386 }
2389 return body.isEmpty ? null : _statement(body); 2387 return body.isEmpty ? null : _statement(body);
2390 } 2388 }
2391 2389
2392 /// Given a type [t], return whether or not t is unsoundly covariant. 2390 /// Given a type [t], return whether or not t is unsoundly covariant.
(...skipping 894 matching lines...) Expand 10 before | Expand all | Expand 10 after
3287 assert(false); 3285 assert(false);
3288 } 3286 }
3289 3287
3290 assert(target != null); 3288 assert(target != null);
3291 3289
3292 if (target is SuperExpression) { 3290 if (target is SuperExpression) {
3293 return _emitSetSuper(lhs, target, id, rhs); 3291 return _emitSetSuper(lhs, target, id, rhs);
3294 } 3292 }
3295 3293
3296 if (target != null && isDynamicInvoke(target)) { 3294 if (target != null && isDynamicInvoke(target)) {
3297 if (_inWhitelistCode(lhs)) {
3298 var vars = <JS.MetaLetVariable, JS.Expression>{};
3299 var l = _visit(_bindValue(vars, 'l', target));
3300 var name = _emitMemberName(id.name);
3301 return new JS.MetaLet(vars, [
3302 js.call('(#[(#[#._extensionType]) ? #[#] : #] = #)', [
3303 l,
3304 l,
3305 _runtimeModule,
3306 _extensionSymbolsModule,
3307 name,
3308 name,
3309 _visit(rhs)
3310 ])
3311 ]);
3312 }
3313 return _callHelper('#(#, #, #)', [ 3295 return _callHelper('#(#, #, #)', [
3314 _emitDynamicOperationName('dput'), 3296 _emitDynamicOperationName('dput'),
3315 _visit(target), 3297 _visit(target),
3316 _emitMemberName(id.name), 3298 _emitMemberName(id.name),
3317 _visit(rhs) 3299 _visit(rhs)
3318 ]); 3300 ]);
3319 } 3301 }
3320 3302
3321 var accessor = id.staticElement; 3303 var accessor = id.staticElement;
3322 var element = 3304 var element =
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after
3610 List<JS.Expression> typeArgs) { 3592 List<JS.Expression> typeArgs) {
3611 var type = getStaticType(target); 3593 var type = getStaticType(target);
3612 var element = node.methodName.staticElement; 3594 var element = node.methodName.staticElement;
3613 bool isStatic = element is ExecutableElement && element.isStatic; 3595 bool isStatic = element is ExecutableElement && element.isStatic;
3614 var name = node.methodName.name; 3596 var name = node.methodName.name;
3615 var memberName = 3597 var memberName =
3616 _emitMemberName(name, type: type, isStatic: isStatic, element: element); 3598 _emitMemberName(name, type: type, isStatic: isStatic, element: element);
3617 3599
3618 JS.Expression jsTarget = _emitTarget(target, element, isStatic); 3600 JS.Expression jsTarget = _emitTarget(target, element, isStatic);
3619 if (isDynamicInvoke(target) || isDynamicInvoke(node.methodName)) { 3601 if (isDynamicInvoke(target) || isDynamicInvoke(node.methodName)) {
3620 if (_inWhitelistCode(target)) {
3621 var vars = <JS.MetaLetVariable, JS.Expression>{};
3622 var l = _visit(_bindValue(vars, 'l', target));
3623 jsTarget = new JS.MetaLet(vars, [
3624 js.call('(#[(#[#._extensionType]) ? #[#] : #]).bind(#)', [
3625 l,
3626 l,
3627 _runtimeModule,
3628 _extensionSymbolsModule,
3629 memberName,
3630 memberName,
3631 l
3632 ])
3633 ]);
3634 if (typeArgs != null) jsTarget = new JS.Call(jsTarget, typeArgs);
3635 return new JS.Call(jsTarget, args);
3636 }
3637 if (typeArgs != null) { 3602 if (typeArgs != null) {
3638 return _callHelper('#(#, #, #, #)', [ 3603 return _callHelper('#(#, #, #, #)', [
3639 _emitDynamicOperationName('dgsend'), 3604 _emitDynamicOperationName('dgsend'),
3640 jsTarget, 3605 jsTarget,
3641 new JS.ArrayInitializer(typeArgs), 3606 new JS.ArrayInitializer(typeArgs),
3642 memberName, 3607 memberName,
3643 args 3608 args
3644 ]); 3609 ]);
3645 } else { 3610 } else {
3646 return _callHelper('#(#, #, #)', 3611 return _callHelper('#(#, #, #)',
(...skipping 11 matching lines...) Expand all
3658 return new JS.Call(jsTarget, args); 3623 return new JS.Call(jsTarget, args);
3659 } 3624 }
3660 3625
3661 JS.Expression _emitDynamicInvoke( 3626 JS.Expression _emitDynamicInvoke(
3662 InvocationExpression node, JS.Expression fn, List<JS.Expression> args) { 3627 InvocationExpression node, JS.Expression fn, List<JS.Expression> args) {
3663 var typeArgs = _emitInvokeTypeArguments(node); 3628 var typeArgs = _emitInvokeTypeArguments(node);
3664 if (typeArgs != null) { 3629 if (typeArgs != null) {
3665 return _callHelper( 3630 return _callHelper(
3666 'dgcall(#, #, #)', [fn, new JS.ArrayInitializer(typeArgs), args]); 3631 'dgcall(#, #, #)', [fn, new JS.ArrayInitializer(typeArgs), args]);
3667 } else { 3632 } else {
3668 if (_inWhitelistCode(node, isCall: true)) {
3669 return new JS.Call(fn, args);
3670 }
3671 return _callHelper('dcall(#, #)', [fn, args]); 3633 return _callHelper('dcall(#, #)', [fn, args]);
3672 } 3634 }
3673 } 3635 }
3674 3636
3675 /// Emits a function call, to a top-level function, local function, or 3637 /// Emits a function call, to a top-level function, local function, or
3676 /// an expression. 3638 /// an expression.
3677 JS.Expression _emitFunctionCall(InvocationExpression node, 3639 JS.Expression _emitFunctionCall(InvocationExpression node,
3678 [Expression function]) { 3640 [Expression function]) {
3679 if (function == null) { 3641 if (function == null) {
3680 function = node.function; 3642 function = node.function;
(...skipping 1284 matching lines...) Expand 10 before | Expand all | Expand 10 after
4965 4927
4966 JS.LiteralString _emitDynamicOperationName(String name) => 4928 JS.LiteralString _emitDynamicOperationName(String name) =>
4967 js.string(options.replCompile ? '${name}Repl' : name); 4929 js.string(options.replCompile ? '${name}Repl' : name);
4968 4930
4969 JS.Expression _emitAccessInternal(Expression target, Element member, 4931 JS.Expression _emitAccessInternal(Expression target, Element member,
4970 String memberName, List<JS.Expression> typeArgs) { 4932 String memberName, List<JS.Expression> typeArgs) {
4971 bool isStatic = member is ClassMemberElement && member.isStatic; 4933 bool isStatic = member is ClassMemberElement && member.isStatic;
4972 var name = _emitMemberName(memberName, 4934 var name = _emitMemberName(memberName,
4973 type: getStaticType(target), isStatic: isStatic, element: member); 4935 type: getStaticType(target), isStatic: isStatic, element: member);
4974 if (isDynamicInvoke(target)) { 4936 if (isDynamicInvoke(target)) {
4975 if (_inWhitelistCode(target)) {
4976 var vars = <JS.MetaLetVariable, JS.Expression>{};
4977 var l = _visit(_bindValue(vars, 'l', target));
4978 return new JS.MetaLet(vars, [
4979 js.call('(#[#._extensionType]) ? #[#[#]] : #.#',
4980 [l, _runtimeModule, l, _extensionSymbolsModule, name, l, name])
4981 ]);
4982 }
4983 return _callHelper('#(#, #)', 4937 return _callHelper('#(#, #)',
4984 [_emitDynamicOperationName('dload'), _visit(target), name]); 4938 [_emitDynamicOperationName('dload'), _visit(target), name]);
4985 } 4939 }
4986 4940
4987 var jsTarget = _emitTarget(target, member, isStatic); 4941 var jsTarget = _emitTarget(target, member, isStatic);
4988 bool isSuper = jsTarget is JS.Super; 4942 bool isSuper = jsTarget is JS.Super;
4989 if (isSuper && 4943 if (isSuper &&
4990 !member.isSynthetic && 4944 !member.isSynthetic &&
4991 member is FieldElementImpl && 4945 member is FieldElementImpl &&
4992 !virtualFields.isVirtual(member)) { 4946 !virtualFields.isVirtual(member)) {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
5029 /// Emits a generic send, like an operator method. 4983 /// Emits a generic send, like an operator method.
5030 /// 4984 ///
5031 /// **Please note** this function does not support method invocation syntax 4985 /// **Please note** this function does not support method invocation syntax
5032 /// `obj.name(args)` because that could be a getter followed by a call. 4986 /// `obj.name(args)` because that could be a getter followed by a call.
5033 /// See [visitMethodInvocation]. 4987 /// See [visitMethodInvocation].
5034 JS.Expression _emitSend( 4988 JS.Expression _emitSend(
5035 Expression target, String name, List<Expression> args) { 4989 Expression target, String name, List<Expression> args) {
5036 var type = getStaticType(target); 4990 var type = getStaticType(target);
5037 var memberName = _emitMemberName(name, type: type); 4991 var memberName = _emitMemberName(name, type: type);
5038 if (isDynamicInvoke(target)) { 4992 if (isDynamicInvoke(target)) {
5039 if (_inWhitelistCode(target)) {
5040 var vars = <JS.MetaLetVariable, JS.Expression>{};
5041 var l = _visit(_bindValue(vars, 'l', target));
5042 return new JS.MetaLet(vars, [
5043 js.call('(#[(#[#._extensionType]) ? #[#] : #]).call(#, #)', [
5044 l,
5045 l,
5046 _runtimeModule,
5047 _extensionSymbolsModule,
5048 memberName,
5049 memberName,
5050 l,
5051 _visitList(args)
5052 ])
5053 ]);
5054 }
5055 // dynamic dispatch 4993 // dynamic dispatch
5056 var dynamicHelper = const {'[]': 'dindex', '[]=': 'dsetindex'}[name]; 4994 var dynamicHelper = const {'[]': 'dindex', '[]=': 'dsetindex'}[name];
5057 if (dynamicHelper != null) { 4995 if (dynamicHelper != null) {
5058 return _callHelper('$dynamicHelper(#, #)', 4996 return _callHelper('$dynamicHelper(#, #)',
5059 [_visit(target) as JS.Expression, _visitList(args)]); 4997 [_visit(target) as JS.Expression, _visitList(args)]);
5060 } else { 4998 } else {
5061 return _callHelper( 4999 return _callHelper(
5062 'dsend(#, #, #)', [_visit(target), memberName, _visitList(args)]); 5000 'dsend(#, #, #)', [_visit(target), memberName, _visitList(args)]);
5063 } 5001 }
5064 } 5002 }
(...skipping 765 matching lines...) Expand 10 before | Expand all | Expand 10 after
5830 5768
5831 JS.Statement _callHelperStatement(String code, args) { 5769 JS.Statement _callHelperStatement(String code, args) {
5832 if (args is List) { 5770 if (args is List) {
5833 args.insert(0, _runtimeModule); 5771 args.insert(0, _runtimeModule);
5834 } else { 5772 } else {
5835 args = [_runtimeModule, args]; 5773 args = [_runtimeModule, args];
5836 } 5774 }
5837 return js.statement('#.$code', args); 5775 return js.statement('#.$code', args);
5838 } 5776 }
5839 5777
5840 // TODO(kevmoo): https://github.com/dart-lang/sdk/issues/27255
5841 // TODO(kevmoo): Remove once pkg/angular2 has moved to the new compiler
5842 // See https://github.com/dart-lang/angular2/issues/48
5843 /// Temporary workaround *cough* total hack *cough*.
5844 ///
5845 /// Maps whitelisted files to a list of whitelisted methods
5846 /// within the file.
5847 ///
5848 /// If the value is null, the entire file is whitelisted.
5849 ///
5850 static const Map<String, List<String>> _uncheckedWhitelist = const {
5851 'dom_renderer.dart': const ['moveNodesAfterSibling'],
5852 'template_ref.dart': const ['createEmbeddedView'],
5853 'ng_class.dart': const ['_applyIterableChanges'],
5854 'ng_for.dart': const ['_bulkRemove', '_bulkInsert'],
5855 'view_container_ref.dart': const ['createEmbeddedView'],
5856 'default_iterable_differ.dart': null,
5857 };
5858
5859 static Set<String> _uncheckedWhitelistCalls = new Set()
5860 ..add('ng_zone_impl.dart')
5861 ..add('stack_zone_specification.dart')
5862 ..add('view_manager.dart')
5863 ..add('view.dart');
5864
5865 bool _inWhitelistCode(AstNode node, {isCall: false}) {
5866 if (!options.useAngular2Whitelist) return false;
5867 var path = currentElement.source.fullName;
5868 var filename = path.split("/").last;
5869 if (_uncheckedWhitelist.containsKey(filename)) {
5870 var whitelisted = _uncheckedWhitelist[filename];
5871 if (whitelisted == null) return true;
5872 var enclosing = node;
5873 while (enclosing != null &&
5874 !(enclosing is ClassMember || enclosing is FunctionDeclaration)) {
5875 enclosing = enclosing.parent;
5876 }
5877 String name = (enclosing as dynamic)?.element?.name;
5878 if (name != null) {
5879 return whitelisted.contains(name);
5880 }
5881 }
5882
5883 // Dynamic calls are less risky so there is no need to whitelist at the
5884 // method level.
5885 if (isCall && _uncheckedWhitelistCalls.contains(filename)) return true;
5886
5887 return path.endsWith(".template.dart");
5888 }
5889
5890 _unreachable(AstNode node) { 5778 _unreachable(AstNode node) {
5891 throw new UnsupportedError( 5779 throw new UnsupportedError(
5892 'tried to generate an unreachable node: `$node`'); 5780 'tried to generate an unreachable node: `$node`');
5893 } 5781 }
5894 5782
5895 /// Unused, see methods for emitting declarations. 5783 /// Unused, see methods for emitting declarations.
5896 @override 5784 @override
5897 visitAnnotation(node) => _unreachable(node); 5785 visitAnnotation(node) => _unreachable(node);
5898 5786
5899 /// Unused, see [_emitArgumentList]. 5787 /// Unused, see [_emitArgumentList].
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
6103 if (targetIdentifier.staticElement is! PrefixElement) return false; 5991 if (targetIdentifier.staticElement is! PrefixElement) return false;
6104 var prefix = targetIdentifier.staticElement as PrefixElement; 5992 var prefix = targetIdentifier.staticElement as PrefixElement;
6105 5993
6106 // The library the prefix is referring to must come from a deferred import. 5994 // The library the prefix is referring to must come from a deferred import.
6107 var containingLibrary = resolutionMap 5995 var containingLibrary = resolutionMap
6108 .elementDeclaredByCompilationUnit(target.root as CompilationUnit) 5996 .elementDeclaredByCompilationUnit(target.root as CompilationUnit)
6109 .library; 5997 .library;
6110 var imports = containingLibrary.getImportsWithPrefix(prefix); 5998 var imports = containingLibrary.getImportsWithPrefix(prefix);
6111 return imports.length == 1 && imports[0].isDeferred; 5999 return imports.length == 1 && imports[0].isDeferred;
6112 } 6000 }
OLDNEW
« no previous file with comments | « no previous file | pkg/dev_compiler/lib/src/compiler/compiler.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698