Skip to content

Commit

Permalink
[web] Move web-only initialization APIs to dart:ui_web (flutter#43111)
Browse files Browse the repository at this point in the history
| Old API in `dart:ui` | New API in `dart:ui_web` |
|-|-|
| ~`webOnlyInitializePlatform`~ | ~`ui_web.initializePlatform`~ |
| `webOnlyWarmupEngine` | `ui_web.bootstrapEngine` |
| `debugEmulateFlutterTesterEnvironment` | `ui_web.debugEmulateFlutterTesterEnvironment` |
| `webOnlySetPluginHandler` | `ui_web.setPluginHandler` |

Part of flutter/flutter#126831
  • Loading branch information
mdebbar authored Jun 29, 2023
1 parent 2bae613 commit 9a3d191
Show file tree
Hide file tree
Showing 26 changed files with 214 additions and 120 deletions.
6 changes: 6 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -2110,9 +2110,12 @@ ORIGIN: ../../../flutter/lib/web_ui/lib/tile_mode.dart + ../../../flutter/LICENS
ORIGIN: ../../../flutter/lib/web_ui/lib/ui.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/lib/ui_web/src/ui_web.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/lib/ui_web/src/ui_web/asset_manager.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/lib/ui_web/src/ui_web/initialization.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/lib/ui_web/src/ui_web/navigation/platform_location.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/lib/ui_web/src/ui_web/navigation/url_strategy.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/lib/ui_web/src/ui_web/platform_view_registry.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/lib/ui_web/src/ui_web/plugins.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/lib/ui_web/src/ui_web/testing.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/lib/window.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/skwasm/canvas.cpp + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/skwasm/contour_measure.cpp + ../../../flutter/LICENSE
Expand Down Expand Up @@ -4791,9 +4794,12 @@ FILE: ../../../flutter/lib/web_ui/lib/tile_mode.dart
FILE: ../../../flutter/lib/web_ui/lib/ui.dart
FILE: ../../../flutter/lib/web_ui/lib/ui_web/src/ui_web.dart
FILE: ../../../flutter/lib/web_ui/lib/ui_web/src/ui_web/asset_manager.dart
FILE: ../../../flutter/lib/web_ui/lib/ui_web/src/ui_web/initialization.dart
FILE: ../../../flutter/lib/web_ui/lib/ui_web/src/ui_web/navigation/platform_location.dart
FILE: ../../../flutter/lib/web_ui/lib/ui_web/src/ui_web/navigation/url_strategy.dart
FILE: ../../../flutter/lib/web_ui/lib/ui_web/src/ui_web/platform_view_registry.dart
FILE: ../../../flutter/lib/web_ui/lib/ui_web/src/ui_web/plugins.dart
FILE: ../../../flutter/lib/web_ui/lib/ui_web/src/ui_web/testing.dart
FILE: ../../../flutter/lib/web_ui/lib/window.dart
FILE: ../../../flutter/lib/web_ui/skwasm/canvas.cpp
FILE: ../../../flutter/lib/web_ui/skwasm/contour_measure.cpp
Expand Down
129 changes: 52 additions & 77 deletions lib/web_ui/lib/initialization.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,89 +28,59 @@ part of ui;
///
/// This is only available on the Web, as native Flutter configures the
/// environment in the native embedder.
// TODO(mdebbar): Deprecate this and remove it.
// https://github.com/flutter/flutter/issues/127395
Future<void> webOnlyInitializePlatform() async {
await engine.initializeEngine();
}

/// Initializes essential bits of the engine before it fully initializes.
/// When [didCreateEngineInitializer] is set, it delegates engine initialization
/// and app startup to the programmer.
/// Else, it immediately triggers the full engine + app bootstrap.
///
/// This method is called by the flutter_tools package, from the entrypoint that
/// it generates around the main method provided by the programmer. See:
/// * https://github.com/flutter/flutter/blob/2bd3e0d914854aa8c12e933f25c5fd8532ae5571/packages/flutter_tools/lib/src/build_system/targets/web.dart#L135-L163
/// * https://github.com/flutter/flutter/blob/61fb2de52c7bdac19b7f2f74eaf3f11237e1e91d/packages/flutter_tools/lib/src/isolated/resident_web_runner.dart#L460-L485
///
/// This function first calls [engine.initializeEngineServices] so the engine
/// can prepare the js-interop layer that is used by web apps (instead of the
/// old `ui.webOnlyFoo` methods/getters).
///
/// It then creates a JsObject that is passed to the [didCreateEngineInitializer]
/// JS callback, to delegate bootstrapping the app to the programmer.
///
/// If said callback is not defined, this assumes that the Flutter Web app is
/// initializing "automatically", as was normal before this feature was
/// introduced. This will immediately run the initEngine and runApp methods
/// (via [engine.AppBootstrap.now]).
///
/// This is the only bit of `dart:ui` that should be directly called by Flutter
/// web apps. Everything else should go through the JS-interop layer created in
/// `engine.warmup`.
///
/// This method should NOT trigger the download of any additional resources
/// (except when the app is in "autoStart" mode).
// TODO(mdebbar): Deprecate this and remove it.
// https://github.com/flutter/flutter/issues/127395
Future<void> webOnlyWarmupEngine({
Function? registerPlugins,
Function? runApp,
}) async {
// Create the object that knows how to bootstrap an app from JS and Dart.
final engine.AppBootstrap bootstrap = engine.AppBootstrap(
initializeEngine: ([engine.JsFlutterConfiguration? configuration]) async {
await engine.initializeEngineServices(jsConfiguration: configuration);
}, runApp: () async {
if (registerPlugins != null) {
registerPlugins();
}
await engine.initializeEngineUi();
if (runApp != null) {
runApp();
}
},
VoidCallback? registerPlugins,
VoidCallback? runApp,
}) {
assert(() {
engine.printWarning(
'The webOnlyWarmupEngine API is deprecated and will be removed in a '
'future release. Please use `bootstrapEngine` from `dart:ui_web` instead.',
);
return true;
}());
return ui_web.bootstrapEngine(
registerPlugins: registerPlugins,
runApp: runApp,
);
}

final engine.FlutterLoader? loader = engine.flutter?.loader;
if (loader == null || loader.isAutoStart) {
// The user does not want control of the app, bootstrap immediately.
engine.domWindow.console.debug('Flutter Web Bootstrap: Auto.');
await bootstrap.autoStart();
} else {
// Yield control of the bootstrap procedure to the user.
engine.domWindow.console.debug('Flutter Web Bootstrap: Programmatic.');
loader.didCreateEngineInitializer(bootstrap.prepareEngineInitializer());
}
// TODO(mdebbar): Deprecate this and remove it.
// https://github.com/flutter/flutter/issues/127395
bool get debugEmulateFlutterTesterEnvironment {
assert(() {
engine.printWarning(
'The debugEmulateFlutterTesterEnvironment getter is deprecated and will '
'be removed in a future release. Please use '
'`debugEmulateFlutterTesterEnvironment` from `dart:ui_web` instead.',
);
return true;
}());
return ui_web.debugEmulateFlutterTesterEnvironment;
}

/// Emulates the `flutter test` environment.
///
/// When set to true, the engine will emulate a specific screen size, and always
/// use the "Ahem" font to reduce test flakiness and dependence on the test
/// environment.
bool get debugEmulateFlutterTesterEnvironment =>
_debugEmulateFlutterTesterEnvironment;
// TODO(mdebbar): Deprecate this and remove it.
// https://github.com/flutter/flutter/issues/127395
set debugEmulateFlutterTesterEnvironment(bool value) {
_debugEmulateFlutterTesterEnvironment = value;
if (_debugEmulateFlutterTesterEnvironment) {
const Size logicalSize = Size(800.0, 600.0);
engine.window.webOnlyDebugPhysicalSizeOverride =
logicalSize * window.devicePixelRatio;
}
engine.debugDisableFontFallbacks = value;
assert(() {
engine.printWarning(
'The debugEmulateFlutterTesterEnvironment setter is deprecated and will '
'be removed in a future release. Please use '
'`debugEmulateFlutterTesterEnvironment` from `dart:ui_web` instead.',
);
return true;
}());
ui_web.debugEmulateFlutterTesterEnvironment = value;
}

bool _debugEmulateFlutterTesterEnvironment = false;

/// Provides the asset manager.
// TODO(mdebbar): Deprecate this and remove it.
// https://github.com/flutter/flutter/issues/127395
ui_web.AssetManager get webOnlyAssetManager {
Expand All @@ -124,12 +94,17 @@ ui_web.AssetManager get webOnlyAssetManager {
return ui_web.assetManager;
}

/// Sets the handler that forwards platform messages to web plugins.
///
/// This function exists because unlike mobile, on the web plugins are also
/// implemented using Dart code, and that code needs a way to receive messages.
void webOnlySetPluginHandler(Future<void> Function(String, ByteData?, PlatformMessageResponseCallback?) handler) {
engine.pluginMessageCallHandler = handler;
// TODO(mdebbar): Deprecate this and remove it.
// https://github.com/flutter/flutter/issues/127395
void webOnlySetPluginHandler(PlatformMessageCallback handler) {
assert(() {
engine.printWarning(
'The webOnlySetPluginHandler API is deprecated and will be removed in a '
'future release. Please use `setPluginHandler` from `dart:ui_web` instead.',
);
return true;
}());
ui_web.setPluginHandler(handler);
}

// TODO(mdebbar): Deprecate this and remove it.
Expand Down
7 changes: 4 additions & 3 deletions lib/web_ui/lib/src/engine/canvaskit/text.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ import 'dart:typed_data';
import 'package:meta/meta.dart';
import 'package:ui/src/engine.dart';
import 'package:ui/ui.dart' as ui;
import 'package:ui/ui_web/src/ui_web.dart' as ui_web;

final bool _ckRequiresClientICU = canvasKit.ParagraphBuilder.RequiresClientICU();

final List<String> _testFonts = <String>['FlutterTest', 'Ahem'];
String? _effectiveFontFamily(String? fontFamily) {
return ui.debugEmulateFlutterTesterEnvironment && !_testFonts.contains(fontFamily)
return ui_web.debugEmulateFlutterTesterEnvironment && !_testFonts.contains(fontFamily)
? _testFonts.first
: fontFamily;
}
Expand Down Expand Up @@ -231,7 +232,7 @@ class CkTextStyle implements ui.TextStyle {
fontStyle,
textBaseline,
_effectiveFontFamily(fontFamily),
ui.debugEmulateFlutterTesterEnvironment ? null : fontFamilyFallback,
ui_web.debugEmulateFlutterTesterEnvironment ? null : fontFamilyFallback,
fontSize,
letterSpacing,
wordSpacing,
Expand Down Expand Up @@ -481,7 +482,7 @@ class CkStrutStyle implements ui.StrutStyle {
ui.FontStyle? fontStyle,
bool? forceStrutHeight,
}) : _fontFamily = _effectiveFontFamily(fontFamily),
_fontFamilyFallback = ui.debugEmulateFlutterTesterEnvironment ? null : fontFamilyFallback,
_fontFamilyFallback = ui_web.debugEmulateFlutterTesterEnvironment ? null : fontFamilyFallback,
_fontSize = fontSize,
_height = height,
_leadingDistribution = leadingDistribution,
Expand Down
5 changes: 3 additions & 2 deletions lib/web_ui/lib/src/engine/html/scene_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import 'dart:typed_data';

import 'package:ui/ui.dart' as ui;
import 'package:ui/ui_web/src/ui_web.dart' as ui_web;

import '../../engine.dart' show kProfileApplyFrame, kProfilePrerollFrame;
import '../dom.dart';
Expand Down Expand Up @@ -111,7 +112,7 @@ class SurfaceSceneBuilder implements ui.SceneBuilder {
// Top level transform contains view configuration to scale
// scene to devicepixelratio. Use identity instead since CSS uses
// logical device pixels.
if (!ui.debugEmulateFlutterTesterEnvironment) {
if (!ui_web.debugEmulateFlutterTesterEnvironment) {
assert(matrix4[0] == window.devicePixelRatio &&
matrix4[5] == window.devicePixelRatio);
}
Expand Down Expand Up @@ -383,7 +384,7 @@ class SurfaceSceneBuilder implements ui.SceneBuilder {
void _addTexture(double dx, double dy, double width, double height,
int textureId, ui.FilterQuality filterQuality) {
// In test mode, allow this to be a no-op.
if (!ui.debugEmulateFlutterTesterEnvironment) {
if (!ui_web.debugEmulateFlutterTesterEnvironment) {
throw UnimplementedError('Textures are not supported in Flutter Web');
}
}
Expand Down
2 changes: 1 addition & 1 deletion lib/web_ui/lib/src/engine/initialization.dart
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ void _setAssetManager(ui_web.AssetManager assetManager) {
Future<void> _downloadAssetFonts() async {
renderer.fontCollection.clear();

if (ui.debugEmulateFlutterTesterEnvironment) {
if (ui_web.debugEmulateFlutterTesterEnvironment) {
// Load the embedded test font before loading fonts from the assets so that
// the embedded test font is the default (first) font.
await renderer.fontCollection.loadFontFromList(
Expand Down
2 changes: 1 addition & 1 deletion lib/web_ui/lib/src/engine/platform_dispatcher.dart
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,7 @@ class EnginePlatformDispatcher extends ui.PlatformDispatcher {
// In widget tests we want to bypass processing of platform messages.
bool returnImmediately = false;
assert(() {
if (ui.debugEmulateFlutterTesterEnvironment) {
if (ui_web.debugEmulateFlutterTesterEnvironment) {
returnImmediately = true;
}
return true;
Expand Down
4 changes: 1 addition & 3 deletions lib/web_ui/lib/src/engine/plugins.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:typed_data';

import 'package:ui/ui.dart' as ui;

Future<void> Function(String, ByteData?, ui.PlatformMessageResponseCallback?)? pluginMessageCallHandler;
ui.PlatformMessageCallback? pluginMessageCallHandler;
3 changes: 2 additions & 1 deletion lib/web_ui/lib/src/engine/semantics/semantics.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import 'dart:typed_data';

import 'package:meta/meta.dart';
import 'package:ui/ui.dart' as ui;
import 'package:ui/ui_web/src/ui_web.dart' as ui_web;

import '../../engine.dart' show registerHotRestartListener;
import '../alarm_clock.dart';
Expand Down Expand Up @@ -2116,7 +2117,7 @@ class EngineSemanticsOwner {
/// Updates the semantics tree from data in the [uiUpdate].
void updateSemantics(ui.SemanticsUpdate uiUpdate) {
if (!_semanticsEnabled) {
if (ui.debugEmulateFlutterTesterEnvironment) {
if (ui_web.debugEmulateFlutterTesterEnvironment) {
// Running Flutter widget tests in a fake environment. Don't enable
// engine semantics. Test semantics trees violate invariants in ways
// production implementation isn't built to handle. For example, tests
Expand Down
5 changes: 3 additions & 2 deletions lib/web_ui/lib/src/engine/text/paragraph.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import 'dart:math' as math;

import 'package:ui/ui.dart' as ui;
import 'package:ui/ui_web/src/ui_web.dart' as ui_web;

import '../browser_detection.dart';
import '../dom.dart';
Expand Down Expand Up @@ -473,7 +474,7 @@ class EngineTextStyle implements ui.TextStyle {
// This makes widget tests predictable and less flaky.
String result = fontFamily;
assert(() {
if (ui.debugEmulateFlutterTesterEnvironment && !_testFonts.contains(fontFamily)) {
if (ui_web.debugEmulateFlutterTesterEnvironment && !_testFonts.contains(fontFamily)) {
result = _testFonts.first;
}
return true;
Expand Down Expand Up @@ -820,7 +821,7 @@ void applyTextStyleToElement({
}
// For test environment use effectiveFontFamily since we need to
// consistently use the correct test font.
if (ui.debugEmulateFlutterTesterEnvironment) {
if (ui_web.debugEmulateFlutterTesterEnvironment) {
cssStyle.fontFamily = canonicalizeFontFamily(style.effectiveFontFamily)!;
} else {
cssStyle.fontFamily = canonicalizeFontFamily(style.fontFamily)!;
Expand Down
3 changes: 2 additions & 1 deletion lib/web_ui/lib/src/engine/text/ruler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// found in the LICENSE file.

import 'package:ui/ui.dart' as ui;
import 'package:ui/ui_web/src/ui_web.dart' as ui_web;

import '../browser_detection.dart';
import '../dom.dart';
Expand Down Expand Up @@ -144,7 +145,7 @@ class TextDimensions {
if (browserEngine == BrowserEngine.firefox &&
// In the flutter tester environment, we use a predictable-size for font
// measurement tests.
!ui.debugEmulateFlutterTesterEnvironment) {
!ui_web.debugEmulateFlutterTesterEnvironment) {
// See subpixel rounding bug :
// https://bugzilla.mozilla.org/show_bug.cgi?id=442139
// This causes bottom of letters such as 'y' to be cutoff and
Expand Down
3 changes: 3 additions & 0 deletions lib/web_ui/lib/ui_web/src/ui_web.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
library ui_web;

export 'ui_web/asset_manager.dart';
export 'ui_web/initialization.dart';
export 'ui_web/navigation/platform_location.dart';
export 'ui_web/navigation/url_strategy.dart';
export 'ui_web/platform_view_registry.dart';
export 'ui_web/plugins.dart';
export 'ui_web/testing.dart';
57 changes: 57 additions & 0 deletions lib/web_ui/lib/ui_web/src/ui_web/initialization.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:ui/src/engine.dart';
import 'package:ui/ui.dart' as ui;

/// Bootstraps the Flutter Web engine and app.
///
/// If the app uses plugins, then the [registerPlugins] callback can be provided
/// to register those plugins. This is done typically by calling
/// `registerPlugins` from the auto-generated `web_plugin_registrant.dart` file.
///
/// The [runApp] callback is invoked to run the app after the engine is fully
/// initialized.
///
/// For more information, see what the `flutter_tools` does in the entrypoint
/// that it generates around the app's main method:
///
/// * https://github.com/flutter/flutter/blob/95be76ab7e3dca2def54454313e97f94f4ac4582/packages/flutter_tools/lib/src/web/file_generators/main_dart.dart#L14-L43
///
/// By default, engine initialization and app startup occur immediately and back
/// to back. They can be programmatically controlled by setting
/// `FlutterLoader.didCreateEngineInitializer`. For more information, see how
/// `flutter.js` does it:
///
/// * https://github.com/flutter/flutter/blob/95be76ab7e3dca2def54454313e97f94f4ac4582/packages/flutter_tools/lib/src/web/file_generators/js/flutter.js
Future<void> bootstrapEngine({
ui.VoidCallback? registerPlugins,
ui.VoidCallback? runApp,
}) async {
// Create the object that knows how to bootstrap an app from JS and Dart.
final AppBootstrap bootstrap = AppBootstrap(
initializeEngine: ([JsFlutterConfiguration? configuration]) async {
await initializeEngineServices(jsConfiguration: configuration);
}, runApp: () async {
if (registerPlugins != null) {
registerPlugins();
}
await initializeEngineUi();
if (runApp != null) {
runApp();
}
},
);

final FlutterLoader? loader = flutter?.loader;
if (loader == null || loader.isAutoStart) {
// The user does not want control of the app, bootstrap immediately.
domWindow.console.debug('Flutter Web Bootstrap: Auto.');
await bootstrap.autoStart();
} else {
// Yield control of the bootstrap procedure to the user.
domWindow.console.debug('Flutter Web Bootstrap: Programmatic.');
loader.didCreateEngineInitializer(bootstrap.prepareEngineInitializer());
}
}
Loading

0 comments on commit 9a3d191

Please sign in to comment.