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

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

Issue 2515353003: Support lazy JS types. (Closed)
Patch Set: rebased Created 4 years, 1 month 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 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 290 matching lines...) Expand 10 before | Expand all | Expand 10 after
301 items.addAll(_typeTable.discharge()); 301 items.addAll(_typeTable.discharge());
302 302
303 // Add the module's code (produced by visiting compilation units, above) 303 // Add the module's code (produced by visiting compilation units, above)
304 _copyAndFlattenBlocks(items, _moduleItems); 304 _copyAndFlattenBlocks(items, _moduleItems);
305 305
306 // Build the module. 306 // Build the module.
307 return new JS.Program(items, name: _buildUnit.name); 307 return new JS.Program(items, name: _buildUnit.name);
308 } 308 }
309 309
310 List<String> _getJSName(Element e) { 310 List<String> _getJSName(Element e) {
311 if (findAnnotation(e.library, isPublicJSAnnotation) == null) { 311 if (e.library == null ||
Jennifer Messerly 2016/11/22 18:18:19 nice fix. I'm curious, do you know how this happen
Jacob 2016/11/22 18:51:37 I suspect one of dynamic or bottom doesn't show up
312 findAnnotation(e.library, isPublicJSAnnotation) == null) {
312 return null; 313 return null;
313 } 314 }
314 315
315 var libraryJSName = getAnnotationName(e.library, isPublicJSAnnotation); 316 var libraryJSName = getAnnotationName(e.library, isPublicJSAnnotation);
316 var libraryPrefix = <String>[]; 317 var libraryPrefix = <String>[];
317 if (libraryJSName != null && libraryJSName.isNotEmpty) { 318 if (libraryJSName != null && libraryJSName.isNotEmpty) {
318 libraryPrefix.addAll(libraryJSName.split('.')); 319 libraryPrefix.addAll(libraryJSName.split('.'));
319 } 320 }
320 321
321 String elementJSName; 322 String elementJSName;
322 if (findAnnotation(e, isPublicJSAnnotation) != null) { 323 if (findAnnotation(e, isPublicJSAnnotation) != null) {
323 elementJSName = getAnnotationName(e, isPublicJSAnnotation) ?? ''; 324 elementJSName = getAnnotationName(e, isPublicJSAnnotation) ?? '';
324 } 325 }
326
325 if (e is TopLevelVariableElement && 327 if (e is TopLevelVariableElement &&
326 e.getter != null && 328 e.getter != null &&
327 (e.getter.isExternal || 329 (e.getter.isExternal ||
328 findAnnotation(e.getter, isPublicJSAnnotation) != null)) { 330 findAnnotation(e.getter, isPublicJSAnnotation) != null)) {
329 elementJSName = getAnnotationName(e.getter, isPublicJSAnnotation) ?? ''; 331 elementJSName = getAnnotationName(e.getter, isPublicJSAnnotation) ?? '';
330 } 332 }
331 if (elementJSName == null) return null; 333 if (elementJSName == null) return null;
332 334
333 var elementJSParts = <String>[]; 335 var elementJSParts = <String>[];
334 if (elementJSName.isNotEmpty) { 336 if (elementJSName.isNotEmpty) {
(...skipping 2363 matching lines...) Expand 10 before | Expand all | Expand 10 after
2698 2700
2699 var name = element.name; 2701 var name = element.name;
2700 2702
2701 // Unqualified class member. This could mean implicit-this, or implicit 2703 // Unqualified class member. This could mean implicit-this, or implicit
2702 // call to a static from the same class. 2704 // call to a static from the same class.
2703 if (element is ClassMemberElement && element is! ConstructorElement) { 2705 if (element is ClassMemberElement && element is! ConstructorElement) {
2704 bool isStatic = element.isStatic; 2706 bool isStatic = element.isStatic;
2705 var type = element.enclosingElement.type; 2707 var type = element.enclosingElement.type;
2706 var member = _emitMemberName(name, isStatic: isStatic, type: type); 2708 var member = _emitMemberName(name, isStatic: isStatic, type: type);
2707 2709
2708 // For static methods, we add the raw type name, without generics or
2709 // library prefix. We don't need those because static calls can't use
2710 // the generic type.
2711 if (isStatic) { 2710 if (isStatic) {
2712 var dynType = _emitType(fillDynamicTypeArgs(type)); 2711 var dynType = _emitStaticAccess(type);
2713 return new JS.PropertyAccess(dynType, member); 2712 return new JS.PropertyAccess(dynType, member);
2714 } 2713 }
2715 2714
2716 // For instance members, we add implicit-this. 2715 // For instance members, we add implicit-this.
2717 // For method tear-offs, we ensure it's a bound method. 2716 // For method tear-offs, we ensure it's a bound method.
2718 var tearOff = element is MethodElement && !inInvocationContext(node); 2717 var tearOff = element is MethodElement && !inInvocationContext(node);
2719 if (tearOff) return _callHelper('bind(this, #)', member); 2718 if (tearOff) return _callHelper('bind(this, #)', member);
2720 return js.call('this.#', member); 2719 return js.call('this.#', member);
2721 } 2720 }
2722 2721
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
2901 ]; 2900 ];
2902 } else { 2901 } else {
2903 typeParts = [ 2902 typeParts = [
2904 js.call('(#) => {#; return #;}', [tf, names, parts]) 2903 js.call('(#) => {#; return #;}', [tf, names, parts])
2905 ]; 2904 ];
2906 } 2905 }
2907 } 2906 }
2908 return typeParts; 2907 return typeParts;
2909 } 2908 }
2910 2909
2910 /// Emits an expression that lets you access statics on a [[type]] from code.
Jennifer Messerly 2016/11/22 18:18:19 comment nit: I don't think you want two brackets,
Jacob 2016/11/22 18:51:37 [[[done]]]
2911 ///
2912 /// If [nameType] is true, then the type will be named. In addition,
2913 /// if [hoistType] is true, then the named type will be hoisted.
2914 JS.Expression _emitConstructorAccess(DartType type,
Jennifer Messerly 2016/11/22 18:18:19 just wanted to say, this is factored in a lovely w
Jacob 2016/11/22 18:51:36 yay!
2915 {bool nameType: true, bool hoistType: true}) {
2916 var interop = _emitJSInterop(type.element);
Jennifer Messerly 2016/11/22 18:18:19 this could be: return _emitJSInterop(type.elemen
Jacob 2016/11/22 18:51:36 Done.
2917 if (interop != null) return interop;
2918
2919 // TODO(jacobr): we could consider duplicating logic instead of calling
Jennifer Messerly 2016/11/22 18:18:19 personally I'm not sure we need this TODO ... we c
Jacob 2016/11/22 18:51:36 sounds good. My only concern is that this is only
2920 // through to the somewhat unrelated _emitType mode. Calling _emitType here
2921 // is acceptable as the type cannot be a JS interop type.
2922 return _emitType(type, nameType: nameType, hoistType: hoistType);
2923 }
2924
2925 /// Emits an expression that lets you access statics on a [[type]] from code.
Jennifer Messerly 2016/11/22 18:18:19 comment nit again: [type] instead of [[type]]
Jacob 2016/11/22 18:51:36 Done.
2926 JS.Expression _emitStaticAccess(DartType type) {
2927 // Make sure we aren't attempting to emit a static access path to a type
2928 // that does not have a valid static access path.
2929 assert(!type.isVoid &&
2930 !type.isDynamic &&
2931 !type.isBottom &&
2932 type is! TypeParameterType);
2933
2934 // For statics, we add the raw type name, without generics or
2935 // library prefix. We don't need those because static calls can't use
2936 // the generic type.
2937 type = fillDynamicTypeArgs(type);
2938 var element = type.element;
2939 _declareBeforeUse(element);
2940
2941 var interop = _emitJSInterop(element);
2942 if (interop != null) return interop;
2943
2944 assert(type.name != '' && type.name != null);
2945
2946 return _emitTopLevelNameNoInterop(element);
2947 }
2948
2911 /// Emits a Dart [type] into code. 2949 /// Emits a Dart [type] into code.
2912 /// 2950 ///
2913 /// If [lowerTypedef] is set, a typedef will be expanded as if it were a 2951 /// If [lowerTypedef] is set, a typedef will be expanded as if it were a
2914 /// function type. Similarly if [lowerGeneric] is set, the `List$()` form 2952 /// function type. Similarly if [lowerGeneric] is set, the `List$()` form
2915 /// will be used instead of `List`. These flags are used when generating 2953 /// will be used instead of `List`. These flags are used when generating
2916 /// the definitions for typedefs and generic types, respectively. 2954 /// the definitions for typedefs and generic types, respectively.
2917 /// 2955 ///
2918 /// If [subClass] is set, then we are setting the base class for the given 2956 /// If [subClass] is set, then we are setting the base class for the given
2919 /// class and should emit the given [className], which will already be 2957 /// class and should emit the given [className], which will already be
2920 /// defined. 2958 /// defined.
2921 /// 2959 ///
2922 /// If [nameType] is true, then the type will be named. In addition, 2960 /// If [nameType] is true, then the type will be named. In addition,
2923 /// if [hoistType] is true, then the named type will be hoisted. 2961 /// if [hoistType] is true, then the named type will be hoisted.
2924 JS.Expression _emitType(DartType type, 2962 JS.Expression _emitType(DartType type,
2925 {bool lowerTypedef: false, 2963 {bool lowerTypedef: false,
2926 bool lowerGeneric: false, 2964 bool lowerGeneric: false,
2927 bool nameType: true, 2965 bool nameType: true,
2928 bool hoistType: true, 2966 bool hoistType: true,
2929 ClassElement subClass, 2967 ClassElement subClass,
2930 JS.Expression className}) { 2968 JS.Expression className}) {
2931 // The void and dynamic types are not defined in core. 2969 // The void and dynamic types are not defined in core.
2932 if (type.isVoid) { 2970 if (type.isVoid) {
2933 return _callHelper('void'); 2971 return _callHelper('void');
2934 } else if (type.isDynamic) { 2972 } else if (type.isDynamic) {
2935 return _callHelper('dynamic'); 2973 return _callHelper('dynamic');
2936 } else if (type.isBottom) { 2974 } else if (type.isBottom) {
2937 return _callHelper('bottom'); 2975 return _callHelper('bottom');
2938 } 2976 }
2939 2977
2940 _declareBeforeUse(type.element); 2978 var element = type.element;
2979 _declareBeforeUse(element);
2980
2981 var interop = _emitJSInterop(element);
2982 // Type parameters don't matter as JS interop types cannot be reified.
Jennifer Messerly 2016/11/22 18:18:19 should we error out if the type is generic? I'm g
Jacob 2016/11/22 18:51:36 Would really like to allow it assuming JS interop
2983 // We have to use lazy JS types because until we have proper module
Jennifer Messerly 2016/11/22 18:18:19 This comment is good, but maybe a code example wou
Jacob 2016/11/22 18:51:37 Done.
2984 // loading for JS libraries bundled with Dart libraries, we will sometimes
2985 // need to load Dart libraries before the corresponding JS libraries are
2986 // actually loaded.
2987 if (interop != null) {
2988 if (_isObjectLiteral(element)) {
2989 return _callHelper(
2990 'lazyAnonymousJSType(#)', js.string(element.displayName));
2991 } else {
2992 return _callHelper('lazyJSType(() => #, #)',
2993 [interop, js.string(_getJSName(element).join('.'))]);
2994 }
2995 }
2941 2996
2942 // TODO(jmesserly): like constants, should we hoist function types out of 2997 // TODO(jmesserly): like constants, should we hoist function types out of
2943 // methods? Similar issue with generic types. For all of these, we may want 2998 // methods? Similar issue with generic types. For all of these, we may want
2944 // to canonicalize them too, at least when inside the same library. 2999 // to canonicalize them too, at least when inside the same library.
2945 var name = type.name; 3000 var name = type.name;
2946 var element = type.element;
2947 if (name == '' || name == null || lowerTypedef) { 3001 if (name == '' || name == null || lowerTypedef) {
2948 // TODO(jmesserly): should we change how typedefs work? They currently 3002 // TODO(jmesserly): should we change how typedefs work? They currently
2949 // go through use similar logic as generic classes. This makes them 3003 // go through use similar logic as generic classes. This makes them
2950 // different from universal function types. 3004 // different from universal function types.
2951 return _emitFunctionType(type as FunctionType, 3005 return _emitFunctionType(type as FunctionType,
2952 lowerTypedef: lowerTypedef, nameType: nameType, hoistType: hoistType); 3006 lowerTypedef: lowerTypedef, nameType: nameType, hoistType: hoistType);
2953 } 3007 }
2954 3008
2955 if (type is TypeParameterType) { 3009 if (type is TypeParameterType) {
2956 _typeParamInConst?.add(type); 3010 _typeParamInConst?.add(type);
2957 return new JS.Identifier(name); 3011 return new JS.Identifier(name);
2958 } 3012 }
2959 3013
2960 if (type == subClass?.type) { 3014 if (type == subClass?.type) return className;
Jennifer Messerly 2016/11/22 18:18:19 nice!
Jacob 2016/11/22 18:51:36 Acknowledged.
2961 return className;
2962 }
2963 3015
2964 if (type is ParameterizedType) { 3016 if (type is ParameterizedType) {
2965 var args = type.typeArguments; 3017 var args = type.typeArguments;
2966 Iterable jsArgs = null; 3018 Iterable jsArgs = null;
2967 if (args.any((a) => !a.isDynamic)) { 3019 if (args.any((a) => !a.isDynamic)) {
2968 jsArgs = args.map((x) => _emitType(x, 3020 jsArgs = args.map((x) => _emitType(x,
2969 nameType: nameType, 3021 nameType: nameType,
2970 hoistType: hoistType, 3022 hoistType: hoistType,
2971 subClass: subClass, 3023 subClass: subClass,
2972 className: className)); 3024 className: className));
2973 } else if (lowerGeneric || element == subClass) { 3025 } else if (lowerGeneric || element == subClass) {
2974 jsArgs = []; 3026 jsArgs = [];
2975 } 3027 }
2976 if (jsArgs != null) { 3028 if (jsArgs != null) {
2977 var genericName = _emitTopLevelName(element, suffix: '\$'); 3029 var genericName = _emitTopLevelName(element, suffix: '\$');
2978 var typeRep = js.call('#(#)', [genericName, jsArgs]); 3030 var typeRep = js.call('#(#)', [genericName, jsArgs]);
2979 return nameType 3031 return nameType
2980 ? _typeTable.nameType(type, typeRep, hoistType: hoistType) 3032 ? _typeTable.nameType(type, typeRep, hoistType: hoistType)
2981 : typeRep; 3033 : typeRep;
2982 } 3034 }
2983 } 3035 }
2984 3036
2985 return _emitTopLevelName(element); 3037 return _emitTopLevelNameNoInterop(element);
2986 } 3038 }
2987 3039
2988 JS.PropertyAccess _emitTopLevelName(Element e, {String suffix: ''}) { 3040 JS.PropertyAccess _emitTopLevelName(Element e, {String suffix: ''}) {
2989 var interop = _emitJSInterop(e); 3041 var interop = _emitJSInterop(e);
2990 if (interop != null) return interop; 3042 if (interop != null) return interop;
3043 return _emitTopLevelNameNoInterop(e, suffix: suffix);
3044 }
3045
3046 JS.PropertyAccess _emitTopLevelNameNoInterop(Element e, {String suffix: ''}) {
2991 String name = getJSExportName(e) + suffix; 3047 String name = getJSExportName(e) + suffix;
2992 return new JS.PropertyAccess( 3048 return new JS.PropertyAccess(
2993 emitLibraryName(e.library), _propertyName(name)); 3049 emitLibraryName(e.library), _propertyName(name));
2994 } 3050 }
2995 3051
2996 @override 3052 @override
2997 JS.Expression visitAssignmentExpression(AssignmentExpression node) { 3053 JS.Expression visitAssignmentExpression(AssignmentExpression node) {
2998 var left = node.leftHandSide; 3054 var left = node.leftHandSide;
2999 var right = node.rightHandSide; 3055 var right = node.rightHandSide;
3000 if (node.operator.type == TokenType.EQ) return _emitSet(left, right); 3056 if (node.operator.type == TokenType.EQ) return _emitSet(left, right);
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
3204 } 3260 }
3205 3261
3206 /// Emits assignment to a static field element or property. 3262 /// Emits assignment to a static field element or property.
3207 JS.Expression _emitSetStaticProperty( 3263 JS.Expression _emitSetStaticProperty(
3208 Expression lhs, Element element, Expression rhs) { 3264 Expression lhs, Element element, Expression rhs) {
3209 // For static methods, we add the raw type name, without generics or 3265 // For static methods, we add the raw type name, without generics or
3210 // library prefix. We don't need those because static calls can't use 3266 // library prefix. We don't need those because static calls can't use
3211 // the generic type. 3267 // the generic type.
3212 ClassElement classElement = element.enclosingElement; 3268 ClassElement classElement = element.enclosingElement;
3213 var type = classElement.type; 3269 var type = classElement.type;
3214 var dynType = _emitType(fillDynamicTypeArgs(type)); 3270 var dynType = _emitStaticAccess(type);
3215 var member = _emitMemberName(element.name, isStatic: true, type: type); 3271 var member = _emitMemberName(element.name, isStatic: true, type: type);
3216 return _visit(rhs).toAssignExpression( 3272 return _visit(rhs).toAssignExpression(
3217 annotate(new JS.PropertyAccess(dynType, member), lhs)); 3273 annotate(new JS.PropertyAccess(dynType, member), lhs));
3218 } 3274 }
3219 3275
3220 /// Emits an assignment to the [element] property of instance referenced by 3276 /// Emits an assignment to the [element] property of instance referenced by
3221 /// [jsTarget]. 3277 /// [jsTarget].
3222 JS.Expression _emitWriteInstanceProperty(Expression lhs, 3278 JS.Expression _emitWriteInstanceProperty(Expression lhs,
3223 JS.Expression jsTarget, Element element, JS.Expression value) { 3279 JS.Expression jsTarget, Element element, JS.Expression value) {
3224 String memberName = element.name; 3280 String memberName = element.name;
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
3284 visitMethodInvocation(MethodInvocation node) { 3340 visitMethodInvocation(MethodInvocation node) {
3285 if (_isDeferredLoadLibrary(node.target, node.methodName)) { 3341 if (_isDeferredLoadLibrary(node.target, node.methodName)) {
3286 // We are calling loadLibrary() on a deferred library prefix. 3342 // We are calling loadLibrary() on a deferred library prefix.
3287 return _callHelper('loadLibrary()'); 3343 return _callHelper('loadLibrary()');
3288 } 3344 }
3289 3345
3290 if (node.operator?.lexeme == '?.') { 3346 if (node.operator?.lexeme == '?.') {
3291 return _emitNullSafe(node); 3347 return _emitNullSafe(node);
3292 } 3348 }
3293 3349
3350 // SSS
Jennifer Messerly 2016/11/22 18:18:19 remove this?
Jacob 2016/11/22 18:51:37 Done.
3294 var result = _emitForeignJS(node); 3351 var result = _emitForeignJS(node);
3295 if (result != null) return result; 3352 if (result != null) return result;
3296 3353
3297 var target = _getTarget(node); 3354 var target = _getTarget(node);
3298 if (target == null || isLibraryPrefix(target)) { 3355 if (target == null || isLibraryPrefix(target)) {
3299 return _emitFunctionCall(node); 3356 return _emitFunctionCall(node);
3300 } 3357 }
3301 if (node.methodName.name == 'call') { 3358 if (node.methodName.name == 'call') {
3302 var targetType = target.staticType; 3359 var targetType = target.staticType;
3303 if (targetType is FunctionType) { 3360 if (targetType is FunctionType) {
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
3355 JS.Expression _getSuperHelperFor(String name, JS.Expression forwardedCall, 3412 JS.Expression _getSuperHelperFor(String name, JS.Expression forwardedCall,
3356 List<JS.Expression> helperArgs) { 3413 List<JS.Expression> helperArgs) {
3357 var helperMethod = 3414 var helperMethod =
3358 new JS.Fun(helperArgs, new JS.Block([new JS.Return(forwardedCall)])); 3415 new JS.Fun(helperArgs, new JS.Block([new JS.Return(forwardedCall)]));
3359 var helperMethodName = new JS.TemporaryId('super\$$name'); 3416 var helperMethodName = new JS.TemporaryId('super\$$name');
3360 _superHelperSymbols.add(helperMethodName); 3417 _superHelperSymbols.add(helperMethodName);
3361 _superHelpers.add(new JS.Method(helperMethodName, helperMethod)); 3418 _superHelpers.add(new JS.Method(helperMethodName, helperMethod));
3362 return helperMethodName; 3419 return helperMethodName;
3363 } 3420 }
3364 3421
3422 JS.Expression _emitTarget(Expression target, Element element, bool isStatic) {
3423 if (isStatic) {
3424 if (element is ConstructorElement)
3425 return _emitConstructorAccess(element.enclosingElement.type);
Jennifer Messerly 2016/11/22 18:18:19 style nit: should have curly braces if it's more t
Jacob 2016/11/22 18:51:36 Done.
3426 if (element is ExecutableElement)
3427 return _emitStaticAccess(
Jennifer Messerly 2016/11/22 18:18:19 same here
Jacob 2016/11/22 18:51:36 Done.
3428 (element.enclosingElement as ClassElement).type);
3429 }
3430 return _visit(target);
3431 }
3432
3365 /// Emits a (possibly generic) instance method call. 3433 /// Emits a (possibly generic) instance method call.
3366 JS.Expression _emitMethodCallInternal( 3434 JS.Expression _emitMethodCallInternal(
3367 Expression target, 3435 Expression target,
3368 MethodInvocation node, 3436 MethodInvocation node,
3369 List<JS.Expression> args, 3437 List<JS.Expression> args,
3370 List<JS.Expression> typeArgs) { 3438 List<JS.Expression> typeArgs) {
3371 var type = getStaticType(target); 3439 var type = getStaticType(target);
3372 var name = node.methodName.name; 3440 var name = node.methodName.name;
3373 var element = node.methodName.staticElement; 3441 var element = node.methodName.staticElement;
3374 bool isStatic = element is ExecutableElement && element.isStatic; 3442 bool isStatic = element is ExecutableElement && element.isStatic;
3375 var memberName = _emitMemberName(name, type: type, isStatic: isStatic); 3443 var memberName = _emitMemberName(name, type: type, isStatic: isStatic);
3376 3444
3377 JS.Expression jsTarget = _visit(target); 3445 JS.Expression jsTarget = _emitTarget(target, element, isStatic);
3378 if (isDynamicInvoke(target) || isDynamicInvoke(node.methodName)) { 3446 if (isDynamicInvoke(target) || isDynamicInvoke(node.methodName)) {
3379 if (_inWhitelistCode(target)) { 3447 if (_inWhitelistCode(target)) {
3380 var vars = <JS.MetaLetVariable, JS.Expression>{}; 3448 var vars = <JS.MetaLetVariable, JS.Expression>{};
3381 var l = _visit(_bindValue(vars, 'l', target)); 3449 var l = _visit(_bindValue(vars, 'l', target));
3382 jsTarget = new JS.MetaLet(vars, [ 3450 jsTarget = new JS.MetaLet(vars, [
3383 js.call('(#[(#[#._extensionType]) ? #[#] : #]).bind(#)', [ 3451 js.call('(#[(#[#._extensionType]) ? #[#] : #]).bind(#)', [
3384 l, 3452 l,
3385 l, 3453 l,
3386 _runtimeModule, 3454 _runtimeModule,
3387 _extensionSymbolsModule, 3455 _extensionSymbolsModule,
(...skipping 504 matching lines...) Expand 10 before | Expand all | Expand 10 after
3892 : parent.getSetter(element.name); 3960 : parent.getSetter(element.name);
3893 } 3961 }
3894 return null; 3962 return null;
3895 } 3963 }
3896 3964
3897 JS.Expression _emitConstructorName( 3965 JS.Expression _emitConstructorName(
3898 ConstructorElement element, DartType type, SimpleIdentifier name) { 3966 ConstructorElement element, DartType type, SimpleIdentifier name) {
3899 var classElem = element.enclosingElement; 3967 var classElem = element.enclosingElement;
3900 var interop = _emitJSInterop(classElem); 3968 var interop = _emitJSInterop(classElem);
3901 if (interop != null) return interop; 3969 if (interop != null) return interop;
3902 var typeName = _emitType(type); 3970 var typeName = _emitConstructorAccess(type);
3903 if (name != null || element.isFactory) { 3971 if (name != null || element.isFactory) {
3904 var namedCtor = _constructorName(element); 3972 var namedCtor = _constructorName(element);
3905 return new JS.PropertyAccess(typeName, namedCtor); 3973 return new JS.PropertyAccess(typeName, namedCtor);
3906 } 3974 }
3907 return typeName; 3975 return typeName;
3908 } 3976 }
3909 3977
3910 @override 3978 @override
3911 visitConstructorName(ConstructorName node) { 3979 visitConstructorName(ConstructorName node) {
3912 return _emitConstructorName(node.staticElement, node.type.type, node.name); 3980 return _emitConstructorName(node.staticElement, node.type.type, node.name);
3913 } 3981 }
3914 3982
3915 JS.Expression _emitInstanceCreationExpression( 3983 JS.Expression _emitInstanceCreationExpression(
3916 ConstructorElement element, 3984 ConstructorElement element,
3917 DartType type, 3985 DartType type,
3918 SimpleIdentifier name, 3986 SimpleIdentifier name,
3919 ArgumentList argumentList, 3987 ArgumentList argumentList,
3920 bool isConst) { 3988 bool isConst) {
3921 JS.Expression emitNew() { 3989 JS.Expression emitNew() {
3922 JS.Expression ctor; 3990 JS.Expression ctor;
3923 bool isFactory = false; 3991 bool isFactory = false;
3924 bool isNative = false; 3992 bool isNative = false;
3925 if (element == null) { 3993 if (element == null) {
3926 // TODO(jmesserly): this only happens if we had a static error. 3994 // TODO(jmesserly): this only happens if we had a static error.
3927 // Should we generate a throw instead? 3995 // Should we generate a throw instead?
3928 ctor = _emitType(type, 3996 ctor = _emitConstructorAccess(type,
3929 nameType: options.hoistInstanceCreation, 3997 nameType: options.hoistInstanceCreation,
3930 hoistType: options.hoistInstanceCreation); 3998 hoistType: options.hoistInstanceCreation);
3931 if (name != null) { 3999 if (name != null) {
3932 ctor = new JS.PropertyAccess(ctor, _propertyName(name.name)); 4000 ctor = new JS.PropertyAccess(ctor, _propertyName(name.name));
3933 } 4001 }
3934 } else { 4002 } else {
3935 ctor = _emitConstructorName(element, type, name); 4003 ctor = _emitConstructorName(element, type, name);
3936 isFactory = element.isFactory; 4004 isFactory = element.isFactory;
3937 var classElem = element.enclosingElement; 4005 var classElem = element.enclosingElement;
3938 isNative = _isJSNative(classElem); 4006 isNative = _isJSNative(classElem);
(...skipping 803 matching lines...) Expand 10 before | Expand all | Expand 10 after
4742 var l = _visit(_bindValue(vars, 'l', target)); 4810 var l = _visit(_bindValue(vars, 'l', target));
4743 return new JS.MetaLet(vars, [ 4811 return new JS.MetaLet(vars, [
4744 js.call('(#[#._extensionType]) ? #[#[#]] : #.#', 4812 js.call('(#[#._extensionType]) ? #[#[#]] : #.#',
4745 [l, _runtimeModule, l, _extensionSymbolsModule, name, l, name]) 4813 [l, _runtimeModule, l, _extensionSymbolsModule, name, l, name])
4746 ]); 4814 ]);
4747 } 4815 }
4748 return _callHelper('#(#, #)', 4816 return _callHelper('#(#, #)',
4749 [_emitDynamicOperationName('dload'), _visit(target), name]); 4817 [_emitDynamicOperationName('dload'), _visit(target), name]);
4750 } 4818 }
4751 4819
4752 var jsTarget = _visit(target); 4820 var jsTarget = _emitTarget(target, member, isStatic);
4753 bool isSuper = jsTarget is JS.Super; 4821 bool isSuper = jsTarget is JS.Super;
4754 4822
4755 if (isSuper && member is FieldElement && !member.isSynthetic) { 4823 if (isSuper && member is FieldElement && !member.isSynthetic) {
4756 // If super.x is actually a field, then x is an instance property since 4824 // If super.x is actually a field, then x is an instance property since
4757 // subclasses cannot override x. 4825 // subclasses cannot override x.
4758 jsTarget = new JS.This(); 4826 jsTarget = new JS.This();
4759 } 4827 }
4760 4828
4761 JS.Expression result; 4829 JS.Expression result;
4762 if (member != null && member is MethodElement && !isStatic) { 4830 if (member != null && member is MethodElement && !isStatic) {
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after
5116 5184
5117 @override 5185 @override
5118 visitNullLiteral(NullLiteral node) => new JS.LiteralNull(); 5186 visitNullLiteral(NullLiteral node) => new JS.LiteralNull();
5119 5187
5120 @override 5188 @override
5121 visitSymbolLiteral(SymbolLiteral node) { 5189 visitSymbolLiteral(SymbolLiteral node) {
5122 JS.Expression emitSymbol() { 5190 JS.Expression emitSymbol() {
5123 // TODO(vsm): When we canonicalize, we need to treat private symbols 5191 // TODO(vsm): When we canonicalize, we need to treat private symbols
5124 // correctly. 5192 // correctly.
5125 var name = js.string(node.components.join('.'), "'"); 5193 var name = js.string(node.components.join('.'), "'");
5126 return js.call('#.new(#)', [_emitType(types.symbolType), name]); 5194 return js
5195 .call('#.new(#)', [_emitConstructorAccess(types.symbolType), name]);
5127 } 5196 }
5128 5197
5129 return _emitConst(emitSymbol); 5198 return _emitConst(emitSymbol);
5130 } 5199 }
5131 5200
5132 @override 5201 @override
5133 visitListLiteral(ListLiteral node) { 5202 visitListLiteral(ListLiteral node) {
5134 var isConst = node.constKeyword != null; 5203 var isConst = node.constKeyword != null;
5135 JS.Expression emitList() { 5204 JS.Expression emitList() {
5136 JS.Expression list = new JS.ArrayInitializer( 5205 JS.Expression list = new JS.ArrayInitializer(
(...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after
5644 var targetIdentifier = target as SimpleIdentifier; 5713 var targetIdentifier = target as SimpleIdentifier;
5645 5714
5646 if (targetIdentifier.staticElement is! PrefixElement) return false; 5715 if (targetIdentifier.staticElement is! PrefixElement) return false;
5647 var prefix = targetIdentifier.staticElement as PrefixElement; 5716 var prefix = targetIdentifier.staticElement as PrefixElement;
5648 5717
5649 // The library the prefix is referring to must come from a deferred import. 5718 // The library the prefix is referring to must come from a deferred import.
5650 var containingLibrary = (target.root as CompilationUnit).element.library; 5719 var containingLibrary = (target.root as CompilationUnit).element.library;
5651 var imports = containingLibrary.getImportsWithPrefix(prefix); 5720 var imports = containingLibrary.getImportsWithPrefix(prefix);
5652 return imports.length == 1 && imports[0].isDeferred; 5721 return imports.length == 1 && imports[0].isDeferred;
5653 } 5722 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698