Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(299)

Side by Side Diff: sdk/lib/_internal/compiler/js_lib/js_helper.dart

Issue 1138313002: Better toString and Error.toSafeString output for closures for dart2js. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698