-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Error compiling Dart Debug Extension with DDC #49617
Comments
It seems like that PR introduces some non-top-level |
That is strange that this isn't caught before the backend by _js_interop_checks (see https://dart-review.googlesource.com/c/sdk/+/247180 for the CL that added this change). I believe methods like: @JS()
class ChromeBrowserAction {
@JS('chrome.browserAction.onClicked.addListener')
external static void onClickedAddListener(Function callback);
} are intended to be kept as a top-level instead (or a class member through nested interfaces to avoid the '.'). cc @sigmundch for more details. |
Oops I completely missed that bug link! Everything is working with refactoring to avoid Personally I think:
is nicer than:
but it's understandable if it doesn't work that way. This is something static nested classes could help solve as well. |
I agree. That 2nd snippet feels much more clunky (and difficult to logically associate) than the former (or something with nested classes). Here's hoping the language team chimes in on that thread. Glad things are working now! |
Indeed, I expect this will be reported as a static error in the future. It appears the crash above was with the current stable 2.17.3 SDK, which doesn't have this change. It is available in the current 2.18 beta, though. @elliette - sorry our documentation on JSInterop is really lacking at the moment. Here are a couple suggestions that may help here. In some cases, it makes sense to expose those static members as top-level methods directly: @JS('chrome.browserAction.onClicked.addListener')
external addOnClickedListener(Function callback); You can also avoid multiple static entry classes if you use a static member for each non-dotted name. For instance, @JS('chrome.browserAction')
class ChromeBrowserAction {
@JS('setIcon')
external static void setIcon(IconInfo iconInfo);
external static ChromeBrowserActionOnClicked get onClicked;
}
@JS()
@anonymous
class ChromeBrowserActionOnClicked {
@JS('addListener')
external static void addListener(Function callback);
} which allows you to write: ChromeBrowserAction.onClicked.addListener(f); instead of ChromeBrowserActionOnClicked.addListener(f); More often than not, it's nice to only use a static/top-level for the first entry in the dotted name, and then use regular instance member for each property in the dotted name: That would look more like this: @JS()
Chrome get chrome;
@JS()
@anonymous
class Chrome {
// Note: static is gone, now it is treated as an instance method of
// the chrome instance returned by the getter above.
external BrowserAction get browserAction;
}
@JS()
@anonymous
class BrowserAction {
// Note: @JS not needed here (the js name is inferred from the Dart name)
external void setIcon(IconInfo iconInfo);
external OnClickedHandler get onClicked;
}
@JS()
@anonymous
class OnClickedHandler {
external void addListener(Function callback);
} Which allows you to write: chrome.browserAction.onClicked.addListener(f) Note that this last approach gives you a better IDE experience too (e.g. discoverability, completion). The quality of the generated interop code is not optimal today with this approach, that will improve with static interop (which we are actively working on at the moment). Unfortunately today static interop is a bit more verbose until we get a new language feature (view classes). Under the current prototype, the example above would need to be tweaked as follows to use static interop: @JS()
Chrome get chrome;
@JS()
@anonymous
@staticInterop // new!
class Chrome {}
extension ChromeExtension on Chrome { // code split into an extension
external BrowserAction get browserAction;
}
@JS()
@anonymous
@staticInterop
class BrowserAction {}
extension BrowserActionExtension on BrowserAction {
external void setIcon(IconInfo iconInfo);
external OnClickedHandler get onClicked;
}
@JS()
@anonymous
@staticInterop
class OnClickedHandler { }
extension OnClickedHandlerExtension on OnClickedHandler {
external void addListener(Function callback);
} With this you can access the API just like in the previous example: chrome.browserAction.onClicked.addListener(f) However, the code generated with dart2js will likely match that of the code using the dotted names in the JS annotation. Hope you find this useful! |
Thank you @sigmundch for the detailed examples, that is very helpful! |
Encountered an error compiling the Dart Debug Extension with DDC (dart2js succeeds).
The text was updated successfully, but these errors were encountered: