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, | |
14 LibraryElement, | 13 LibraryElement, |
15 MemberElement, | 14 MemberElement, |
16 MethodElement; | 15 MethodElement; |
17 import '../elements/entities.dart'; | 16 import '../elements/entities.dart'; |
18 import '../native/behavior.dart' show NativeBehavior; | 17 import '../native/behavior.dart' show NativeBehavior; |
19 | 18 |
20 /// Basic information for native classes and methods and js-interop | 19 /// Basic information for native classes and methods and js-interop |
21 /// classes. | 20 /// classes. |
22 /// | 21 /// |
23 /// This information is computed during loading using [NativeClassDataBuilder]. | 22 /// This information is computed during loading using [NativeClassDataBuilder]. |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
56 NativeBehavior getNativeMethodBehavior(MethodElement method); | 55 NativeBehavior getNativeMethodBehavior(MethodElement method); |
57 | 56 |
58 /// Returns the [NativeBehavior] for reading from the native [field]. | 57 /// Returns the [NativeBehavior] for reading from the native [field]. |
59 NativeBehavior getNativeFieldLoadBehavior(FieldElement field); | 58 NativeBehavior getNativeFieldLoadBehavior(FieldElement field); |
60 | 59 |
61 /// Returns the [NativeBehavior] for writing to the native [field]. | 60 /// Returns the [NativeBehavior] for writing to the native [field]. |
62 NativeBehavior getNativeFieldStoreBehavior(FieldElement field); | 61 NativeBehavior getNativeFieldStoreBehavior(FieldElement field); |
63 | 62 |
64 /// Returns `true` if the name of [element] is fixed for the generated | 63 /// Returns `true` if the name of [element] is fixed for the generated |
65 /// JavaScript. | 64 /// JavaScript. |
66 bool hasFixedBackendName(Element element); | 65 bool hasFixedBackendName(MemberElement element); |
67 | 66 |
68 /// Computes the name for [element] to use in the generated JavaScript. This | 67 /// Computes the name for [element] to use in the generated JavaScript. This |
69 /// is either given through a native annotation or a js interop annotation. | 68 /// is either given through a native annotation or a js interop annotation. |
70 String getFixedBackendName(Entity entity); | 69 String getFixedBackendName(MemberEntity element); |
70 | |
71 /// Computes the name prefix for [element to use in the generated JavaScript. | |
Siggi Cherem (dart-lang)
2017/03/14 04:48:19
nit: add missing ]
Johnni Winther
2017/03/15 11:42:14
Done.
| |
72 /// For static and top-level members and constructors this is based on the | |
73 /// names for the library and/or the enclosing class. | |
Siggi Cherem (dart-lang)
2017/03/14 04:48:19
might be worth clarifying that here you mean JS na
Johnni Winther
2017/03/15 11:42:14
Done.
| |
74 String getFixedBackendMethodPath(MethodElement element); | |
71 | 75 |
72 /// Returns the list of non-directive native tag words for [cls]. | 76 /// Returns the list of non-directive native tag words for [cls]. |
73 List<String> getNativeTagsOfClass(ClassElement cls); | 77 List<String> getNativeTagsOfClass(ClassElement cls); |
74 | 78 |
75 /// Returns `true` if [cls] has a `!nonleaf` tag word. | 79 /// Returns `true` if [cls] has a `!nonleaf` tag word. |
76 bool hasNativeTagsForcedNonLeaf(ClassElement cls); | 80 bool hasNativeTagsForcedNonLeaf(ClassElement cls); |
77 | 81 |
78 /// Returns `true` if [element] is part of JsInterop. | 82 /// Returns `true` if [element] is a JsInterop method. |
79 /// | 83 bool isJsInteropMember(MemberEntity element); |
80 /// Deprecated: Use [isJsInteropLibrary], [isJsInteropClass] or | |
81 /// [isJsInteropMember] instead. | |
82 @deprecated | |
83 bool isJsInterop(Element element); | |
84 | 84 |
85 /// Returns `true` if [element] is a JsInterop method. | 85 /// Returns the explicit js interop name for library [element]. |
86 bool isJsInteropMember(MethodElement element); | 86 String getJsInteropLibraryName(LibraryElement element); |
87 | 87 |
88 /// Returns the explicit js interop name for [element]. | 88 /// Returns the explicit js interop name for class [element]. |
89 String getJsInteropName(Element element); | 89 String getJsInteropClassName(ClassElement element); |
90 | |
91 /// Returns the explicit js interop name for member [element]. | |
92 String getJsInteropMemberName(MemberElement element); | |
90 | 93 |
91 /// Apply JS$ escaping scheme to convert possible escaped Dart names into | 94 /// Apply JS$ escaping scheme to convert possible escaped Dart names into |
92 /// JS names. | 95 /// JS names. |
93 String getUnescapedJSInteropName(String name); | 96 String computeUnescapedJSInteropName(String name); |
94 } | 97 } |
95 | 98 |
96 abstract class NativeClassDataBuilder { | 99 abstract class NativeClassDataBuilder { |
97 /// Sets the native tag info for [cls]. | 100 /// Sets the native tag info for [cls]. |
98 /// | 101 /// |
99 /// The tag info string contains comma-separated 'words' which are either | 102 /// The tag info string contains comma-separated 'words' which are either |
100 /// dispatch tags (having JavaScript identifier syntax) and directives that | 103 /// dispatch tags (having JavaScript identifier syntax) and directives that |
101 /// begin with `!`. | 104 /// begin with `!`. |
102 void setNativeClassTagInfo(ClassElement cls, String tagInfo); | 105 void setNativeClassTagInfo(ClassElement cls, String tagInfo); |
103 | 106 |
(...skipping 20 matching lines...) Expand all Loading... | |
124 List<String> getNativeTagsOfClassRaw(ClassElement cls); | 127 List<String> getNativeTagsOfClassRaw(ClassElement cls); |
125 | 128 |
126 /// Returns [element] as an explicit part of JsInterop. The js interop name is | 129 /// Returns [element] as an explicit part of JsInterop. The js interop name is |
127 /// expected to be computed later. | 130 /// expected to be computed later. |
128 void markAsJsInteropMember(MemberElement element); | 131 void markAsJsInteropMember(MemberElement element); |
129 | 132 |
130 /// Sets the native [name] for the member [element]. This name is used for | 133 /// Sets the native [name] for the member [element]. This name is used for |
131 /// [element] in the generated JavaScript. | 134 /// [element] in the generated JavaScript. |
132 void setNativeMemberName(MemberElement element, String name); | 135 void setNativeMemberName(MemberElement element, String name); |
133 | 136 |
134 /// Sets the explicit js interop [name] for [element]. | 137 /// Sets the explicit js interop [name] for the library [element]. |
135 void setJsInteropName(Element element, String name); | 138 void setJsInteropLibraryName(LibraryElement element, String name); |
139 | |
140 /// Sets the explicit js interop [name] for the class [element]. | |
141 void setJsInteropClassName(ClassElement element, String name); | |
142 | |
143 /// Sets the explicit js interop [name] for the member [element]. | |
144 void setJsInteropMemberName(MemberElement element, String name); | |
136 } | 145 } |
137 | 146 |
138 class NativeDataImpl | 147 class NativeDataImpl |
139 implements NativeData, NativeDataBuilder, NativeClassDataBuilder { | 148 implements NativeData, NativeDataBuilder, NativeClassDataBuilder { |
140 /// The JavaScript names for elements implemented via typed JavaScript | 149 /// The JavaScript names for elements implemented via typed JavaScript |
141 /// interop. | 150 /// interop. |
142 Map<Element, String> jsInteropNames = <Element, String>{}; | 151 Map<LibraryElement, String> jsInteropLibraryNames = |
152 <LibraryElement, String>{}; | |
153 Map<ClassElement, String> jsInteropClassNames = <ClassElement, String>{}; | |
154 Map<MemberElement, String> jsInteropMemberNames = <MemberElement, String>{}; | |
143 | 155 |
144 /// The JavaScript names for native JavaScript elements implemented. | 156 /// The JavaScript names for native JavaScript elements implemented. |
145 Map<Element, String> nativeMemberName = <Element, String>{}; | 157 Map<Element, String> nativeMemberName = <Element, String>{}; |
146 | 158 |
147 /// Tag info for native JavaScript classes names. See | 159 /// Tag info for native JavaScript classes names. See |
148 /// [setNativeClassTagInfo]. | 160 /// [setNativeClassTagInfo]. |
149 Map<ClassElement, String> nativeClassTagInfo = <ClassElement, String>{}; | 161 Map<ClassElement, String> nativeClassTagInfo = <ClassElement, String>{}; |
150 | 162 |
151 /// Cache for [NativeBehavior]s for calling native methods. | 163 /// Cache for [NativeBehavior]s for calling native methods. |
152 Map<MethodElement, NativeBehavior> nativeMethodBehavior = | 164 Map<MethodElement, NativeBehavior> nativeMethodBehavior = |
153 <MethodElement, NativeBehavior>{}; | 165 <MethodElement, NativeBehavior>{}; |
154 | 166 |
155 /// Cache for [NativeBehavior]s for reading from native fields. | 167 /// Cache for [NativeBehavior]s for reading from native fields. |
156 Map<MemberElement, NativeBehavior> nativeFieldLoadBehavior = | 168 Map<MemberElement, NativeBehavior> nativeFieldLoadBehavior = |
157 <FieldElement, NativeBehavior>{}; | 169 <FieldElement, NativeBehavior>{}; |
158 | 170 |
159 /// Cache for [NativeBehavior]s for writing to native fields. | 171 /// Cache for [NativeBehavior]s for writing to native fields. |
160 Map<MemberElement, NativeBehavior> nativeFieldStoreBehavior = | 172 Map<MemberElement, NativeBehavior> nativeFieldStoreBehavior = |
161 <FieldElement, NativeBehavior>{}; | 173 <FieldElement, NativeBehavior>{}; |
162 | 174 |
163 /// Prefix used to escape JS names that are not valid Dart names | 175 /// Prefix used to escape JS names that are not valid Dart names |
164 /// when using JSInterop. | 176 /// when using JSInterop. |
165 static const String _jsInteropEscapePrefix = r'JS$'; | 177 static const String _jsInteropEscapePrefix = r'JS$'; |
166 | 178 |
167 /// Returns `true` if [element] is explicitly marked as part of JsInterop. | 179 /// Returns `true` if [element] is explicitly marked as part of JsInterop. |
168 bool _isJsInterop(Element element) { | 180 bool _isJsInteropLibrary(LibraryElement element) { |
169 return jsInteropNames.containsKey(element.declaration); | 181 return jsInteropLibraryNames.containsKey(element); |
170 } | 182 } |
171 | 183 |
172 /// Marks [element] as an explicit part of JsInterop. The js interop name is | 184 /// Returns `true` if [element] is explicitly marked as part of JsInterop. |
173 /// expected to be computed later. | 185 bool _isJsInteropClass(ClassElement element) { |
174 void markAsJsInterop(Element element) { | 186 return jsInteropClassNames.containsKey(element); |
175 jsInteropNames[element.declaration] = null; | 187 } |
188 | |
189 /// Returns `true` if [element] is explicitly marked as part of JsInterop. | |
190 bool _isJsInteropMember(MemberElement element) { | |
191 return jsInteropMemberNames.containsKey(element); | |
176 } | 192 } |
177 | 193 |
178 @override | 194 @override |
179 void markAsJsInteropLibrary(LibraryElement element) { | 195 void markAsJsInteropLibrary(LibraryElement element) { |
180 markAsJsInterop(element); | 196 jsInteropLibraryNames[element] = null; |
181 } | 197 } |
182 | 198 |
183 @override | 199 @override |
184 void markAsJsInteropClass(ClassElement element) { | 200 void markAsJsInteropClass(ClassElement element) { |
185 markAsJsInterop(element); | 201 jsInteropClassNames[element] = null; |
186 } | 202 } |
187 | 203 |
188 @override | 204 @override |
189 void markAsJsInteropMember(MemberElement element) { | 205 void markAsJsInteropMember(MemberElement element) { |
190 markAsJsInterop(element); | 206 jsInteropMemberNames[element] = null; |
191 } | 207 } |
192 | 208 |
193 /// Sets the explicit js interop [name] for [element]. | 209 /// Sets the explicit js interop [name] for the library [element]. |
194 void setJsInteropName(Element element, String name) { | 210 void setJsInteropLibraryName(LibraryElement element, String name) { |
195 assert(invariant(element, isJsInterop(element), | 211 assert(invariant(element, _isJsInteropLibrary(element), |
196 message: | 212 message: |
197 'Element $element is not js interop but given a js interop name.')); | 213 'Library $element is not js interop but given a js interop name.')); |
198 jsInteropNames[element.declaration] = name; | 214 jsInteropLibraryNames[element] = name; |
199 } | 215 } |
200 | 216 |
201 /// Returns the explicit js interop name for [element]. | 217 /// Sets the explicit js interop [name] for the class [element]. |
202 String getJsInteropName(Element element) { | 218 void setJsInteropClassName(ClassElement element, String name) { |
203 return jsInteropNames[element.declaration]; | 219 assert(invariant(element, _isJsInteropClass(element), |
220 message: | |
221 'Class $element is not js interop but given a js interop name.')); | |
222 jsInteropClassNames[element] = name; | |
204 } | 223 } |
205 | 224 |
206 /// Returns `true` if [element] is part of JsInterop. | 225 /// Sets the explicit js interop [name] for the member [element]. |
207 bool isJsInterop(Element element) { | 226 void setJsInteropMemberName(MemberElement element, String name) { |
208 // An function is part of JsInterop in the following cases: | 227 assert(invariant(element, _isJsInteropMember(element), |
209 // * It has a jsInteropName annotation | 228 message: |
210 // * It is external member of a class or library tagged as JsInterop. | 229 'Member $element is not js interop but given a js interop name.')); |
230 jsInteropMemberNames[element] = name; | |
231 } | |
232 | |
233 /// Returns the explicit js interop name for library [element]. | |
234 String getJsInteropLibraryName(LibraryElement element) { | |
235 return jsInteropLibraryNames[element]; | |
236 } | |
237 | |
238 /// Returns the explicit js interop name for class [element]. | |
239 String getJsInteropClassName(ClassElement element) { | |
240 return jsInteropClassNames[element]; | |
241 } | |
242 | |
243 /// Returns the explicit js interop name for member [element]. | |
244 String getJsInteropMemberName(MemberElement element) { | |
245 return jsInteropMemberNames[element]; | |
246 } | |
247 | |
248 /// Returns `true` if [element] is a JsInterop library. | |
249 bool isJsInteropLibrary(LibraryElement element) => | |
250 _isJsInteropLibrary(element); | |
251 | |
252 /// Returns `true` if [element] is a JsInterop class. | |
253 bool isJsInteropClass(ClassElement element) => _isJsInteropClass(element); | |
254 | |
255 /// Returns `true` if [element] is a JsInterop method. | |
256 bool isJsInteropMember(MemberElement element) { | |
211 if (element.isFunction || element.isConstructor || element.isAccessor) { | 257 if (element.isFunction || element.isConstructor || element.isAccessor) { |
212 FunctionElement function = element; | 258 MethodElement function = element; |
213 if (!function.isExternal) return false; | 259 if (!function.isExternal) return false; |
214 | 260 |
215 if (_isJsInterop(function)) return true; | 261 if (_isJsInteropMember(function)) return true; |
216 if (function.isClassMember) return isJsInterop(function.contextClass); | 262 if (function.isClassMember) { |
217 if (function.isTopLevel) return isJsInterop(function.library); | 263 return _isJsInteropClass(function.enclosingClass); |
264 } | |
265 if (function.isTopLevel) { | |
266 return _isJsInteropLibrary(function.library); | |
267 } | |
218 return false; | 268 return false; |
219 } else { | 269 } else { |
220 return _isJsInterop(element); | 270 return _isJsInteropMember(element); |
221 } | 271 } |
222 } | 272 } |
223 | 273 |
224 /// Returns `true` if [element] is a JsInterop library. | |
225 bool isJsInteropLibrary(LibraryElement element) => isJsInterop(element); | |
226 | |
227 /// Returns `true` if [element] is a JsInterop class. | |
228 bool isJsInteropClass(ClassElement element) => isJsInterop(element); | |
229 | |
230 /// Returns `true` if [element] is a JsInterop method. | |
231 bool isJsInteropMember(MethodElement element) => isJsInterop(element); | |
232 | |
233 /// Returns `true` if the name of [element] is fixed for the generated | 274 /// Returns `true` if the name of [element] is fixed for the generated |
234 /// JavaScript. | 275 /// JavaScript. |
235 bool hasFixedBackendName(Element element) { | 276 bool hasFixedBackendName(MemberElement element) { |
236 return isJsInterop(element) || | 277 return isJsInteropMember(element) || |
237 nativeMemberName.containsKey(element.declaration); | 278 nativeMemberName.containsKey(element.declaration); |
238 } | 279 } |
239 | 280 |
240 String _jsNameHelper(Element element) { | |
241 String jsInteropName = jsInteropNames[element.declaration]; | |
242 assert(invariant(element, !(_isJsInterop(element) && jsInteropName == null), | |
243 message: | |
244 'Element $element is js interop but js interop name has not yet ' | |
245 'been computed.')); | |
246 if (jsInteropName != null && jsInteropName.isNotEmpty) { | |
247 return jsInteropName; | |
248 } | |
249 return element.isLibrary ? 'self' : getUnescapedJSInteropName(element.name); | |
250 } | |
251 | |
252 /// Computes the name for [element] to use in the generated JavaScript. This | 281 /// Computes the name for [element] to use in the generated JavaScript. This |
253 /// is either given through a native annotation or a js interop annotation. | 282 /// is either given through a native annotation or a js interop annotation. |
254 String getFixedBackendName(Entity entity) { | 283 String getFixedBackendName(MemberElement element) { |
255 // TODO(johnniwinther): Remove this assignment from [Entity] to [Element] | |
256 // when `.declaration` is no longer needed. | |
257 Element element = entity; | |
258 String name = nativeMemberName[element.declaration]; | 284 String name = nativeMemberName[element.declaration]; |
259 if (name == null && isJsInterop(element)) { | 285 if (name == null && isJsInteropMember(element)) { |
260 // If an element isJsInterop but _isJsInterop is false that means it is | 286 // If an element isJsInterop but _isJsInterop is false that means it is |
261 // considered interop as the parent class is interop. | 287 // considered interop as the parent class is interop. |
262 name = _jsNameHelper( | 288 name = element.isConstructor |
263 element.isConstructor ? element.enclosingClass : element); | 289 ? _jsClassNameHelper(element.enclosingClass) |
290 : _jsMemberNameHelper(element); | |
264 nativeMemberName[element.declaration] = name; | 291 nativeMemberName[element.declaration] = name; |
265 } | 292 } |
266 return name; | 293 return name; |
267 } | 294 } |
268 | 295 |
269 /// Whether [element] corresponds to a native JavaScript construct either | 296 String _jsLibraryNameHelper(LibraryElement element) { |
270 /// through the native mechanism (`@Native(...)` or the `native` pseudo | 297 String jsInteropName = getJsInteropLibraryName(element); |
271 /// keyword) which is only allowed for internal libraries or via the typed | 298 if (jsInteropName != null && jsInteropName.isNotEmpty) return jsInteropName; |
272 /// JavaScriptInterop mechanism which is allowed for user libraries. | 299 return 'self'; |
273 bool isNative(Element element) { | 300 } |
274 if (isJsInterop(element)) return true; | 301 |
275 if (element.isClass) { | 302 String _jsClassNameHelper(ClassElement element) { |
276 return nativeClassTagInfo.containsKey(element.declaration); | 303 String jsInteropName = getJsInteropClassName(element); |
277 } else { | 304 if (jsInteropName != null && jsInteropName.isNotEmpty) return jsInteropName; |
278 return nativeMemberName.containsKey(element.declaration); | 305 return computeUnescapedJSInteropName(element.name); |
306 } | |
307 | |
308 String _jsMemberNameHelper(MemberElement element) { | |
309 String jsInteropName = jsInteropMemberNames[element]; | |
310 assert(invariant(element, | |
311 !(jsInteropMemberNames.containsKey(element) && jsInteropName == null), | |
312 message: | |
313 'Member $element is js interop but js interop name has not yet ' | |
314 'been computed.')); | |
315 if (jsInteropName != null && jsInteropName.isNotEmpty) { | |
316 return jsInteropName; | |
279 } | 317 } |
318 return computeUnescapedJSInteropName(element.name); | |
319 } | |
320 | |
321 /// Returns a JavaScript path specifying the context in which | |
322 /// [element.fixedBackendName] should be evaluated. Only applicable for | |
323 /// elements using typed JavaScript interop. | |
324 /// For example: fixedBackendPath for the static method createMap in the | |
325 /// Map class of the goog.map JavaScript library would have path | |
326 /// "goog.maps.Map". | |
327 String getFixedBackendMethodPath(MethodElement element) { | |
328 if (!isJsInteropMember(element)) return null; | |
329 if (element.isInstanceMember) return 'this'; | |
330 if (element.isConstructor) { | |
331 return _fixedBackendClassPath(element.enclosingClass); | |
332 } | |
333 StringBuffer sb = new StringBuffer(); | |
334 sb.write(_jsLibraryNameHelper(element.library)); | |
335 if (element.enclosingClass != null) { | |
336 sb..write('.')..write(_jsClassNameHelper(element.enclosingClass)); | |
337 } | |
338 return sb.toString(); | |
339 } | |
340 | |
341 String _fixedBackendClassPath(ClassElement element) { | |
342 if (!isJsInteropClass(element)) return null; | |
343 return _jsLibraryNameHelper(element.library); | |
280 } | 344 } |
281 | 345 |
282 /// Returns `true` if [cls] is a native class. | 346 /// Returns `true` if [cls] is a native class. |
283 bool isNativeClass(ClassElement element) => isNative(element); | 347 bool isNativeClass(ClassElement element) { |
348 if (isJsInteropClass(element)) return true; | |
349 return nativeClassTagInfo.containsKey(element); | |
350 } | |
284 | 351 |
285 /// Returns `true` if [element] is a native member of a native class. | 352 /// Returns `true` if [element] is a native member of a native class. |
286 bool isNativeMember(MemberElement element) => isNative(element); | 353 bool isNativeMember(MemberElement element) { |
354 if (isJsInteropMember(element)) return true; | |
355 return nativeMemberName.containsKey(element); | |
356 } | |
287 | 357 |
288 /// Returns `true` if [element] or any of its superclasses is native. | 358 /// Returns `true` if [element] or any of its superclasses is native. |
289 bool isNativeOrExtendsNative(ClassElement element) { | 359 bool isNativeOrExtendsNative(ClassElement element) { |
290 if (element == null) return false; | 360 if (element == null) return false; |
291 if (isNativeClass(element) || isJsInteropClass(element)) { | 361 if (isNativeClass(element) || isJsInteropClass(element)) { |
292 return true; | 362 return true; |
293 } | 363 } |
294 assert(element.isResolved); | 364 assert(element.isResolved); |
295 return isNativeOrExtendsNative(element.superclass); | 365 return isNativeOrExtendsNative(element.superclass); |
296 } | 366 } |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
383 } | 453 } |
384 | 454 |
385 /// Registers the [behavior] for writing to the native [field]. | 455 /// Registers the [behavior] for writing to the native [field]. |
386 void setNativeFieldStoreBehavior( | 456 void setNativeFieldStoreBehavior( |
387 FieldElement field, NativeBehavior behavior) { | 457 FieldElement field, NativeBehavior behavior) { |
388 nativeFieldStoreBehavior[field] = behavior; | 458 nativeFieldStoreBehavior[field] = behavior; |
389 } | 459 } |
390 | 460 |
391 /// Apply JS$ escaping scheme to convert possible escaped Dart names into | 461 /// Apply JS$ escaping scheme to convert possible escaped Dart names into |
392 /// JS names. | 462 /// JS names. |
393 String getUnescapedJSInteropName(String name) { | 463 String computeUnescapedJSInteropName(String name) { |
394 return name.startsWith(_jsInteropEscapePrefix) | 464 return name.startsWith(_jsInteropEscapePrefix) |
395 ? name.substring(_jsInteropEscapePrefix.length) | 465 ? name.substring(_jsInteropEscapePrefix.length) |
396 : name; | 466 : name; |
397 } | 467 } |
398 } | 468 } |
OLD | NEW |