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

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

Issue 1156273010: fixes browser/runtime_test, and a few extension member fixes (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 5 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
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library dev_compiler.src.codegen.js_codegen; 5 library dev_compiler.src.codegen.js_codegen;
6 6
7 import 'dart:collection' show HashSet, HashMap, SplayTreeSet; 7 import 'dart:collection' show HashSet, HashMap, SplayTreeSet;
8 8
9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; 9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator;
10 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator; 10 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator;
(...skipping 540 matching lines...) Expand 10 before | Expand all | Expand 10 after
551 ])); 551 ]));
552 } 552 }
553 553
554 // Interfaces 554 // Interfaces
555 if (classElem.interfaces.isNotEmpty) { 555 if (classElem.interfaces.isNotEmpty) {
556 body.add(js.statement('#[dart.implements] = () => #;', [ 556 body.add(js.statement('#[dart.implements] = () => #;', [
557 name, 557 name,
558 new JS.ArrayInitializer( 558 new JS.ArrayInitializer(
559 classElem.interfaces.map(_emitTypeName).toList()) 559 classElem.interfaces.map(_emitTypeName).toList())
560 ])); 560 ]));
561
562 // If a concrete class implements one of our extensions, we might need to
563 // add forwarders.
564 var extensions = _extensionsToImplement(classElem);
565 if (extensions.isNotEmpty) {
566 var methodNames = [];
567 for (var e in extensions) {
568 methodNames.add(_emitMemberDeclarationName(e));
569 }
570 body.add(js.statement('dart.defineExtensionMembers(#, #);', [
571 name,
572 new JS.ArrayInitializer(methodNames,
573 multiline: methodNames.length > 4)
574 ]));
575 }
576 } 561 }
577 562
578 // Named constructors 563 // Named constructors
579 for (ConstructorDeclaration member in ctors) { 564 for (ConstructorDeclaration member in ctors) {
580 if (member.name != null && member.factoryKeyword == null) { 565 if (member.name != null && member.factoryKeyword == null) {
581 body.add(js.statement('dart.defineNamedConstructor(#, #);', [ 566 body.add(js.statement('dart.defineNamedConstructor(#, #);', [
582 name, 567 name,
583 _emitMemberName(member.name.name, isStatic: true) 568 _emitMemberName(member.name.name, isStatic: true)
584 ])); 569 ]));
585 } 570 }
(...skipping 15 matching lines...) Expand all
601 var tMethods = []; 586 var tMethods = [];
602 var sNames = []; 587 var sNames = [];
603 for (MethodDeclaration node in methods) { 588 for (MethodDeclaration node in methods) {
604 if (!(node.isSetter || node.isGetter || node.isAbstract)) { 589 if (!(node.isSetter || node.isGetter || node.isAbstract)) {
605 var name = node.name.name; 590 var name = node.name.name;
606 var element = node.element; 591 var element = node.element;
607 var inheritedElement = 592 var inheritedElement =
608 classElem.lookUpInheritedConcreteMethod(name, currentLibrary); 593 classElem.lookUpInheritedConcreteMethod(name, currentLibrary);
609 if (inheritedElement != null && 594 if (inheritedElement != null &&
610 inheritedElement.type == element.type) continue; 595 inheritedElement.type == element.type) continue;
611 var memberName = _emitMemberDeclarationName(element); 596 var memberName = _elementMemberName(element);
612 var parts = 597 var parts =
613 _emitFunctionTypeParts(element.type, dynamicIsBottom: false); 598 _emitFunctionTypeParts(element.type, dynamicIsBottom: false);
614 var property = 599 var property =
615 new JS.Property(memberName, new JS.ArrayInitializer(parts)); 600 new JS.Property(memberName, new JS.ArrayInitializer(parts));
616 if (node.isStatic) { 601 if (node.isStatic) {
617 tStatics.add(property); 602 tStatics.add(property);
618 sNames.add(memberName); 603 sNames.add(memberName);
619 } else { 604 } else {
620 tMethods.add(property); 605 tMethods.add(property);
621 } 606 }
(...skipping 26 matching lines...) Expand all
648 sigFields.add(build('statics', tStatics)); 633 sigFields.add(build('statics', tStatics));
649 sigFields.add(aNames); 634 sigFields.add(aNames);
650 } 635 }
651 if (!sigFields.isEmpty) { 636 if (!sigFields.isEmpty) {
652 var sig = new JS.ObjectInitializer(sigFields); 637 var sig = new JS.ObjectInitializer(sigFields);
653 var classExpr = new JS.Identifier(name); 638 var classExpr = new JS.Identifier(name);
654 body.add(js.statement('dart.setSignature(#, #);', [classExpr, sig])); 639 body.add(js.statement('dart.setSignature(#, #);', [classExpr, sig]));
655 } 640 }
656 } 641 }
657 642
643 // If a concrete class implements one of our extensions, we might need to
644 // add forwarders.
645 var extensions = _extensionsToImplement(classElem);
646 if (extensions.isNotEmpty) {
647 var methodNames = [];
648 for (var e in extensions) {
649 methodNames.add(_elementMemberName(e, declaration: true));
650 }
651 body.add(js.statement('dart.defineExtensionMembers(#, #);', [
652 name,
653 new JS.ArrayInitializer(methodNames, multiline: methodNames.length > 4)
654 ]));
655 }
656
658 return _statement(body); 657 return _statement(body);
659 } 658 }
660 659
661 List<ExecutableElement> _extensionsToImplement(ClassElement element) { 660 List<ExecutableElement> _extensionsToImplement(ClassElement element) {
662 var members = <ExecutableElement>[]; 661 var members = <ExecutableElement>[];
663 if (_extensionTypes.contains(element)) return members; 662 if (_extensionTypes.contains(element)) return members;
664 663
665 // Collect all extension types we implement. 664 // Collect all extension types we implement.
666 var type = element.type; 665 var type = element.type;
667 var types = new Set<ClassElement>(); 666 var types = new Set<ClassElement>();
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after
1041 } 1040 }
1042 1041
1043 JS.Method _emitMethodDeclaration(DartType type, MethodDeclaration node) { 1042 JS.Method _emitMethodDeclaration(DartType type, MethodDeclaration node) {
1044 if (node.isAbstract || _externalOrNative(node)) { 1043 if (node.isAbstract || _externalOrNative(node)) {
1045 return null; 1044 return null;
1046 } 1045 }
1047 1046
1048 var params = _visit(node.parameters); 1047 var params = _visit(node.parameters);
1049 if (params == null) params = []; 1048 if (params == null) params = [];
1050 1049
1051 return new JS.Method(_emitMemberDeclarationName(node.element), 1050 return new JS.Method(_elementMemberName(node.element, declaration: true),
1052 new JS.Fun(params, _visit(node.body)), 1051 new JS.Fun(params, _visit(node.body)),
1053 isGetter: node.isGetter, 1052 isGetter: node.isGetter,
1054 isSetter: node.isSetter, 1053 isSetter: node.isSetter,
1055 isStatic: node.isStatic); 1054 isStatic: node.isStatic);
1056 } 1055 }
1057 1056
1058 @override 1057 @override
1059 JS.Statement visitFunctionDeclaration(FunctionDeclaration node) { 1058 JS.Statement visitFunctionDeclaration(FunctionDeclaration node) {
1060 assert(node.parent is CompilationUnit); 1059 assert(node.parent is CompilationUnit);
1061 1060
(...skipping 1455 matching lines...) Expand 10 before | Expand all | Expand 10 after
2517 /// Visits a list of expressions, creating a comma expression if needed in JS. 2516 /// Visits a list of expressions, creating a comma expression if needed in JS.
2518 JS.Expression _visitListToBinary(List<Expression> nodes, String operator) { 2517 JS.Expression _visitListToBinary(List<Expression> nodes, String operator) {
2519 if (nodes == null || nodes.isEmpty) return null; 2518 if (nodes == null || nodes.isEmpty) return null;
2520 return new JS.Expression.binary(_visitList(nodes), operator); 2519 return new JS.Expression.binary(_visitList(nodes), operator);
2521 } 2520 }
2522 2521
2523 /// Like [_emitMemberName], but for declaration sites. 2522 /// Like [_emitMemberName], but for declaration sites.
2524 /// 2523 ///
2525 /// Unlike call sites, we always have an element available, so we can use it 2524 /// Unlike call sites, we always have an element available, so we can use it
2526 /// directly rather than computing the relevant options for [_emitMemberName]. 2525 /// directly rather than computing the relevant options for [_emitMemberName].
2527 JS.Expression _emitMemberDeclarationName(ExecutableElement e) { 2526 JS.Expression _elementMemberName(ExecutableElement e,
2527 {bool declaration: false}) {
2528 String name; 2528 String name;
2529 if (e is PropertyAccessorElement) { 2529 if (e is PropertyAccessorElement) {
2530 name = e.variable.name; 2530 name = e.variable.name;
2531 } else { 2531 } else {
2532 name = e.name; 2532 name = e.name;
2533 } 2533 }
2534 return _emitMemberName(name, 2534 return _emitMemberName(name,
2535 type: (e.enclosingElement as ClassElement).type, 2535 type: (e.enclosingElement as ClassElement).type,
2536 unary: e.parameters.isEmpty, 2536 unary: e.parameters.isEmpty,
2537 isStatic: e.isStatic, 2537 isStatic: e.isStatic,
2538 declaration: true); 2538 declaration: declaration);
2539 } 2539 }
2540 2540
2541 /// This handles member renaming for private names and operators. 2541 /// This handles member renaming for private names and operators.
2542 /// 2542 ///
2543 /// Private names are generated using ES6 symbols: 2543 /// Private names are generated using ES6 symbols:
2544 /// 2544 ///
2545 /// // At the top of the module: 2545 /// // At the top of the module:
2546 /// let _x = Symbol('_x'); 2546 /// let _x = Symbol('_x');
2547 /// let _y = Symbol('_y'); 2547 /// let _y = Symbol('_y');
2548 /// ... 2548 /// ...
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
2592 2592
2593 if (name == '[]') { 2593 if (name == '[]') {
2594 name = 'get'; 2594 name = 'get';
2595 } else if (name == '[]=') { 2595 } else if (name == '[]=') {
2596 name = 'set'; 2596 name = 'set';
2597 } else if (name == '-' && unary) { 2597 } else if (name == '-' && unary) {
2598 name = 'unary-'; 2598 name = 'unary-';
2599 } 2599 }
2600 2600
2601 // Dart "extension" methods. Used for JS Array, Boolean, Number, String. 2601 // Dart "extension" methods. Used for JS Array, Boolean, Number, String.
2602 if (!declaration && _extensionTypes.contains(type.element)) { 2602 // Special case `length`. We can call it directly.
2603 // Special case `length`. We can call it directly. 2603 if (_extensionTypes.contains(type.element) && name != 'length') {
2604 if (name != 'length') return js.call('dartx.#', _propertyName(name)); 2604 var code = declaration ? 'dart.extensionMember(#)' : 'dartx.#';
2605 return js.call(code, _propertyName(name));
2605 } 2606 }
2606 2607
2607 return _propertyName(name); 2608 return _propertyName(name);
2608 } 2609 }
2609 2610
2610 bool _externalOrNative(node) => 2611 bool _externalOrNative(node) =>
2611 node.externalKeyword != null || _functionBody(node) is NativeFunctionBody; 2612 node.externalKeyword != null || _functionBody(node) is NativeFunctionBody;
2612 2613
2613 FunctionBody _functionBody(node) => 2614 FunctionBody _functionBody(node) =>
2614 node is FunctionDeclaration ? node.functionExpression.body : node.body; 2615 node is FunctionDeclaration ? node.functionExpression.body : node.body;
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
2699 2700
2700 /// A special kind of element created by the compiler, signifying a temporary 2701 /// A special kind of element created by the compiler, signifying a temporary
2701 /// variable. These objects use instance equality, and should be shared 2702 /// variable. These objects use instance equality, and should be shared
2702 /// everywhere in the tree where they are treated as the same variable. 2703 /// everywhere in the tree where they are treated as the same variable.
2703 class TemporaryVariableElement extends LocalVariableElementImpl { 2704 class TemporaryVariableElement extends LocalVariableElementImpl {
2704 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); 2705 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name);
2705 2706
2706 int get hashCode => identityHashCode(this); 2707 int get hashCode => identityHashCode(this);
2707 bool operator ==(Object other) => identical(this, other); 2708 bool operator ==(Object other) => identical(this, other);
2708 } 2709 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698