| 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 // 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; | 7 import 'dart:collection' show HashSet, HashMap; |
| 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 1259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1270 code = 'dart.$DCALL(#, #)'; | 1270 code = 'dart.$DCALL(#, #)'; |
| 1271 } else { | 1271 } else { |
| 1272 code = '#(#)'; | 1272 code = '#(#)'; |
| 1273 } | 1273 } |
| 1274 return js.call( | 1274 return js.call( |
| 1275 code, [_visit(node.methodName), _visit(node.argumentList)]); | 1275 code, [_visit(node.methodName), _visit(node.argumentList)]); |
| 1276 } | 1276 } |
| 1277 | 1277 |
| 1278 var type = getStaticType(target); | 1278 var type = getStaticType(target); |
| 1279 var name = node.methodName.name; | 1279 var name = node.methodName.name; |
| 1280 var memberName = _emitMemberName(name, type: type); | 1280 var element = node.methodName.staticElement; |
| 1281 bool isStatic = element is ExecutableElement && element.isStatic; |
| 1282 var memberName = _emitMemberName(name, type: type, isStatic: isStatic); |
| 1281 | 1283 |
| 1282 if (rules.isDynamicTarget(target)) { | 1284 if (rules.isDynamicTarget(target)) { |
| 1283 code = 'dart.$DSEND(#, #, #)'; | 1285 code = 'dart.$DSEND(#, #, #)'; |
| 1284 } else if (rules.isDynamicCall(node.methodName)) { | 1286 } else if (rules.isDynamicCall(node.methodName)) { |
| 1285 // This is a dynamic call to a statically know target. For example: | 1287 // This is a dynamic call to a statically know target. For example: |
| 1286 // class Foo { Function bar; } | 1288 // class Foo { Function bar; } |
| 1287 // new Foo().bar(); // dynamic call | 1289 // new Foo().bar(); // dynamic call |
| 1288 code = 'dart.$DCALL(#.#, #)'; | 1290 code = 'dart.$DCALL(#.#, #)'; |
| 1289 } else if (_requiresStaticDispatch(target, name)) { | 1291 } else if (_requiresStaticDispatch(target, name)) { |
| 1290 assert(rules.objectMembers[name] is FunctionType); | 1292 assert(rules.objectMembers[name] is FunctionType); |
| (...skipping 606 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1897 if (!type.isObject && | 1899 if (!type.isObject && |
| 1898 !_isJSBuiltinType(type) && | 1900 !_isJSBuiltinType(type) && |
| 1899 _isNonNullableExpression(target)) { | 1901 _isNonNullableExpression(target)) { |
| 1900 return false; | 1902 return false; |
| 1901 } | 1903 } |
| 1902 return true; | 1904 return true; |
| 1903 } | 1905 } |
| 1904 | 1906 |
| 1905 /// Shared code for [PrefixedIdentifier] and [PropertyAccess]. | 1907 /// Shared code for [PrefixedIdentifier] and [PropertyAccess]. |
| 1906 JS.Expression _emitGet(Expression target, SimpleIdentifier memberId) { | 1908 JS.Expression _emitGet(Expression target, SimpleIdentifier memberId) { |
| 1907 var name = _emitMemberName(memberId.name, type: getStaticType(target)); | 1909 var member = memberId.staticElement; |
| 1910 bool isStatic = member is ExecutableElement && member.isStatic; |
| 1911 var name = _emitMemberName(memberId.name, |
| 1912 type: getStaticType(target), isStatic: isStatic); |
| 1908 if (rules.isDynamicTarget(target)) { | 1913 if (rules.isDynamicTarget(target)) { |
| 1909 return js.call('dart.$DLOAD(#, #)', [_visit(target), name]); | 1914 return js.call('dart.$DLOAD(#, #)', [_visit(target), name]); |
| 1910 } | 1915 } |
| 1911 | 1916 |
| 1912 String code; | 1917 String code; |
| 1913 var member = memberId.staticElement; | |
| 1914 if (member != null && member is MethodElement) { | 1918 if (member != null && member is MethodElement) { |
| 1915 // Tear-off methods: explicitly bind it. | 1919 // Tear-off methods: explicitly bind it. |
| 1916 if (_requiresStaticDispatch(target, memberId.name)) { | 1920 if (_requiresStaticDispatch(target, memberId.name)) { |
| 1917 return js.call('dart.#.bind(#)', [name, _visit(target)]); | 1921 return js.call('dart.#.bind(#)', [name, _visit(target)]); |
| 1918 } | 1922 } |
| 1919 if (isStateless(target, target)) { | 1923 if (isStateless(target, target)) { |
| 1920 return js.call('#.#.bind(#)', [_visit(target), name, _visit(target)]); | 1924 return js.call('#.#.bind(#)', [_visit(target), name, _visit(target)]); |
| 1921 } | 1925 } |
| 1922 code = 'dart.bind(#, #)'; | 1926 code = 'dart.bind(#, #)'; |
| 1923 } else if (_requiresStaticDispatch(target, memberId.name)) { | 1927 } else if (_requiresStaticDispatch(target, memberId.name)) { |
| (...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2351 /// <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_
Objects/Map> | 2355 /// <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_
Objects/Map> |
| 2352 /// | 2356 /// |
| 2353 /// Unary minus looks like: `x['unary-']()`. Note that [unary] must be passed | 2357 /// Unary minus looks like: `x['unary-']()`. Note that [unary] must be passed |
| 2354 /// for this transformation to happen, otherwise binary minus is assumed. | 2358 /// for this transformation to happen, otherwise binary minus is assumed. |
| 2355 /// | 2359 /// |
| 2356 /// Equality is a bit special, it is generated via the Dart `equals` runtime | 2360 /// Equality is a bit special, it is generated via the Dart `equals` runtime |
| 2357 /// helper, that checks for null. The user defined method is called '=='. | 2361 /// helper, that checks for null. The user defined method is called '=='. |
| 2358 /// | 2362 /// |
| 2359 JS.Expression _emitMemberName(String name, | 2363 JS.Expression _emitMemberName(String name, |
| 2360 {DartType type, bool unary: false, bool isStatic: false}) { | 2364 {DartType type, bool unary: false, bool isStatic: false}) { |
| 2365 |
| 2366 // Static methods skip most of the rename steps. |
| 2367 if (isStatic) { |
| 2368 if (invalidJSStaticMethodName(name)) { |
| 2369 // Choose an string name. Use an invalid identifier so it won't conflict |
| 2370 // with any valid member names. |
| 2371 // TODO(jmesserly): this works around the problem, but I'm pretty sure w
e |
| 2372 // don't need it, as static methods seemed to work. The only concrete |
| 2373 // issue we saw was in the defineNamedConstructor helper function. |
| 2374 name = '$name*'; |
| 2375 } |
| 2376 return _propertyName(name); |
| 2377 } |
| 2378 |
| 2361 if (name.startsWith('_')) { | 2379 if (name.startsWith('_')) { |
| 2362 return _privateNames.putIfAbsent( | 2380 return _privateNames.putIfAbsent( |
| 2363 name, () => _initSymbol(new JSTemporary(name))); | 2381 name, () => _initSymbol(new JSTemporary(name))); |
| 2364 } | 2382 } |
| 2365 | 2383 |
| 2366 // Check for extension method: | 2384 // Check for extension method: |
| 2367 var extLibrary = _findExtensionLibrary(name, type); | 2385 var extLibrary = _findExtensionLibrary(name, type); |
| 2368 | 2386 |
| 2369 if (name == '[]') { | 2387 if (name == '[]') { |
| 2370 name = 'get'; | 2388 name = 'get'; |
| 2371 } else if (name == '[]=') { | 2389 } else if (name == '[]=') { |
| 2372 name = 'set'; | 2390 name = 'set'; |
| 2373 } else if (name == '-' && unary) { | 2391 } else if (name == '-' && unary) { |
| 2374 name = 'unary-'; | 2392 name = 'unary-'; |
| 2375 } | 2393 } |
| 2376 | 2394 |
| 2377 if (isStatic && invalidJSStaticMethodName(name)) { | |
| 2378 // Choose an string name. Use an invalid identifier so it won't conflict | |
| 2379 // with any valid member names. | |
| 2380 // TODO(jmesserly): this works around the problem, but I'm pretty sure we | |
| 2381 // don't need it, as static methods seemed to work. The only concrete | |
| 2382 // issue we saw was in the defineNamedConstructor helper function. | |
| 2383 name = '$name*'; | |
| 2384 } | |
| 2385 | |
| 2386 if (extLibrary != null) { | 2395 if (extLibrary != null) { |
| 2387 return _extensionMethodName(name, extLibrary); | 2396 return _extensionMethodName(name, extLibrary); |
| 2388 } | 2397 } |
| 2389 | 2398 |
| 2390 return _propertyName(name); | 2399 return _propertyName(name); |
| 2391 } | 2400 } |
| 2392 | 2401 |
| 2393 LibraryElement _findExtensionLibrary(String name, DartType type) { | 2402 LibraryElement _findExtensionLibrary(String name, DartType type) { |
| 2394 if (type is! InterfaceType) return null; | 2403 if (type is! InterfaceType) return null; |
| 2395 | 2404 |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2511 // TODO(jmesserly): validate the library. See issue #135. | 2520 // TODO(jmesserly): validate the library. See issue #135. |
| 2512 bool _isJsNameAnnotation(DartObjectImpl value) => value.type.name == 'JsName'; | 2521 bool _isJsNameAnnotation(DartObjectImpl value) => value.type.name == 'JsName'; |
| 2513 | 2522 |
| 2514 bool _isJsPeerInterface(DartObjectImpl value) => | 2523 bool _isJsPeerInterface(DartObjectImpl value) => |
| 2515 value.type.name == 'JsPeerInterface'; | 2524 value.type.name == 'JsPeerInterface'; |
| 2516 | 2525 |
| 2517 // TODO(jacobr): we would like to do something like the following | 2526 // TODO(jacobr): we would like to do something like the following |
| 2518 // but we don't have summary support yet. | 2527 // but we don't have summary support yet. |
| 2519 // bool _supportJsExtensionMethod(AnnotatedNode node) => | 2528 // bool _supportJsExtensionMethod(AnnotatedNode node) => |
| 2520 // _getAnnotation(node, "SupportJsExtensionMethod") != null; | 2529 // _getAnnotation(node, "SupportJsExtensionMethod") != null; |
| OLD | NEW |