OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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_helper; | 5 library _js_helper; |
6 | 6 |
7 import 'dart:_async_await_error_codes' as async_error_codes; | 7 import 'dart:_async_await_error_codes' as async_error_codes; |
8 | 8 |
9 import 'dart:_js_embedded_names' show | 9 import 'dart:_js_embedded_names' show |
10 DEFERRED_LIBRARY_URIS, | 10 DEFERRED_LIBRARY_URIS, |
(...skipping 1848 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1859 | 1859 |
1860 class NullError extends Error implements NoSuchMethodError { | 1860 class NullError extends Error implements NoSuchMethodError { |
1861 final String _message; | 1861 final String _message; |
1862 final String _method; | 1862 final String _method; |
1863 | 1863 |
1864 NullError(this._message, match) | 1864 NullError(this._message, match) |
1865 : _method = match == null ? null : JS('', '#.method', match); | 1865 : _method = match == null ? null : JS('', '#.method', match); |
1866 | 1866 |
1867 String toString() { | 1867 String toString() { |
1868 if (_method == null) return 'NullError: $_message'; | 1868 if (_method == null) return 'NullError: $_message'; |
1869 return 'NullError: Cannot call "$_method" on null'; | 1869 return "NullError: method not found: '$_method' on null"; |
1870 } | 1870 } |
1871 } | 1871 } |
1872 | 1872 |
1873 class JsNoSuchMethodError extends Error implements NoSuchMethodError { | 1873 class JsNoSuchMethodError extends Error implements NoSuchMethodError { |
1874 final String _message; | 1874 final String _message; |
1875 final String _method; | 1875 final String _method; |
1876 final String _receiver; | 1876 final String _receiver; |
1877 | 1877 |
1878 JsNoSuchMethodError(this._message, match) | 1878 JsNoSuchMethodError(this._message, match) |
1879 : _method = match == null ? null : JS('String|Null', '#.method', match), | 1879 : _method = match == null ? null : JS('String|Null', '#.method', match), |
1880 _receiver = | 1880 _receiver = |
1881 match == null ? null : JS('String|Null', '#.receiver', match); | 1881 match == null ? null : JS('String|Null', '#.receiver', match); |
1882 | 1882 |
1883 String toString() { | 1883 String toString() { |
1884 if (_method == null) return 'NoSuchMethodError: $_message'; | 1884 if (_method == null) return 'NoSuchMethodError: $_message'; |
1885 if (_receiver == null) { | 1885 if (_receiver == null) { |
1886 return 'NoSuchMethodError: Cannot call "$_method" ($_message)'; | 1886 return "NoSuchMethodError: method not found: '$_method' ($_message)"; |
1887 } | 1887 } |
1888 return 'NoSuchMethodError: Cannot call "$_method" on "$_receiver" ' | 1888 return "NoSuchMethodError: " |
1889 '($_message)'; | 1889 "method not found: '$_method' on '$_receiver' ($_message)"; |
1890 } | 1890 } |
1891 } | 1891 } |
1892 | 1892 |
1893 class UnknownJsTypeError extends Error { | 1893 class UnknownJsTypeError extends Error { |
1894 final String _message; | 1894 final String _message; |
1895 | 1895 |
1896 UnknownJsTypeError(this._message); | 1896 UnknownJsTypeError(this._message); |
1897 | 1897 |
1898 String toString() => _message.isEmpty ? 'Error' : 'Error: $_message'; | 1898 String toString() => _message.isEmpty ? 'Error' : 'Error: $_message'; |
1899 } | 1899 } |
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2229 // for each computed prototype property: | 2229 // for each computed prototype property: |
2230 // proto[property] = ...; | 2230 // proto[property] = ...; |
2231 // proto._init = BC; | 2231 // proto._init = BC; |
2232 // var dynClosureConstructor = | 2232 // var dynClosureConstructor = |
2233 // new Function('self', 'target', 'receiver', 'name', | 2233 // new Function('self', 'target', 'receiver', 'name', |
2234 // 'this._init(self, target, receiver, name)'); | 2234 // 'this._init(self, target, receiver, name)'); |
2235 // proto.constructor = dynClosureConstructor; | 2235 // proto.constructor = dynClosureConstructor; |
2236 // dynClosureConstructor.prototype = proto; | 2236 // dynClosureConstructor.prototype = proto; |
2237 // return dynClosureConstructor; | 2237 // return dynClosureConstructor; |
2238 | 2238 |
2239 // We need to create a new subclass of either TearOffClosure or | 2239 // We need to create a new subclass of TearOffClosure, one of StaticClosure |
2240 // BoundClosure. For this, we need to create an object whose prototype is | 2240 // or BoundClosure. For this, we need to create an object whose prototype |
2241 // the prototype is either TearOffClosure.prototype or | 2241 // is the prototype is either StaticClosure.prototype or |
2242 // BoundClosure.prototype, respectively in pseudo JavaScript code. The | 2242 // BoundClosure.prototype, respectively in pseudo JavaScript code. The |
2243 // simplest way to access the JavaScript construction function of a Dart | 2243 // simplest way to access the JavaScript construction function of a Dart |
2244 // class is to create an instance and access its constructor property. The | 2244 // class is to create an instance and access its constructor property. |
2245 // newly created instance could in theory be used directly as the | 2245 // Creating an instance ensures that any lazy class initialization has taken |
2246 // prototype, but it might include additional fields that we don't need. | 2246 // place. The newly created instance could in theory be used directly as the |
2247 // So we only use the new instance to access the constructor property and | 2247 // prototype, but it might include additional fields that we don't need. So |
2248 // use Object.create to create the desired prototype. | 2248 // we only use the new instance to access the constructor property and use |
| 2249 // Object.create to create the desired prototype. |
| 2250 // |
| 2251 // TODO(sra): Perhaps cache the prototype to avoid the allocation. |
2249 var prototype = isStatic | 2252 var prototype = isStatic |
2250 ? JS('TearOffClosure', 'Object.create(#.constructor.prototype)', | 2253 ? JS('StaticClosure', 'Object.create(#.constructor.prototype)', |
2251 new TearOffClosure()) | 2254 new StaticClosure()) |
2252 : JS('BoundClosure', 'Object.create(#.constructor.prototype)', | 2255 : JS('BoundClosure', 'Object.create(#.constructor.prototype)', |
2253 new BoundClosure(null, null, null, null)); | 2256 new BoundClosure(null, null, null, null)); |
2254 | 2257 |
2255 JS('', '#.\$initialize = #', prototype, JS('', '#.constructor', prototype)); | 2258 JS('', '#.\$initialize = #', prototype, JS('', '#.constructor', prototype)); |
2256 var constructor = isStatic | 2259 var constructor = isStatic |
2257 ? JS('', 'function(){this.\$initialize()}') | 2260 ? JS('', 'function(){this.\$initialize()}') |
2258 : isCsp | 2261 : isCsp |
2259 ? JS('', 'function(a,b,c,d) {this.\$initialize(a,b,c,d)}') | 2262 ? JS('', 'function(a,b,c,d) {this.\$initialize(a,b,c,d)}') |
2260 : JS('', | 2263 : JS('', |
2261 'new Function("a","b","c","d",' | 2264 'new Function("a,b,c,d", "this.\$initialize(a,b,c,d);" + #)', |
2262 '"this.\$initialize(a,b,c,d);"+#)', | |
2263 functionCounter++); | 2265 functionCounter++); |
2264 | 2266 |
2265 // It is necessary to set the constructor property, otherwise it will be | 2267 // It is necessary to set the constructor property, otherwise it will be |
2266 // "Object". | 2268 // "Object". |
2267 JS('', '#.constructor = #', prototype, constructor); | 2269 JS('', '#.constructor = #', prototype, constructor); |
2268 | 2270 |
2269 JS('', '#.prototype = #', constructor, prototype); | 2271 JS('', '#.prototype = #', constructor, prototype); |
2270 | 2272 |
2271 // Create a closure and "monkey" patch it with call stubs. | 2273 // Create a closure and "monkey" patch it with call stubs. |
2272 var trampoline = function; | 2274 var trampoline = function; |
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2555 } | 2557 } |
2556 | 2558 |
2557 // The backend adds a special getter of the form | 2559 // The backend adds a special getter of the form |
2558 // | 2560 // |
2559 // Closure get call => this; | 2561 // Closure get call => this; |
2560 // | 2562 // |
2561 // to allow tearing off a closure from itself. We do this magically in the | 2563 // to allow tearing off a closure from itself. We do this magically in the |
2562 // backend rather than simply adding it here, as we do not want this getter | 2564 // backend rather than simply adding it here, as we do not want this getter |
2563 // to be visible to resolution and the generation of extra stubs. | 2565 // to be visible to resolution and the generation of extra stubs. |
2564 | 2566 |
2565 String toString() => "Closure"; | 2567 String toString() { |
| 2568 String name = Primitives.objectTypeName(this); |
| 2569 return "Closure '$name'"; |
| 2570 } |
2566 } | 2571 } |
2567 | 2572 |
2568 /// Called from implicit method getter (aka tear-off). | 2573 /// Called from implicit method getter (aka tear-off). |
2569 closureFromTearOff(receiver, | 2574 closureFromTearOff(receiver, |
2570 functions, | 2575 functions, |
2571 reflectionInfo, | 2576 reflectionInfo, |
2572 isStatic, | 2577 isStatic, |
2573 jsArguments, | 2578 jsArguments, |
2574 name) { | 2579 name) { |
2575 return Closure.fromTearOff( | 2580 return Closure.fromTearOff( |
2576 receiver, | 2581 receiver, |
2577 JSArray.markFixedList(functions), | 2582 JSArray.markFixedList(functions), |
2578 reflectionInfo is List ? JSArray.markFixedList(reflectionInfo) | 2583 reflectionInfo is List ? JSArray.markFixedList(reflectionInfo) |
2579 : reflectionInfo, | 2584 : reflectionInfo, |
2580 JS('bool', '!!#', isStatic), | 2585 JS('bool', '!!#', isStatic), |
2581 jsArguments, | 2586 jsArguments, |
2582 JS('String', '#', name)); | 2587 JS('String', '#', name)); |
2583 } | 2588 } |
2584 | 2589 |
2585 /// Represents an implicit closure of a function. | 2590 /// Represents an implicit closure of a function. |
2586 class TearOffClosure extends Closure { | 2591 abstract class TearOffClosure extends Closure { |
2587 } | 2592 } |
2588 | 2593 |
2589 /// Represents a 'tear-off' closure, that is an instance method bound | 2594 class StaticClosure extends TearOffClosure { |
2590 /// to a specific receiver (instance). | 2595 String toString() { |
| 2596 String name = JS('String|Null', '#.\$name', this); |
| 2597 if (name == null) return "Closure of unknown static method"; |
| 2598 return "Closure of static method '$name'"; |
| 2599 } |
| 2600 } |
| 2601 |
| 2602 /// Represents a 'tear-off' or property extraction closure of an instance |
| 2603 /// method, that is an instance method bound to a specific receiver (instance). |
2591 class BoundClosure extends TearOffClosure { | 2604 class BoundClosure extends TearOffClosure { |
2592 /// The receiver or interceptor. | 2605 /// The receiver or interceptor. |
2593 // TODO(ahe): This could just be the interceptor, we always know if | 2606 // TODO(ahe): This could just be the interceptor, we always know if |
2594 // we need the interceptor when generating the call method. | 2607 // we need the interceptor when generating the call method. |
2595 final _self; | 2608 final _self; |
2596 | 2609 |
2597 /// The method. | 2610 /// The method. |
2598 final _target; | 2611 final _target; |
2599 | 2612 |
2600 /// The receiver. Null if [_self] is not an interceptor. | 2613 /// The receiver. Null if [_self] is not an interceptor. |
(...skipping 24 matching lines...) Expand all Loading... |
2625 // use the hashCode method we define for those primitive types. | 2638 // use the hashCode method we define for those primitive types. |
2626 receiverHashCode = _receiver.hashCode; | 2639 receiverHashCode = _receiver.hashCode; |
2627 } else { | 2640 } else { |
2628 // A bound closure on an intercepted native class, just use the | 2641 // A bound closure on an intercepted native class, just use the |
2629 // identity hash code. | 2642 // identity hash code. |
2630 receiverHashCode = Primitives.objectHashCode(_receiver); | 2643 receiverHashCode = Primitives.objectHashCode(_receiver); |
2631 } | 2644 } |
2632 return receiverHashCode ^ Primitives.objectHashCode(_target); | 2645 return receiverHashCode ^ Primitives.objectHashCode(_target); |
2633 } | 2646 } |
2634 | 2647 |
| 2648 toString() { |
| 2649 var receiver = _receiver == null ? _self : _receiver; |
| 2650 return "Closure '$_name' of ${Primitives.objectToString(receiver)}"; |
| 2651 } |
| 2652 |
2635 @NoInline() | 2653 @NoInline() |
2636 static selfOf(BoundClosure closure) => closure._self; | 2654 static selfOf(BoundClosure closure) => closure._self; |
2637 | 2655 |
2638 static targetOf(BoundClosure closure) => closure._target; | 2656 static targetOf(BoundClosure closure) => closure._target; |
2639 | 2657 |
2640 @NoInline() | 2658 @NoInline() |
2641 static receiverOf(BoundClosure closure) => closure._receiver; | 2659 static receiverOf(BoundClosure closure) => closure._receiver; |
2642 | 2660 |
2643 static nameOf(BoundClosure closure) => closure._name; | 2661 static nameOf(BoundClosure closure) => closure._name; |
2644 | 2662 |
(...skipping 1423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4068 // This is a function that will return a helper function that does the | 4086 // This is a function that will return a helper function that does the |
4069 // iteration of the sync*. | 4087 // iteration of the sync*. |
4070 // | 4088 // |
4071 // Each invocation should give a body with fresh state. | 4089 // Each invocation should give a body with fresh state. |
4072 final dynamic /* js function */ _outerHelper; | 4090 final dynamic /* js function */ _outerHelper; |
4073 | 4091 |
4074 SyncStarIterable(this._outerHelper); | 4092 SyncStarIterable(this._outerHelper); |
4075 | 4093 |
4076 Iterator get iterator => new SyncStarIterator(JS('', '#()', _outerHelper)); | 4094 Iterator get iterator => new SyncStarIterator(JS('', '#()', _outerHelper)); |
4077 } | 4095 } |
OLD | NEW |