| Index: sdk/lib/_internal/compiler/js_lib/js_helper.dart
|
| diff --git a/sdk/lib/_internal/compiler/js_lib/js_helper.dart b/sdk/lib/_internal/compiler/js_lib/js_helper.dart
|
| index f0d7ebf803f1ff4c4edb2752038a87e466b39232..e4e9c88992b868fbda76ea36814fc38a1e54e3de 100644
|
| --- a/sdk/lib/_internal/compiler/js_lib/js_helper.dart
|
| +++ b/sdk/lib/_internal/compiler/js_lib/js_helper.dart
|
| @@ -1866,7 +1866,7 @@ class NullError extends Error implements NoSuchMethodError {
|
|
|
| String toString() {
|
| if (_method == null) return 'NullError: $_message';
|
| - return 'NullError: Cannot call "$_method" on null';
|
| + return "NullError: method not found: '$_method' on null";
|
| }
|
| }
|
|
|
| @@ -1883,10 +1883,10 @@ class JsNoSuchMethodError extends Error implements NoSuchMethodError {
|
| String toString() {
|
| if (_method == null) return 'NoSuchMethodError: $_message';
|
| if (_receiver == null) {
|
| - return 'NoSuchMethodError: Cannot call "$_method" ($_message)';
|
| + return "NoSuchMethodError: method not found: '$_method' ($_message)";
|
| }
|
| - return 'NoSuchMethodError: Cannot call "$_method" on "$_receiver" '
|
| - '($_message)';
|
| + return "NoSuchMethodError: "
|
| + "method not found: '$_method' on '$_receiver' ($_message)";
|
| }
|
| }
|
|
|
| @@ -2236,19 +2236,22 @@ abstract class Closure implements Function {
|
| // dynClosureConstructor.prototype = proto;
|
| // return dynClosureConstructor;
|
|
|
| - // We need to create a new subclass of either TearOffClosure or
|
| - // BoundClosure. For this, we need to create an object whose prototype is
|
| - // the prototype is either TearOffClosure.prototype or
|
| + // We need to create a new subclass of TearOffClosure, one of StaticClosure
|
| + // or BoundClosure. For this, we need to create an object whose prototype
|
| + // is the prototype is either StaticClosure.prototype or
|
| // BoundClosure.prototype, respectively in pseudo JavaScript code. The
|
| // simplest way to access the JavaScript construction function of a Dart
|
| - // class is to create an instance and access its constructor property. The
|
| - // newly created instance could in theory be used directly as the
|
| - // prototype, but it might include additional fields that we don't need.
|
| - // So we only use the new instance to access the constructor property and
|
| - // use Object.create to create the desired prototype.
|
| + // class is to create an instance and access its constructor property.
|
| + // Creating an instance ensures that any lazy class initialization has taken
|
| + // place. The newly created instance could in theory be used directly as the
|
| + // prototype, but it might include additional fields that we don't need. So
|
| + // we only use the new instance to access the constructor property and use
|
| + // Object.create to create the desired prototype.
|
| + //
|
| + // TODO(sra): Perhaps cache the prototype to avoid the allocation.
|
| var prototype = isStatic
|
| - ? JS('TearOffClosure', 'Object.create(#.constructor.prototype)',
|
| - new TearOffClosure())
|
| + ? JS('StaticClosure', 'Object.create(#.constructor.prototype)',
|
| + new StaticClosure())
|
| : JS('BoundClosure', 'Object.create(#.constructor.prototype)',
|
| new BoundClosure(null, null, null, null));
|
|
|
| @@ -2258,8 +2261,7 @@ abstract class Closure implements Function {
|
| : isCsp
|
| ? JS('', 'function(a,b,c,d) {this.\$initialize(a,b,c,d)}')
|
| : JS('',
|
| - 'new Function("a","b","c","d",'
|
| - '"this.\$initialize(a,b,c,d);"+#)',
|
| + 'new Function("a,b,c,d", "this.\$initialize(a,b,c,d);" + #)',
|
| functionCounter++);
|
|
|
| // It is necessary to set the constructor property, otherwise it will be
|
| @@ -2562,7 +2564,10 @@ abstract class Closure implements Function {
|
| // backend rather than simply adding it here, as we do not want this getter
|
| // to be visible to resolution and the generation of extra stubs.
|
|
|
| - String toString() => "Closure";
|
| + String toString() {
|
| + String name = Primitives.objectTypeName(this);
|
| + return "Closure '$name'";
|
| + }
|
| }
|
|
|
| /// Called from implicit method getter (aka tear-off).
|
| @@ -2583,11 +2588,19 @@ closureFromTearOff(receiver,
|
| }
|
|
|
| /// Represents an implicit closure of a function.
|
| -class TearOffClosure extends Closure {
|
| +abstract class TearOffClosure extends Closure {
|
| }
|
|
|
| -/// Represents a 'tear-off' closure, that is an instance method bound
|
| -/// to a specific receiver (instance).
|
| +class StaticClosure extends TearOffClosure {
|
| + String toString() {
|
| + String name = JS('String|Null', '#.\$name', this);
|
| + if (name == null) return "Closure of unknown static method";
|
| + return "Closure of static method '$name'";
|
| + }
|
| +}
|
| +
|
| +/// Represents a 'tear-off' or property extraction closure of an instance
|
| +/// method, that is an instance method bound to a specific receiver (instance).
|
| class BoundClosure extends TearOffClosure {
|
| /// The receiver or interceptor.
|
| // TODO(ahe): This could just be the interceptor, we always know if
|
| @@ -2632,6 +2645,11 @@ class BoundClosure extends TearOffClosure {
|
| return receiverHashCode ^ Primitives.objectHashCode(_target);
|
| }
|
|
|
| + toString() {
|
| + var receiver = _receiver == null ? _self : _receiver;
|
| + return "Closure '$_name' of ${Primitives.objectToString(receiver)}";
|
| + }
|
| +
|
| @NoInline()
|
| static selfOf(BoundClosure closure) => closure._self;
|
|
|
|
|