OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 _interceptors; | 5 library _interceptors; |
6 | 6 |
7 import 'dart:_js_embedded_names' show | 7 import 'dart:_js_embedded_names' show |
8 DISPATCH_PROPERTY_NAME, | 8 DISPATCH_PROPERTY_NAME, |
9 TYPE_TO_INTERCEPTOR_MAP; | 9 TYPE_TO_INTERCEPTOR_MAP; |
10 | 10 |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 * The code `r.foo(a)` is compiled to `getInterceptor(r).foo$1(r, a)`. The | 243 * The code `r.foo(a)` is compiled to `getInterceptor(r).foo$1(r, a)`. The |
244 * value returned by [getInterceptor] holds the methods separately from the | 244 * value returned by [getInterceptor] holds the methods separately from the |
245 * state of the instance. The compiler converts the methods on an interceptor | 245 * state of the instance. The compiler converts the methods on an interceptor |
246 * to take the Dart `this` argument as an explicit `receiver` argument. The | 246 * to take the Dart `this` argument as an explicit `receiver` argument. The |
247 * JavaScript `this` parameter is bound to the interceptor. | 247 * JavaScript `this` parameter is bound to the interceptor. |
248 * | 248 * |
249 * In order to have uniform call sites, if a method is defined on an | 249 * In order to have uniform call sites, if a method is defined on an |
250 * interceptor, methods of that name on plain unintercepted classes also use the | 250 * interceptor, methods of that name on plain unintercepted classes also use the |
251 * interceptor calling convention. The plain classes are _self-interceptors_, | 251 * interceptor calling convention. The plain classes are _self-interceptors_, |
252 * and for them, `getInterceptor(r)` returns `r`. Methods on plain | 252 * and for them, `getInterceptor(r)` returns `r`. Methods on plain |
253 * unintercepted classes have a redundant `receiver` argument and, to enable | 253 * unintercepted classes have a redundant `receiver` argument and should ignore |
254 * some optimizations, must ignore `receiver` in favour of `this`. | 254 * it in favour of `this`. |
255 * | 255 * |
256 * In the case of mixins, a method may be placed on both an intercepted class | 256 * In the case of mixins, a method may be placed on both an intercepted class |
257 * and an unintercepted class. In this case, the method must use the `receiver` | 257 * and an unintercepted class. In this case, the method must use the `receiver` |
258 * parameter. | 258 * parameter. |
259 * | 259 * |
260 * | 260 * |
261 * There are various optimizations of the general call pattern. | 261 * There are various optimizations of the general call pattern. |
262 * | 262 * |
263 * When the interceptor can be statically determined, it can be used directly: | 263 * When the interceptor can be statically determined, it can be used directly: |
264 * | 264 * |
(...skipping 22 matching lines...) Expand all Loading... |
287 */ | 287 */ |
288 abstract class Interceptor { | 288 abstract class Interceptor { |
289 const Interceptor(); | 289 const Interceptor(); |
290 | 290 |
291 bool operator ==(other) => identical(this, other); | 291 bool operator ==(other) => identical(this, other); |
292 | 292 |
293 int get hashCode => Primitives.objectHashCode(this); | 293 int get hashCode => Primitives.objectHashCode(this); |
294 | 294 |
295 String toString() => Primitives.objectToHumanReadableString(this); | 295 String toString() => Primitives.objectToHumanReadableString(this); |
296 | 296 |
297 // [Interceptor.noSuchMethod] is identical to [Object.noSuchMethod]. However, | |
298 // each copy is compiled differently. The presence of the method on an | |
299 // Interceptor class forces [noSuchMethod] to use interceptor calling | |
300 // convention. In the [Interceptor] version, `this` is the explicit receiver | |
301 // argument. In the [Object] version, as Object is not an intercepted class, | |
302 // `this` is the JavaScript receiver, and the explicit receiver is ignored. | |
303 // The noSuchMethod stubs for selectors that use the interceptor calling | |
304 // convention do not know the calling convention and forward `this` and | |
305 // `receiver` to one of these noSuchMethod implementations which selects the | |
306 // correct Dart receiver. | |
307 // | |
308 // We don't allow [noSuchMethod] on intercepted classes (that would force all | |
309 // calls to use interceptor calling convention). If we did allow it, the | |
310 // interceptor context would select the correct `this`. | |
311 dynamic noSuchMethod(Invocation invocation) { | 297 dynamic noSuchMethod(Invocation invocation) { |
312 throw new NoSuchMethodError( | 298 throw new NoSuchMethodError( |
313 this, | 299 this, |
314 invocation.memberName, | 300 invocation.memberName, |
315 invocation.positionalArguments, | 301 invocation.positionalArguments, |
316 invocation.namedArguments); | 302 invocation.namedArguments); |
317 } | 303 } |
318 | 304 |
319 Type get runtimeType => getRuntimeType(this); | 305 Type get runtimeType => getRuntimeType(this); |
320 } | 306 } |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
416 * Interceptor for unclassified JavaScript objects, typically objects with a | 402 * Interceptor for unclassified JavaScript objects, typically objects with a |
417 * non-trivial prototype chain. | 403 * non-trivial prototype chain. |
418 * | 404 * |
419 * This class also serves as a fallback for unknown JavaScript exceptions. | 405 * This class also serves as a fallback for unknown JavaScript exceptions. |
420 */ | 406 */ |
421 class UnknownJavaScriptObject extends JavaScriptObject { | 407 class UnknownJavaScriptObject extends JavaScriptObject { |
422 const UnknownJavaScriptObject(); | 408 const UnknownJavaScriptObject(); |
423 | 409 |
424 String toString() => JS('String', 'String(#)', this); | 410 String toString() => JS('String', 'String(#)', this); |
425 } | 411 } |
OLD | NEW |