| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 js_backend.native_data; | 5 library js_backend.native_data; |
| 6 | 6 |
| 7 import '../common.dart'; | 7 import '../common.dart'; |
| 8 import '../common_elements.dart' show ElementEnvironment; | 8 import '../common_elements.dart' show ElementEnvironment; |
| 9 import '../elements/entities.dart'; | 9 import '../elements/entities.dart'; |
| 10 import '../native/behavior.dart' show NativeBehavior; | 10 import '../native/behavior.dart' show NativeBehavior; |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 166 /// Sets the native tag info for [cls]. | 166 /// Sets the native tag info for [cls]. |
| 167 /// | 167 /// |
| 168 /// The tag info string contains comma-separated 'words' which are either | 168 /// The tag info string contains comma-separated 'words' which are either |
| 169 /// dispatch tags (having JavaScript identifier syntax) and directives that | 169 /// dispatch tags (having JavaScript identifier syntax) and directives that |
| 170 /// begin with `!`. | 170 /// begin with `!`. |
| 171 void setNativeClassTagInfo(ClassEntity cls, String tagText) { | 171 void setNativeClassTagInfo(ClassEntity cls, String tagText) { |
| 172 // TODO(johnniwinther): Assert that this is only called once. The memory | 172 // TODO(johnniwinther): Assert that this is only called once. The memory |
| 173 // compiler copies pre-processed elements into a new compiler through | 173 // compiler copies pre-processed elements into a new compiler through |
| 174 // [Compiler.onLibraryScanned] and thereby causes multiple calls to this | 174 // [Compiler.onLibraryScanned] and thereby causes multiple calls to this |
| 175 // method. | 175 // method. |
| 176 assert(invariant( | 176 assert( |
| 177 cls, | |
| 178 nativeClassTagInfo[cls] == null || | 177 nativeClassTagInfo[cls] == null || |
| 179 nativeClassTagInfo[cls].text == tagText, | 178 nativeClassTagInfo[cls].text == tagText, |
| 180 message: "Native tag info set inconsistently on $cls: " | 179 failedAt( |
| 180 cls, |
| 181 "Native tag info set inconsistently on $cls: " |
| 181 "Existing tag info '${nativeClassTagInfo[cls]}', " | 182 "Existing tag info '${nativeClassTagInfo[cls]}', " |
| 182 "new tag info '$tagText'.")); | 183 "new tag info '$tagText'.")); |
| 183 nativeClassTagInfo[cls] = new NativeClassTag(tagText); | 184 nativeClassTagInfo[cls] = new NativeClassTag(tagText); |
| 184 } | 185 } |
| 185 | 186 |
| 186 @override | 187 @override |
| 187 void markAsJsInteropLibrary(LibraryEntity element) { | 188 void markAsJsInteropLibrary(LibraryEntity element) { |
| 188 jsInteropLibraries.add(element); | 189 jsInteropLibraries.add(element); |
| 189 } | 190 } |
| 190 | 191 |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 288 Map<MemberEntity, String> jsInteropMemberNames = <MemberEntity, String>{}; | 289 Map<MemberEntity, String> jsInteropMemberNames = <MemberEntity, String>{}; |
| 289 | 290 |
| 290 NativeDataBuilderImpl(this._nativeBasicData); | 291 NativeDataBuilderImpl(this._nativeBasicData); |
| 291 | 292 |
| 292 /// Sets the native [name] for the member [element]. This name is used for | 293 /// Sets the native [name] for the member [element]. This name is used for |
| 293 /// [element] in the generated JavaScript. | 294 /// [element] in the generated JavaScript. |
| 294 void setNativeMemberName(MemberEntity element, String name) { | 295 void setNativeMemberName(MemberEntity element, String name) { |
| 295 // TODO(johnniwinther): Avoid setting this more than once. The enqueuer | 296 // TODO(johnniwinther): Avoid setting this more than once. The enqueuer |
| 296 // might enqueue [element] several times (before processing it) and computes | 297 // might enqueue [element] several times (before processing it) and computes |
| 297 // name on each call to `internalAddToWorkList`. | 298 // name on each call to `internalAddToWorkList`. |
| 298 assert(invariant(element, | 299 assert( |
| 299 nativeMemberName[element] == null || nativeMemberName[element] == name, | 300 nativeMemberName[element] == null || nativeMemberName[element] == name, |
| 300 message: "Native member name set inconsistently on $element: " | 301 failedAt( |
| 302 element, |
| 303 "Native member name set inconsistently on $element: " |
| 301 "Existing name '${nativeMemberName[element]}', " | 304 "Existing name '${nativeMemberName[element]}', " |
| 302 "new name '$name'.")); | 305 "new name '$name'.")); |
| 303 nativeMemberName[element] = name; | 306 nativeMemberName[element] = name; |
| 304 } | 307 } |
| 305 | 308 |
| 306 /// Registers the [behavior] for calling the native [method]. | 309 /// Registers the [behavior] for calling the native [method]. |
| 307 void setNativeMethodBehavior(FunctionEntity method, NativeBehavior behavior) { | 310 void setNativeMethodBehavior(FunctionEntity method, NativeBehavior behavior) { |
| 308 nativeMethodBehavior[method] = behavior; | 311 nativeMethodBehavior[method] = behavior; |
| 309 } | 312 } |
| 310 | 313 |
| 311 /// Registers the [behavior] for reading from the native [field]. | 314 /// Registers the [behavior] for reading from the native [field]. |
| 312 void setNativeFieldLoadBehavior(FieldEntity field, NativeBehavior behavior) { | 315 void setNativeFieldLoadBehavior(FieldEntity field, NativeBehavior behavior) { |
| 313 nativeFieldLoadBehavior[field] = behavior; | 316 nativeFieldLoadBehavior[field] = behavior; |
| 314 } | 317 } |
| 315 | 318 |
| 316 /// Registers the [behavior] for writing to the native [field]. | 319 /// Registers the [behavior] for writing to the native [field]. |
| 317 void setNativeFieldStoreBehavior(FieldEntity field, NativeBehavior behavior) { | 320 void setNativeFieldStoreBehavior(FieldEntity field, NativeBehavior behavior) { |
| 318 nativeFieldStoreBehavior[field] = behavior; | 321 nativeFieldStoreBehavior[field] = behavior; |
| 319 } | 322 } |
| 320 | 323 |
| 321 /// Sets the explicit js interop [name] for the library [element]. | 324 /// Sets the explicit js interop [name] for the library [element]. |
| 322 void setJsInteropLibraryName(LibraryEntity element, String name) { | 325 void setJsInteropLibraryName(LibraryEntity element, String name) { |
| 323 assert(invariant(element, _nativeBasicData.isJsInteropLibrary(element), | 326 assert( |
| 324 message: | 327 _nativeBasicData.isJsInteropLibrary(element), |
| 328 failedAt(element, |
| 325 'Library $element is not js interop but given a js interop name.')); | 329 'Library $element is not js interop but given a js interop name.')); |
| 326 jsInteropLibraryNames[element] = name; | 330 jsInteropLibraryNames[element] = name; |
| 327 } | 331 } |
| 328 | 332 |
| 329 @override | 333 @override |
| 330 void markJsInteropClassAsAnonymous(ClassEntity element) { | 334 void markJsInteropClassAsAnonymous(ClassEntity element) { |
| 331 anonymousJsInteropClasses.add(element); | 335 anonymousJsInteropClasses.add(element); |
| 332 } | 336 } |
| 333 | 337 |
| 334 /// Sets the explicit js interop [name] for the class [element]. | 338 /// Sets the explicit js interop [name] for the class [element]. |
| 335 void setJsInteropClassName(ClassEntity element, String name) { | 339 void setJsInteropClassName(ClassEntity element, String name) { |
| 336 assert(invariant(element, _nativeBasicData.isJsInteropClass(element), | 340 assert( |
| 337 message: | 341 _nativeBasicData.isJsInteropClass(element), |
| 342 failedAt(element, |
| 338 'Class $element is not js interop but given a js interop name.')); | 343 'Class $element is not js interop but given a js interop name.')); |
| 339 jsInteropClassNames[element] = name; | 344 jsInteropClassNames[element] = name; |
| 340 } | 345 } |
| 341 | 346 |
| 342 @override | 347 @override |
| 343 void markAsJsInteropMember(MemberEntity element) { | 348 void markAsJsInteropMember(MemberEntity element) { |
| 344 jsInteropMemberNames[element] = null; | 349 jsInteropMemberNames[element] = null; |
| 345 } | 350 } |
| 346 | 351 |
| 347 /// Sets the explicit js interop [name] for the member [element]. | 352 /// Sets the explicit js interop [name] for the member [element]. |
| 348 void setJsInteropMemberName(MemberEntity element, String name) { | 353 void setJsInteropMemberName(MemberEntity element, String name) { |
| 349 assert(invariant(element, jsInteropMemberNames.containsKey(element), | 354 assert( |
| 350 message: | 355 jsInteropMemberNames.containsKey(element), |
| 356 failedAt(element, |
| 351 'Member $element is not js interop but given a js interop name.')); | 357 'Member $element is not js interop but given a js interop name.')); |
| 352 jsInteropMemberNames[element] = name; | 358 jsInteropMemberNames[element] = name; |
| 353 } | 359 } |
| 354 | 360 |
| 355 @override | 361 @override |
| 356 NativeData close() => new NativeDataImpl( | 362 NativeData close() => new NativeDataImpl( |
| 357 _nativeBasicData, | 363 _nativeBasicData, |
| 358 nativeMemberName, | 364 nativeMemberName, |
| 359 nativeMethodBehavior, | 365 nativeMethodBehavior, |
| 360 nativeFieldLoadBehavior, | 366 nativeFieldLoadBehavior, |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 511 } | 517 } |
| 512 | 518 |
| 513 String _jsClassNameHelper(ClassEntity element) { | 519 String _jsClassNameHelper(ClassEntity element) { |
| 514 String jsInteropName = getJsInteropClassName(element); | 520 String jsInteropName = getJsInteropClassName(element); |
| 515 if (jsInteropName != null && jsInteropName.isNotEmpty) return jsInteropName; | 521 if (jsInteropName != null && jsInteropName.isNotEmpty) return jsInteropName; |
| 516 return computeUnescapedJSInteropName(element.name); | 522 return computeUnescapedJSInteropName(element.name); |
| 517 } | 523 } |
| 518 | 524 |
| 519 String _jsMemberNameHelper(MemberEntity element) { | 525 String _jsMemberNameHelper(MemberEntity element) { |
| 520 String jsInteropName = jsInteropMemberNames[element]; | 526 String jsInteropName = jsInteropMemberNames[element]; |
| 521 assert(invariant(element, | 527 assert( |
| 522 !(jsInteropMemberNames.containsKey(element) && jsInteropName == null), | 528 !(jsInteropMemberNames.containsKey(element) && jsInteropName == null), |
| 523 message: | 529 failedAt( |
| 530 element, |
| 524 'Member $element is js interop but js interop name has not yet ' | 531 'Member $element is js interop but js interop name has not yet ' |
| 525 'been computed.')); | 532 'been computed.')); |
| 526 if (jsInteropName != null && jsInteropName.isNotEmpty) { | 533 if (jsInteropName != null && jsInteropName.isNotEmpty) { |
| 527 return jsInteropName; | 534 return jsInteropName; |
| 528 } | 535 } |
| 529 return computeUnescapedJSInteropName(element.name); | 536 return computeUnescapedJSInteropName(element.name); |
| 530 } | 537 } |
| 531 | 538 |
| 532 /// Returns a JavaScript path specifying the context in which | 539 /// Returns a JavaScript path specifying the context in which |
| 533 /// [element.fixedBackendName] should be evaluated. Only applicable for | 540 /// [element.fixedBackendName] should be evaluated. Only applicable for |
| (...skipping 21 matching lines...) Expand all Loading... |
| 555 } | 562 } |
| 556 | 563 |
| 557 /// Returns `true` if [element] is a native member of a native class. | 564 /// Returns `true` if [element] is a native member of a native class. |
| 558 bool isNativeMember(MemberEntity element) { | 565 bool isNativeMember(MemberEntity element) { |
| 559 if (isJsInteropMember(element)) return true; | 566 if (isJsInteropMember(element)) return true; |
| 560 return nativeMemberName.containsKey(element); | 567 return nativeMemberName.containsKey(element); |
| 561 } | 568 } |
| 562 | 569 |
| 563 /// Returns the [NativeBehavior] for calling the native [method]. | 570 /// Returns the [NativeBehavior] for calling the native [method]. |
| 564 NativeBehavior getNativeMethodBehavior(FunctionEntity method) { | 571 NativeBehavior getNativeMethodBehavior(FunctionEntity method) { |
| 565 assert(invariant(method, nativeMethodBehavior.containsKey(method), | 572 assert( |
| 566 message: "No native method behavior has been computed for $method.")); | 573 nativeMethodBehavior.containsKey(method), |
| 574 failedAt(method, |
| 575 "No native method behavior has been computed for $method.")); |
| 567 return nativeMethodBehavior[method]; | 576 return nativeMethodBehavior[method]; |
| 568 } | 577 } |
| 569 | 578 |
| 570 /// Returns the [NativeBehavior] for reading from the native [field]. | 579 /// Returns the [NativeBehavior] for reading from the native [field]. |
| 571 NativeBehavior getNativeFieldLoadBehavior(FieldEntity field) { | 580 NativeBehavior getNativeFieldLoadBehavior(FieldEntity field) { |
| 572 assert(invariant(field, nativeFieldLoadBehavior.containsKey(field), | 581 assert( |
| 573 message: "No native field load behavior has been " | 582 nativeFieldLoadBehavior.containsKey(field), |
| 583 failedAt( |
| 584 field, |
| 585 "No native field load behavior has been " |
| 574 "computed for $field.")); | 586 "computed for $field.")); |
| 575 return nativeFieldLoadBehavior[field]; | 587 return nativeFieldLoadBehavior[field]; |
| 576 } | 588 } |
| 577 | 589 |
| 578 /// Returns the [NativeBehavior] for writing to the native [field]. | 590 /// Returns the [NativeBehavior] for writing to the native [field]. |
| 579 NativeBehavior getNativeFieldStoreBehavior(FieldEntity field) { | 591 NativeBehavior getNativeFieldStoreBehavior(FieldEntity field) { |
| 580 assert(invariant(field, nativeFieldStoreBehavior.containsKey(field), | 592 assert( |
| 581 message: "No native field store behavior has been " | 593 nativeFieldStoreBehavior.containsKey(field), |
| 582 "computed for $field.")); | 594 failedAt(field, |
| 595 "No native field store behavior has been computed for $field.")); |
| 583 return nativeFieldStoreBehavior[field]; | 596 return nativeFieldStoreBehavior[field]; |
| 584 } | 597 } |
| 585 | 598 |
| 586 /// Apply JS$ escaping scheme to convert possible escaped Dart names into | 599 /// Apply JS$ escaping scheme to convert possible escaped Dart names into |
| 587 /// JS names. | 600 /// JS names. |
| 588 String computeUnescapedJSInteropName(String name) { | 601 String computeUnescapedJSInteropName(String name) { |
| 589 return name.startsWith(_jsInteropEscapePrefix) | 602 return name.startsWith(_jsInteropEscapePrefix) |
| 590 ? name.substring(_jsInteropEscapePrefix.length) | 603 ? name.substring(_jsInteropEscapePrefix.length) |
| 591 : name; | 604 : name; |
| 592 } | 605 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 620 int get hashCode => Hashing.listHash(names, isNonLeaf.hashCode); | 633 int get hashCode => Hashing.listHash(names, isNonLeaf.hashCode); |
| 621 | 634 |
| 622 bool operator ==(other) { | 635 bool operator ==(other) { |
| 623 if (identical(this, other)) return true; | 636 if (identical(this, other)) return true; |
| 624 if (other is! NativeClassTag) return false; | 637 if (other is! NativeClassTag) return false; |
| 625 return equalElements(names, other.names) && isNonLeaf == other.isNonLeaf; | 638 return equalElements(names, other.names) && isNonLeaf == other.isNonLeaf; |
| 626 } | 639 } |
| 627 | 640 |
| 628 String toString() => text; | 641 String toString() => text; |
| 629 } | 642 } |
| OLD | NEW |