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

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

Issue 2021553002: Make whitelist check per element (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 | lib/src/compiler/compiler.dart » ('j') | lib/src/compiler/compiler.dart » ('J')
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
131 List<JS.TemporaryId> _superHelperSymbols = <JS.TemporaryId>[]; 129 List<JS.TemporaryId> _superHelperSymbols = <JS.TemporaryId>[];
132 List<JS.Method> _superHelpers = <JS.Method>[]; 130 List<JS.Method> _superHelpers = <JS.Method>[];
133 131
134 List<TypeParameterType> _typeParamInConst = null; 132 List<TypeParameterType> _typeParamInConst = null;
135 133
136 /// Whether we are currently generating code for the body of a `JS()` call. 134 /// Whether we are currently generating code for the body of a `JS()` call.
137 bool _isInForeignJS = false; 135 bool _isInForeignJS = false;
138 136
139 CodeGenerator(AnalysisContext c, this.options, this._extensionTypes) 137 CodeGenerator(AnalysisContext c, this.options, this._extensionTypes)
140 : context = c, 138 : context = c,
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after
419 417
420 if (item != null) _moduleItems.add(item); 418 if (item != null) _moduleItems.add(item);
421 } 419 }
422 420
423 void _declareBeforeUse(Element e) { 421 void _declareBeforeUse(Element e) {
424 _loader.declareBeforeUse(e, _emitDeclaration); 422 _loader.declareBeforeUse(e, _emitDeclaration);
425 } 423 }
426 424
427 @override 425 @override
428 void visitCompilationUnit(CompilationUnit unit) { 426 void visitCompilationUnit(CompilationUnit unit) {
429 _inAngularTemplate =
430 unit.element.source.fullName.endsWith(".template.dart");
431
432 _constField = new ConstFieldVisitor(types, unit.element.source); 427 _constField = new ConstFieldVisitor(types, unit.element.source);
433 428
434 for (var declaration in unit.declarations) { 429 for (var declaration in unit.declarations) {
435 var element = declaration.element; 430 var element = declaration.element;
436 if (element != null) { 431 if (element != null) {
437 _emitDeclaration(element); 432 _emitDeclaration(element);
438 } else { 433 } else {
439 declaration.accept(this); 434 declaration.accept(this);
440 } 435 }
441 } 436 }
442 for (var directive in unit.directives) { 437 for (var directive in unit.directives) {
443 directive.accept(this); 438 directive.accept(this);
444 } 439 }
445 _inAngularTemplate = false;
446 } 440 }
447 441
448 @override 442 @override
449 void visitLibraryDirective(LibraryDirective node) {} 443 void visitLibraryDirective(LibraryDirective node) {}
450 444
451 @override 445 @override
452 void visitImportDirective(ImportDirective node) { 446 void visitImportDirective(ImportDirective node) {
453 // We don't handle imports here. 447 // We don't handle imports here.
454 // 448 //
455 // Instead, we collect imports whenever we need to generate a reference 449 // Instead, we collect imports whenever we need to generate a reference
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
541 return js.call('dart.asInt(#)', jsFrom); 535 return js.call('dart.asInt(#)', jsFrom);
542 } 536 }
543 537
544 // A no-op in JavaScript. 538 // A no-op in JavaScript.
545 return jsFrom; 539 return jsFrom;
546 } 540 }
547 541
548 var type = _emitType(to, 542 var type = _emitType(to,
549 nameType: options.nameTypeTests || options.hoistTypeTests, 543 nameType: options.nameTypeTests || options.hoistTypeTests,
550 hoistType: options.hoistTypeTests); 544 hoistType: options.hoistTypeTests);
551 if (_inAngularTemplate) return jsFrom; 545 if (_inWhitelistCode(node)) return jsFrom;
552 if (isReifiedCoercion(node)) { 546 if (isReifiedCoercion(node)) {
553 return js.call('dart.check(#, #)', [jsFrom, type]); 547 return js.call('dart.check(#, #)', [jsFrom, type]);
554 } else { 548 } else {
555 return js.call('dart.as(#, #)', [jsFrom, type]); 549 return js.call('dart.as(#, #)', [jsFrom, type]);
556 } 550 }
557 } 551 }
558 552
559 bool isReifiedCoercion(AstNode node) { 553 bool isReifiedCoercion(AstNode node) {
560 // TODO(sra): Find a better way to recognize reified coercion, since we 554 // TODO(sra): Find a better way to recognize reified coercion, since we
561 // can't set the isSynthetic attribute. 555 // can't set the isSynthetic attribute.
(...skipping 1168 matching lines...) Expand 10 before | Expand all | Expand 10 after
1730 } 1724 }
1731 } 1725 }
1732 1726
1733 // TODO(jmesserly): various problems here, see: 1727 // TODO(jmesserly): various problems here, see:
1734 // https://github.com/dart-lang/dev_compiler/issues/116 1728 // https://github.com/dart-lang/dev_compiler/issues/116
1735 var paramType = param.element.type; 1729 var paramType = param.element.type;
1736 if (node is MethodDeclaration && _unsoundCovariant(paramType, true)) { 1730 if (node is MethodDeclaration && _unsoundCovariant(paramType, true)) {
1737 var castType = _emitType(paramType, 1731 var castType = _emitType(paramType,
1738 nameType: options.nameTypeTests || options.hoistTypeTests, 1732 nameType: options.nameTypeTests || options.hoistTypeTests,
1739 hoistType: options.hoistTypeTests); 1733 hoistType: options.hoistTypeTests);
1740 if (!_inAngularTemplate) { 1734 if (!_inWhitelistCode(node)) {
1741 body.add(js.statement('dart.as(#, #);', [jsParam, castType])); 1735 body.add(js.statement('dart.as(#, #);', [jsParam, castType]));
1742 } 1736 }
1743 } 1737 }
1744 } 1738 }
1745 return body.isEmpty ? null : _statement(body); 1739 return body.isEmpty ? null : _statement(body);
1746 } 1740 }
1747 1741
1748 /// Given a type [t], return whether or not t is unsoundly covariant. 1742 /// Given a type [t], return whether or not t is unsoundly covariant.
1749 /// If [contravariant] is true, then t appears in a contravariant 1743 /// If [contravariant] is true, then t appears in a contravariant
1750 /// position. 1744 /// position.
(...skipping 779 matching lines...) Expand 10 before | Expand all | Expand 10 after
2530 } 2524 }
2531 2525
2532 target = _getTarget(lhs); 2526 target = _getTarget(lhs);
2533 id = lhs.propertyName; 2527 id = lhs.propertyName;
2534 } else if (lhs is PrefixedIdentifier) { 2528 } else if (lhs is PrefixedIdentifier) {
2535 target = lhs.prefix; 2529 target = lhs.prefix;
2536 id = lhs.identifier; 2530 id = lhs.identifier;
2537 } 2531 }
2538 2532
2539 if (target != null && DynamicInvoke.get(target)) { 2533 if (target != null && DynamicInvoke.get(target)) {
2540 if (_inAngularTemplate) { 2534 if (_inWhitelistCode(lhs)) {
2541 return _visit(rhs).toAssignExpression(_visit(lhs)); 2535 return _visit(rhs).toAssignExpression(_visit(lhs));
2542 } 2536 }
2543 return js.call('dart.dput(#, #, #)', 2537 return js.call('dart.dput(#, #, #)',
2544 [_visit(target), _emitMemberName(id.name), _visit(rhs)]); 2538 [_visit(target), _emitMemberName(id.name), _visit(rhs)]);
2545 } 2539 }
2546 2540
2547 return _visit(rhs).toAssignExpression(_visit(lhs)); 2541 return _visit(rhs).toAssignExpression(_visit(lhs));
2548 } 2542 }
2549 2543
2550 JS.Expression _emitNullSafeSet(PropertyAccess node, Expression right) { 2544 JS.Expression _emitNullSafeSet(PropertyAccess node, Expression right) {
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
2663 List<JS.Expression> args, 2657 List<JS.Expression> args,
2664 List<JS.Expression> typeArgs) { 2658 List<JS.Expression> typeArgs) {
2665 var type = getStaticType(target); 2659 var type = getStaticType(target);
2666 var name = node.methodName.name; 2660 var name = node.methodName.name;
2667 var element = node.methodName.staticElement; 2661 var element = node.methodName.staticElement;
2668 bool isStatic = element is ExecutableElement && element.isStatic; 2662 bool isStatic = element is ExecutableElement && element.isStatic;
2669 var memberName = _emitMemberName(name, type: type, isStatic: isStatic); 2663 var memberName = _emitMemberName(name, type: type, isStatic: isStatic);
2670 2664
2671 JS.Expression jsTarget = _visit(target); 2665 JS.Expression jsTarget = _visit(target);
2672 if (DynamicInvoke.get(target) || DynamicInvoke.get(node.methodName)) { 2666 if (DynamicInvoke.get(target) || DynamicInvoke.get(node.methodName)) {
2673 if (_inAngularTemplate) { 2667 if (_inWhitelistCode(target)) {
2674 jsTarget = new JS.PropertyAccess(jsTarget, memberName); 2668 jsTarget = new JS.PropertyAccess(jsTarget, memberName);
2675 if (typeArgs != null) jsTarget = new JS.Call(jsTarget, typeArgs); 2669 if (typeArgs != null) jsTarget = new JS.Call(jsTarget, typeArgs);
2676 return new JS.Call(jsTarget, args); 2670 return new JS.Call(jsTarget, args);
2677 } 2671 }
2678 if (typeArgs != null) { 2672 if (typeArgs != null) {
2679 return js.call('dart.dgsend(#, #, #, #)', 2673 return js.call('dart.dgsend(#, #, #, #)',
2680 [jsTarget, new JS.ArrayInitializer(typeArgs), memberName, args]); 2674 [jsTarget, new JS.ArrayInitializer(typeArgs), memberName, args]);
2681 } else { 2675 } else {
2682 return js.call('dart.dsend(#, #, #)', [jsTarget, memberName, args]); 2676 return js.call('dart.dsend(#, #, #)', [jsTarget, memberName, args]);
2683 } 2677 }
(...skipping 13 matching lines...) Expand all
2697 /// an expression. 2691 /// an expression.
2698 JS.Expression _emitFunctionCall(InvocationExpression node) { 2692 JS.Expression _emitFunctionCall(InvocationExpression node) {
2699 var fn = _visit(node.function); 2693 var fn = _visit(node.function);
2700 var args = _visit(node.argumentList) as List<JS.Expression>; 2694 var args = _visit(node.argumentList) as List<JS.Expression>;
2701 if (DynamicInvoke.get(node.function)) { 2695 if (DynamicInvoke.get(node.function)) {
2702 var typeArgs = _emitInvokeTypeArguments(node); 2696 var typeArgs = _emitInvokeTypeArguments(node);
2703 if (typeArgs != null) { 2697 if (typeArgs != null) {
2704 return js.call('dart.dgcall(#, #, #)', 2698 return js.call('dart.dgcall(#, #, #)',
2705 [fn, new JS.ArrayInitializer(typeArgs), args]); 2699 [fn, new JS.ArrayInitializer(typeArgs), args]);
2706 } else { 2700 } else {
2707 if (_inAngularTemplate) { 2701 if (_inWhitelistCode(node)) {
2708 return new JS.Call(fn, args); 2702 return new JS.Call(fn, args);
2709 } 2703 }
2710 return js.call('dart.dcall(#, #)', [fn, args]); 2704 return js.call('dart.dcall(#, #)', [fn, args]);
2711 } 2705 }
2712 } else { 2706 } else {
2713 return new JS.Call(_applyInvokeTypeArguments(fn, node), args); 2707 return new JS.Call(_applyInvokeTypeArguments(fn, node), args);
2714 } 2708 }
2715 } 2709 }
2716 2710
2717 JS.Expression _applyInvokeTypeArguments( 2711 JS.Expression _applyInvokeTypeArguments(
(...skipping 1160 matching lines...) Expand 10 before | Expand all | Expand 10 after
3878 if (type == null) return null; 3872 if (type == null) return null;
3879 return _emitFunctionTypeArguments(type, instantiated); 3873 return _emitFunctionTypeArguments(type, instantiated);
3880 } 3874 }
3881 3875
3882 JS.Expression _emitAccessInternal(Expression target, Element member, 3876 JS.Expression _emitAccessInternal(Expression target, Element member,
3883 String memberName, List<JS.Expression> typeArgs) { 3877 String memberName, List<JS.Expression> typeArgs) {
3884 bool isStatic = member is ClassMemberElement && member.isStatic; 3878 bool isStatic = member is ClassMemberElement && member.isStatic;
3885 var name = _emitMemberName(memberName, 3879 var name = _emitMemberName(memberName,
3886 type: getStaticType(target), isStatic: isStatic); 3880 type: getStaticType(target), isStatic: isStatic);
3887 if (DynamicInvoke.get(target)) { 3881 if (DynamicInvoke.get(target)) {
3888 if (_inAngularTemplate) { 3882 if (_inWhitelistCode(target)) {
3889 return js.call('#.#', [_visit(target), name]); 3883 return js.call('#.#', [_visit(target), name]);
3890 } 3884 }
3891 return js.call('dart.dload(#, #)', [_visit(target), name]); 3885 return js.call('dart.dload(#, #)', [_visit(target), name]);
3892 } 3886 }
3893 3887
3894 var jsTarget = _visit(target); 3888 var jsTarget = _visit(target);
3895 bool isSuper = jsTarget is JS.Super; 3889 bool isSuper = jsTarget is JS.Super;
3896 3890
3897 if (isSuper && member is FieldElement && !member.isSynthetic) { 3891 if (isSuper && member is FieldElement && !member.isSynthetic) {
3898 // If super.x is actually a field, then x is an instance property since 3892 // If super.x is actually a field, then x is an instance property since
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
3931 Expression target, String name, List<Expression> args) { 3925 Expression target, String name, List<Expression> args) {
3932 var type = getStaticType(target); 3926 var type = getStaticType(target);
3933 var memberName = _emitMemberName(name, unary: args.isEmpty, type: type); 3927 var memberName = _emitMemberName(name, unary: args.isEmpty, type: type);
3934 if (DynamicInvoke.get(target)) { 3928 if (DynamicInvoke.get(target)) {
3935 // dynamic dispatch 3929 // dynamic dispatch
3936 var dynamicHelper = const {'[]': 'dindex', '[]=': 'dsetindex'}[name]; 3930 var dynamicHelper = const {'[]': 'dindex', '[]=': 'dsetindex'}[name];
3937 if (dynamicHelper != null) { 3931 if (dynamicHelper != null) {
3938 return js.call( 3932 return js.call(
3939 'dart.$dynamicHelper(#, #)', [_visit(target), _visitList(args)]); 3933 'dart.$dynamicHelper(#, #)', [_visit(target), _visitList(args)]);
3940 } 3934 }
3941 if (_inAngularTemplate) { 3935 if (_inWhitelistCode(target)) {
3942 return js 3936 return js
3943 .call('#.#(#)', [_visit(target), memberName, _visitList(args)]); 3937 .call('#.#(#)', [_visit(target), memberName, _visitList(args)]);
3944 } else { 3938 } else {
3945 return js.call('dart.dsend(#, #, #)', 3939 return js.call('dart.dsend(#, #, #)',
3946 [_visit(target), memberName, _visitList(args)]); 3940 [_visit(target), memberName, _visitList(args)]);
3947 } 3941 }
3948 } 3942 }
3949 3943
3950 // Generic dispatch to a statically known method. 3944 // Generic dispatch to a statically known method.
3951 return js.call('#.#(#)', [_visit(target), memberName, _visitList(args)]); 3945 return js.call('#.#(#)', [_visit(target), memberName, _visitList(args)]);
(...skipping 661 matching lines...) Expand 10 before | Expand all | Expand 10 after
4613 if (type.isDynamic) { 4607 if (type.isDynamic) {
4614 return type; 4608 return type;
4615 } else if (type is InterfaceType && type.element == expectedType.element) { 4609 } else if (type is InterfaceType && type.element == expectedType.element) {
4616 return type.typeArguments[0]; 4610 return type.typeArguments[0];
4617 } else { 4611 } else {
4618 // TODO(leafp): The above only handles the case where the return type 4612 // TODO(leafp): The above only handles the case where the return type
4619 // is exactly Future/Stream/Iterable. Handle the subtype case. 4613 // is exactly Future/Stream/Iterable. Handle the subtype case.
4620 return DynamicTypeImpl.instance; 4614 return DynamicTypeImpl.instance;
4621 } 4615 }
4622 } 4616 }
4617
4618 /// Maps whitelisted files to a list of whitelisted methods
4619 /// within the file.
4620 ///
4621 /// If the value is null, the entire file is whitelisted.
4622 static Map<String, List<String>> _uncheckedWhitelist = {};
4623
4624 bool _inWhitelistCode(AstNode node) {
4625 if (!options.useUncheckedWhitelist) return false;
4626 var path = _loader.currentElement.source.fullName;
4627 var filename = path.split("/").last;
4628 if (_uncheckedWhitelist.containsKey(filename)) {
4629 var whitelisted = _uncheckedWhitelist[filename];
4630 if (whitelisted == null) return true;
4631 var enclosing = node;
4632 while (enclosing != null &&
4633 !(enclosing is ClassMember || enclosing is FunctionDeclaration)) {
4634 enclosing = enclosing.parent;
4635 }
4636 String name = (enclosing as dynamic)?.element?.name;
4637 if (name != null) {
4638 return whitelisted.contains(name);
4639 }
4640 }
4641 return path.endsWith(".template.dart");
4642 }
4623 } 4643 }
4624 4644
4625 /// Choose a canonical name from the library element. 4645 /// Choose a canonical name from the library element.
4626 /// This never uses the library's name (the identifier in the `library` 4646 /// This never uses the library's name (the identifier in the `library`
4627 /// declaration) as it doesn't have any meaningful rules enforced. 4647 /// declaration) as it doesn't have any meaningful rules enforced.
4628 String jsLibraryName(String buildRoot, LibraryElement library) { 4648 String jsLibraryName(String buildRoot, LibraryElement library) {
4629 var uri = library.source.uri; 4649 var uri = library.source.uri;
4630 if (uri.scheme == 'dart') { 4650 if (uri.scheme == 'dart') {
4631 return uri.path; 4651 return uri.path;
4632 } 4652 }
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
4672 } 4692 }
4673 4693
4674 bool isLibraryPrefix(Expression node) => 4694 bool isLibraryPrefix(Expression node) =>
4675 node is SimpleIdentifier && node.staticElement is PrefixElement; 4695 node is SimpleIdentifier && node.staticElement is PrefixElement;
4676 4696
4677 LibraryElement _getLibrary(AnalysisContext c, String uri) => 4697 LibraryElement _getLibrary(AnalysisContext c, String uri) =>
4678 c.computeLibraryElement(c.sourceFactory.forUri(uri)); 4698 c.computeLibraryElement(c.sourceFactory.forUri(uri));
4679 4699
4680 bool _isDartRuntime(LibraryElement l) => 4700 bool _isDartRuntime(LibraryElement l) =>
4681 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; 4701 l.isInSdk && l.source.uri.toString() == 'dart:_runtime';
OLDNEW
« no previous file with comments | « no previous file | lib/src/compiler/compiler.dart » ('j') | lib/src/compiler/compiler.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698