Open TheOneWithTheBraid opened 2 years ago
IIRC, this isn't allowed as Future
s aren't Promise
s. The Future
returned by your Dart function in JS won't necessarily have the methods you're expecting, and there isn't a futureToPromise
function like there is for promiseToFuture
. @sigmundch to confirm, but it seems like it might be useful to add errors here in allowInterop
to inform users.
Yes, I believe you are correct @srujzs
I had to do some weird gymnastics to create a JS object with a method that's expected to return a promise: https://github.com/flutter/engine/pull/36253/files#diff-c12aeab766e5e21494fb2a61877c898072f52aa21a8f8663ad9e74144f17357a
futureToPromise
would be handy. Or perhaps allowInterop
could support async functions (since async
is part of the language both for Dart and JS).
@yjbanov I had a similar problem just now. I needed to be able to create a Promise
in Dart so that I could pass it through allowInterop()
back to a library for which I'm writing some interop for.
I did manage to write a wrapper using the existing @staticInterop
annotation.
Perhaps we could include a static interop definition for Promise
in the SDK? (a la futureToPromise
)
Code sample:
// main.dart This file just wires up a function to the window so that could easily test it.
import 'package:js/js.dart';
import 'package:js/js_util.dart';
import 'dart:html' as html;
@JS()
@staticInterop
class JSWindow {}
extension JSWindowExtension on JSWindow {
external void Function(Promise input) get testFunction;
}
// This one is all I needed, don't forget to call allowInterop() on the executor!
@JS()
@staticInterop
class Promise {
external factory Promise(
void Function(Promise? Function(Object?) resolve, Promise? Function(Object?) reject) executor,
);
}
void main() async {
var jsWindow = html.window as JSWindow;
await Future.delayed(const Duration(seconds: 2));
jsWindow.testFunction(Promise(allowInterop(
(resolve, reject) async {
await Future.delayed(const Duration(seconds: 2));
resolve(
Promise(
allowInterop((resolve2, reject2) {
print('RESOLVING!');
resolve2(42);
}),
),
);
//resolve(42);
//reject(500);
//reject(jsify(<String, dynamic>{
// 'foo': 42,
//}));
},
)));
}
// api.js
window.testFunction = async function(input) {
if(input instanceof Promise) {
input.then((value) => {
console.log(`resolved with: ${value}`);
},
(reason) => {
console.log(`rejected with: ${JSON.stringify(reason)}`);
},
);
}
}
cc @srujzs Another pain point :)
I think the Flutter engine has a similar futureToPromise
function to the code above. We do have a JSPromise
now in dart:js_interop that users can use as part of JS types, but it's very minimal. We only have a toDart
function on it that calls promiseToFuture
, but I can totally see a toJS
that calls JSPromise
's external constructor.
It seems like the
package:js
has problems interlooping simpleFuture
callbacks, such as:When calling this function by JS (
myDartFunction().then((value) => {console.log(value);})
), the following error is thrown: