Chromium Code Reviews| 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 '../elements/elements.dart' | 8 import '../elements/elements.dart' |
| 9 show | 9 show |
| 10 ClassElement, | 10 ClassElement, |
| 11 Element, | 11 Element, |
| 12 FieldElement, | 12 FieldElement, |
| 13 FunctionElement, | 13 FunctionElement, |
| 14 LibraryElement, | |
| 14 MemberElement, | 15 MemberElement, |
| 15 MethodElement; | 16 MethodElement; |
| 16 import '../elements/entities.dart'; | 17 import '../elements/entities.dart'; |
| 17 import '../native/behavior.dart' show NativeBehavior; | 18 import '../native/behavior.dart' show NativeBehavior; |
| 18 | 19 |
| 19 /// Basic information for native classes and methods and js-interop | 20 /// Basic information for native classes and methods and js-interop |
| 20 /// classes. | 21 /// classes. |
| 21 /// | 22 /// |
| 22 /// This information is computed during loading using [NativeClassDataBuilder]. | 23 /// This information is computed during loading using [NativeClassDataBuilder]. |
| 23 abstract class NativeClassData { | 24 abstract class NativeClassData { |
| 24 /// Returns `true` if [cls] corresponds to a native JavaScript class. | 25 /// Returns `true` if [cls] corresponds to a native JavaScript class. |
| 25 /// | 26 /// |
| 26 /// A class is marked as native either through the `@Native(...)` annotation | 27 /// A class is marked as native either through the `@Native(...)` annotation |
| 27 /// allowed for internal libraries or via the typed JavaScriptInterop | 28 /// allowed for internal libraries or via the typed JavaScriptInterop |
| 28 /// mechanism allowed for user libraries. | 29 /// mechanism allowed for user libraries. |
| 29 bool isNativeClass(ClassEntity element); | 30 bool isNativeClass(ClassEntity element); |
| 30 | 31 |
| 31 /// Returns `true` if [element] or any of its superclasses is native. | 32 /// Returns `true` if [element] or any of its superclasses is native. |
| 32 bool isNativeOrExtendsNative(ClassElement element); | 33 bool isNativeOrExtendsNative(ClassElement element); |
| 33 | 34 |
| 34 /// Returns `true` if [element] corresponds to a native JavaScript member. | 35 /// Returns `true` if [element] is a JsInterop library. |
| 35 /// | 36 bool isJsInteropLibrary(LibraryElement element); |
|
Siggi Cherem (dart-lang)
2017/03/14 04:09:15
couple random thoughts here:
- maybe this means w
Johnni Winther
2017/03/15 10:55:13
Acknowledged.
| |
| 36 /// A member is marked as native either through the native mechanism | |
| 37 /// (`@Native(...)` or the `native` pseudo keyword) allowed for internal | |
| 38 /// libraries or via the typed JavaScriptInterop mechanism allowed for user | |
| 39 /// libraries. | |
| 40 bool isNativeMember(MemberEntity element); | |
| 41 | 37 |
| 42 /// Returns `true` if [element] is a JsInterop class. | 38 /// Returns `true` if [element] is a JsInterop class. |
| 43 bool isJsInteropClass(ClassElement element); | 39 bool isJsInteropClass(ClassElement element); |
| 44 } | 40 } |
| 45 | 41 |
| 46 /// Additional element information for native classes and methods and js-interop | 42 /// Additional element information for native classes and methods and js-interop |
| 47 /// methods. | 43 /// methods. |
| 48 /// | 44 /// |
| 49 /// This information is computed during resolution using [NativeDataBuilder]. | 45 /// This information is computed during resolution using [NativeDataBuilder]. |
| 50 abstract class NativeData extends NativeClassData { | 46 abstract class NativeData extends NativeClassData { |
| 47 /// Returns `true` if [element] corresponds to a native JavaScript member. | |
| 48 /// | |
| 49 /// A member is marked as native either through the native mechanism | |
| 50 /// (`@Native(...)` or the `native` pseudo keyword) allowed for internal | |
| 51 /// libraries or via the typed JavaScriptInterop mechanism allowed for user | |
| 52 /// libraries. | |
| 53 bool isNativeMember(MemberEntity element); | |
| 54 | |
| 51 /// Returns the [NativeBehavior] for calling the native [method]. | 55 /// Returns the [NativeBehavior] for calling the native [method]. |
| 52 NativeBehavior getNativeMethodBehavior(MethodElement method); | 56 NativeBehavior getNativeMethodBehavior(MethodElement method); |
| 53 | 57 |
| 54 /// Returns the [NativeBehavior] for reading from the native [field]. | 58 /// Returns the [NativeBehavior] for reading from the native [field]. |
| 55 NativeBehavior getNativeFieldLoadBehavior(FieldElement field); | 59 NativeBehavior getNativeFieldLoadBehavior(FieldElement field); |
| 56 | 60 |
| 57 /// Returns the [NativeBehavior] for writing to the native [field]. | 61 /// Returns the [NativeBehavior] for writing to the native [field]. |
| 58 NativeBehavior getNativeFieldStoreBehavior(FieldElement field); | 62 NativeBehavior getNativeFieldStoreBehavior(FieldElement field); |
| 59 | 63 |
| 60 /// Returns `true` if the name of [element] is fixed for the generated | 64 /// Returns `true` if the name of [element] is fixed for the generated |
| 61 /// JavaScript. | 65 /// JavaScript. |
| 62 bool hasFixedBackendName(Element element); | 66 bool hasFixedBackendName(Element element); |
| 63 | 67 |
| 64 /// Computes the name for [element] to use in the generated JavaScript. This | 68 /// Computes the name for [element] to use in the generated JavaScript. This |
| 65 /// is either given through a native annotation or a js interop annotation. | 69 /// is either given through a native annotation or a js interop annotation. |
| 66 String getFixedBackendName(Entity entity); | 70 String getFixedBackendName(Entity entity); |
| 67 | 71 |
| 68 /// Returns the list of non-directive native tag words for [cls]. | 72 /// Returns the list of non-directive native tag words for [cls]. |
| 69 List<String> getNativeTagsOfClass(ClassElement cls); | 73 List<String> getNativeTagsOfClass(ClassElement cls); |
| 70 | 74 |
| 71 /// Returns `true` if [cls] has a `!nonleaf` tag word. | 75 /// Returns `true` if [cls] has a `!nonleaf` tag word. |
| 72 bool hasNativeTagsForcedNonLeaf(ClassElement cls); | 76 bool hasNativeTagsForcedNonLeaf(ClassElement cls); |
| 73 | 77 |
| 74 /// Returns `true` if [element] is part of JsInterop. | 78 /// Returns `true` if [element] is part of JsInterop. |
| 79 /// | |
| 80 /// Deprecated: Use [isJsInteropLibrary], [isJsInteropClass] or | |
| 81 /// [isJsInteropMember] instead. | |
| 82 @deprecated | |
| 75 bool isJsInterop(Element element); | 83 bool isJsInterop(Element element); |
| 76 | 84 |
| 77 /// Returns `true` if [element] is a JsInterop method. | 85 /// Returns `true` if [element] is a JsInterop method. |
| 78 bool isJsInteropMethod(MethodElement element); | 86 bool isJsInteropMember(MethodElement element); |
| 79 | 87 |
| 80 /// Returns the explicit js interop name for [element]. | 88 /// Returns the explicit js interop name for [element]. |
| 81 String getJsInteropName(Element element); | 89 String getJsInteropName(Element element); |
| 82 | 90 |
| 83 /// Apply JS$ escaping scheme to convert possible escaped Dart names into | 91 /// Apply JS$ escaping scheme to convert possible escaped Dart names into |
| 84 /// JS names. | 92 /// JS names. |
| 85 String getUnescapedJSInteropName(String name); | 93 String getUnescapedJSInteropName(String name); |
| 86 } | 94 } |
| 87 | 95 |
| 88 abstract class NativeClassDataBuilder { | 96 abstract class NativeClassDataBuilder { |
| 89 /// Sets the native tag info for [cls]. | 97 /// Sets the native tag info for [cls]. |
| 90 /// | 98 /// |
| 91 /// The tag info string contains comma-separated 'words' which are either | 99 /// The tag info string contains comma-separated 'words' which are either |
| 92 /// dispatch tags (having JavaScript identifier syntax) and directives that | 100 /// dispatch tags (having JavaScript identifier syntax) and directives that |
| 93 /// begin with `!`. | 101 /// begin with `!`. |
| 94 void setNativeClassTagInfo(ClassElement cls, String tagInfo); | 102 void setNativeClassTagInfo(ClassElement cls, String tagInfo); |
| 95 | 103 |
| 96 /// Returns the list of native tag words for [cls]. | 104 /// Marks [element] as an explicit part of JsInterop. The js interop name is |
| 97 List<String> getNativeTagsOfClassRaw(ClassElement cls); | 105 /// expected to be computed later. |
| 106 void markAsJsInteropLibrary(LibraryElement element); | |
| 98 | 107 |
| 99 /// Sets the native [name] for the member [element]. This name is used for | 108 /// Marks [element] as an explicit part of JsInterop. The js interop name is |
| 100 /// [element] in the generated JavaScript. | |
| 101 void setNativeMemberName(MemberElement element, String name); | |
| 102 | |
| 103 /// Returns [element] as an explicit part of JsInterop. The js interop name is | |
| 104 /// expected to be computed later. | 109 /// expected to be computed later. |
| 105 void markAsJsInterop(Element element); | 110 void markAsJsInteropClass(ClassElement element); |
| 106 | |
| 107 /// Sets the explicit js interop [name] for [element]. | |
| 108 void setJsInteropName(Element element, String name); | |
| 109 } | 111 } |
| 110 | 112 |
| 111 abstract class NativeDataBuilder { | 113 abstract class NativeDataBuilder { |
| 112 /// Registers the [behavior] for calling the native [method]. | 114 /// Registers the [behavior] for calling the native [method]. |
| 113 void setNativeMethodBehavior(MethodElement method, NativeBehavior behavior); | 115 void setNativeMethodBehavior(MethodElement method, NativeBehavior behavior); |
| 114 | 116 |
| 115 /// Registers the [behavior] for reading from the native [field]. | 117 /// Registers the [behavior] for reading from the native [field]. |
| 116 void setNativeFieldLoadBehavior(FieldElement field, NativeBehavior behavior); | 118 void setNativeFieldLoadBehavior(FieldElement field, NativeBehavior behavior); |
| 117 | 119 |
| 118 /// Registers the [behavior] for writing to the native [field]. | 120 /// Registers the [behavior] for writing to the native [field]. |
| 119 void setNativeFieldStoreBehavior(FieldElement field, NativeBehavior behavior); | 121 void setNativeFieldStoreBehavior(FieldElement field, NativeBehavior behavior); |
| 122 | |
| 123 /// Returns the list of native tag words for [cls]. | |
| 124 List<String> getNativeTagsOfClassRaw(ClassElement cls); | |
| 125 | |
| 126 /// Returns [element] as an explicit part of JsInterop. The js interop name is | |
| 127 /// expected to be computed later. | |
| 128 void markAsJsInteropMember(MemberElement element); | |
| 129 | |
| 130 /// Sets the native [name] for the member [element]. This name is used for | |
| 131 /// [element] in the generated JavaScript. | |
| 132 void setNativeMemberName(MemberElement element, String name); | |
| 133 | |
| 134 /// Sets the explicit js interop [name] for [element]. | |
| 135 void setJsInteropName(Element element, String name); | |
| 120 } | 136 } |
| 121 | 137 |
| 122 class NativeDataImpl | 138 class NativeDataImpl |
| 123 implements NativeData, NativeDataBuilder, NativeClassDataBuilder { | 139 implements NativeData, NativeDataBuilder, NativeClassDataBuilder { |
| 124 /// The JavaScript names for elements implemented via typed JavaScript | 140 /// The JavaScript names for elements implemented via typed JavaScript |
| 125 /// interop. | 141 /// interop. |
| 126 Map<Element, String> jsInteropNames = <Element, String>{}; | 142 Map<Element, String> jsInteropNames = <Element, String>{}; |
| 127 | 143 |
| 128 /// The JavaScript names for native JavaScript elements implemented. | 144 /// The JavaScript names for native JavaScript elements implemented. |
| 129 Map<Element, String> nativeMemberName = <Element, String>{}; | 145 Map<Element, String> nativeMemberName = <Element, String>{}; |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 146 | 162 |
| 147 /// Prefix used to escape JS names that are not valid Dart names | 163 /// Prefix used to escape JS names that are not valid Dart names |
| 148 /// when using JSInterop. | 164 /// when using JSInterop. |
| 149 static const String _jsInteropEscapePrefix = r'JS$'; | 165 static const String _jsInteropEscapePrefix = r'JS$'; |
| 150 | 166 |
| 151 /// Returns `true` if [element] is explicitly marked as part of JsInterop. | 167 /// Returns `true` if [element] is explicitly marked as part of JsInterop. |
| 152 bool _isJsInterop(Element element) { | 168 bool _isJsInterop(Element element) { |
| 153 return jsInteropNames.containsKey(element.declaration); | 169 return jsInteropNames.containsKey(element.declaration); |
| 154 } | 170 } |
| 155 | 171 |
| 156 /// Returns [element] as an explicit part of JsInterop. The js interop name is | 172 /// Marks [element] as an explicit part of JsInterop. The js interop name is |
| 157 /// expected to be computed later. | 173 /// expected to be computed later. |
| 158 void markAsJsInterop(Element element) { | 174 void markAsJsInterop(Element element) { |
| 159 jsInteropNames[element.declaration] = null; | 175 jsInteropNames[element.declaration] = null; |
| 160 } | 176 } |
| 161 | 177 |
| 178 @override | |
| 179 void markAsJsInteropLibrary(LibraryElement element) { | |
| 180 markAsJsInterop(element); | |
| 181 } | |
| 182 | |
| 183 @override | |
| 184 void markAsJsInteropClass(ClassElement element) { | |
| 185 markAsJsInterop(element); | |
| 186 } | |
| 187 | |
| 188 @override | |
| 189 void markAsJsInteropMember(MemberElement element) { | |
| 190 markAsJsInterop(element); | |
| 191 } | |
| 192 | |
| 162 /// Sets the explicit js interop [name] for [element]. | 193 /// Sets the explicit js interop [name] for [element]. |
| 163 void setJsInteropName(Element element, String name) { | 194 void setJsInteropName(Element element, String name) { |
| 164 assert(invariant(element, isJsInterop(element), | 195 assert(invariant(element, isJsInterop(element), |
| 165 message: | 196 message: |
| 166 'Element $element is not js interop but given a js interop name.')); | 197 'Element $element is not js interop but given a js interop name.')); |
| 167 jsInteropNames[element.declaration] = name; | 198 jsInteropNames[element.declaration] = name; |
| 168 } | 199 } |
| 169 | 200 |
| 170 /// Returns the explicit js interop name for [element]. | 201 /// Returns the explicit js interop name for [element]. |
| 171 String getJsInteropName(Element element) { | 202 String getJsInteropName(Element element) { |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 183 | 214 |
| 184 if (_isJsInterop(function)) return true; | 215 if (_isJsInterop(function)) return true; |
| 185 if (function.isClassMember) return isJsInterop(function.contextClass); | 216 if (function.isClassMember) return isJsInterop(function.contextClass); |
| 186 if (function.isTopLevel) return isJsInterop(function.library); | 217 if (function.isTopLevel) return isJsInterop(function.library); |
| 187 return false; | 218 return false; |
| 188 } else { | 219 } else { |
| 189 return _isJsInterop(element); | 220 return _isJsInterop(element); |
| 190 } | 221 } |
| 191 } | 222 } |
| 192 | 223 |
| 224 /// Returns `true` if [element] is a JsInterop library. | |
| 225 bool isJsInteropLibrary(LibraryElement element) => isJsInterop(element); | |
| 226 | |
| 193 /// Returns `true` if [element] is a JsInterop class. | 227 /// Returns `true` if [element] is a JsInterop class. |
| 194 bool isJsInteropClass(ClassElement element) => isJsInterop(element); | 228 bool isJsInteropClass(ClassElement element) => isJsInterop(element); |
| 195 | 229 |
| 196 /// Returns `true` if [element] is a JsInterop method. | 230 /// Returns `true` if [element] is a JsInterop method. |
| 197 bool isJsInteropMethod(MethodElement element) => isJsInterop(element); | 231 bool isJsInteropMember(MethodElement element) => isJsInterop(element); |
| 198 | 232 |
| 199 /// Returns `true` if the name of [element] is fixed for the generated | 233 /// Returns `true` if the name of [element] is fixed for the generated |
| 200 /// JavaScript. | 234 /// JavaScript. |
| 201 bool hasFixedBackendName(Element element) { | 235 bool hasFixedBackendName(Element element) { |
| 202 return isJsInterop(element) || | 236 return isJsInterop(element) || |
| 203 nativeMemberName.containsKey(element.declaration); | 237 nativeMemberName.containsKey(element.declaration); |
| 204 } | 238 } |
| 205 | 239 |
| 206 String _jsNameHelper(Element element) { | 240 String _jsNameHelper(Element element) { |
| 207 String jsInteropName = jsInteropNames[element.declaration]; | 241 String jsInteropName = jsInteropNames[element.declaration]; |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 355 } | 389 } |
| 356 | 390 |
| 357 /// Apply JS$ escaping scheme to convert possible escaped Dart names into | 391 /// Apply JS$ escaping scheme to convert possible escaped Dart names into |
| 358 /// JS names. | 392 /// JS names. |
| 359 String getUnescapedJSInteropName(String name) { | 393 String getUnescapedJSInteropName(String name) { |
| 360 return name.startsWith(_jsInteropEscapePrefix) | 394 return name.startsWith(_jsInteropEscapePrefix) |
| 361 ? name.substring(_jsInteropEscapePrefix.length) | 395 ? name.substring(_jsInteropEscapePrefix.length) |
| 362 : name; | 396 : name; |
| 363 } | 397 } |
| 364 } | 398 } |
| OLD | NEW |