Skip to content

noSuchMethod isn't getting called on web on beta/dev channels (works fine on stable) #50750

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
westy92 opened this issue Dec 15, 2022 · 3 comments

Comments

@westy92
Copy link

westy92 commented Dec 15, 2022

In my sample code, on the Web platform, noSuchMethod(...) is not getting invoked. It works fine on stable, but is not working on beta/dev/master.

I have tested with MacOS (latest, 13.0.1) on Chrome (latest, Version 108.0.5359.124 (Official Build) (x86_64)). Also tested on DartPad.

Problematic versions:

  • current beta (dart 2.19.0-444.1.beta)
  • current dev
  • current master (2.19.0-467.0.dev)

Works fine on the latest stable version (2.18.5)!

Expected behavior:

inside noSuchMethod

Actual behavior:

Uncaught Error: NoSuchMethodError: method not found: '_value'
Receiver: Instance of 'MyDateTime'
Arguments: []

Sample code:

class MyDateTime implements DateTime {
  const MyDateTime(int year)
      : _year = year;
  final int _year;

  DateTime get dateTime {
    return DateTime(_year);
  }

  @override
  DateTime add(Duration duration) {
    return dateTime.add(duration);
  }

  @override
  int compareTo(DateTime other) {
    return dateTime.compareTo(other);
  }

  @override
  int get day => dateTime.day;

  @override
  Duration difference(DateTime other) {
    return dateTime.difference(other);
  }

  @override
  int get hashCode => dateTime.hashCode;

  @override
  int get hour => dateTime.hour;

  @override
  bool isAfter(DateTime other) {
    return dateTime.isAfter(other);
  }

  @override
  bool isAtSameMomentAs(DateTime other) {
    return dateTime.isAtSameMomentAs(other);
  }

  @override
  bool isBefore(DateTime other) {
    return dateTime.isBefore(other);
  }

  @override
  bool get isUtc => dateTime.isUtc;

  @override
  int get microsecond => dateTime.microsecond;

  @override
  int get microsecondsSinceEpoch => dateTime.microsecondsSinceEpoch;

  @override
  int get millisecond => dateTime.millisecond;

  @override
  int get millisecondsSinceEpoch => dateTime.millisecondsSinceEpoch;

  @override
  int get minute => dateTime.minute;

  @override
  int get month => dateTime.month;

  @override
  int get second => dateTime.second;

  @override
  DateTime subtract(Duration duration) {
    return dateTime.subtract(duration);
  }

  @override
  String get timeZoneName => dateTime.timeZoneName;

  @override
  Duration get timeZoneOffset => dateTime.timeZoneOffset;

  @override
  String toIso8601String() {
    return dateTime.toIso8601String();
  }

  @override
  DateTime toLocal() {
    return dateTime.toLocal();
  }

  @override
  DateTime toUtc() {
    return dateTime.toUtc();
  }

  @override
  int get weekday => dateTime.weekday;

  @override
  int get year => dateTime.year;

  @override
  bool operator ==(Object other) {
    return dateTime == other;
  }

  @override
  dynamic noSuchMethod(Invocation invocation) {
    print('inside noSuchMethod');
    return 0;
  }
}

void main() {
    final d1 = DateTime(2022, 2);
    final d2 = const MyDateTime(2022);
    d1.difference(d2);
}
@lrhn
Copy link
Member

lrhn commented Dec 17, 2022

I believe this is a deliberate change in how implicit implementations of private members from other libraries work. (#49687)

When you implement an interface which has an inaccessible member (private member from another library), it used to be implemented by an implicit "noSuchMethod-forwarder", the same kind of forwarder you get if a normal member is missing and you have a non-default noSuchMethod.

This was changed in 2.19, so now the inaccessible member implementation directly throws a noSuchMethod. You cannot implement private members of other libraries, not even using noSuchMethod.

@lrhn
Copy link
Member

lrhn commented Dec 20, 2022

We've landed a change to the web DateTime implementations, so it shouldn't be failing in this way any more.
You still won't be able to intercept inaccessible private members, this particular code will just not call private members any more.

@lrhn lrhn closed this as completed Dec 20, 2022
@ipcjs
Copy link

ipcjs commented Dec 20, 2022

👍🏻️8ad7661

Can the commit be merged into the next version of Dart?
This is very important in order not to break the existing code.

copybara-service bot pushed a commit that referenced this issue Jan 2, 2023
…ion.

Changes `other._value` to `other.millisecondsSinceEpoch`,
which prevents crashing if provided with a different implementation
of `DateTime`.

Exposed by #50750.

Bug: https://dartbug.com/50750
Cherry-pick: #50821
Change-Id: I1dfc0bb4e8a44ef0df432c9a916a6620691e0547
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/277002
Commit-Queue: Lasse Nielsen <[email protected]>
Reviewed-by: Nate Bosch <[email protected]>
Auto-Submit: Lasse Nielsen <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants