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

[web] Move web-only initialization APIs to dart:ui_web #43111

Merged
merged 8 commits into from
Jun 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this something that is needed for end users, or is this only for our testing? If it's only for our engine testing, it probably should live within engine or similar, rather than be exposed to web_ui?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Never mind, this is used all over the bootstrap and the framework!)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatively, this could be hidden behind JS-interop, if we don't want it to show up in the public APIs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

debugEmulateFlutterTesterEnvironment has effect on several things including the usage of Ahem font. If users want their tests to produce real text (e.g. for screenshots), they have to disable 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