OLD | NEW |
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 Loading... |
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 || |
| 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 Loading... |
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 Loading... |
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. |
| 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, |
| 2915 {bool nameType: true, bool hoistType: true}) { |
| 2916 return _emitJSInterop(type.element) ?? |
| 2917 _emitType(type, nameType: nameType, hoistType: hoistType); |
| 2918 } |
| 2919 |
| 2920 /// Emits an expression that lets you access statics on a [type] from code. |
| 2921 JS.Expression _emitStaticAccess(DartType type) { |
| 2922 // Make sure we aren't attempting to emit a static access path to a type |
| 2923 // that does not have a valid static access path. |
| 2924 assert(!type.isVoid && |
| 2925 !type.isDynamic && |
| 2926 !type.isBottom && |
| 2927 type is! TypeParameterType); |
| 2928 |
| 2929 // For statics, we add the raw type name, without generics or |
| 2930 // library prefix. We don't need those because static calls can't use |
| 2931 // the generic type. |
| 2932 type = fillDynamicTypeArgs(type); |
| 2933 var element = type.element; |
| 2934 _declareBeforeUse(element); |
| 2935 |
| 2936 var interop = _emitJSInterop(element); |
| 2937 if (interop != null) return interop; |
| 2938 |
| 2939 assert(type.name != '' && type.name != null); |
| 2940 |
| 2941 return _emitTopLevelNameNoInterop(element); |
| 2942 } |
| 2943 |
2911 /// Emits a Dart [type] into code. | 2944 /// Emits a Dart [type] into code. |
2912 /// | 2945 /// |
2913 /// If [lowerTypedef] is set, a typedef will be expanded as if it were a | 2946 /// 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 | 2947 /// function type. Similarly if [lowerGeneric] is set, the `List$()` form |
2915 /// will be used instead of `List`. These flags are used when generating | 2948 /// will be used instead of `List`. These flags are used when generating |
2916 /// the definitions for typedefs and generic types, respectively. | 2949 /// the definitions for typedefs and generic types, respectively. |
2917 /// | 2950 /// |
2918 /// If [subClass] is set, then we are setting the base class for the given | 2951 /// 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 | 2952 /// class and should emit the given [className], which will already be |
2920 /// defined. | 2953 /// defined. |
2921 /// | 2954 /// |
2922 /// If [nameType] is true, then the type will be named. In addition, | 2955 /// If [nameType] is true, then the type will be named. In addition, |
2923 /// if [hoistType] is true, then the named type will be hoisted. | 2956 /// if [hoistType] is true, then the named type will be hoisted. |
2924 JS.Expression _emitType(DartType type, | 2957 JS.Expression _emitType(DartType type, |
2925 {bool lowerTypedef: false, | 2958 {bool lowerTypedef: false, |
2926 bool lowerGeneric: false, | 2959 bool lowerGeneric: false, |
2927 bool nameType: true, | 2960 bool nameType: true, |
2928 bool hoistType: true, | 2961 bool hoistType: true, |
2929 ClassElement subClass, | 2962 ClassElement subClass, |
2930 JS.Expression className}) { | 2963 JS.Expression className}) { |
2931 // The void and dynamic types are not defined in core. | 2964 // The void and dynamic types are not defined in core. |
2932 if (type.isVoid) { | 2965 if (type.isVoid) { |
2933 return _callHelper('void'); | 2966 return _callHelper('void'); |
2934 } else if (type.isDynamic) { | 2967 } else if (type.isDynamic) { |
2935 return _callHelper('dynamic'); | 2968 return _callHelper('dynamic'); |
2936 } else if (type.isBottom) { | 2969 } else if (type.isBottom) { |
2937 return _callHelper('bottom'); | 2970 return _callHelper('bottom'); |
2938 } | 2971 } |
2939 | 2972 |
2940 _declareBeforeUse(type.element); | 2973 var element = type.element; |
| 2974 _declareBeforeUse(element); |
| 2975 |
| 2976 var interop = _emitJSInterop(element); |
| 2977 // Type parameters don't matter as JS interop types cannot be reified. |
| 2978 // We have to use lazy JS types because until we have proper module |
| 2979 // loading for JS libraries bundled with Dart libraries, we will sometimes |
| 2980 // need to load Dart libraries before the corresponding JS libraries are |
| 2981 // actually loaded. |
| 2982 // Given a JS type such as: |
| 2983 // @JS('google.maps.Location') |
| 2984 // class Location { ... } |
| 2985 // We can't emit a reference to MyType because the JS library that defines |
| 2986 // it may be loaded after our code. So for now, we use a special lazy type |
| 2987 // object to represent MyType. |
| 2988 // Anonymous JS types do not have a corresponding concrete JS type so we |
| 2989 // have to use a helper to define them. |
| 2990 if (interop != null) { |
| 2991 if (_isObjectLiteral(element)) { |
| 2992 return _callHelper( |
| 2993 'lazyAnonymousJSType(#)', js.string(element.displayName)); |
| 2994 } else { |
| 2995 return _callHelper('lazyJSType(() => #, #)', |
| 2996 [interop, js.string(_getJSName(element).join('.'))]); |
| 2997 } |
| 2998 } |
2941 | 2999 |
2942 // TODO(jmesserly): like constants, should we hoist function types out of | 3000 // 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 | 3001 // 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. | 3002 // to canonicalize them too, at least when inside the same library. |
2945 var name = type.name; | 3003 var name = type.name; |
2946 var element = type.element; | |
2947 if (name == '' || name == null || lowerTypedef) { | 3004 if (name == '' || name == null || lowerTypedef) { |
2948 // TODO(jmesserly): should we change how typedefs work? They currently | 3005 // TODO(jmesserly): should we change how typedefs work? They currently |
2949 // go through use similar logic as generic classes. This makes them | 3006 // go through use similar logic as generic classes. This makes them |
2950 // different from universal function types. | 3007 // different from universal function types. |
2951 return _emitFunctionType(type as FunctionType, | 3008 return _emitFunctionType(type as FunctionType, |
2952 lowerTypedef: lowerTypedef, nameType: nameType, hoistType: hoistType); | 3009 lowerTypedef: lowerTypedef, nameType: nameType, hoistType: hoistType); |
2953 } | 3010 } |
2954 | 3011 |
2955 if (type is TypeParameterType) { | 3012 if (type is TypeParameterType) { |
2956 _typeParamInConst?.add(type); | 3013 _typeParamInConst?.add(type); |
2957 return new JS.Identifier(name); | 3014 return new JS.Identifier(name); |
2958 } | 3015 } |
2959 | 3016 |
2960 if (type == subClass?.type) { | 3017 if (type == subClass?.type) return className; |
2961 return className; | |
2962 } | |
2963 | 3018 |
2964 if (type is ParameterizedType) { | 3019 if (type is ParameterizedType) { |
2965 var args = type.typeArguments; | 3020 var args = type.typeArguments; |
2966 Iterable jsArgs = null; | 3021 Iterable jsArgs = null; |
2967 if (args.any((a) => !a.isDynamic)) { | 3022 if (args.any((a) => !a.isDynamic)) { |
2968 jsArgs = args.map((x) => _emitType(x, | 3023 jsArgs = args.map((x) => _emitType(x, |
2969 nameType: nameType, | 3024 nameType: nameType, |
2970 hoistType: hoistType, | 3025 hoistType: hoistType, |
2971 subClass: subClass, | 3026 subClass: subClass, |
2972 className: className)); | 3027 className: className)); |
2973 } else if (lowerGeneric || element == subClass) { | 3028 } else if (lowerGeneric || element == subClass) { |
2974 jsArgs = []; | 3029 jsArgs = []; |
2975 } | 3030 } |
2976 if (jsArgs != null) { | 3031 if (jsArgs != null) { |
2977 var genericName = _emitTopLevelName(element, suffix: '\$'); | 3032 var genericName = _emitTopLevelName(element, suffix: '\$'); |
2978 var typeRep = js.call('#(#)', [genericName, jsArgs]); | 3033 var typeRep = js.call('#(#)', [genericName, jsArgs]); |
2979 return nameType | 3034 return nameType |
2980 ? _typeTable.nameType(type, typeRep, hoistType: hoistType) | 3035 ? _typeTable.nameType(type, typeRep, hoistType: hoistType) |
2981 : typeRep; | 3036 : typeRep; |
2982 } | 3037 } |
2983 } | 3038 } |
2984 | 3039 |
2985 return _emitTopLevelName(element); | 3040 return _emitTopLevelNameNoInterop(element); |
2986 } | 3041 } |
2987 | 3042 |
2988 JS.PropertyAccess _emitTopLevelName(Element e, {String suffix: ''}) { | 3043 JS.PropertyAccess _emitTopLevelName(Element e, {String suffix: ''}) { |
2989 var interop = _emitJSInterop(e); | 3044 var interop = _emitJSInterop(e); |
2990 if (interop != null) return interop; | 3045 if (interop != null) return interop; |
| 3046 return _emitTopLevelNameNoInterop(e, suffix: suffix); |
| 3047 } |
| 3048 |
| 3049 JS.PropertyAccess _emitTopLevelNameNoInterop(Element e, {String suffix: ''}) { |
2991 String name = getJSExportName(e) + suffix; | 3050 String name = getJSExportName(e) + suffix; |
2992 return new JS.PropertyAccess( | 3051 return new JS.PropertyAccess( |
2993 emitLibraryName(e.library), _propertyName(name)); | 3052 emitLibraryName(e.library), _propertyName(name)); |
2994 } | 3053 } |
2995 | 3054 |
2996 @override | 3055 @override |
2997 JS.Expression visitAssignmentExpression(AssignmentExpression node) { | 3056 JS.Expression visitAssignmentExpression(AssignmentExpression node) { |
2998 var left = node.leftHandSide; | 3057 var left = node.leftHandSide; |
2999 var right = node.rightHandSide; | 3058 var right = node.rightHandSide; |
3000 if (node.operator.type == TokenType.EQ) return _emitSet(left, right); | 3059 if (node.operator.type == TokenType.EQ) return _emitSet(left, right); |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3204 } | 3263 } |
3205 | 3264 |
3206 /// Emits assignment to a static field element or property. | 3265 /// Emits assignment to a static field element or property. |
3207 JS.Expression _emitSetStaticProperty( | 3266 JS.Expression _emitSetStaticProperty( |
3208 Expression lhs, Element element, Expression rhs) { | 3267 Expression lhs, Element element, Expression rhs) { |
3209 // For static methods, we add the raw type name, without generics or | 3268 // 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 | 3269 // library prefix. We don't need those because static calls can't use |
3211 // the generic type. | 3270 // the generic type. |
3212 ClassElement classElement = element.enclosingElement; | 3271 ClassElement classElement = element.enclosingElement; |
3213 var type = classElement.type; | 3272 var type = classElement.type; |
3214 var dynType = _emitType(fillDynamicTypeArgs(type)); | 3273 var dynType = _emitStaticAccess(type); |
3215 var member = _emitMemberName(element.name, isStatic: true, type: type); | 3274 var member = _emitMemberName(element.name, isStatic: true, type: type); |
3216 return _visit(rhs).toAssignExpression( | 3275 return _visit(rhs).toAssignExpression( |
3217 annotate(new JS.PropertyAccess(dynType, member), lhs)); | 3276 annotate(new JS.PropertyAccess(dynType, member), lhs)); |
3218 } | 3277 } |
3219 | 3278 |
3220 /// Emits an assignment to the [element] property of instance referenced by | 3279 /// Emits an assignment to the [element] property of instance referenced by |
3221 /// [jsTarget]. | 3280 /// [jsTarget]. |
3222 JS.Expression _emitWriteInstanceProperty(Expression lhs, | 3281 JS.Expression _emitWriteInstanceProperty(Expression lhs, |
3223 JS.Expression jsTarget, Element element, JS.Expression value) { | 3282 JS.Expression jsTarget, Element element, JS.Expression value) { |
3224 String memberName = element.name; | 3283 String memberName = element.name; |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3355 JS.Expression _getSuperHelperFor(String name, JS.Expression forwardedCall, | 3414 JS.Expression _getSuperHelperFor(String name, JS.Expression forwardedCall, |
3356 List<JS.Expression> helperArgs) { | 3415 List<JS.Expression> helperArgs) { |
3357 var helperMethod = | 3416 var helperMethod = |
3358 new JS.Fun(helperArgs, new JS.Block([new JS.Return(forwardedCall)])); | 3417 new JS.Fun(helperArgs, new JS.Block([new JS.Return(forwardedCall)])); |
3359 var helperMethodName = new JS.TemporaryId('super\$$name'); | 3418 var helperMethodName = new JS.TemporaryId('super\$$name'); |
3360 _superHelperSymbols.add(helperMethodName); | 3419 _superHelperSymbols.add(helperMethodName); |
3361 _superHelpers.add(new JS.Method(helperMethodName, helperMethod)); | 3420 _superHelpers.add(new JS.Method(helperMethodName, helperMethod)); |
3362 return helperMethodName; | 3421 return helperMethodName; |
3363 } | 3422 } |
3364 | 3423 |
| 3424 JS.Expression _emitTarget(Expression target, Element element, bool isStatic) { |
| 3425 if (isStatic) { |
| 3426 if (element is ConstructorElement) { |
| 3427 return _emitConstructorAccess(element.enclosingElement.type); |
| 3428 } |
| 3429 if (element is ExecutableElement) { |
| 3430 return _emitStaticAccess( |
| 3431 (element.enclosingElement as ClassElement).type); |
| 3432 } |
| 3433 } |
| 3434 return _visit(target); |
| 3435 } |
| 3436 |
3365 /// Emits a (possibly generic) instance method call. | 3437 /// Emits a (possibly generic) instance method call. |
3366 JS.Expression _emitMethodCallInternal( | 3438 JS.Expression _emitMethodCallInternal( |
3367 Expression target, | 3439 Expression target, |
3368 MethodInvocation node, | 3440 MethodInvocation node, |
3369 List<JS.Expression> args, | 3441 List<JS.Expression> args, |
3370 List<JS.Expression> typeArgs) { | 3442 List<JS.Expression> typeArgs) { |
3371 var type = getStaticType(target); | 3443 var type = getStaticType(target); |
3372 var name = node.methodName.name; | 3444 var name = node.methodName.name; |
3373 var element = node.methodName.staticElement; | 3445 var element = node.methodName.staticElement; |
3374 bool isStatic = element is ExecutableElement && element.isStatic; | 3446 bool isStatic = element is ExecutableElement && element.isStatic; |
3375 var memberName = _emitMemberName(name, type: type, isStatic: isStatic); | 3447 var memberName = _emitMemberName(name, type: type, isStatic: isStatic); |
3376 | 3448 |
3377 JS.Expression jsTarget = _visit(target); | 3449 JS.Expression jsTarget = _emitTarget(target, element, isStatic); |
3378 if (isDynamicInvoke(target) || isDynamicInvoke(node.methodName)) { | 3450 if (isDynamicInvoke(target) || isDynamicInvoke(node.methodName)) { |
3379 if (_inWhitelistCode(target)) { | 3451 if (_inWhitelistCode(target)) { |
3380 var vars = <JS.MetaLetVariable, JS.Expression>{}; | 3452 var vars = <JS.MetaLetVariable, JS.Expression>{}; |
3381 var l = _visit(_bindValue(vars, 'l', target)); | 3453 var l = _visit(_bindValue(vars, 'l', target)); |
3382 jsTarget = new JS.MetaLet(vars, [ | 3454 jsTarget = new JS.MetaLet(vars, [ |
3383 js.call('(#[(#[#._extensionType]) ? #[#] : #]).bind(#)', [ | 3455 js.call('(#[(#[#._extensionType]) ? #[#] : #]).bind(#)', [ |
3384 l, | 3456 l, |
3385 l, | 3457 l, |
3386 _runtimeModule, | 3458 _runtimeModule, |
3387 _extensionSymbolsModule, | 3459 _extensionSymbolsModule, |
(...skipping 504 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3892 : parent.getSetter(element.name); | 3964 : parent.getSetter(element.name); |
3893 } | 3965 } |
3894 return null; | 3966 return null; |
3895 } | 3967 } |
3896 | 3968 |
3897 JS.Expression _emitConstructorName( | 3969 JS.Expression _emitConstructorName( |
3898 ConstructorElement element, DartType type, SimpleIdentifier name) { | 3970 ConstructorElement element, DartType type, SimpleIdentifier name) { |
3899 var classElem = element.enclosingElement; | 3971 var classElem = element.enclosingElement; |
3900 var interop = _emitJSInterop(classElem); | 3972 var interop = _emitJSInterop(classElem); |
3901 if (interop != null) return interop; | 3973 if (interop != null) return interop; |
3902 var typeName = _emitType(type); | 3974 var typeName = _emitConstructorAccess(type); |
3903 if (name != null || element.isFactory) { | 3975 if (name != null || element.isFactory) { |
3904 var namedCtor = _constructorName(element); | 3976 var namedCtor = _constructorName(element); |
3905 return new JS.PropertyAccess(typeName, namedCtor); | 3977 return new JS.PropertyAccess(typeName, namedCtor); |
3906 } | 3978 } |
3907 return typeName; | 3979 return typeName; |
3908 } | 3980 } |
3909 | 3981 |
3910 @override | 3982 @override |
3911 visitConstructorName(ConstructorName node) { | 3983 visitConstructorName(ConstructorName node) { |
3912 return _emitConstructorName(node.staticElement, node.type.type, node.name); | 3984 return _emitConstructorName(node.staticElement, node.type.type, node.name); |
3913 } | 3985 } |
3914 | 3986 |
3915 JS.Expression _emitInstanceCreationExpression( | 3987 JS.Expression _emitInstanceCreationExpression( |
3916 ConstructorElement element, | 3988 ConstructorElement element, |
3917 DartType type, | 3989 DartType type, |
3918 SimpleIdentifier name, | 3990 SimpleIdentifier name, |
3919 ArgumentList argumentList, | 3991 ArgumentList argumentList, |
3920 bool isConst) { | 3992 bool isConst) { |
3921 JS.Expression emitNew() { | 3993 JS.Expression emitNew() { |
3922 JS.Expression ctor; | 3994 JS.Expression ctor; |
3923 bool isFactory = false; | 3995 bool isFactory = false; |
3924 bool isNative = false; | 3996 bool isNative = false; |
3925 if (element == null) { | 3997 if (element == null) { |
3926 // TODO(jmesserly): this only happens if we had a static error. | 3998 // TODO(jmesserly): this only happens if we had a static error. |
3927 // Should we generate a throw instead? | 3999 // Should we generate a throw instead? |
3928 ctor = _emitType(type, | 4000 ctor = _emitConstructorAccess(type, |
3929 nameType: options.hoistInstanceCreation, | 4001 nameType: options.hoistInstanceCreation, |
3930 hoistType: options.hoistInstanceCreation); | 4002 hoistType: options.hoistInstanceCreation); |
3931 if (name != null) { | 4003 if (name != null) { |
3932 ctor = new JS.PropertyAccess(ctor, _propertyName(name.name)); | 4004 ctor = new JS.PropertyAccess(ctor, _propertyName(name.name)); |
3933 } | 4005 } |
3934 } else { | 4006 } else { |
3935 ctor = _emitConstructorName(element, type, name); | 4007 ctor = _emitConstructorName(element, type, name); |
3936 isFactory = element.isFactory; | 4008 isFactory = element.isFactory; |
3937 var classElem = element.enclosingElement; | 4009 var classElem = element.enclosingElement; |
3938 isNative = _isJSNative(classElem); | 4010 isNative = _isJSNative(classElem); |
(...skipping 803 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4742 var l = _visit(_bindValue(vars, 'l', target)); | 4814 var l = _visit(_bindValue(vars, 'l', target)); |
4743 return new JS.MetaLet(vars, [ | 4815 return new JS.MetaLet(vars, [ |
4744 js.call('(#[#._extensionType]) ? #[#[#]] : #.#', | 4816 js.call('(#[#._extensionType]) ? #[#[#]] : #.#', |
4745 [l, _runtimeModule, l, _extensionSymbolsModule, name, l, name]) | 4817 [l, _runtimeModule, l, _extensionSymbolsModule, name, l, name]) |
4746 ]); | 4818 ]); |
4747 } | 4819 } |
4748 return _callHelper('#(#, #)', | 4820 return _callHelper('#(#, #)', |
4749 [_emitDynamicOperationName('dload'), _visit(target), name]); | 4821 [_emitDynamicOperationName('dload'), _visit(target), name]); |
4750 } | 4822 } |
4751 | 4823 |
4752 var jsTarget = _visit(target); | 4824 var jsTarget = _emitTarget(target, member, isStatic); |
4753 bool isSuper = jsTarget is JS.Super; | 4825 bool isSuper = jsTarget is JS.Super; |
4754 | 4826 |
4755 if (isSuper && member is FieldElement && !member.isSynthetic) { | 4827 if (isSuper && member is FieldElement && !member.isSynthetic) { |
4756 // If super.x is actually a field, then x is an instance property since | 4828 // If super.x is actually a field, then x is an instance property since |
4757 // subclasses cannot override x. | 4829 // subclasses cannot override x. |
4758 jsTarget = new JS.This(); | 4830 jsTarget = new JS.This(); |
4759 } | 4831 } |
4760 | 4832 |
4761 JS.Expression result; | 4833 JS.Expression result; |
4762 if (member != null && member is MethodElement && !isStatic) { | 4834 if (member != null && member is MethodElement && !isStatic) { |
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5116 | 5188 |
5117 @override | 5189 @override |
5118 visitNullLiteral(NullLiteral node) => new JS.LiteralNull(); | 5190 visitNullLiteral(NullLiteral node) => new JS.LiteralNull(); |
5119 | 5191 |
5120 @override | 5192 @override |
5121 visitSymbolLiteral(SymbolLiteral node) { | 5193 visitSymbolLiteral(SymbolLiteral node) { |
5122 JS.Expression emitSymbol() { | 5194 JS.Expression emitSymbol() { |
5123 // TODO(vsm): When we canonicalize, we need to treat private symbols | 5195 // TODO(vsm): When we canonicalize, we need to treat private symbols |
5124 // correctly. | 5196 // correctly. |
5125 var name = js.string(node.components.join('.'), "'"); | 5197 var name = js.string(node.components.join('.'), "'"); |
5126 return js.call('#.new(#)', [_emitType(types.symbolType), name]); | 5198 return js |
| 5199 .call('#.new(#)', [_emitConstructorAccess(types.symbolType), name]); |
5127 } | 5200 } |
5128 | 5201 |
5129 return _emitConst(emitSymbol); | 5202 return _emitConst(emitSymbol); |
5130 } | 5203 } |
5131 | 5204 |
5132 @override | 5205 @override |
5133 visitListLiteral(ListLiteral node) { | 5206 visitListLiteral(ListLiteral node) { |
5134 var isConst = node.constKeyword != null; | 5207 var isConst = node.constKeyword != null; |
5135 JS.Expression emitList() { | 5208 JS.Expression emitList() { |
5136 JS.Expression list = new JS.ArrayInitializer( | 5209 JS.Expression list = new JS.ArrayInitializer( |
(...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5644 var targetIdentifier = target as SimpleIdentifier; | 5717 var targetIdentifier = target as SimpleIdentifier; |
5645 | 5718 |
5646 if (targetIdentifier.staticElement is! PrefixElement) return false; | 5719 if (targetIdentifier.staticElement is! PrefixElement) return false; |
5647 var prefix = targetIdentifier.staticElement as PrefixElement; | 5720 var prefix = targetIdentifier.staticElement as PrefixElement; |
5648 | 5721 |
5649 // The library the prefix is referring to must come from a deferred import. | 5722 // The library the prefix is referring to must come from a deferred import. |
5650 var containingLibrary = (target.root as CompilationUnit).element.library; | 5723 var containingLibrary = (target.root as CompilationUnit).element.library; |
5651 var imports = containingLibrary.getImportsWithPrefix(prefix); | 5724 var imports = containingLibrary.getImportsWithPrefix(prefix); |
5652 return imports.length == 1 && imports[0].isDeferred; | 5725 return imports.length == 1 && imports[0].isDeferred; |
5653 } | 5726 } |
OLD | NEW |