 Chromium Code Reviews
 Chromium Code Reviews Issue 2732793002:
  Add NativeDataResolver  (Closed)
    
  
    Issue 2732793002:
  Add NativeDataResolver  (Closed) 
  | 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 |