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 '../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 20 matching lines...) Expand all Loading... | |
| 31 bool isNativeOrExtendsNative(ClassEntity element); | 31 bool isNativeOrExtendsNative(ClassEntity element); |
| 32 | 32 |
| 33 /// Returns `true` if js interop features are used. | 33 /// Returns `true` if js interop features are used. |
| 34 bool get isJsInteropUsed; | 34 bool get isJsInteropUsed; |
| 35 | 35 |
| 36 /// Returns `true` if [element] is a JsInterop library. | 36 /// Returns `true` if [element] is a JsInterop library. |
| 37 bool isJsInteropLibrary(LibraryEntity element); | 37 bool isJsInteropLibrary(LibraryEntity element); |
| 38 | 38 |
| 39 /// Returns `true` if [element] is a JsInterop class. | 39 /// Returns `true` if [element] is a JsInterop class. |
| 40 bool isJsInteropClass(ClassEntity element); | 40 bool isJsInteropClass(ClassEntity element); |
| 41 | |
| 42 /// Returns `true` if [element] is a JsInterop member. | |
| 43 bool isJsInteropMember(MemberEntity element); | |
| 41 } | 44 } |
| 42 | 45 |
| 43 /// Additional element information for native classes and methods and js-interop | 46 /// Additional element information for native classes and methods and js-interop |
| 44 /// methods. | 47 /// methods. |
| 45 /// | 48 /// |
| 46 /// This information is computed during resolution using [NativeDataBuilder]. | 49 /// This information is computed during resolution using [NativeDataBuilder]. |
| 47 abstract class NativeData extends NativeBasicData { | 50 abstract class NativeData extends NativeBasicData { |
| 48 /// Returns `true` if [element] corresponds to a native JavaScript member. | 51 /// Returns `true` if [element] corresponds to a native JavaScript member. |
| 49 /// | 52 /// |
| 50 /// A member is marked as native either through the native mechanism | 53 /// A member is marked as native either through the native mechanism |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 97 } | 100 } |
| 98 | 101 |
| 99 abstract class NativeBasicDataBuilder { | 102 abstract class NativeBasicDataBuilder { |
| 100 /// Sets the native tag info for [cls]. | 103 /// Sets the native tag info for [cls]. |
| 101 /// | 104 /// |
| 102 /// The tag info string contains comma-separated 'words' which are either | 105 /// The tag info string contains comma-separated 'words' which are either |
| 103 /// dispatch tags (having JavaScript identifier syntax) and directives that | 106 /// dispatch tags (having JavaScript identifier syntax) and directives that |
| 104 /// begin with `!`. | 107 /// begin with `!`. |
| 105 void setNativeClassTagInfo(ClassEntity cls, String tagInfo); | 108 void setNativeClassTagInfo(ClassEntity cls, String tagInfo); |
| 106 | 109 |
| 107 /// Marks [element] as an explicit part of JsInterop. The js interop name is | 110 /// Marks [element] as an explicit part of js interop. |
| 108 /// expected to be computed later. | 111 /// |
| 109 void markAsJsInteropLibrary(LibraryEntity element); | 112 /// If [name] is provided, it sets the explicit js interop name for the |
| 113 /// library [element], other the js interop name is expected to be computed | |
| 114 /// later. | |
| 115 void markAsJsInteropLibrary(LibraryEntity element, {String name}); | |
| 110 | 116 |
| 111 /// Marks [element] as an explicit part of JsInterop. The js interop name is | 117 /// Marks [element] as an explicit part of js interop. |
| 112 /// expected to be computed later. | 118 /// |
| 113 void markAsJsInteropClass(ClassEntity element); | 119 /// If [name] is provided, it sets the explicit js interop name for the |
| 120 /// class [element], other the js interop name is expected to be computed | |
| 121 /// later. | |
| 122 void markAsJsInteropClass(ClassEntity element, | |
| 123 {String name, bool isAnonymous: false}); | |
| 124 | |
| 125 /// Marks [element] as an explicit part of js interop and sets the explicit js | |
| 126 /// interop [name] for the member [element]. | |
| 127 void markAsJsInteropMember(MemberEntity element, String name); | |
| 114 | 128 |
| 115 /// Creates the [NativeBasicData] object for the data collected in this | 129 /// Creates the [NativeBasicData] object for the data collected in this |
| 116 /// builder. | 130 /// builder. |
| 117 NativeBasicData close(ElementEnvironment environment); | 131 NativeBasicData close(ElementEnvironment environment); |
| 118 } | 132 } |
| 119 | 133 |
| 120 abstract class NativeDataBuilder { | 134 abstract class NativeDataBuilder { |
| 121 /// Registers the [behavior] for calling the native [method]. | 135 /// Registers the [behavior] for calling the native [method]. |
| 122 void setNativeMethodBehavior(FunctionEntity method, NativeBehavior behavior); | 136 void setNativeMethodBehavior(FunctionEntity method, NativeBehavior behavior); |
| 123 | 137 |
| 124 /// Registers the [behavior] for reading from the native [field]. | 138 /// Registers the [behavior] for reading from the native [field]. |
| 125 void setNativeFieldLoadBehavior(FieldEntity field, NativeBehavior behavior); | 139 void setNativeFieldLoadBehavior(FieldEntity field, NativeBehavior behavior); |
| 126 | 140 |
| 127 /// Registers the [behavior] for writing to the native [field]. | 141 /// Registers the [behavior] for writing to the native [field]. |
| 128 void setNativeFieldStoreBehavior(FieldEntity field, NativeBehavior behavior); | 142 void setNativeFieldStoreBehavior(FieldEntity field, NativeBehavior behavior); |
| 129 | 143 |
| 130 /// Returns [element] as an explicit part of JsInterop. The js interop name is | 144 /// Marks [element] as an explicit part of JsInterop. The js interop name is |
| 131 /// expected to be computed later. | 145 /// expected to be computed later. |
| 132 void markAsJsInteropMember(MemberEntity element); | 146 void markAsJsInteropMember(MemberEntity element); |
| 133 | 147 |
| 134 /// Sets the native [name] for the member [element]. This name is used for | 148 /// Sets the native [name] for the member [element]. This name is used for |
| 135 /// [element] in the generated JavaScript. | 149 /// [element] in the generated JavaScript. |
| 136 void setNativeMemberName(MemberEntity element, String name); | 150 void setNativeMemberName(MemberEntity element, String name); |
| 137 | 151 |
| 138 /// Sets the explicit js interop [name] for the library [element]. | 152 /// Sets the explicit js interop [name] for the library [element]. |
| 139 void setJsInteropLibraryName(LibraryEntity element, String name); | 153 void setJsInteropLibraryName(LibraryEntity element, String name); |
| 140 | 154 |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 151 NativeData close(); | 165 NativeData close(); |
| 152 } | 166 } |
| 153 | 167 |
| 154 class NativeBasicDataBuilderImpl implements NativeBasicDataBuilder { | 168 class NativeBasicDataBuilderImpl implements NativeBasicDataBuilder { |
| 155 /// Tag info for native JavaScript classes names. See | 169 /// Tag info for native JavaScript classes names. See |
| 156 /// [setNativeClassTagInfo]. | 170 /// [setNativeClassTagInfo]. |
| 157 Map<ClassEntity, NativeClassTag> nativeClassTagInfo = | 171 Map<ClassEntity, NativeClassTag> nativeClassTagInfo = |
| 158 <ClassEntity, NativeClassTag>{}; | 172 <ClassEntity, NativeClassTag>{}; |
| 159 | 173 |
| 160 /// The JavaScript libraries implemented via typed JavaScript interop. | 174 /// The JavaScript libraries implemented via typed JavaScript interop. |
| 161 Set<LibraryEntity> jsInteropLibraries = new Set<LibraryEntity>(); | 175 Map<LibraryEntity, String> jsInteropLibraries = <LibraryEntity, String>{}; |
| 162 | 176 |
| 163 /// The JavaScript classes implemented via typed JavaScript interop. | 177 /// The JavaScript classes implemented via typed JavaScript interop. |
| 164 Set<ClassEntity> jsInteropClasses = new Set<ClassEntity>(); | 178 Map<ClassEntity, String> jsInteropClasses = <ClassEntity, String>{}; |
| 179 | |
| 180 /// JavaScript interop classes annotated with `@anonymous` | |
| 181 Set<ClassEntity> anonymousJsInteropClasses = new Set<ClassEntity>(); | |
| 182 | |
| 183 /// The JavaScript members implemented via typed JavaScript interop. | |
| 184 Map<MemberEntity, String> jsInteropMembers = <MemberEntity, String>{}; | |
| 165 | 185 |
| 166 /// Sets the native tag info for [cls]. | 186 /// Sets the native tag info for [cls]. |
| 167 /// | 187 /// |
| 168 /// The tag info string contains comma-separated 'words' which are either | 188 /// The tag info string contains comma-separated 'words' which are either |
| 169 /// dispatch tags (having JavaScript identifier syntax) and directives that | 189 /// dispatch tags (having JavaScript identifier syntax) and directives that |
| 170 /// begin with `!`. | 190 /// begin with `!`. |
| 171 void setNativeClassTagInfo(ClassEntity cls, String tagText) { | 191 void setNativeClassTagInfo(ClassEntity cls, String tagText) { |
| 172 // TODO(johnniwinther): Assert that this is only called once. The memory | 192 // TODO(johnniwinther): Assert that this is only called once. The memory |
| 173 // compiler copies pre-processed elements into a new compiler through | 193 // compiler copies pre-processed elements into a new compiler through |
| 174 // [Compiler.onLibraryScanned] and thereby causes multiple calls to this | 194 // [Compiler.onLibraryScanned] and thereby causes multiple calls to this |
| 175 // method. | 195 // method. |
| 176 assert( | 196 assert( |
| 177 nativeClassTagInfo[cls] == null || | 197 nativeClassTagInfo[cls] == null || |
| 178 nativeClassTagInfo[cls].text == tagText, | 198 nativeClassTagInfo[cls].text == tagText, |
| 179 failedAt( | 199 failedAt( |
| 180 cls, | 200 cls, |
| 181 "Native tag info set inconsistently on $cls: " | 201 "Native tag info set inconsistently on $cls: " |
| 182 "Existing tag info '${nativeClassTagInfo[cls]}', " | 202 "Existing tag info '${nativeClassTagInfo[cls]}', " |
| 183 "new tag info '$tagText'.")); | 203 "new tag info '$tagText'.")); |
| 184 nativeClassTagInfo[cls] = new NativeClassTag(tagText); | 204 nativeClassTagInfo[cls] = new NativeClassTag(tagText); |
| 185 } | 205 } |
| 186 | 206 |
| 187 @override | 207 @override |
| 188 void markAsJsInteropLibrary(LibraryEntity element) { | 208 void markAsJsInteropLibrary(LibraryEntity element, {String name}) { |
| 189 jsInteropLibraries.add(element); | 209 jsInteropLibraries[element] = name; |
| 190 } | 210 } |
| 191 | 211 |
| 192 @override | 212 @override |
| 193 void markAsJsInteropClass(ClassEntity element) { | 213 void markAsJsInteropClass(ClassEntity element, |
| 194 jsInteropClasses.add(element); | 214 {String name, bool isAnonymous: false}) { |
| 215 jsInteropClasses[element] = name; | |
|
Siggi Cherem (dart-lang)
2017/08/08 00:06:46
do we expect a name when isAnonymous is true? shou
Johnni Winther
2017/08/09 08:34:36
We should. Adding a TODO
| |
| 216 if (isAnonymous) { | |
| 217 anonymousJsInteropClasses.add(element); | |
| 218 } | |
| 219 } | |
| 220 | |
| 221 @override | |
| 222 void markAsJsInteropMember(MemberEntity element, String name) { | |
| 223 jsInteropMembers[element] = name; | |
| 195 } | 224 } |
| 196 | 225 |
| 197 NativeBasicData close(ElementEnvironment environment) { | 226 NativeBasicData close(ElementEnvironment environment) { |
| 198 return new NativeBasicDataImpl( | 227 return new NativeBasicDataImpl( |
| 199 environment, nativeClassTagInfo, jsInteropLibraries, jsInteropClasses); | 228 environment, |
| 229 nativeClassTagInfo, | |
| 230 jsInteropLibraries, | |
| 231 jsInteropClasses, | |
| 232 anonymousJsInteropClasses, | |
| 233 jsInteropMembers); | |
| 200 } | 234 } |
| 201 } | 235 } |
| 202 | 236 |
| 203 class NativeBasicDataImpl implements NativeBasicData { | 237 class NativeBasicDataImpl implements NativeBasicData { |
| 204 final ElementEnvironment _env; | 238 final ElementEnvironment _env; |
| 205 | 239 |
| 206 /// Tag info for native JavaScript classes names. See | 240 /// Tag info for native JavaScript classes names. See |
| 207 /// [setNativeClassTagInfo]. | 241 /// [setNativeClassTagInfo]. |
| 208 final Map<ClassEntity, NativeClassTag> nativeClassTagInfo; | 242 final Map<ClassEntity, NativeClassTag> nativeClassTagInfo; |
| 209 | 243 |
| 210 /// The JavaScript libraries implemented via typed JavaScript interop. | 244 /// The JavaScript libraries implemented via typed JavaScript interop. |
| 211 final Set<LibraryEntity> jsInteropLibraries; | 245 final Map<LibraryEntity, String> jsInteropLibraries; |
| 212 | 246 |
| 213 /// The JavaScript classes implemented via typed JavaScript interop. | 247 /// The JavaScript classes implemented via typed JavaScript interop. |
| 214 final Set<ClassEntity> jsInteropClasses; | 248 final Map<ClassEntity, String> jsInteropClasses; |
| 215 | 249 |
| 216 NativeBasicDataImpl(this._env, this.nativeClassTagInfo, | 250 /// JavaScript interop classes annotated with `@anonymous` |
| 217 this.jsInteropLibraries, this.jsInteropClasses); | 251 final Set<ClassEntity> anonymousJsInteropClasses; |
| 218 | 252 |
| 219 /// Returns `true` if [cls] is a native class. | 253 /// The JavaScript members implemented via typed JavaScript interop. |
| 254 final Map<MemberEntity, String> jsInteropMembers; | |
| 255 | |
| 256 NativeBasicDataImpl( | |
| 257 this._env, | |
| 258 this.nativeClassTagInfo, | |
| 259 this.jsInteropLibraries, | |
| 260 this.jsInteropClasses, | |
| 261 this.anonymousJsInteropClasses, | |
| 262 this.jsInteropMembers); | |
| 263 | |
| 264 @override | |
| 220 bool isNativeClass(ClassEntity element) { | 265 bool isNativeClass(ClassEntity element) { |
| 221 if (isJsInteropClass(element)) return true; | 266 if (isJsInteropClass(element)) return true; |
| 222 return nativeClassTagInfo.containsKey(element); | 267 return nativeClassTagInfo.containsKey(element); |
| 223 } | 268 } |
| 224 | 269 |
| 225 /// Returns the list of non-directive native tag words for [cls]. | 270 @override |
| 226 List<String> getNativeTagsOfClass(ClassEntity cls) { | 271 List<String> getNativeTagsOfClass(ClassEntity cls) { |
| 227 return nativeClassTagInfo[cls].names; | 272 return nativeClassTagInfo[cls].names; |
| 228 } | 273 } |
| 229 | 274 |
| 230 /// Returns `true` if [cls] has a `!nonleaf` tag word. | 275 @override |
| 231 bool hasNativeTagsForcedNonLeaf(ClassEntity cls) { | 276 bool hasNativeTagsForcedNonLeaf(ClassEntity cls) { |
| 232 return nativeClassTagInfo[cls].isNonLeaf; | 277 return nativeClassTagInfo[cls].isNonLeaf; |
| 233 } | 278 } |
| 234 | 279 |
| 280 @override | |
| 235 bool get isJsInteropUsed => | 281 bool get isJsInteropUsed => |
| 236 jsInteropLibraries.isNotEmpty || jsInteropClasses.isNotEmpty; | 282 jsInteropLibraries.isNotEmpty || jsInteropClasses.isNotEmpty; |
| 237 | 283 |
| 238 /// Returns `true` if [element] is explicitly marked as part of JsInterop. | 284 @override |
| 239 bool isJsInteropLibrary(LibraryEntity element) { | 285 bool isJsInteropLibrary(LibraryEntity element) { |
| 240 return jsInteropLibraries.contains(element); | 286 return jsInteropLibraries.containsKey(element); |
| 241 } | 287 } |
| 242 | 288 |
| 243 /// Returns `true` if [element] is explicitly marked as part of JsInterop. | 289 @override |
| 244 bool isJsInteropClass(ClassEntity element) { | 290 bool isJsInteropClass(ClassEntity element) { |
| 245 return jsInteropClasses.contains(element); | 291 return jsInteropClasses.containsKey(element); |
| 246 } | 292 } |
| 247 | 293 |
| 248 /// Returns `true` if [element] or any of its superclasses is native. | 294 @override |
| 295 bool isJsInteropMember(MemberEntity element) { | |
| 296 return jsInteropMembers.containsKey(element); | |
| 297 } | |
| 298 | |
| 299 @override | |
| 249 bool isNativeOrExtendsNative(ClassEntity element) { | 300 bool isNativeOrExtendsNative(ClassEntity element) { |
| 250 if (element == null) return false; | 301 if (element == null) return false; |
| 251 if (isNativeClass(element) || isJsInteropClass(element)) { | 302 if (isNativeClass(element) || isJsInteropClass(element)) { |
| 252 return true; | 303 return true; |
| 253 } | 304 } |
| 254 return isNativeOrExtendsNative(_env.getSuperClass(element)); | 305 return isNativeOrExtendsNative(_env.getSuperClass(element)); |
| 255 } | 306 } |
| 256 } | 307 } |
| 257 | 308 |
| 258 class NativeDataBuilderImpl implements NativeDataBuilder { | 309 class NativeDataBuilderImpl implements NativeDataBuilder { |
| 259 final NativeBasicData _nativeBasicData; | 310 final NativeBasicDataImpl _nativeBasicData; |
| 260 | 311 |
| 261 /// The JavaScript names for native JavaScript elements implemented. | 312 /// The JavaScript names for native JavaScript elements implemented. |
| 262 Map<MemberEntity, String> nativeMemberName = <MemberEntity, String>{}; | 313 Map<MemberEntity, String> nativeMemberName = <MemberEntity, String>{}; |
| 263 | 314 |
| 264 /// Cache for [NativeBehavior]s for calling native methods. | 315 /// Cache for [NativeBehavior]s for calling native methods. |
| 265 Map<FunctionEntity, NativeBehavior> nativeMethodBehavior = | 316 Map<FunctionEntity, NativeBehavior> nativeMethodBehavior = |
| 266 <FunctionEntity, NativeBehavior>{}; | 317 <FunctionEntity, NativeBehavior>{}; |
| 267 | 318 |
| 268 /// Cache for [NativeBehavior]s for reading from native fields. | 319 /// Cache for [NativeBehavior]s for reading from native fields. |
| 269 Map<MemberEntity, NativeBehavior> nativeFieldLoadBehavior = | 320 Map<MemberEntity, NativeBehavior> nativeFieldLoadBehavior = |
| 270 <FieldEntity, NativeBehavior>{}; | 321 <FieldEntity, NativeBehavior>{}; |
| 271 | 322 |
| 272 /// Cache for [NativeBehavior]s for writing to native fields. | 323 /// Cache for [NativeBehavior]s for writing to native fields. |
| 273 Map<MemberEntity, NativeBehavior> nativeFieldStoreBehavior = | 324 Map<MemberEntity, NativeBehavior> nativeFieldStoreBehavior = |
| 274 <FieldEntity, NativeBehavior>{}; | 325 <FieldEntity, NativeBehavior>{}; |
| 275 | 326 |
| 276 /// The JavaScript names for libraries implemented via typed JavaScript | 327 /// The JavaScript names for libraries implemented via typed JavaScript |
| 277 /// interop. | 328 /// interop. |
| 278 Map<LibraryEntity, String> jsInteropLibraryNames = <LibraryEntity, String>{}; | 329 final Map<LibraryEntity, String> jsInteropLibraries; |
| 279 | 330 |
| 280 /// JavaScript interop classes annotated with `@anonymous` | 331 /// JavaScript interop classes annotated with `@anonymous` |
| 281 Set<ClassEntity> anonymousJsInteropClasses = new Set<ClassEntity>(); | 332 final Set<ClassEntity> anonymousJsInteropClasses; |
| 282 | 333 |
| 283 /// The JavaScript names for classes implemented via typed JavaScript | 334 /// The JavaScript names for classes implemented via typed JavaScript |
| 284 /// interop. | 335 /// interop. |
| 285 Map<ClassEntity, String> jsInteropClassNames = <ClassEntity, String>{}; | 336 final Map<ClassEntity, String> jsInteropClasses; |
| 286 | 337 |
| 287 /// The JavaScript names for members implemented via typed JavaScript | 338 /// The JavaScript names for members implemented via typed JavaScript |
| 288 /// interop. | 339 /// interop. |
| 289 Map<MemberEntity, String> jsInteropMemberNames = <MemberEntity, String>{}; | 340 final Map<MemberEntity, String> jsInteropMembers; |
| 290 | 341 |
| 291 NativeDataBuilderImpl(this._nativeBasicData); | 342 NativeDataBuilderImpl(this._nativeBasicData) |
| 343 : jsInteropLibraries = _nativeBasicData.jsInteropLibraries, | |
| 344 jsInteropClasses = _nativeBasicData.jsInteropClasses, | |
| 345 anonymousJsInteropClasses = _nativeBasicData.anonymousJsInteropClasses, | |
| 346 jsInteropMembers = _nativeBasicData.jsInteropMembers; | |
| 292 | 347 |
| 293 /// Sets the native [name] for the member [element]. This name is used for | 348 /// Sets the native [name] for the member [element]. This name is used for |
| 294 /// [element] in the generated JavaScript. | 349 /// [element] in the generated JavaScript. |
| 295 void setNativeMemberName(MemberEntity element, String name) { | 350 void setNativeMemberName(MemberEntity element, String name) { |
| 296 // TODO(johnniwinther): Avoid setting this more than once. The enqueuer | 351 // TODO(johnniwinther): Avoid setting this more than once. The enqueuer |
| 297 // might enqueue [element] several times (before processing it) and computes | 352 // might enqueue [element] several times (before processing it) and computes |
| 298 // name on each call to `internalAddToWorkList`. | 353 // name on each call to `internalAddToWorkList`. |
| 299 assert( | 354 assert( |
| 300 nativeMemberName[element] == null || nativeMemberName[element] == name, | 355 nativeMemberName[element] == null || nativeMemberName[element] == name, |
| 301 failedAt( | 356 failedAt( |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 320 void setNativeFieldStoreBehavior(FieldEntity field, NativeBehavior behavior) { | 375 void setNativeFieldStoreBehavior(FieldEntity field, NativeBehavior behavior) { |
| 321 nativeFieldStoreBehavior[field] = behavior; | 376 nativeFieldStoreBehavior[field] = behavior; |
| 322 } | 377 } |
| 323 | 378 |
| 324 /// Sets the explicit js interop [name] for the library [element]. | 379 /// Sets the explicit js interop [name] for the library [element]. |
| 325 void setJsInteropLibraryName(LibraryEntity element, String name) { | 380 void setJsInteropLibraryName(LibraryEntity element, String name) { |
| 326 assert( | 381 assert( |
| 327 _nativeBasicData.isJsInteropLibrary(element), | 382 _nativeBasicData.isJsInteropLibrary(element), |
| 328 failedAt(element, | 383 failedAt(element, |
| 329 'Library $element is not js interop but given a js interop name.')); | 384 'Library $element is not js interop but given a js interop name.')); |
| 330 jsInteropLibraryNames[element] = name; | 385 jsInteropLibraries[element] = name; |
| 331 } | 386 } |
| 332 | 387 |
| 333 @override | 388 @override |
| 334 void markJsInteropClassAsAnonymous(ClassEntity element) { | 389 void markJsInteropClassAsAnonymous(ClassEntity element) { |
| 335 anonymousJsInteropClasses.add(element); | 390 anonymousJsInteropClasses.add(element); |
| 336 } | 391 } |
| 337 | 392 |
| 338 /// Sets the explicit js interop [name] for the class [element]. | 393 /// Sets the explicit js interop [name] for the class [element]. |
| 339 void setJsInteropClassName(ClassEntity element, String name) { | 394 void setJsInteropClassName(ClassEntity element, String name) { |
| 340 assert( | 395 assert( |
| 341 _nativeBasicData.isJsInteropClass(element), | 396 _nativeBasicData.isJsInteropClass(element), |
| 342 failedAt(element, | 397 failedAt(element, |
| 343 'Class $element is not js interop but given a js interop name.')); | 398 'Class $element is not js interop but given a js interop name.')); |
| 344 jsInteropClassNames[element] = name; | 399 jsInteropClasses[element] = name; |
| 345 } | 400 } |
| 346 | 401 |
| 347 @override | 402 @override |
| 348 void markAsJsInteropMember(MemberEntity element) { | 403 void markAsJsInteropMember(MemberEntity element) { |
| 349 jsInteropMemberNames[element] = null; | 404 jsInteropMembers[element] = null; |
| 350 } | 405 } |
| 351 | 406 |
| 352 /// Sets the explicit js interop [name] for the member [element]. | 407 /// Sets the explicit js interop [name] for the member [element]. |
| 353 void setJsInteropMemberName(MemberEntity element, String name) { | 408 void setJsInteropMemberName(MemberEntity element, String name) { |
| 354 assert( | 409 assert( |
| 355 jsInteropMemberNames.containsKey(element), | 410 jsInteropMembers.containsKey(element), |
| 356 failedAt(element, | 411 failedAt(element, |
| 357 'Member $element is not js interop but given a js interop name.')); | 412 'Member $element is not js interop but given a js interop name.')); |
| 358 jsInteropMemberNames[element] = name; | 413 jsInteropMembers[element] = name; |
| 359 } | 414 } |
| 360 | 415 |
| 361 @override | 416 @override |
| 362 NativeData close() => new NativeDataImpl( | 417 NativeData close() => new NativeDataImpl( |
| 363 _nativeBasicData, | 418 _nativeBasicData, |
| 364 nativeMemberName, | 419 nativeMemberName, |
| 365 nativeMethodBehavior, | 420 nativeMethodBehavior, |
| 366 nativeFieldLoadBehavior, | 421 nativeFieldLoadBehavior, |
| 367 nativeFieldStoreBehavior, | 422 nativeFieldStoreBehavior, |
| 368 jsInteropLibraryNames, | 423 jsInteropLibraries, |
| 369 anonymousJsInteropClasses, | 424 anonymousJsInteropClasses, |
| 370 jsInteropClassNames, | 425 jsInteropClasses, |
| 371 jsInteropMemberNames); | 426 jsInteropMembers); |
| 372 } | 427 } |
| 373 | 428 |
| 374 class NativeDataImpl implements NativeData, NativeBasicDataImpl { | 429 class NativeDataImpl implements NativeData, NativeBasicDataImpl { |
| 375 /// Prefix used to escape JS names that are not valid Dart names | 430 /// Prefix used to escape JS names that are not valid Dart names |
| 376 /// when using JSInterop. | 431 /// when using JSInterop. |
| 377 static const String _jsInteropEscapePrefix = r'JS$'; | 432 static const String _jsInteropEscapePrefix = r'JS$'; |
| 378 | 433 |
| 379 final NativeBasicDataImpl _nativeBasicData; | 434 final NativeBasicDataImpl _nativeBasicData; |
| 380 | 435 |
| 381 /// The JavaScript names for native JavaScript elements implemented. | 436 /// The JavaScript names for native JavaScript elements implemented. |
| 382 final Map<MemberEntity, String> nativeMemberName; | 437 final Map<MemberEntity, String> nativeMemberName; |
| 383 | 438 |
| 384 /// Cache for [NativeBehavior]s for calling native methods. | 439 /// Cache for [NativeBehavior]s for calling native methods. |
| 385 final Map<FunctionEntity, NativeBehavior> nativeMethodBehavior; | 440 final Map<FunctionEntity, NativeBehavior> nativeMethodBehavior; |
| 386 | 441 |
| 387 /// Cache for [NativeBehavior]s for reading from native fields. | 442 /// Cache for [NativeBehavior]s for reading from native fields. |
| 388 final Map<MemberEntity, NativeBehavior> nativeFieldLoadBehavior; | 443 final Map<MemberEntity, NativeBehavior> nativeFieldLoadBehavior; |
| 389 | 444 |
| 390 /// Cache for [NativeBehavior]s for writing to native fields. | 445 /// Cache for [NativeBehavior]s for writing to native fields. |
| 391 final Map<MemberEntity, NativeBehavior> nativeFieldStoreBehavior; | 446 final Map<MemberEntity, NativeBehavior> nativeFieldStoreBehavior; |
| 392 | 447 |
| 393 /// The JavaScript names for libraries implemented via typed JavaScript | 448 /// The JavaScript names for libraries implemented via typed JavaScript |
| 394 /// interop. | 449 /// interop. |
| 395 final Map<LibraryEntity, String> jsInteropLibraryNames; | 450 final Map<LibraryEntity, String> jsInteropLibraries; |
| 396 | 451 |
| 397 /// JavaScript interop classes annotated with `@anonymous` | 452 /// JavaScript interop classes annotated with `@anonymous` |
| 398 final Set<ClassEntity> anonymousJsInteropClasses; | 453 final Set<ClassEntity> anonymousJsInteropClasses; |
| 399 | 454 |
| 400 /// The JavaScript names for classes implemented via typed JavaScript | 455 /// The JavaScript names for classes implemented via typed JavaScript |
| 401 /// interop. | 456 /// interop. |
| 402 final Map<ClassEntity, String> jsInteropClassNames; | 457 final Map<ClassEntity, String> jsInteropClasses; |
| 403 | 458 |
| 404 /// The JavaScript names for members implemented via typed JavaScript | 459 /// The JavaScript names for members implemented via typed JavaScript |
| 405 /// interop. | 460 /// interop. |
| 406 final Map<MemberEntity, String> jsInteropMemberNames; | 461 final Map<MemberEntity, String> jsInteropMembers; |
| 407 | 462 |
| 408 NativeDataImpl( | 463 NativeDataImpl( |
| 409 this._nativeBasicData, | 464 this._nativeBasicData, |
| 410 this.nativeMemberName, | 465 this.nativeMemberName, |
| 411 this.nativeMethodBehavior, | 466 this.nativeMethodBehavior, |
| 412 this.nativeFieldLoadBehavior, | 467 this.nativeFieldLoadBehavior, |
| 413 this.nativeFieldStoreBehavior, | 468 this.nativeFieldStoreBehavior, |
| 414 this.jsInteropLibraryNames, | 469 this.jsInteropLibraries, |
| 415 this.anonymousJsInteropClasses, | 470 this.anonymousJsInteropClasses, |
| 416 this.jsInteropClassNames, | 471 this.jsInteropClasses, |
| 417 this.jsInteropMemberNames); | 472 this.jsInteropMembers); |
| 418 | 473 |
| 419 @override | 474 @override |
| 420 bool isAnonymousJsInteropClass(ClassEntity element) { | 475 bool isAnonymousJsInteropClass(ClassEntity element) { |
| 421 return anonymousJsInteropClasses.contains(element); | 476 return anonymousJsInteropClasses.contains(element); |
| 422 } | 477 } |
| 423 | 478 |
| 424 /// Returns `true` if [cls] is a native class. | 479 /// Returns `true` if [cls] is a native class. |
| 425 bool isNativeClass(ClassEntity element) => | 480 bool isNativeClass(ClassEntity element) => |
| 426 _nativeBasicData.isNativeClass(element); | 481 _nativeBasicData.isNativeClass(element); |
| 427 | 482 |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 442 /// Returns `true` if [element] is a JsInterop class. | 497 /// Returns `true` if [element] is a JsInterop class. |
| 443 bool isJsInteropClass(ClassEntity element) => | 498 bool isJsInteropClass(ClassEntity element) => |
| 444 _nativeBasicData.isJsInteropClass(element); | 499 _nativeBasicData.isJsInteropClass(element); |
| 445 | 500 |
| 446 /// Returns `true` if [element] or any of its superclasses is native. | 501 /// Returns `true` if [element] or any of its superclasses is native. |
| 447 bool isNativeOrExtendsNative(ClassEntity element) => | 502 bool isNativeOrExtendsNative(ClassEntity element) => |
| 448 _nativeBasicData.isNativeOrExtendsNative(element); | 503 _nativeBasicData.isNativeOrExtendsNative(element); |
| 449 | 504 |
| 450 /// Returns the explicit js interop name for library [element]. | 505 /// Returns the explicit js interop name for library [element]. |
| 451 String getJsInteropLibraryName(LibraryEntity element) { | 506 String getJsInteropLibraryName(LibraryEntity element) { |
| 452 return jsInteropLibraryNames[element]; | 507 return jsInteropLibraries[element]; |
| 453 } | 508 } |
| 454 | 509 |
| 455 /// Returns the explicit js interop name for class [element]. | 510 /// Returns the explicit js interop name for class [element]. |
| 456 String getJsInteropClassName(ClassEntity element) { | 511 String getJsInteropClassName(ClassEntity element) { |
| 457 return jsInteropClassNames[element]; | 512 return jsInteropClasses[element]; |
| 458 } | 513 } |
| 459 | 514 |
| 460 /// Returns the explicit js interop name for member [element]. | 515 /// Returns the explicit js interop name for member [element]. |
| 461 String getJsInteropMemberName(MemberEntity element) { | 516 String getJsInteropMemberName(MemberEntity element) { |
| 462 return jsInteropMemberNames[element]; | 517 return jsInteropMembers[element]; |
| 463 } | 518 } |
| 464 | 519 |
| 465 /// Returns `true` if [element] is explicitly marked as part of JsInterop. | 520 /// Returns `true` if [element] is explicitly marked as part of JsInterop. |
| 466 bool _isJsInteropMember(MemberEntity element) { | 521 bool _isJsInteropMember(MemberEntity element) { |
| 467 return jsInteropMemberNames.containsKey(element); | 522 return jsInteropMembers.containsKey(element); |
| 468 } | 523 } |
| 469 | 524 |
| 470 /// Returns `true` if [element] is a JsInterop method. | 525 /// Returns `true` if [element] is a JsInterop method. |
| 471 bool isJsInteropMember(MemberEntity element) { | 526 bool isJsInteropMember(MemberEntity element) { |
| 472 if (element.isFunction || | 527 if (element.isFunction || |
| 473 element.isConstructor || | 528 element.isConstructor || |
| 474 element.isGetter || | 529 element.isGetter || |
| 475 element.isSetter) { | 530 element.isSetter) { |
| 476 FunctionEntity function = element; | 531 FunctionEntity function = element; |
| 477 if (!function.isExternal) return false; | 532 if (!function.isExternal) return false; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 516 return 'self'; | 571 return 'self'; |
| 517 } | 572 } |
| 518 | 573 |
| 519 String _jsClassNameHelper(ClassEntity element) { | 574 String _jsClassNameHelper(ClassEntity element) { |
| 520 String jsInteropName = getJsInteropClassName(element); | 575 String jsInteropName = getJsInteropClassName(element); |
| 521 if (jsInteropName != null && jsInteropName.isNotEmpty) return jsInteropName; | 576 if (jsInteropName != null && jsInteropName.isNotEmpty) return jsInteropName; |
| 522 return computeUnescapedJSInteropName(element.name); | 577 return computeUnescapedJSInteropName(element.name); |
| 523 } | 578 } |
| 524 | 579 |
| 525 String _jsMemberNameHelper(MemberEntity element) { | 580 String _jsMemberNameHelper(MemberEntity element) { |
| 526 String jsInteropName = jsInteropMemberNames[element]; | 581 String jsInteropName = jsInteropMembers[element]; |
| 527 assert( | 582 assert( |
| 528 !(jsInteropMemberNames.containsKey(element) && jsInteropName == null), | 583 !(jsInteropMembers.containsKey(element) && jsInteropName == null), |
| 529 failedAt( | 584 failedAt( |
| 530 element, | 585 element, |
| 531 'Member $element is js interop but js interop name has not yet ' | 586 'Member $element is js interop but js interop name has not yet ' |
| 532 'been computed.')); | 587 'been computed.')); |
| 533 if (jsInteropName != null && jsInteropName.isNotEmpty) { | 588 if (jsInteropName != null && jsInteropName.isNotEmpty) { |
| 534 return jsInteropName; | 589 return jsInteropName; |
| 535 } | 590 } |
| 536 return computeUnescapedJSInteropName(element.name); | 591 return computeUnescapedJSInteropName(element.name); |
| 537 } | 592 } |
| 538 | 593 |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 598 | 653 |
| 599 /// Apply JS$ escaping scheme to convert possible escaped Dart names into | 654 /// Apply JS$ escaping scheme to convert possible escaped Dart names into |
| 600 /// JS names. | 655 /// JS names. |
| 601 String computeUnescapedJSInteropName(String name) { | 656 String computeUnescapedJSInteropName(String name) { |
| 602 return name.startsWith(_jsInteropEscapePrefix) | 657 return name.startsWith(_jsInteropEscapePrefix) |
| 603 ? name.substring(_jsInteropEscapePrefix.length) | 658 ? name.substring(_jsInteropEscapePrefix.length) |
| 604 : name; | 659 : name; |
| 605 } | 660 } |
| 606 | 661 |
| 607 @override | 662 @override |
| 608 Set<ClassEntity> get jsInteropClasses => _nativeBasicData.jsInteropClasses; | |
| 609 | |
| 610 @override | |
| 611 Set<LibraryEntity> get jsInteropLibraries => | |
| 612 _nativeBasicData.jsInteropLibraries; | |
| 613 | |
| 614 @override | |
| 615 Map<ClassEntity, NativeClassTag> get nativeClassTagInfo => | 663 Map<ClassEntity, NativeClassTag> get nativeClassTagInfo => |
| 616 _nativeBasicData.nativeClassTagInfo; | 664 _nativeBasicData.nativeClassTagInfo; |
| 617 | 665 |
| 618 @override | 666 @override |
| 619 ElementEnvironment get _env => _nativeBasicData._env; | 667 ElementEnvironment get _env => _nativeBasicData._env; |
| 620 } | 668 } |
| 621 | 669 |
| 622 class NativeClassTag { | 670 class NativeClassTag { |
| 623 final List<String> names; | 671 final List<String> names; |
| 624 final bool isNonLeaf; | 672 final bool isNonLeaf; |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 647 int get hashCode => Hashing.listHash(names, isNonLeaf.hashCode); | 695 int get hashCode => Hashing.listHash(names, isNonLeaf.hashCode); |
| 648 | 696 |
| 649 bool operator ==(other) { | 697 bool operator ==(other) { |
| 650 if (identical(this, other)) return true; | 698 if (identical(this, other)) return true; |
| 651 if (other is! NativeClassTag) return false; | 699 if (other is! NativeClassTag) return false; |
| 652 return equalElements(names, other.names) && isNonLeaf == other.isNonLeaf; | 700 return equalElements(names, other.names) && isNonLeaf == other.isNonLeaf; |
| 653 } | 701 } |
| 654 | 702 |
| 655 String toString() => text; | 703 String toString() => text; |
| 656 } | 704 } |
| OLD | NEW |