dart-lang / sdk

The Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.
https://dart.dev
BSD 3-Clause "New" or "Revised" License
10.12k stars 1.57k forks source link

JS interop makes non-breaking JS changes break Dart code #48186

Open nex3 opened 2 years ago

nex3 commented 2 years ago

In JS, it's legal to pass more arguments to a function than that function declares. For example, (() => {})(1) is valid code. In Dart this is not legal, and (() {})(1) will produce an error.

The issue comes when passing Dart functions to JS. Despite needing to wrap the JS functions in allowInterop(), Dart doesn't actually allow them to take multiple arguments. This violates JS libraries' assumptions about what changes are non-breaking, and leads to real-world breakages such as sass/dart-sass#1625.

sigmundch commented 6 months ago

@srujzs - in thinking about the other issue (high-order conversions with ExternalDartObjectReference in function parameters), I realized that a similar idea would be helpful to address this issue. That is: to switch from a single generic allow-interop implementation, to mutliple specialized implementations depending on the static type of the argument to allow interop.

Those specialized implementations would no longer need to use Function.apply in the body, making them a bit leaner and faster. We'd also be able to accept and ignore additional arguments at that point.

srujzs commented 6 months ago

Oh I briefly mentioned this in the other issue (#55342) before I saw this, but I agree. :)

srujzs commented 3 months ago

FYI @nex3 - this has landed with Function.toJS. I'll leave this open since we haven't addressed the same issue with allowInterop yet. That would be a bit more complicated since we can't rely on static type information only.