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.28k stars 1.58k forks source link

[js_interop] How to handle JS definition that uses explicit default arguments #59568

Closed navaronbracke closed 1 day ago

navaronbracke commented 1 day ago

The new interop docs state the following for optional parameters:

Unlike with non-external methods, optional arguments do not get replaced with their default value, but are instead omitted.

See https://dart.dev/interop/js-interop/usage#parameters

However, what if the underlying definition you're using does provide a default argument, which it relies on? In Dart, default arguments have to be const, but in JS that isn't the case.

Is there any guidance on this?

Concrete example, from the Auth0 JS SDK:

  // JS
  public async handleRedirectCallback<TAppState = any>(
    url: string = window.location.href
  ): Promise<RedirectLoginResult<TAppState>> {
    const queryStringFragments = url.split('?').slice(1);

    // irrelevant code...
  }

  // Dart
  external Future<RedirectLoginResult> handleRedirectCallback([
    final String? url,
  ]);

I'm using Dart 3.5.3

dart-github-bot commented 1 day ago

Summary: Dart's JS interop doesn't handle JS functions with non-const default arguments. The user needs guidance on how to handle this mismatch.

lrhn commented 1 day ago

If the JS function has a default value, omitting the argument from the Dart side is exactly what you want.

I tried this in dartpad.dev:

import "dart:js_interop";

@JS()
external void eval(String text);
@JS()
external int ctr([int value]);

void main() {
  // Set up function with default value.
  eval(r"var $ctr = 0; function ctr(value = ++$ctr) { return $ctr = value; }");
  print(ctr());
  print(ctr());
  print(ctr(42));
  print(ctr());
}

The Dart external ctr function has an optional parameter with no given default, and if called without an argument, that invokes the JS function with no argument too.

navaronbracke commented 1 day ago

Hmm, this does seem to work locally on a new sample. So this is probably an issue on my end. However, the package that I saw this on did use a very old language version.