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

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: merged & format 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
« no previous file with comments | « lib/runtime/dart_runtime.js ('k') | test/browser/index.html » ('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 // 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 523 matching lines...) Expand 10 before | Expand all | Expand 10 after
534 534
535 /// Emit class members that need to come after the class declaration, such 535 /// Emit class members that need to come after the class declaration, such
536 /// as static fields. See [_emitClassMethods] for things that are emitted 536 /// as static fields. See [_emitClassMethods] for things that are emitted
537 /// inside the ES6 `class { ... }` node. 537 /// inside the ES6 `class { ... }` node.
538 JS.Statement _finishClassMembers(ClassElement classElem, 538 JS.Statement _finishClassMembers(ClassElement classElem,
539 JS.ClassExpression cls, List<ConstructorDeclaration> ctors, 539 JS.ClassExpression cls, List<ConstructorDeclaration> ctors,
540 List<FieldDeclaration> fields, List<MethodDeclaration> methods, 540 List<FieldDeclaration> fields, List<MethodDeclaration> methods,
541 String jsPeerName) { 541 String jsPeerName) {
542 var name = classElem.name; 542 var name = classElem.name;
543 var body = <JS.Statement>[]; 543 var body = <JS.Statement>[];
544
545 if (jsPeerName != null) {
546 var dartxNames = [];
547 for (var m in methods) {
548 if (!m.isAbstract && !m.isStatic && m.element.isPublic) {
549 dartxNames.add(_elementMemberName(m.element, allowExtensions: false));
550 }
551 }
552 body.add(js.statement('dart.defineExtensionNames(#)',
553 [new JS.ArrayInitializer(dartxNames, multiline: true)]));
554 }
555
544 body.add(new JS.ClassDeclaration(cls)); 556 body.add(new JS.ClassDeclaration(cls));
545 557
546 // TODO(jmesserly): we should really just extend native Array. 558 // TODO(jmesserly): we should really just extend native Array.
547 if (jsPeerName != null && classElem.typeParameters.isNotEmpty) { 559 if (jsPeerName != null && classElem.typeParameters.isNotEmpty) {
548 body.add(js.statement('dart.setBaseClass(#, dart.global.#);', [ 560 body.add(js.statement('dart.setBaseClass(#, dart.global.#);', [
549 classElem.name, 561 classElem.name,
550 _propertyName(jsPeerName) 562 _propertyName(jsPeerName)
551 ])); 563 ]));
552 } 564 }
553 565
554 // Interfaces 566 // Interfaces
555 if (classElem.interfaces.isNotEmpty) { 567 if (classElem.interfaces.isNotEmpty) {
556 body.add(js.statement('#[dart.implements] = () => #;', [ 568 body.add(js.statement('#[dart.implements] = () => #;', [
557 name, 569 name,
558 new JS.ArrayInitializer( 570 new JS.ArrayInitializer(
559 classElem.interfaces.map(_emitTypeName).toList()) 571 classElem.interfaces.map(_emitTypeName).toList())
560 ])); 572 ]));
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 } 573 }
577 574
578 // Named constructors 575 // Named constructors
579 for (ConstructorDeclaration member in ctors) { 576 for (ConstructorDeclaration member in ctors) {
580 if (member.name != null && member.factoryKeyword == null) { 577 if (member.name != null && member.factoryKeyword == null) {
581 body.add(js.statement('dart.defineNamedConstructor(#, #);', [ 578 body.add(js.statement('dart.defineNamedConstructor(#, #);', [
582 name, 579 name,
583 _emitMemberName(member.name.name, isStatic: true) 580 _emitMemberName(member.name.name, isStatic: true)
584 ])); 581 ]));
585 } 582 }
(...skipping 15 matching lines...) Expand all
601 var tMethods = []; 598 var tMethods = [];
602 var sNames = []; 599 var sNames = [];
603 for (MethodDeclaration node in methods) { 600 for (MethodDeclaration node in methods) {
604 if (!(node.isSetter || node.isGetter || node.isAbstract)) { 601 if (!(node.isSetter || node.isGetter || node.isAbstract)) {
605 var name = node.name.name; 602 var name = node.name.name;
606 var element = node.element; 603 var element = node.element;
607 var inheritedElement = 604 var inheritedElement =
608 classElem.lookUpInheritedConcreteMethod(name, currentLibrary); 605 classElem.lookUpInheritedConcreteMethod(name, currentLibrary);
609 if (inheritedElement != null && 606 if (inheritedElement != null &&
610 inheritedElement.type == element.type) continue; 607 inheritedElement.type == element.type) continue;
611 var memberName = _emitMemberDeclarationName(element); 608 var memberName = _elementMemberName(element);
612 var parts = 609 var parts =
613 _emitFunctionTypeParts(element.type, dynamicIsBottom: false); 610 _emitFunctionTypeParts(element.type, dynamicIsBottom: false);
614 var property = 611 var property =
615 new JS.Property(memberName, new JS.ArrayInitializer(parts)); 612 new JS.Property(memberName, new JS.ArrayInitializer(parts));
616 if (node.isStatic) { 613 if (node.isStatic) {
617 tStatics.add(property); 614 tStatics.add(property);
618 sNames.add(memberName); 615 sNames.add(memberName);
619 } else { 616 } else {
620 tMethods.add(property); 617 tMethods.add(property);
621 } 618 }
(...skipping 26 matching lines...) Expand all
648 sigFields.add(build('statics', tStatics)); 645 sigFields.add(build('statics', tStatics));
649 sigFields.add(aNames); 646 sigFields.add(aNames);
650 } 647 }
651 if (!sigFields.isEmpty) { 648 if (!sigFields.isEmpty) {
652 var sig = new JS.ObjectInitializer(sigFields); 649 var sig = new JS.ObjectInitializer(sigFields);
653 var classExpr = new JS.Identifier(name); 650 var classExpr = new JS.Identifier(name);
654 body.add(js.statement('dart.setSignature(#, #);', [classExpr, sig])); 651 body.add(js.statement('dart.setSignature(#, #);', [classExpr, sig]));
655 } 652 }
656 } 653 }
657 654
655 // If a concrete class implements one of our extensions, we might need to
656 // add forwarders.
657 var extensions = _extensionsToImplement(classElem);
658 if (extensions.isNotEmpty) {
659 var methodNames = [];
660 for (var e in extensions) {
661 methodNames.add(_elementMemberName(e));
662 }
663 body.add(js.statement('dart.defineExtensionMembers(#, #);', [
664 name,
665 new JS.ArrayInitializer(methodNames, multiline: methodNames.length > 4)
666 ]));
667 }
668
658 return _statement(body); 669 return _statement(body);
659 } 670 }
660 671
661 List<ExecutableElement> _extensionsToImplement(ClassElement element) { 672 List<ExecutableElement> _extensionsToImplement(ClassElement element) {
662 var members = <ExecutableElement>[]; 673 var members = <ExecutableElement>[];
663 if (_extensionTypes.contains(element)) return members; 674 if (_extensionTypes.contains(element)) return members;
664 675
665 // Collect all extension types we implement. 676 // Collect all extension types we implement.
666 var type = element.type; 677 var type = element.type;
667 var types = new Set<ClassElement>(); 678 var types = new Set<ClassElement>();
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after
1041 } 1052 }
1042 1053
1043 JS.Method _emitMethodDeclaration(DartType type, MethodDeclaration node) { 1054 JS.Method _emitMethodDeclaration(DartType type, MethodDeclaration node) {
1044 if (node.isAbstract || _externalOrNative(node)) { 1055 if (node.isAbstract || _externalOrNative(node)) {
1045 return null; 1056 return null;
1046 } 1057 }
1047 1058
1048 var params = _visit(node.parameters); 1059 var params = _visit(node.parameters);
1049 if (params == null) params = []; 1060 if (params == null) params = [];
1050 1061
1051 return new JS.Method(_emitMemberDeclarationName(node.element), 1062 return new JS.Method(
1052 new JS.Fun(params, _visit(node.body)), 1063 _elementMemberName(node.element), new JS.Fun(params, _visit(node.body)),
1053 isGetter: node.isGetter, 1064 isGetter: node.isGetter,
1054 isSetter: node.isSetter, 1065 isSetter: node.isSetter,
1055 isStatic: node.isStatic); 1066 isStatic: node.isStatic);
1056 } 1067 }
1057 1068
1058 @override 1069 @override
1059 JS.Statement visitFunctionDeclaration(FunctionDeclaration node) { 1070 JS.Statement visitFunctionDeclaration(FunctionDeclaration node) {
1060 assert(node.parent is CompilationUnit); 1071 assert(node.parent is CompilationUnit);
1061 1072
1062 if (_externalOrNative(node)) return null; 1073 if (_externalOrNative(node)) return null;
(...skipping 1475 matching lines...) Expand 10 before | Expand all | Expand 10 after
2538 /// Visits a list of expressions, creating a comma expression if needed in JS. 2549 /// Visits a list of expressions, creating a comma expression if needed in JS.
2539 JS.Expression _visitListToBinary(List<Expression> nodes, String operator) { 2550 JS.Expression _visitListToBinary(List<Expression> nodes, String operator) {
2540 if (nodes == null || nodes.isEmpty) return null; 2551 if (nodes == null || nodes.isEmpty) return null;
2541 return new JS.Expression.binary(_visitList(nodes), operator); 2552 return new JS.Expression.binary(_visitList(nodes), operator);
2542 } 2553 }
2543 2554
2544 /// Like [_emitMemberName], but for declaration sites. 2555 /// Like [_emitMemberName], but for declaration sites.
2545 /// 2556 ///
2546 /// Unlike call sites, we always have an element available, so we can use it 2557 /// Unlike call sites, we always have an element available, so we can use it
2547 /// directly rather than computing the relevant options for [_emitMemberName]. 2558 /// directly rather than computing the relevant options for [_emitMemberName].
2548 JS.Expression _emitMemberDeclarationName(ExecutableElement e) { 2559 JS.Expression _elementMemberName(ExecutableElement e,
2560 {bool allowExtensions: true}) {
2549 String name; 2561 String name;
2550 if (e is PropertyAccessorElement) { 2562 if (e is PropertyAccessorElement) {
2551 name = e.variable.name; 2563 name = e.variable.name;
2552 } else { 2564 } else {
2553 name = e.name; 2565 name = e.name;
2554 } 2566 }
2555 return _emitMemberName(name, 2567 return _emitMemberName(name,
2556 type: (e.enclosingElement as ClassElement).type, 2568 type: (e.enclosingElement as ClassElement).type,
2557 unary: e.parameters.isEmpty, 2569 unary: e.parameters.isEmpty,
2558 isStatic: e.isStatic, 2570 isStatic: e.isStatic,
2559 declaration: true); 2571 allowExtensions: allowExtensions);
2560 } 2572 }
2561 2573
2562 /// This handles member renaming for private names and operators. 2574 /// This handles member renaming for private names and operators.
2563 /// 2575 ///
2564 /// Private names are generated using ES6 symbols: 2576 /// Private names are generated using ES6 symbols:
2565 /// 2577 ///
2566 /// // At the top of the module: 2578 /// // At the top of the module:
2567 /// let _x = Symbol('_x'); 2579 /// let _x = Symbol('_x');
2568 /// let _y = Symbol('_y'); 2580 /// let _y = Symbol('_y');
2569 /// ... 2581 /// ...
(...skipping 24 matching lines...) Expand all
2594 /// This follows the same pattern as EcmaScript 6 Map: 2606 /// This follows the same pattern as EcmaScript 6 Map:
2595 /// <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_ Objects/Map> 2607 /// <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_ Objects/Map>
2596 /// 2608 ///
2597 /// Unary minus looks like: `x['unary-']()`. Note that [unary] must be passed 2609 /// Unary minus looks like: `x['unary-']()`. Note that [unary] must be passed
2598 /// for this transformation to happen, otherwise binary minus is assumed. 2610 /// for this transformation to happen, otherwise binary minus is assumed.
2599 /// 2611 ///
2600 /// Equality is a bit special, it is generated via the Dart `equals` runtime 2612 /// Equality is a bit special, it is generated via the Dart `equals` runtime
2601 /// helper, that checks for null. The user defined method is called '=='. 2613 /// helper, that checks for null. The user defined method is called '=='.
2602 /// 2614 ///
2603 JS.Expression _emitMemberName(String name, {DartType type, bool unary: false, 2615 JS.Expression _emitMemberName(String name, {DartType type, bool unary: false,
2604 bool isStatic: false, bool declaration: false}) { 2616 bool isStatic: false, bool allowExtensions: true}) {
2605 2617
2606 // Static members skip the rename steps. 2618 // Static members skip the rename steps.
2607 if (isStatic) return _propertyName(name); 2619 if (isStatic) return _propertyName(name);
2608 2620
2609 if (name.startsWith('_')) { 2621 if (name.startsWith('_')) {
2610 return _privateNames.putIfAbsent( 2622 return _privateNames.putIfAbsent(
2611 name, () => _initSymbol(new JS.TemporaryId(name))); 2623 name, () => _initSymbol(new JS.TemporaryId(name)));
2612 } 2624 }
2613 2625
2614 if (name == '[]') { 2626 if (name == '[]') {
2615 name = 'get'; 2627 name = 'get';
2616 } else if (name == '[]=') { 2628 } else if (name == '[]=') {
2617 name = 'set'; 2629 name = 'set';
2618 } else if (name == '-' && unary) { 2630 } else if (name == '-' && unary) {
2619 name = 'unary-'; 2631 name = 'unary-';
2620 } 2632 }
2621 2633
2622 // Dart "extension" methods. Used for JS Array, Boolean, Number, String. 2634 // Dart "extension" methods. Used for JS Array, Boolean, Number, String.
2623 if (!declaration && _extensionTypes.contains(type.element)) { 2635 if (allowExtensions && _extensionTypes.contains(type.element)) {
2624 // Special case `length`. We can call it directly. 2636 // Special case `length`. We can call it directly.
2625 if (name != 'length') return js.call('dartx.#', _propertyName(name)); 2637 if (name != 'length') return js.call('dartx.#', _propertyName(name));
2626 } 2638 }
2627 2639
2628 return _propertyName(name); 2640 return _propertyName(name);
2629 } 2641 }
2630 2642
2631 bool _externalOrNative(node) => 2643 bool _externalOrNative(node) =>
2632 node.externalKeyword != null || _functionBody(node) is NativeFunctionBody; 2644 node.externalKeyword != null || _functionBody(node) is NativeFunctionBody;
2633 2645
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
2720 2732
2721 /// A special kind of element created by the compiler, signifying a temporary 2733 /// A special kind of element created by the compiler, signifying a temporary
2722 /// variable. These objects use instance equality, and should be shared 2734 /// variable. These objects use instance equality, and should be shared
2723 /// everywhere in the tree where they are treated as the same variable. 2735 /// everywhere in the tree where they are treated as the same variable.
2724 class TemporaryVariableElement extends LocalVariableElementImpl { 2736 class TemporaryVariableElement extends LocalVariableElementImpl {
2725 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); 2737 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name);
2726 2738
2727 int get hashCode => identityHashCode(this); 2739 int get hashCode => identityHashCode(this);
2728 bool operator ==(Object other) => identical(this, other); 2740 bool operator ==(Object other) => identical(this, other);
2729 } 2741 }
OLDNEW
« no previous file with comments | « lib/runtime/dart_runtime.js ('k') | test/browser/index.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698