Skip to content
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

[dart:js_interop] Add a way to internalize undefined values and pass it back to JS #54025

Open
ykmnkmi opened this issue Nov 13, 2023 · 5 comments
Labels
area-web Use area-web for Dart web related issues, including the DDC and dart2js compilers and JS interop. web-js-interop Issues that impact all js interop

Comments

@ykmnkmi
Copy link
Contributor

ykmnkmi commented Nov 13, 2023

jsObject.prop = undefined;
@lrhn lrhn added web-js-interop Issues that impact all js interop type-question A question about expected behavior or functionality area-web Use area-web for Dart web related issues, including the DDC and dart2js compilers and JS interop. labels Nov 13, 2023
@srujzs
Copy link
Contributor

srujzs commented Nov 14, 2023

Alas, this is one of the few remaining sharp corners to solve. I mention this in #49353.

I don't have a great recommendation here as undefined is always reified to Dart null in dart2wasm, so this will require leveraging some JS code to do the assignment until we resolve this.

@srujzs srujzs changed the title [dart:js_interop] How to set an object property to undefined? [dart:js_interop] Add a way to internalize undefined values and pass it back to JS Jan 25, 2024
@felix-ht
Copy link

felix-ht commented Apr 4, 2024

Just ported a rather big dart interop lib (https://pub.dev/packages/mapbox_gl_dart/) to the new js_interop

Ran into trouble with a constructor that constructs an invalid object if null is (explictly) passed. I fixed it by passing a valid default value (in this case 0 and a good default).

I would much rather be able to set undefined, as there are certainly libs where no sane defaults are possible and only undefined is an options. Also couples the dart code much closer to the js code as one has to check what defaults make sense for the current version of the js lib.

@srujzs
Copy link
Contributor

srujzs commented Apr 11, 2024

Thanks for migrating! That's exciting to see.

Also couples the dart code much closer to the js code as one has to check what defaults make sense for the current version of the js lib.

Can you explain a bit more what you meant by this?

I agree undefined is still needed. I think the one complication I haven't really resolved is how to expose an undefined value such that it fits into the JS type hierarchy. If we had union types, this would be easier. Without union types, we could imagine a JSAny? singleton e.g.

JSAny? get undefined => // some compiler internals

Which resolves the case where you pass it to JS, but doesn't resolve the case where it's passed back as dart2wasm won't know to treat that JSAny? different from other JSAny?s and therefore will convert it to Dart null. We could maybe use a typedef e.g.

typedef JSAnyOrUndefined = JSAny;

that statically tells the compiler to not convert the undefined to null when used on a return value. Then we can make the singleton above typed as this typedef as well. However, this means you don't have a way of expressing something like "JS string or undefined" as you're stuck with JSAny.

Another way of maybe resolving this is using an annotation on an external member to tell the compiler not to convert undefineds, but annotations are not great.

@felix-ht
Copy link

Also couples the dart code much closer to the js code as one has to check what defaults make sense for the current version of the js lib.

Can you explain a bit more what you meant by this?

I have to replicate the defaults of JS values in the dart interop code. A new version of the js libary might change the defaults, but the dart interop would keep whatever was defined in the dart side. If i can pass undefined the JS libary should use its defaults - if i (implicitly) pass null if often gets used as the acutal value.

@ykmnkmi
Copy link
Contributor Author

ykmnkmi commented Apr 15, 2024

Sometimes I'm write code like this, which is not sound:

@JS('fn')
external void _fn(
  JSAny first, [
  JSAny? second, // JS side checks if it's null or undefined
]);

void fn(JSAny first, [Object? second = const Object()]) {
  if (identical(second, const Object())) {
    _fn(first);
  } else {
    _fn(first, second as JSAny?);
  }
}

@srujzs srujzs removed the type-question A question about expected behavior or functionality label Apr 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-web Use area-web for Dart web related issues, including the DDC and dart2js compilers and JS interop. web-js-interop Issues that impact all js interop
Projects
Status: No status
Development

No branches or pull requests

4 participants