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

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

Issue 1948563002: allow 'super' in async and finally blocks (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 4 years, 7 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_sdk.js ('k') | lib/src/compiler/source_map_printer.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 // 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 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 FunctionBody _currentFunction; 111 FunctionBody _currentFunction;
112 112
113 /// Helper class for emitting elements in the proper order to allow 113 /// Helper class for emitting elements in the proper order to allow
114 /// JS to load the module. 114 /// JS to load the module.
115 ElementLoader _loader; 115 ElementLoader _loader;
116 116
117 BuildUnit _buildUnit; 117 BuildUnit _buildUnit;
118 118
119 String _buildRoot; 119 String _buildRoot;
120 120
121 bool _superAllowed = true;
122
123 List<JS.TemporaryId> _superHelperSymbols = <JS.TemporaryId>[];
124 List<JS.Method> _superHelpers = <JS.Method>[];
125
121 /// Whether we are currently generating code for the body of a `JS()` call. 126 /// Whether we are currently generating code for the body of a `JS()` call.
122 bool _isInForeignJS = false; 127 bool _isInForeignJS = false;
123 128
124 CodeGenerator(AnalysisContext c, this.options, this._extensionTypes) 129 CodeGenerator(AnalysisContext c, this.options, this._extensionTypes)
125 : context = c, 130 : context = c,
126 types = c.typeProvider, 131 types = c.typeProvider,
127 _asyncStreamIterator = 132 _asyncStreamIterator =
128 _getLibrary(c, 'dart:async').getType('StreamIterator').type, 133 _getLibrary(c, 'dart:async').getType('StreamIterator').type,
129 _jsArray = _getLibrary(c, 'dart:_interceptors').getType('JSArray'), 134 _jsArray = _getLibrary(c, 'dart:_interceptors').getType('JSArray'),
130 dartCoreLibrary = _getLibrary(c, 'dart:core'), 135 dartCoreLibrary = _getLibrary(c, 'dart:core'),
(...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after
588 _registerPropertyOverrides(classElem, className, superclasses, allFields, 593 _registerPropertyOverrides(classElem, className, superclasses, allFields,
589 virtualFields, virtualFieldSymbols, staticFieldOverrides); 594 virtualFields, virtualFieldSymbols, staticFieldOverrides);
590 595
591 var classExpr = _emitClassExpression(classElem, 596 var classExpr = _emitClassExpression(classElem,
592 _emitClassMethods(node, ctors, fields, superclasses, virtualFields), 597 _emitClassMethods(node, ctors, fields, superclasses, virtualFields),
593 fields: allFields); 598 fields: allFields);
594 599
595 var body = <JS.Statement>[]; 600 var body = <JS.Statement>[];
596 var extensions = _extensionsToImplement(classElem); 601 var extensions = _extensionsToImplement(classElem);
597 _initExtensionSymbols(classElem, methods, fields, body); 602 _initExtensionSymbols(classElem, methods, fields, body);
603 _emitSuperHelperSymbols(_superHelperSymbols, body);
598 604
599 // Emit the class, e.g. `core.Object = class Object { ... }` 605 // Emit the class, e.g. `core.Object = class Object { ... }`
600 _defineClass(classElem, className, classExpr, body); 606 _defineClass(classElem, className, classExpr, body);
601 607
602 // Emit things that come after the ES6 `class ... { ... }`. 608 // Emit things that come after the ES6 `class ... { ... }`.
603 _setBaseClass(classElem, className, body); 609 _setBaseClass(classElem, className, body);
604 _defineNamedConstructors(ctors, body, className); 610 _defineNamedConstructors(ctors, body, className);
605 _emitVirtualFieldSymbols(virtualFieldSymbols, body); 611 _emitVirtualFieldSymbols(virtualFieldSymbols, body);
606 _emitClassSignature(methods, classElem, ctors, extensions, className, body); 612 _emitClassSignature(methods, classElem, ctors, extensions, className, body);
607 _defineExtensionMembers(extensions, className, body); 613 _defineExtensionMembers(extensions, className, body);
608 _emitClassMetadata(node.metadata, className, body); 614 _emitClassMetadata(node.metadata, className, body);
609 615
610 JS.Statement classDef = _statement(body); 616 JS.Statement classDef = _statement(body);
611 var typeFormals = classElem.typeParameters; 617 var typeFormals = classElem.typeParameters;
612 if (typeFormals.isNotEmpty) { 618 if (typeFormals.isNotEmpty) {
613 classDef = _defineClassTypeArguments(classElem, typeFormals, classDef); 619 classDef = _defineClassTypeArguments(classElem, typeFormals, classDef);
614 } 620 }
615 621
616 body = <JS.Statement>[classDef]; 622 body = <JS.Statement>[classDef];
617 _emitStaticFields(staticFields, staticFieldOverrides, classElem, body); 623 _emitStaticFields(staticFields, staticFieldOverrides, classElem, body);
618 _registerExtensionType(classElem, body); 624 _registerExtensionType(classElem, body);
619 return _statement(body); 625 return _statement(body);
620 } 626 }
621 627
628 void _emitSuperHelperSymbols(
629 List<JS.TemporaryId> superHelperSymbols, List<JS.Statement> body) {
630 for (var id in superHelperSymbols) {
631 body.add(js.statement('const # = Symbol(#)', [id, js.string(id.name)]));
632 }
633 superHelperSymbols.clear();
634 }
635
622 void _registerPropertyOverrides( 636 void _registerPropertyOverrides(
623 ClassElement classElem, 637 ClassElement classElem,
624 JS.Expression className, 638 JS.Expression className,
625 List<ClassElement> superclasses, 639 List<ClassElement> superclasses,
626 List<FieldDeclaration> fields, 640 List<FieldDeclaration> fields,
627 Map<FieldElement, JS.TemporaryId> virtualFields, 641 Map<FieldElement, JS.TemporaryId> virtualFields,
628 List<JS.Statement> virtualFieldSymbols, 642 List<JS.Statement> virtualFieldSymbols,
629 Set<FieldElement> staticFieldOverrides) { 643 Set<FieldElement> staticFieldOverrides) {
630 for (var field in fields) { 644 for (var field in fields) {
631 for (VariableDeclaration field in field.fields.variables) { 645 for (VariableDeclaration field in field.fields.variables) {
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after
890 // helper on a parent class. This pattern is common in the core libraries 904 // helper on a parent class. This pattern is common in the core libraries
891 // (e.g. IterableMixin<E> and IterableBase<E>). 905 // (e.g. IterableMixin<E> and IterableBase<E>).
892 // 906 //
893 // (We could do this same optimization for any interface with an `iterator` 907 // (We could do this same optimization for any interface with an `iterator`
894 // method, but that's more expensive to check for, so it doesn't seem worth 908 // method, but that's more expensive to check for, so it doesn't seem worth
895 // it. The above case for an explicit `iterator` method will catch those.) 909 // it. The above case for an explicit `iterator` method will catch those.)
896 if (!hasJsPeer && !hasIterator && _implementsIterable(type)) { 910 if (!hasJsPeer && !hasIterator && _implementsIterable(type)) {
897 jsMethods.add(_emitIterable(type)); 911 jsMethods.add(_emitIterable(type));
898 } 912 }
899 913
914 // Add all of the super helper methods
915 jsMethods.addAll(_superHelpers);
916 _superHelpers.clear();
917
900 return jsMethods.where((m) => m != null).toList(growable: false); 918 return jsMethods.where((m) => m != null).toList(growable: false);
901 } 919 }
902 920
903 /// This is called whenever a derived class needs to introduce a new field, 921 /// This is called whenever a derived class needs to introduce a new field,
904 /// shadowing a field or getter/setter pair on its parent. 922 /// shadowing a field or getter/setter pair on its parent.
905 /// 923 ///
906 /// This is important because otherwise, trying to read or write the field 924 /// This is important because otherwise, trying to read or write the field
907 /// would end up calling the getter or setter, and one of those might not even 925 /// would end up calling the getter or setter, and one of those might not even
908 /// exist, resulting in a runtime error. Even if they did exist, that's the 926 /// exist, resulting in a runtime error. Even if they did exist, that's the
909 /// wrong behavior if a new field was declared. 927 /// wrong behavior if a new field was declared.
(...skipping 713 matching lines...) Expand 10 before | Expand all | Expand 10 after
1623 return new JS.Fun(params, js.statement('{ return this.#; }', [name])); 1641 return new JS.Fun(params, js.statement('{ return this.#; }', [name]));
1624 } else if (node.isSetter) { 1642 } else if (node.isSetter) {
1625 return new JS.Fun( 1643 return new JS.Fun(
1626 params, js.statement('{ this.# = #; }', [name, params.last])); 1644 params, js.statement('{ this.# = #; }', [name, params.last]));
1627 } else { 1645 } else {
1628 return new JS.Fun( 1646 return new JS.Fun(
1629 params, js.statement('{ return this.#(#); }', [name, params])); 1647 params, js.statement('{ return this.#(#); }', [name, params]));
1630 } 1648 }
1631 } 1649 }
1632 1650
1633 JS.Method _emitMethodDeclaration(DartType type, MethodDeclaration node) { 1651 JS.Method _emitMethodDeclaration(InterfaceType type, MethodDeclaration node) {
1634 if (node.isAbstract) { 1652 if (node.isAbstract) {
1635 return null; 1653 return null;
1636 } 1654 }
1637 1655
1638 JS.Fun fn; 1656 JS.Fun fn;
1639 if (_externalOrNative(node)) { 1657 if (_externalOrNative(node)) {
1640 fn = _emitNativeFunctionBody(node); 1658 fn = _emitNativeFunctionBody(node);
1641 // TODO(vsm): Remove if / when we handle the static case above. 1659 // TODO(vsm): Remove if / when we handle the static case above.
1642 if (fn == null) return null; 1660 if (fn == null) return null;
1643 } else { 1661 } else {
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after
1949 // `await` is generated as `yield`. 1967 // `await` is generated as `yield`.
1950 // runtime/_generators.js has an example of what the code is generated as. 1968 // runtime/_generators.js has an example of what the code is generated as.
1951 var savedController = _asyncStarController; 1969 var savedController = _asyncStarController;
1952 List jsParams = visitFormalParameterList(parameters); 1970 List jsParams = visitFormalParameterList(parameters);
1953 if (kind == 'asyncStar') { 1971 if (kind == 'asyncStar') {
1954 _asyncStarController = new JS.TemporaryId('stream'); 1972 _asyncStarController = new JS.TemporaryId('stream');
1955 jsParams.insert(0, _asyncStarController); 1973 jsParams.insert(0, _asyncStarController);
1956 } else { 1974 } else {
1957 _asyncStarController = null; 1975 _asyncStarController = null;
1958 } 1976 }
1977 var savedSuperAllowed = _superAllowed;
1978 _superAllowed = false;
1959 // Visit the body with our async* controller set. 1979 // Visit the body with our async* controller set.
1960 var jsBody = _visit(body); 1980 var jsBody = _visit(body);
1981 _superAllowed = savedSuperAllowed;
1961 _asyncStarController = savedController; 1982 _asyncStarController = savedController;
1962 1983
1963 DartType returnType = _getExpectedReturnType(element); 1984 DartType returnType = _getExpectedReturnType(element);
1964 JS.Expression gen = new JS.Fun(jsParams, jsBody, 1985 JS.Expression gen = new JS.Fun(jsParams, jsBody,
1965 isGenerator: true, returnType: emitTypeRef(returnType)); 1986 isGenerator: true, returnType: emitTypeRef(returnType));
1966 if (JS.This.foundIn(gen)) { 1987 if (JS.This.foundIn(gen)) {
1967 gen = js.call('#.bind(this)', gen); 1988 gen = js.call('#.bind(this)', gen);
1968 } 1989 }
1969 1990
1970 var T = _emitTypeName(returnType); 1991 var T = _emitTypeName(returnType);
(...skipping 25 matching lines...) Expand all
1996 return new JS.Block([ 2017 return new JS.Block([
1997 declareFn, 2018 declareFn,
1998 _emitFunctionTagged(name, func.element.type).toStatement() 2019 _emitFunctionTagged(name, func.element.type).toStatement()
1999 ]); 2020 ]);
2000 } 2021 }
2001 2022
2002 /// Emits a simple identifier, including handling an inferred generic 2023 /// Emits a simple identifier, including handling an inferred generic
2003 /// function instantiation. 2024 /// function instantiation.
2004 @override 2025 @override
2005 JS.Expression visitSimpleIdentifier(SimpleIdentifier node) { 2026 JS.Expression visitSimpleIdentifier(SimpleIdentifier node) {
2006 return _applyFunctionTypeArguments( 2027 var typeArgs = _getTypeArgs(node.staticElement, node.staticType);
2007 _emitSimpleIdentifier(node), node.staticElement, node.staticType); 2028 var simpleId = _emitSimpleIdentifier(node);
2029 if (typeArgs == null) {
2030 return simpleId;
2031 }
2032 return js.call('dart.gbind(#, #)', [simpleId, typeArgs]);
2008 } 2033 }
2009 2034
2010 /// Emits a simple identifier, handling implicit `this` as well as 2035 /// Emits a simple identifier, handling implicit `this` as well as
2011 /// going through the qualified library name if necessary, but *not* handling 2036 /// going through the qualified library name if necessary, but *not* handling
2012 /// inferred generic function instantiation. 2037 /// inferred generic function instantiation.
2013 JS.Expression _emitSimpleIdentifier(SimpleIdentifier node) { 2038 JS.Expression _emitSimpleIdentifier(SimpleIdentifier node) {
2014 var accessor = node.staticElement; 2039 var accessor = node.staticElement;
2015 if (accessor == null) { 2040 if (accessor == null) {
2016 return js.commentExpression( 2041 return js.commentExpression(
2017 'Unimplemented unknown name', new JS.Identifier(node.name)); 2042 'Unimplemented unknown name', new JS.Identifier(node.name));
(...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after
2377 if (result != null) return result; 2402 if (result != null) return result;
2378 2403
2379 var target = _getTarget(node); 2404 var target = _getTarget(node);
2380 if (target == null || isLibraryPrefix(target)) { 2405 if (target == null || isLibraryPrefix(target)) {
2381 return _emitFunctionCall(node); 2406 return _emitFunctionCall(node);
2382 } 2407 }
2383 2408
2384 return _emitMethodCall(target, node); 2409 return _emitMethodCall(target, node);
2385 } 2410 }
2386 2411
2412 JS.Expression _emitMethodCall(Expression target, MethodInvocation node) {
2413 List<JS.Expression> args = _visit(node.argumentList);
2414 var typeArgs = _emitInvokeTypeArguments(node);
2415
2416 if (target is SuperExpression && !_superAllowed) {
2417 return _emitSuperHelperCall(typeArgs, args, target, node);
2418 }
2419
2420 return _emitMethodCallInternal(target, node, args, typeArgs);
2421 }
2422
2423 JS.Expression _emitSuperHelperCall(List<JS.Expression> typeArgs,
2424 List<JS.Expression> args, SuperExpression target, MethodInvocation node) {
2425 var fakeTypeArgs =
2426 typeArgs?.map((_) => new JS.TemporaryId('a'))?.toList(growable: false);
2427 var fakeArgs =
2428 args.map((_) => new JS.TemporaryId('a')).toList(growable: false);
2429 var combinedFakeArgs = <JS.TemporaryId>[];
2430 if (fakeTypeArgs != null) {
2431 combinedFakeArgs.addAll(fakeTypeArgs);
2432 }
2433 combinedFakeArgs.addAll(fakeArgs);
2434
2435 var forwardedCall =
2436 _emitMethodCallInternal(target, node, fakeArgs, fakeTypeArgs);
2437 var superForwarder = _getSuperHelperFor(
2438 node.methodName.name, forwardedCall, combinedFakeArgs);
2439
2440 var combinedRealArgs = <JS.Expression>[];
2441 if (typeArgs != null) {
2442 combinedRealArgs.addAll(typeArgs);
2443 }
2444 combinedRealArgs.addAll(args);
2445
2446 return js.call('this.#(#)', [superForwarder, combinedRealArgs]);
2447 }
2448
2449 JS.Expression _getSuperHelperFor(String name, JS.Expression forwardedCall,
2450 List<JS.Expression> helperArgs) {
2451 var helperMethod =
2452 new JS.Fun(helperArgs, new JS.Block([new JS.Return(forwardedCall)]));
2453 var helperMethodName = new JS.TemporaryId('super\$$name');
2454 _superHelperSymbols.add(helperMethodName);
2455 _superHelpers.add(new JS.Method(helperMethodName, helperMethod));
2456 return helperMethodName;
2457 }
2458
2387 /// Emits a (possibly generic) instance method call. 2459 /// Emits a (possibly generic) instance method call.
2388 JS.Expression _emitMethodCall(Expression target, MethodInvocation node) { 2460 JS.Expression _emitMethodCallInternal(
2461 Expression target,
2462 MethodInvocation node,
2463 List<JS.Expression> args,
2464 List<JS.Expression> typeArgs) {
2389 var type = getStaticType(target); 2465 var type = getStaticType(target);
2390 var name = node.methodName.name; 2466 var name = node.methodName.name;
2391 var element = node.methodName.staticElement; 2467 var element = node.methodName.staticElement;
2392 bool isStatic = element is ExecutableElement && element.isStatic; 2468 bool isStatic = element is ExecutableElement && element.isStatic;
2393 var memberName = _emitMemberName(name, type: type, isStatic: isStatic); 2469 var memberName = _emitMemberName(name, type: type, isStatic: isStatic);
2394 2470
2395 JS.Expression jsTarget = _visit(target); 2471 JS.Expression jsTarget = _visit(target);
2396 var typeArgs = _emitInvokeTypeArguments(node);
2397 List<JS.Expression> args = _visit(node.argumentList);
2398 if (DynamicInvoke.get(target)) { 2472 if (DynamicInvoke.get(target)) {
2399 if (typeArgs != null) { 2473 if (typeArgs != null) {
2400 return js.call('dart.dgsend(#, #, #, #)', 2474 return js.call('dart.dgsend(#, #, #, #)',
2401 [jsTarget, new JS.ArrayInitializer(typeArgs), memberName, args]); 2475 [jsTarget, new JS.ArrayInitializer(typeArgs), memberName, args]);
2402 } else { 2476 } else {
2403 return js.call('dart.dsend(#, #, #)', [jsTarget, memberName, args]); 2477 return js.call('dart.dsend(#, #, #)', [jsTarget, memberName, args]);
2404 } 2478 }
2405 } 2479 }
2406 if (_isObjectMemberCall(target, name)) { 2480 if (_isObjectMemberCall(target, name)) {
2407 // Object methods require a helper for null checks & native types. 2481 // Object methods require a helper for null checks & native types.
2408 assert(typeArgs == null); // Object methods don't take type args. 2482 assert(typeArgs == null); // Object methods don't take type args.
2409 return js.call('dart.#(#, #)', [memberName, jsTarget, args]); 2483 return js.call('dart.#(#, #)', [memberName, jsTarget, args]);
2410 } 2484 }
2411 2485
2412 jsTarget = new JS.PropertyAccess(jsTarget, memberName); 2486 jsTarget = new JS.PropertyAccess(jsTarget, memberName);
2487
2413 if (typeArgs != null) jsTarget = new JS.Call(jsTarget, typeArgs); 2488 if (typeArgs != null) jsTarget = new JS.Call(jsTarget, typeArgs);
2414 2489
2415 if (DynamicInvoke.get(node.methodName)) { 2490 if (DynamicInvoke.get(node.methodName)) {
2416 // This is a dynamic call to a statically known target. For example: 2491 // This is a dynamic call to a statically known target. For example:
2417 // class Foo { Function bar; } 2492 // class Foo { Function bar; }
2418 // new Foo().bar(); // dynamic call 2493 // new Foo().bar(); // dynamic call
2419 return js.call('dart.dcall(#, #)', [jsTarget, args]); 2494 return js.call('dart.dcall(#, #)', [jsTarget, args]);
2420 } 2495 }
2421 2496
2422 return new JS.Call(jsTarget, args); 2497 return new JS.Call(jsTarget, args);
(...skipping 1114 matching lines...) Expand 10 before | Expand all | Expand 10 after
3537 (_extensionTypes.hasNativeSubtype(type) && target is! SuperExpression); 3612 (_extensionTypes.hasNativeSubtype(type) && target is! SuperExpression);
3538 } 3613 }
3539 3614
3540 /// Shared code for [PrefixedIdentifier] and [PropertyAccess]. 3615 /// Shared code for [PrefixedIdentifier] and [PropertyAccess].
3541 JS.Expression _emitAccess( 3616 JS.Expression _emitAccess(
3542 Expression target, SimpleIdentifier memberId, DartType resultType) { 3617 Expression target, SimpleIdentifier memberId, DartType resultType) {
3543 Element member = memberId.staticElement; 3618 Element member = memberId.staticElement;
3544 if (member is PropertyAccessorElement) { 3619 if (member is PropertyAccessorElement) {
3545 member = (member as PropertyAccessorElement).variable; 3620 member = (member as PropertyAccessorElement).variable;
3546 } 3621 }
3622 String memberName = memberId.name;
3623 var typeArgs = _getTypeArgs(member, resultType);
3624
3625 if (target is SuperExpression && !_superAllowed) {
3626 return _emitSuperHelperAccess(target, member, memberName, typeArgs);
3627 }
3628 return _emitAccessInternal(target, member, memberName, typeArgs);
3629 }
3630
3631 JS.Expression _emitSuperHelperAccess(SuperExpression target, Element member,
3632 String memberName, List<JS.Expression> typeArgs) {
3633 var fakeTypeArgs =
3634 typeArgs?.map((_) => new JS.TemporaryId('a'))?.toList(growable: false);
3635
3636 var forwardedAccess =
3637 _emitAccessInternal(target, member, memberName, fakeTypeArgs);
3638 var superForwarder = _getSuperHelperFor(
3639 memberName, forwardedAccess, fakeTypeArgs ?? const []);
3640
3641 return js.call('this.#(#)', [superForwarder, typeArgs ?? const []]);
3642 }
3643
3644 List<JS.Expression> _getTypeArgs(Element member, DartType instantiated) {
3645 DartType type;
3646 if (member is ExecutableElement) {
3647 type = member.type;
3648 } else if (member is VariableElement) {
3649 type = member.type;
3650 }
3651
3652 // TODO(jmesserly): handle explicitly passed type args.
3653 if (type == null) return null;
3654 return _emitFunctionTypeArguments(type, instantiated);
3655 }
3656
3657 JS.Expression _emitAccessInternal(Expression target, Element member,
3658 String memberName, List<JS.Expression> typeArgs) {
3547 bool isStatic = member is ClassMemberElement && member.isStatic; 3659 bool isStatic = member is ClassMemberElement && member.isStatic;
3548 var name = _emitMemberName(memberId.name, 3660 var name = _emitMemberName(memberName,
3549 type: getStaticType(target), isStatic: isStatic); 3661 type: getStaticType(target), isStatic: isStatic);
3550 if (DynamicInvoke.get(target)) { 3662 if (DynamicInvoke.get(target)) {
3551 return js.call('dart.dload(#, #)', [_visit(target), name]); 3663 return js.call('dart.dload(#, #)', [_visit(target), name]);
3552 } 3664 }
3553 3665
3554 var jsTarget = _visit(target); 3666 var jsTarget = _visit(target);
3555 bool isSuper = jsTarget is JS.Super; 3667 bool isSuper = jsTarget is JS.Super;
3556 3668
3557 if (isSuper && member is FieldElement && !member.isSynthetic) { 3669 if (isSuper && member is FieldElement && !member.isSynthetic) {
3558 // If super.x is actually a field, then x is an instance property since 3670 // If super.x is actually a field, then x is an instance property since
3559 // subclasses cannot override x. 3671 // subclasses cannot override x.
3560 jsTarget = new JS.This(); 3672 jsTarget = new JS.This();
3561 } 3673 }
3562 3674
3563 JS.Expression result; 3675 JS.Expression result;
3564 if (member != null && member is MethodElement && !isStatic) { 3676 if (member != null && member is MethodElement && !isStatic) {
3565 // Tear-off methods: explicitly bind it. 3677 // Tear-off methods: explicitly bind it.
3566 if (isSuper) { 3678 if (isSuper) {
3567 result = js.call('dart.bind(this, #, #.#)', [name, jsTarget, name]); 3679 result = js.call('dart.bind(this, #, #.#)', [name, jsTarget, name]);
3568 } else if (_isObjectMemberCall(target, memberId.name)) { 3680 } else if (_isObjectMemberCall(target, memberName)) {
3569 result = js.call('dart.bind(#, #, dart.#)', [jsTarget, name, name]); 3681 result = js.call('dart.bind(#, #, dart.#)', [jsTarget, name, name]);
3570 } else { 3682 } else {
3571 result = js.call('dart.bind(#, #)', [jsTarget, name]); 3683 result = js.call('dart.bind(#, #)', [jsTarget, name]);
3572 } 3684 }
3573 } else if (_isObjectMemberCall(target, memberId.name)) { 3685 } else if (_isObjectMemberCall(target, memberName)) {
3574 result = js.call('dart.#(#)', [name, jsTarget]); 3686 result = js.call('dart.#(#)', [name, jsTarget]);
3575 } else { 3687 } else {
3576 result = js.call('#.#', [jsTarget, name]); 3688 result = js.call('#.#', [jsTarget, name]);
3577 } 3689 }
3578 return _applyFunctionTypeArguments(result, member, resultType); 3690 if (typeArgs == null) {
3579 } 3691 return result;
3580
3581 /// If this is an inferred instantiation of a generic function/method, this
3582 /// will add the inferred type arguments.
3583 JS.Expression _applyFunctionTypeArguments(
3584 JS.Expression result, Element member, DartType instantiated) {
3585 DartType type;
3586 if (member is ExecutableElement) {
3587 type = member.type;
3588 } else if (member is VariableElement) {
3589 type = member.type;
3590 } 3692 }
3591
3592 // TODO(jmesserly): handle explicitly passed type args.
3593 if (type == null) return result;
3594 var typeArgs = _emitFunctionTypeArguments(type, instantiated);
3595 if (typeArgs == null) return result;
3596 return js.call('dart.gbind(#, #)', [result, typeArgs]); 3693 return js.call('dart.gbind(#, #)', [result, typeArgs]);
3597 } 3694 }
3598 3695
3599 /// Emits a generic send, like an operator method. 3696 /// Emits a generic send, like an operator method.
3600 /// 3697 ///
3601 /// **Please note** this function does not support method invocation syntax 3698 /// **Please note** this function does not support method invocation syntax
3602 /// `obj.name(args)` because that could be a getter followed by a call. 3699 /// `obj.name(args)` because that could be a getter followed by a call.
3603 /// See [visitMethodInvocation]. 3700 /// See [visitMethodInvocation].
3604 JS.Expression _emitSend( 3701 JS.Expression _emitSend(
3605 Expression target, String name, List<Expression> args) { 3702 Expression target, String name, List<Expression> args) {
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
3783 } 3880 }
3784 3881
3785 @override 3882 @override
3786 visitContinueStatement(ContinueStatement node) { 3883 visitContinueStatement(ContinueStatement node) {
3787 var label = node.label; 3884 var label = node.label;
3788 return new JS.Continue(label?.name); 3885 return new JS.Continue(label?.name);
3789 } 3886 }
3790 3887
3791 @override 3888 @override
3792 visitTryStatement(TryStatement node) { 3889 visitTryStatement(TryStatement node) {
3793 return new JS.Try(_visit(node.body), _visitCatch(node.catchClauses), 3890 var savedSuperAllowed = _superAllowed;
3794 _visit(node.finallyBlock)); 3891 _superAllowed = false;
3892 var finallyBlock = _visit(node.finallyBlock);
3893 _superAllowed = savedSuperAllowed;
3894 return new JS.Try(
3895 _visit(node.body), _visitCatch(node.catchClauses), finallyBlock);
3795 } 3896 }
3796 3897
3797 _visitCatch(NodeList<CatchClause> clauses) { 3898 _visitCatch(NodeList<CatchClause> clauses) {
3798 if (clauses == null || clauses.isEmpty) return null; 3899 if (clauses == null || clauses.isEmpty) return null;
3799 3900
3800 // TODO(jmesserly): need a better way to get a temporary variable. 3901 // TODO(jmesserly): need a better way to get a temporary variable.
3801 // This could incorrectly shadow a user's name. 3902 // This could incorrectly shadow a user's name.
3802 var savedCatch = _catchParameter; 3903 var savedCatch = _catchParameter;
3803 3904
3804 if (clauses.length == 1 && clauses.single.exceptionParameter != null) { 3905 if (clauses.length == 1 && clauses.single.exceptionParameter != null) {
(...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after
4292 } 4393 }
4293 4394
4294 bool isLibraryPrefix(Expression node) => 4395 bool isLibraryPrefix(Expression node) =>
4295 node is SimpleIdentifier && node.staticElement is PrefixElement; 4396 node is SimpleIdentifier && node.staticElement is PrefixElement;
4296 4397
4297 LibraryElement _getLibrary(AnalysisContext c, String uri) => 4398 LibraryElement _getLibrary(AnalysisContext c, String uri) =>
4298 c.computeLibraryElement(c.sourceFactory.forUri(uri)); 4399 c.computeLibraryElement(c.sourceFactory.forUri(uri));
4299 4400
4300 bool _isDartRuntime(LibraryElement l) => 4401 bool _isDartRuntime(LibraryElement l) =>
4301 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; 4402 l.isInSdk && l.source.uri.toString() == 'dart:_runtime';
OLDNEW
« no previous file with comments | « lib/runtime/dart_sdk.js ('k') | lib/src/compiler/source_map_printer.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698