Skip to content

Commit

Permalink
Some fixes for dart2wasm (#38167)
Browse files Browse the repository at this point in the history
* A few fixes to get things compiling via dart2wasm.

* Use `futureToPromise`.

* Some more fixes for dart2wasm.

* Allow promises to have nullable objects.
  • Loading branch information
eyebrowsoffire authored Dec 13, 2022
1 parent 984ec30 commit cda2be8
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 35 deletions.
33 changes: 10 additions & 23 deletions lib/web_ui/lib/src/engine/app_bootstrap.dart
Original file line number Diff line number Diff line change
Expand Up @@ -40,30 +40,17 @@ class AppBootstrap {
// This is a convenience method that lets the programmer call "autoStart"
// from JavaScript immediately after the main.dart.js has loaded.
// Returns a promise that resolves to the Flutter app that was started.
autoStart: allowInterop(() {
return Promise<FlutterApp>(allowInterop((
PromiseResolver<FlutterApp> resolve,
PromiseRejecter _,
) async {
await autoStart();
// Return the App that was just started
resolve(_prepareFlutterApp());
}));
}),
autoStart: allowInterop(() => futureToPromise(() async {
await autoStart();
// Return the App that was just started
return _prepareFlutterApp();
}())),
// Calls [_initEngine], and returns a JS Promise that resolves to an
// app runner object.
initializeEngine: allowInterop(([JsFlutterConfiguration? configuration]) {
// `params` coming from Javascript may be used to configure the engine intialization.
// The internal `initEngine` function must accept those params.
return Promise<FlutterAppRunner>(allowInterop((
PromiseResolver<FlutterAppRunner> resolve,
PromiseRejecter _,
) async {
await _initializeEngine(configuration);
// Return an app runner object
resolve(_prepareAppRunner());
}));
}),
initializeEngine: allowInterop(([JsFlutterConfiguration? configuration]) => futureToPromise(() async {
await _initializeEngine(configuration);
return _prepareAppRunner();
}()))
);
}

Expand All @@ -77,7 +64,7 @@ class AppBootstrap {
) async {
await _runApp();
// Return the App that was just started
resolve(_prepareFlutterApp());
resolve.resolve(_prepareFlutterApp());
}));
}));
}
Expand Down
7 changes: 4 additions & 3 deletions lib/web_ui/lib/src/engine/canvaskit/canvaskit_api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -176,9 +176,9 @@ class ColorSpace {}
@staticInterop
class SkWebGLContextOptions {
external factory SkWebGLContextOptions({
required int antialias,
required double antialias,
// WebGL version: 1 or 2.
required int majorVersion,
required double majorVersion,
});
}

Expand Down Expand Up @@ -1362,7 +1362,8 @@ final SkFloat32List _sharedSkColor3 = mallocFloat32List(4);
@JS('window.flutterCanvasKit.Path')
@staticInterop
class SkPath {
external factory SkPath([SkPath? other]);
external factory SkPath();
external factory SkPath.from(SkPath other);
}

extension SkPathExtension on SkPath {
Expand Down
2 changes: 1 addition & 1 deletion lib/web_ui/lib/src/engine/canvaskit/surface.dart
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ class Surface {
// Default to no anti-aliasing. Paint commands can be explicitly
// anti-aliased by setting their `Paint` object's `antialias` property.
antialias: _kUsingMSAA ? 1 : 0,
majorVersion: webGLVersion,
majorVersion: webGLVersion.toDouble(),
),
).toInt();

Expand Down
2 changes: 1 addition & 1 deletion lib/web_ui/lib/src/engine/js_interop/js_loader.dart
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ abstract class FlutterEngineInitializer{
/// [JsFlutterConfiguration] comes from `../configuration.dart`. It is the same
/// object that can be used to configure flutter "inline", through the
/// (to be deprecated) `window.flutterConfiguration` object.
typedef InitializeEngineFn = Promise<FlutterAppRunner?> Function([JsFlutterConfiguration?]);
typedef InitializeEngineFn = Promise<FlutterAppRunner> Function([JsFlutterConfiguration?]);

/// Typedef for the `autoStart` function that can be called straight from an engine initializer instance.
/// (Similar to [RunAppFn], but taking no specific "runApp" parameters).
Expand Down
33 changes: 27 additions & 6 deletions lib/web_ui/lib/src/engine/js_interop/js_promise.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,39 @@
library js_promise;

import 'package:js/js.dart';
import 'package:js/js_util.dart' as js_util;

@JS()
@staticInterop
class PromiseResolver<T extends Object?> {}

extension PromiseResolverExtension<T extends Object?> on PromiseResolver<T> {
void resolve(T result) => js_util.callMethod(this, 'call', <Object>[this, if (result != null) result]);
}

@JS()
@staticInterop
class PromiseRejecter {}

extension PromiseRejecterExtension on PromiseRejecter {
void reject(Object? error) => js_util.callMethod(this, 'call', <Object>[this, if (error != null) error]);
}

/// Type-safe JS Promises
@JS('Promise')
@staticInterop
abstract class Promise<T> {
abstract class Promise<T extends Object?> {
/// A constructor for a JS promise
external factory Promise(PromiseExecutor<T> executor);
}

/// The type of function that is used to create a Promise<T>
typedef PromiseExecutor<T> = void Function(PromiseResolver<T> resolve, PromiseRejecter reject);
/// The type of function used to resolve a Promise<T>
typedef PromiseResolver<T> = void Function(T result);
/// The type of function used to reject a Promise (of any <T>)
typedef PromiseRejecter = void Function(Object? error);
typedef PromiseExecutor<T extends Object?> = void Function(PromiseResolver<T> resolve, PromiseRejecter reject);

Promise<T> futureToPromise<T extends Object>(Future<T> future) {
return Promise<T>(allowInterop((PromiseResolver<T> resolver, PromiseRejecter rejecter) {
future.then(
(T value) => resolver.resolve(value),
onError: (Object? error) => rejecter.reject(error));
}));
}
2 changes: 1 addition & 1 deletion lib/web_ui/lib/src/engine/navigation/history.dart
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ class MultiEntriesBrowserHistory extends BrowserHistory {
if (_hasSerialCount(currentState)) {
final Map<dynamic, dynamic> stateMap =
currentState! as Map<dynamic, dynamic>;
return stateMap['serialCount'] as int;
return (stateMap['serialCount'] as double).toInt();
}
return 0;
}
Expand Down

0 comments on commit cda2be8

Please sign in to comment.