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' show ClassElement; | 8 import '../elements/elements.dart' show ClassElement; |
9 import '../elements/entities.dart'; | 9 import '../elements/entities.dart'; |
10 import '../native/behavior.dart' show NativeBehavior; | 10 import '../native/behavior.dart' show NativeBehavior; |
11 import '../util/util.dart'; | 11 import '../util/util.dart'; |
12 | 12 |
13 /// Basic information for native classes and methods and js-interop | 13 /// Basic information for native classes and js-interop libraries and classes. |
14 /// classes. | |
15 /// | 14 /// |
16 /// This information is computed during loading using [NativeClassDataBuilder]. | 15 /// This information is computed during loading using [NativeBasicDataBuilder]. |
17 abstract class NativeClassData { | 16 abstract class NativeBasicData { |
18 /// Returns `true` if [cls] corresponds to a native JavaScript class. | 17 /// Returns `true` if [cls] corresponds to a native JavaScript class. |
19 /// | 18 /// |
20 /// A class is marked as native either through the `@Native(...)` annotation | 19 /// A class is marked as native either through the `@Native(...)` annotation |
21 /// allowed for internal libraries or via the typed JavaScriptInterop | 20 /// allowed for internal libraries or via the typed JavaScriptInterop |
22 /// mechanism allowed for user libraries. | 21 /// mechanism allowed for user libraries. |
23 bool isNativeClass(ClassEntity element); | 22 bool isNativeClass(ClassEntity element); |
24 | 23 |
25 /// Returns the list of non-directive native tag words for [cls]. | 24 /// Returns the list of non-directive native tag words for [cls]. |
26 List<String> getNativeTagsOfClass(ClassEntity cls); | 25 List<String> getNativeTagsOfClass(ClassEntity cls); |
27 | 26 |
28 /// Returns `true` if [cls] has a `!nonleaf` tag word. | 27 /// Returns `true` if [cls] has a `!nonleaf` tag word. |
29 bool hasNativeTagsForcedNonLeaf(ClassEntity cls); | 28 bool hasNativeTagsForcedNonLeaf(ClassEntity cls); |
30 | 29 |
31 /// Returns `true` if [element] or any of its superclasses is native. | 30 /// Returns `true` if [element] or any of its superclasses is native. |
32 bool isNativeOrExtendsNative(ClassEntity element); | 31 bool isNativeOrExtendsNative(ClassEntity element); |
33 | 32 |
34 /// Returns `true` if [element] is a JsInterop library. | 33 /// Returns `true` if [element] is a JsInterop library. |
35 bool isJsInteropLibrary(LibraryEntity element); | 34 bool isJsInteropLibrary(LibraryEntity element); |
36 | 35 |
37 /// Returns `true` if [element] is a JsInterop class. | 36 /// Returns `true` if [element] is a JsInterop class. |
38 bool isJsInteropClass(ClassEntity element); | 37 bool isJsInteropClass(ClassEntity element); |
39 } | 38 } |
40 | 39 |
41 /// Additional element information for native classes and methods and js-interop | 40 /// Additional element information for native classes and methods and js-interop |
42 /// methods. | 41 /// methods. |
43 /// | 42 /// |
44 /// This information is computed during resolution using [NativeDataBuilder]. | 43 /// This information is computed during resolution using [NativeDataBuilder]. |
45 abstract class NativeData extends NativeClassData { | 44 abstract class NativeData extends NativeBasicData { |
46 /// Returns `true` if [element] corresponds to a native JavaScript member. | 45 /// Returns `true` if [element] corresponds to a native JavaScript member. |
47 /// | 46 /// |
48 /// A member is marked as native either through the native mechanism | 47 /// A member is marked as native either through the native mechanism |
49 /// (`@Native(...)` or the `native` pseudo keyword) allowed for internal | 48 /// (`@Native(...)` or the `native` pseudo keyword) allowed for internal |
50 /// libraries or via the typed JavaScriptInterop mechanism allowed for user | 49 /// libraries or via the typed JavaScriptInterop mechanism allowed for user |
51 /// libraries. | 50 /// libraries. |
52 bool isNativeMember(MemberEntity element); | 51 bool isNativeMember(MemberEntity element); |
53 | 52 |
54 /// Returns the [NativeBehavior] for calling the native [method]. | 53 /// Returns the [NativeBehavior] for calling the native [method]. |
55 NativeBehavior getNativeMethodBehavior(FunctionEntity method); | 54 NativeBehavior getNativeMethodBehavior(FunctionEntity method); |
(...skipping 28 matching lines...) Expand all Loading... | |
84 String getJsInteropClassName(ClassEntity element); | 83 String getJsInteropClassName(ClassEntity element); |
85 | 84 |
86 /// Returns the explicit js interop name for member [element]. | 85 /// Returns the explicit js interop name for member [element]. |
87 String getJsInteropMemberName(MemberEntity element); | 86 String getJsInteropMemberName(MemberEntity element); |
88 | 87 |
89 /// Apply JS$ escaping scheme to convert possible escaped Dart names into | 88 /// Apply JS$ escaping scheme to convert possible escaped Dart names into |
90 /// JS names. | 89 /// JS names. |
91 String computeUnescapedJSInteropName(String name); | 90 String computeUnescapedJSInteropName(String name); |
92 } | 91 } |
93 | 92 |
94 abstract class NativeClassDataBuilder { | 93 abstract class NativeBasicDataBuilder { |
95 /// Sets the native tag info for [cls]. | 94 /// Sets the native tag info for [cls]. |
96 /// | 95 /// |
97 /// The tag info string contains comma-separated 'words' which are either | 96 /// The tag info string contains comma-separated 'words' which are either |
98 /// dispatch tags (having JavaScript identifier syntax) and directives that | 97 /// dispatch tags (having JavaScript identifier syntax) and directives that |
99 /// begin with `!`. | 98 /// begin with `!`. |
100 void setNativeClassTagInfo(ClassEntity cls, String tagInfo); | 99 void setNativeClassTagInfo(ClassEntity cls, String tagInfo); |
101 | 100 |
102 /// Marks [element] as an explicit part of JsInterop. The js interop name is | 101 /// Marks [element] as an explicit part of JsInterop. The js interop name is |
103 /// expected to be computed later. | 102 /// expected to be computed later. |
104 void markAsJsInteropLibrary(LibraryEntity element); | 103 void markAsJsInteropLibrary(LibraryEntity element); |
(...skipping 24 matching lines...) Expand all Loading... | |
129 /// Sets the explicit js interop [name] for the library [element]. | 128 /// Sets the explicit js interop [name] for the library [element]. |
130 void setJsInteropLibraryName(LibraryEntity element, String name); | 129 void setJsInteropLibraryName(LibraryEntity element, String name); |
131 | 130 |
132 /// Sets the explicit js interop [name] for the class [element]. | 131 /// Sets the explicit js interop [name] for the class [element]. |
133 void setJsInteropClassName(ClassEntity element, String name); | 132 void setJsInteropClassName(ClassEntity element, String name); |
134 | 133 |
135 /// Sets the explicit js interop [name] for the member [element]. | 134 /// Sets the explicit js interop [name] for the member [element]. |
136 void setJsInteropMemberName(MemberEntity element, String name); | 135 void setJsInteropMemberName(MemberEntity element, String name); |
137 } | 136 } |
138 | 137 |
139 class NativeClassDataImpl implements NativeClassDataBuilder, NativeClassData { | 138 class NativeBasicDataImpl implements NativeBasicDataBuilder, NativeBasicData { |
140 /// Tag info for native JavaScript classes names. See | 139 /// Tag info for native JavaScript classes names. See |
141 /// [setNativeClassTagInfo]. | 140 /// [setNativeClassTagInfo]. |
142 Map<ClassEntity, NativeClassTag> nativeClassTagInfo = | 141 Map<ClassEntity, NativeClassTag> nativeClassTagInfo = |
143 <ClassEntity, NativeClassTag>{}; | 142 <ClassEntity, NativeClassTag>{}; |
144 | 143 |
145 /// The JavaScript libraries implemented via typed JavaScript interop. | 144 /// The JavaScript libraries implemented via typed JavaScript interop. |
146 Set<LibraryEntity> jsInteropLibraries = new Set<LibraryEntity>(); | 145 Set<LibraryEntity> jsInteropLibraries = new Set<LibraryEntity>(); |
147 | 146 |
148 /// The JavaScript classes implemented via typed JavaScript interop. | 147 /// The JavaScript classes implemented via typed JavaScript interop. |
149 Set<ClassEntity> jsInteropClasses = new Set<ClassEntity>(); | 148 Set<ClassEntity> jsInteropClasses = new Set<ClassEntity>(); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
214 assert(element.isResolved); | 213 assert(element.isResolved); |
215 return isNativeOrExtendsNative(element.superclass); | 214 return isNativeOrExtendsNative(element.superclass); |
216 } | 215 } |
217 } | 216 } |
218 | 217 |
219 class NativeDataImpl implements NativeDataBuilder, NativeData { | 218 class NativeDataImpl implements NativeDataBuilder, NativeData { |
220 /// Prefix used to escape JS names that are not valid Dart names | 219 /// Prefix used to escape JS names that are not valid Dart names |
221 /// when using JSInterop. | 220 /// when using JSInterop. |
222 static const String _jsInteropEscapePrefix = r'JS$'; | 221 static const String _jsInteropEscapePrefix = r'JS$'; |
223 | 222 |
224 final NativeClassData _nativeClassData; | 223 final NativeBasicData _nativeBaseData; |
Siggi Cherem (dart-lang)
2017/03/17 23:50:55
should the variable be BasicData too? I have a fee
| |
225 | 224 |
226 /// The JavaScript names for native JavaScript elements implemented. | 225 /// The JavaScript names for native JavaScript elements implemented. |
227 Map<MemberEntity, String> nativeMemberName = <MemberEntity, String>{}; | 226 Map<MemberEntity, String> nativeMemberName = <MemberEntity, String>{}; |
228 | 227 |
229 /// Cache for [NativeBehavior]s for calling native methods. | 228 /// Cache for [NativeBehavior]s for calling native methods. |
230 Map<FunctionEntity, NativeBehavior> nativeMethodBehavior = | 229 Map<FunctionEntity, NativeBehavior> nativeMethodBehavior = |
231 <FunctionEntity, NativeBehavior>{}; | 230 <FunctionEntity, NativeBehavior>{}; |
232 | 231 |
233 /// Cache for [NativeBehavior]s for reading from native fields. | 232 /// Cache for [NativeBehavior]s for reading from native fields. |
234 Map<MemberEntity, NativeBehavior> nativeFieldLoadBehavior = | 233 Map<MemberEntity, NativeBehavior> nativeFieldLoadBehavior = |
235 <FieldEntity, NativeBehavior>{}; | 234 <FieldEntity, NativeBehavior>{}; |
236 | 235 |
237 /// Cache for [NativeBehavior]s for writing to native fields. | 236 /// Cache for [NativeBehavior]s for writing to native fields. |
238 Map<MemberEntity, NativeBehavior> nativeFieldStoreBehavior = | 237 Map<MemberEntity, NativeBehavior> nativeFieldStoreBehavior = |
239 <FieldEntity, NativeBehavior>{}; | 238 <FieldEntity, NativeBehavior>{}; |
240 | 239 |
241 /// The JavaScript names for elements implemented via typed JavaScript | 240 /// The JavaScript names for elements implemented via typed JavaScript |
242 /// interop. | 241 /// interop. |
243 Map<LibraryEntity, String> jsInteropLibraryNames = <LibraryEntity, String>{}; | 242 Map<LibraryEntity, String> jsInteropLibraryNames = <LibraryEntity, String>{}; |
244 Map<ClassEntity, String> jsInteropClassNames = <ClassEntity, String>{}; | 243 Map<ClassEntity, String> jsInteropClassNames = <ClassEntity, String>{}; |
245 | 244 |
246 /// The JavaScript names for elements implemented via typed JavaScript | 245 /// The JavaScript names for elements implemented via typed JavaScript |
247 /// interop. | 246 /// interop. |
248 Map<MemberEntity, String> jsInteropMemberNames = <MemberEntity, String>{}; | 247 Map<MemberEntity, String> jsInteropMemberNames = <MemberEntity, String>{}; |
249 | 248 |
250 NativeDataImpl(this._nativeClassData); | 249 NativeDataImpl(this._nativeBaseData); |
251 | 250 |
252 /// Sets the native [name] for the member [element]. This name is used for | 251 /// Sets the native [name] for the member [element]. This name is used for |
253 /// [element] in the generated JavaScript. | 252 /// [element] in the generated JavaScript. |
254 void setNativeMemberName(MemberEntity element, String name) { | 253 void setNativeMemberName(MemberEntity element, String name) { |
255 // TODO(johnniwinther): Avoid setting this more than once. The enqueuer | 254 // TODO(johnniwinther): Avoid setting this more than once. The enqueuer |
256 // might enqueue [element] several times (before processing it) and computes | 255 // might enqueue [element] several times (before processing it) and computes |
257 // name on each call to `internalAddToWorkList`. | 256 // name on each call to `internalAddToWorkList`. |
258 assert(invariant(element, | 257 assert(invariant(element, |
259 nativeMemberName[element] == null || nativeMemberName[element] == name, | 258 nativeMemberName[element] == null || nativeMemberName[element] == name, |
260 message: "Native member name set inconsistently on $element: " | 259 message: "Native member name set inconsistently on $element: " |
(...skipping 12 matching lines...) Expand all Loading... | |
273 nativeFieldLoadBehavior[field] = behavior; | 272 nativeFieldLoadBehavior[field] = behavior; |
274 } | 273 } |
275 | 274 |
276 /// Registers the [behavior] for writing to the native [field]. | 275 /// Registers the [behavior] for writing to the native [field]. |
277 void setNativeFieldStoreBehavior(FieldEntity field, NativeBehavior behavior) { | 276 void setNativeFieldStoreBehavior(FieldEntity field, NativeBehavior behavior) { |
278 nativeFieldStoreBehavior[field] = behavior; | 277 nativeFieldStoreBehavior[field] = behavior; |
279 } | 278 } |
280 | 279 |
281 /// Sets the explicit js interop [name] for the library [element]. | 280 /// Sets the explicit js interop [name] for the library [element]. |
282 void setJsInteropLibraryName(LibraryEntity element, String name) { | 281 void setJsInteropLibraryName(LibraryEntity element, String name) { |
283 assert(invariant(element, _nativeClassData.isJsInteropLibrary(element), | 282 assert(invariant(element, _nativeBaseData.isJsInteropLibrary(element), |
284 message: | 283 message: |
285 'Library $element is not js interop but given a js interop name.')); | 284 'Library $element is not js interop but given a js interop name.')); |
286 jsInteropLibraryNames[element] = name; | 285 jsInteropLibraryNames[element] = name; |
287 } | 286 } |
288 | 287 |
289 /// Sets the explicit js interop [name] for the class [element]. | 288 /// Sets the explicit js interop [name] for the class [element]. |
290 void setJsInteropClassName(ClassEntity element, String name) { | 289 void setJsInteropClassName(ClassEntity element, String name) { |
291 assert(invariant(element, _nativeClassData.isJsInteropClass(element), | 290 assert(invariant(element, _nativeBaseData.isJsInteropClass(element), |
292 message: | 291 message: |
293 'Class $element is not js interop but given a js interop name.')); | 292 'Class $element is not js interop but given a js interop name.')); |
294 jsInteropClassNames[element] = name; | 293 jsInteropClassNames[element] = name; |
295 } | 294 } |
296 | 295 |
297 @override | 296 @override |
298 void markAsJsInteropMember(MemberEntity element) { | 297 void markAsJsInteropMember(MemberEntity element) { |
299 jsInteropMemberNames[element] = null; | 298 jsInteropMemberNames[element] = null; |
300 } | 299 } |
301 | 300 |
302 /// Returns `true` if [element] is explicitly marked as part of JsInterop. | 301 /// Returns `true` if [element] is explicitly marked as part of JsInterop. |
303 bool _isJsInteropMember(MemberEntity element) { | 302 bool _isJsInteropMember(MemberEntity element) { |
304 return jsInteropMemberNames.containsKey(element); | 303 return jsInteropMemberNames.containsKey(element); |
305 } | 304 } |
306 | 305 |
307 /// Sets the explicit js interop [name] for the member [element]. | 306 /// Sets the explicit js interop [name] for the member [element]. |
308 void setJsInteropMemberName(MemberEntity element, String name) { | 307 void setJsInteropMemberName(MemberEntity element, String name) { |
309 assert(invariant(element, _isJsInteropMember(element), | 308 assert(invariant(element, _isJsInteropMember(element), |
310 message: | 309 message: |
311 'Member $element is not js interop but given a js interop name.')); | 310 'Member $element is not js interop but given a js interop name.')); |
312 jsInteropMemberNames[element] = name; | 311 jsInteropMemberNames[element] = name; |
313 } | 312 } |
314 | 313 |
315 /// Returns `true` if [cls] is a native class. | 314 /// Returns `true` if [cls] is a native class. |
316 bool isNativeClass(ClassEntity element) => | 315 bool isNativeClass(ClassEntity element) => |
317 _nativeClassData.isNativeClass(element); | 316 _nativeBaseData.isNativeClass(element); |
318 | 317 |
319 /// Returns the list of non-directive native tag words for [cls]. | 318 /// Returns the list of non-directive native tag words for [cls]. |
320 List<String> getNativeTagsOfClass(ClassEntity cls) => | 319 List<String> getNativeTagsOfClass(ClassEntity cls) => |
321 _nativeClassData.getNativeTagsOfClass(cls); | 320 _nativeBaseData.getNativeTagsOfClass(cls); |
322 | 321 |
323 /// Returns `true` if [cls] has a `!nonleaf` tag word. | 322 /// Returns `true` if [cls] has a `!nonleaf` tag word. |
324 bool hasNativeTagsForcedNonLeaf(ClassEntity cls) => | 323 bool hasNativeTagsForcedNonLeaf(ClassEntity cls) => |
325 _nativeClassData.hasNativeTagsForcedNonLeaf(cls); | 324 _nativeBaseData.hasNativeTagsForcedNonLeaf(cls); |
326 | 325 |
327 /// Returns `true` if [element] is a JsInterop library. | 326 /// Returns `true` if [element] is a JsInterop library. |
328 bool isJsInteropLibrary(LibraryEntity element) => | 327 bool isJsInteropLibrary(LibraryEntity element) => |
329 _nativeClassData.isJsInteropLibrary(element); | 328 _nativeBaseData.isJsInteropLibrary(element); |
330 | 329 |
331 /// Returns `true` if [element] is a JsInterop class. | 330 /// Returns `true` if [element] is a JsInterop class. |
332 bool isJsInteropClass(ClassEntity element) => | 331 bool isJsInteropClass(ClassEntity element) => |
333 _nativeClassData.isJsInteropClass(element); | 332 _nativeBaseData.isJsInteropClass(element); |
334 | 333 |
335 /// Returns `true` if [element] or any of its superclasses is native. | 334 /// Returns `true` if [element] or any of its superclasses is native. |
336 bool isNativeOrExtendsNative(ClassEntity element) => | 335 bool isNativeOrExtendsNative(ClassEntity element) => |
337 _nativeClassData.isNativeOrExtendsNative(element); | 336 _nativeBaseData.isNativeOrExtendsNative(element); |
338 | 337 |
339 /// Returns the explicit js interop name for library [element]. | 338 /// Returns the explicit js interop name for library [element]. |
340 String getJsInteropLibraryName(LibraryEntity element) { | 339 String getJsInteropLibraryName(LibraryEntity element) { |
341 return jsInteropLibraryNames[element]; | 340 return jsInteropLibraryNames[element]; |
342 } | 341 } |
343 | 342 |
344 /// Returns the explicit js interop name for class [element]. | 343 /// Returns the explicit js interop name for class [element]. |
345 String getJsInteropClassName(ClassEntity element) { | 344 String getJsInteropClassName(ClassEntity element) { |
346 return jsInteropClassNames[element]; | 345 return jsInteropClassNames[element]; |
347 } | 346 } |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
510 int get hashCode => Hashing.listHash(names, isNonLeaf.hashCode); | 509 int get hashCode => Hashing.listHash(names, isNonLeaf.hashCode); |
511 | 510 |
512 bool operator ==(other) { | 511 bool operator ==(other) { |
513 if (identical(this, other)) return true; | 512 if (identical(this, other)) return true; |
514 if (other is! NativeClassTag) return false; | 513 if (other is! NativeClassTag) return false; |
515 return equalElements(names, other.names) && isNonLeaf == other.isNonLeaf; | 514 return equalElements(names, other.names) && isNonLeaf == other.isNonLeaf; |
516 } | 515 } |
517 | 516 |
518 String toString() => text; | 517 String toString() => text; |
519 } | 518 } |
OLD | NEW |