[web] Move remaining web-only APIs to dart:ui_web (flutter/engine#44516)

- Warn on `webOnlyInitializePlatform` and replace all usages with `ui_web.bootstrapEngine`.
- Remove unused `webOnlyPaintedBy` parameter.
- `webOnlyDebugPhysicalSizeOverride` => `ui_web.debugPhysicalSizeOverride`.
- `webOnlyInstantiateImageCodecFromUrl` => `ui_web.createImageCodecFromUrl`.
- `WebOnlyImageCodecChunkCallback` => `ui_web.ImageCodecChunkCallback`.
- `_webOnlyDidWarnAboutPerformanceOverlay` => `_didWarnAboutPerformanceOverlay`.
- Remove unnecessary usage of `futurize`.

Part of https://github.com/flutter/flutter/issues/126831
This commit is contained in:
Mouad Debbar
2023-08-22 15:17:16 -04:00
committed by GitHub
parent 5fa5cb698e
commit a7f0c0c789
28 changed files with 144 additions and 47 deletions

View File

@@ -2142,6 +2142,7 @@ 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/benchmarks.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/lib/ui_web/src/ui_web/images.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
@@ -4870,6 +4871,7 @@ 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/benchmarks.dart
FILE: ../../../flutter/lib/web_ui/lib/ui_web/src/ui_web/images.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

View File

@@ -31,6 +31,13 @@ part of ui;
// TODO(mdebbar): Deprecate this and remove it.
// https://github.com/flutter/flutter/issues/127395
Future<void> webOnlyInitializePlatform() async {
assert(() {
engine.printWarning(
'The webOnlyInitializePlatform API is deprecated and will be removed in a '
'future release. Please use `bootstrapEngine` from `dart:ui_web` instead.',
);
return true;
}());
await engine.initializeEngine();
}

View File

@@ -533,9 +533,22 @@ class TargetImageSize {
final int? height;
}
Future<Codec> webOnlyInstantiateImageCodecFromUrl(Uri uri,
{engine.WebOnlyImageCodecChunkCallback? chunkCallback}) =>
engine.renderer.instantiateImageCodecFromUrl(uri, chunkCallback: chunkCallback);
// TODO(mdebbar): Deprecate this and remove it.
// https://github.com/flutter/flutter/issues/127395
Future<Codec> webOnlyInstantiateImageCodecFromUrl(
Uri uri, {
ui_web.ImageCodecChunkCallback? chunkCallback,
}) {
assert(() {
engine.printWarning(
'The webOnlyInstantiateImageCodecFromUrl API is deprecated and will be '
'removed in a future release. Please use `createImageCodecFromUrl` from '
'`dart:ui_web` instead.',
);
return true;
}());
return ui_web.createImageCodecFromUrl(uri, chunkCallback: chunkCallback);
}
void decodeImageFromList(Uint8List list, ImageDecoderCallback callback) {
_decodeImageFromListAsync(list, callback);

View File

@@ -8,6 +8,7 @@ import 'dart:typed_data';
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;
/// Instantiates a [ui.Codec] backed by an `SkAnimatedImage` from Skia.
FutureOr<ui.Codec> skiaInstantiateImageCodec(Uint8List list,
@@ -159,7 +160,7 @@ const String _kNetworkImageMessage = 'Failed to load network image.';
/// Instantiates a [ui.Codec] backed by an `SkAnimatedImage` from Skia after
/// requesting from URI.
Future<ui.Codec> skiaInstantiateWebImageCodec(
String url, WebOnlyImageCodecChunkCallback? chunkCallback) async {
String url, ui_web.ImageCodecChunkCallback? chunkCallback) async {
final Uint8List list = await fetchImage(url, chunkCallback);
if (browserSupportsImageDecoder) {
return CkBrowserImageDecoder.create(data: list, debugSource: url);
@@ -169,7 +170,7 @@ Future<ui.Codec> skiaInstantiateWebImageCodec(
}
/// Sends a request to fetch image data.
Future<Uint8List> fetchImage(String url, WebOnlyImageCodecChunkCallback? chunkCallback) async {
Future<Uint8List> fetchImage(String url, ui_web.ImageCodecChunkCallback? chunkCallback) async {
try {
final HttpFetchResponse response = await httpFetch(url);
final int? contentLength = response.contentLength;
@@ -200,7 +201,7 @@ Future<Uint8List> fetchImage(String url, WebOnlyImageCodecChunkCallback? chunkCa
/// Reads the [payload] in chunks using the browser's Streams API
///
/// See: https://developer.mozilla.org/en-US/docs/Web/API/Streams_API
Future<Uint8List> readChunked(HttpFetchPayload payload, int contentLength, WebOnlyImageCodecChunkCallback chunkCallback) async {
Future<Uint8List> readChunked(HttpFetchPayload payload, int contentLength, ui_web.ImageCodecChunkCallback chunkCallback) async {
final JSUint8Array result = createUint8ArrayFromLength(contentLength);
int position = 0;
int cumulativeBytesLoaded = 0;

View File

@@ -81,7 +81,6 @@ class LayerSceneBuilder implements ui.SceneBuilder {
ui.Offset offset = ui.Offset.zero,
double width = 0.0,
double height = 0.0,
Object? webOnlyPaintedBy,
}) {
currentLayer.add(PlatformViewLayer(viewId, offset, width, height));
}

View File

@@ -209,7 +209,7 @@ class CanvasKitRenderer implements Renderer {
@override
Future<ui.Codec> instantiateImageCodecFromUrl(
Uri uri, {
WebOnlyImageCodecChunkCallback? chunkCallback
ui_web.ImageCodecChunkCallback? chunkCallback
}) => skiaInstantiateWebImageCodec(uri.toString(), chunkCallback);
@override

View File

@@ -8,6 +8,7 @@ import 'dart:typed_data';
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;
class HtmlRenderer implements Renderer {
static HtmlRenderer get instance => _instance;
@@ -176,11 +177,9 @@ class HtmlRenderer implements Renderer {
@override
Future<ui.Codec> instantiateImageCodecFromUrl(
Uri uri, {
WebOnlyImageCodecChunkCallback? chunkCallback}) {
return futurize<ui.Codec>((Callback<ui.Codec> callback) {
callback(HtmlCodec(uri.toString(), chunkCallback: chunkCallback));
return null;
});
ui_web.ImageCodecChunkCallback? chunkCallback,
}) async {
return HtmlCodec(uri.toString(), chunkCallback: chunkCallback);
}
@override

View File

@@ -329,7 +329,7 @@ class SurfaceSceneBuilder implements ui.SceneBuilder {
/// overlay or not.
///
/// We use this to avoid spamming the console with redundant warning messages.
static bool _webOnlyDidWarnAboutPerformanceOverlay = false;
static bool _didWarnAboutPerformanceOverlay = false;
void _addPerformanceOverlay(
int enabledOptions,
@@ -338,8 +338,8 @@ class SurfaceSceneBuilder implements ui.SceneBuilder {
double top,
double bottom,
) {
if (!_webOnlyDidWarnAboutPerformanceOverlay) {
_webOnlyDidWarnAboutPerformanceOverlay = true;
if (!_didWarnAboutPerformanceOverlay) {
_didWarnAboutPerformanceOverlay = true;
printWarning("The performance overlay isn't supported on the web");
}
}

View File

@@ -6,6 +6,7 @@ import 'dart:async';
import 'dart:typed_data';
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';
@@ -20,14 +21,15 @@ Object? get _jsImageDecodeFunction => getJsProperty<Object?>(
);
final bool _supportsDecode = _jsImageDecodeFunction != null;
typedef WebOnlyImageCodecChunkCallback = void Function(
int cumulativeBytesLoaded, int expectedTotalBytes);
// TODO(mdebbar): Deprecate this and remove it.
// https://github.com/flutter/flutter/issues/127395
typedef WebOnlyImageCodecChunkCallback = ui_web.ImageCodecChunkCallback;
class HtmlCodec implements ui.Codec {
HtmlCodec(this.src, {this.chunkCallback});
final String src;
final WebOnlyImageCodecChunkCallback? chunkCallback;
final ui_web.ImageCodecChunkCallback? chunkCallback;
@override
int get frameCount => 1;

View File

@@ -8,6 +8,7 @@ import 'dart:typed_data';
import 'package:ui/src/engine/skwasm/skwasm_stub.dart' if (dart.library.ffi) 'package:ui/src/engine/skwasm/skwasm_impl.dart';
import 'package:ui/ui.dart' as ui;
import 'package:ui/ui_web/src/ui_web.dart' as ui_web;
import 'browser_detection.dart';
import 'canvaskit/renderer.dart';
@@ -15,7 +16,6 @@ import 'configuration.dart';
import 'embedder.dart';
import 'fonts.dart';
import 'html/renderer.dart';
import 'html_image_codec.dart';
final Renderer _renderer = Renderer._internal();
Renderer get renderer => _renderer;
@@ -131,7 +131,7 @@ abstract class Renderer {
Future<ui.Codec> instantiateImageCodecFromUrl(
Uri uri, {
WebOnlyImageCodecChunkCallback? chunkCallback,
ui_web.ImageCodecChunkCallback? chunkCallback,
});
void decodeImageFromPixels(

View File

@@ -389,7 +389,7 @@ class SkwasmRenderer implements Renderer {
@override
Future<ui.Codec> instantiateImageCodecFromUrl(
Uri uri, {
WebOnlyImageCodecChunkCallback? chunkCallback
ui_web.ImageCodecChunkCallback? chunkCallback
}) async {
final DomResponse response = await rawHttpGet(uri.toString());
final String? contentType = response.headers.get('Content-Type');

View File

@@ -145,7 +145,7 @@ class SkwasmRenderer implements Renderer {
}
@override
Future<ui.Codec> instantiateImageCodecFromUrl(Uri uri, {WebOnlyImageCodecChunkCallback? chunkCallback}) {
Future<ui.Codec> instantiateImageCodecFromUrl(Uri uri, {ui_web.ImageCodecChunkCallback? chunkCallback}) {
throw UnimplementedError('Skwasm not implemented on this platform.');
}

View File

@@ -255,8 +255,8 @@ class EngineFlutterWindow extends ui.SingletonFlutterWindow {
bool override = false;
assert(() {
if (webOnlyDebugPhysicalSizeOverride != null) {
_physicalSize = webOnlyDebugPhysicalSizeOverride;
if (debugPhysicalSizeOverride != null) {
_physicalSize = debugPhysicalSizeOverride;
override = true;
}
return true;
@@ -319,8 +319,37 @@ class EngineFlutterWindow extends ui.SingletonFlutterWindow {
/// Lazily populated and cleared at the end of the frame.
ui.Size? _physicalSize;
/// Overrides the value of [physicalSize] in tests.
ui.Size? webOnlyDebugPhysicalSizeOverride;
// TODO(mdebbar): Deprecate this and remove it.
// https://github.com/flutter/flutter/issues/127395
ui.Size? get webOnlyDebugPhysicalSizeOverride {
assert(() {
printWarning(
'The webOnlyDebugPhysicalSizeOverride API is deprecated and will be '
'removed in a future release. Please use '
'`SingletonFlutterWindow.debugPhysicalSizeOverride` from `dart:ui_web` '
'instead.',
);
return true;
}());
return debugPhysicalSizeOverride;
}
// TODO(mdebbar): Deprecate this and remove it.
// https://github.com/flutter/flutter/issues/127395
set webOnlyDebugPhysicalSizeOverride(ui.Size? value) {
assert(() {
printWarning(
'The webOnlyDebugPhysicalSizeOverride API is deprecated and will be '
'removed in a future release. Please use '
'`SingletonFlutterWindow.debugPhysicalSizeOverride` from `dart:ui_web` '
'instead.',
);
return true;
}());
debugPhysicalSizeOverride = value;
}
ui.Size? debugPhysicalSizeOverride;
}
/// The Web implementation of [ui.SingletonFlutterWindow].
@@ -336,7 +365,7 @@ class EngineSingletonFlutterWindow extends EngineFlutterWindow {
/// Overrides the default device pixel ratio.
///
/// This is useful in tests to emulate screens of different dimensions.
void debugOverrideDevicePixelRatio(double value) {
void debugOverrideDevicePixelRatio(double? value) {
_debugDevicePixelRatio = value;
}

View File

@@ -10,6 +10,7 @@ library ui_web;
export 'ui_web/asset_manager.dart';
export 'ui_web/benchmarks.dart';
export 'ui_web/images.dart';
export 'ui_web/initialization.dart';
export 'ui_web/navigation/platform_location.dart';
export 'ui_web/navigation/url_strategy.dart';

View File

@@ -0,0 +1,27 @@
// 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;
/// Signature of the callback that receives progress updates as image chunks are
/// loaded.
typedef ImageCodecChunkCallback = void Function(
int cumulativeBytesLoaded,
int expectedTotalBytes,
);
/// Creates a [ui.Codec] for the image located at [uri].
///
/// The [chunkCallback] is called with progress updates as image chunks are
/// loaded.
Future<ui.Codec> createImageCodecFromUrl(
Uri uri, {
ImageCodecChunkCallback? chunkCallback,
}) {
return renderer.instantiateImageCodecFromUrl(
uri,
chunkCallback: chunkCallback,
);
}

View File

@@ -5,6 +5,18 @@
import 'package:ui/src/engine.dart';
import 'package:ui/ui.dart' as ui;
extension SingletonFlutterWindowExtension on ui.SingletonFlutterWindow {
/// Overrides the value of [physicalSize] in tests.
set debugPhysicalSizeOverride(ui.Size? value) {
(this as EngineFlutterWindow).debugPhysicalSizeOverride = value;
}
}
/// Overrides the value of [ui.FlutterView.devicePixelRatio] in tests.
void debugOverrideDevicePixelRatio(double? value) {
(ui.window as EngineSingletonFlutterWindow).debugOverrideDevicePixelRatio(value);
}
/// Whether the Flutter engine is running in `flutter test` emulation mode.
///
/// When true, the engine will emulate a specific screen size, and always
@@ -18,8 +30,7 @@ set debugEmulateFlutterTesterEnvironment(bool value) {
_debugEmulateFlutterTesterEnvironment = value;
if (_debugEmulateFlutterTesterEnvironment) {
const ui.Size logicalSize = ui.Size(800.0, 600.0);
window.webOnlyDebugPhysicalSizeOverride =
logicalSize * window.devicePixelRatio;
window.debugPhysicalSizeOverride = logicalSize * window.devicePixelRatio;
}
debugDisableFontFallbacks = value;
}

View File

@@ -644,7 +644,7 @@ void testMain() {
sb.addPicture(ui.Offset.zero, picture);
sb.addPlatformView(0, width: 10, height: 10);
window.webOnlyDebugPhysicalSizeOverride = const ui.Size(100, 100);
window.debugPhysicalSizeOverride = const ui.Size(100, 100);
window.debugForceResize();
CanvasKitRenderer.instance.rasterizer.draw(sb.build().layerTree);
_expectSceneMatches(<_EmbeddedViewMarker>[
@@ -653,7 +653,7 @@ void testMain() {
_overlay,
]);
window.webOnlyDebugPhysicalSizeOverride = const ui.Size(200, 200);
window.debugPhysicalSizeOverride = const ui.Size(200, 200);
window.debugForceResize();
CanvasKitRenderer.instance.rasterizer.draw(sb.build().layerTree);
_expectSceneMatches(<_EmbeddedViewMarker>[
@@ -662,7 +662,7 @@ void testMain() {
_overlay,
]);
window.webOnlyDebugPhysicalSizeOverride = null;
window.debugPhysicalSizeOverride = null;
window.debugForceResize();
// ImageDecoder is not supported in Safari or Firefox.
}, skip: isSafari || isFirefox);

View File

@@ -10,6 +10,7 @@ import 'package:test/test.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;
void main() {
internalBootstrapBrowserTest(() => testMain);
@@ -182,7 +183,7 @@ const String kJsonIPLR = r'''
void testMain() {
setUpAll(() async {
await ui.webOnlyInitializePlatform();
await ui_web.bootstrapEngine();
});
test('FragmentProgram can be created from JSON IPLR bundle', () {

View File

@@ -7,6 +7,7 @@ import 'package:test/test.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;
void main() {
internalBootstrapBrowserTest(() => testMain);
@@ -15,7 +16,7 @@ void main() {
void testMain() {
group('$LayerScene', () {
setUpAll(() async {
await ui.webOnlyInitializePlatform();
await ui_web.bootstrapEngine();
});
test('toImage returns an image', () async {

View File

@@ -32,7 +32,7 @@ void setUpUnitTests({
// this stuff in.
const double devicePixelRatio = 3.0;
engine.window.debugOverrideDevicePixelRatio(devicePixelRatio);
engine.window.webOnlyDebugPhysicalSizeOverride =
engine.window.debugPhysicalSizeOverride =
const ui.Size(800 * devicePixelRatio, 600 * devicePixelRatio);
engine.scheduleFrameCallback = () {};
}

View File

@@ -8,14 +8,14 @@ import 'dart:typed_data';
import 'package:test/bootstrap/browser.dart';
import 'package:test/test.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;
void main() {
internalBootstrapBrowserTest(() => testMain);
}
Future<void> testMain() async {
await ui.webOnlyInitializePlatform();
await ui_web.bootstrapEngine();
// Test successful HTTP roundtrips where the server returns a happy status
// code and a payload.

View File

@@ -9,6 +9,7 @@ import 'package:test/bootstrap/browser.dart';
import 'package:test/test.dart';
import 'package:ui/src/engine/html_image_codec.dart';
import 'package:ui/ui.dart' as ui;
import 'package:ui/ui_web/src/ui_web.dart' as ui_web;
import '../../common/test_initialization.dart';
@@ -104,7 +105,7 @@ Future<void> testMain() async {
group('ImageCodecUrl', () {
test('loads sample image from web', () async {
final Uri uri = Uri.base.resolve('sample_image1.png');
final HtmlCodec codec = await ui.webOnlyInstantiateImageCodecFromUrl(uri) as HtmlCodec;
final HtmlCodec codec = await ui_web.createImageCodecFromUrl(uri) as HtmlCodec;
final ui.FrameInfo frameInfo = await codec.getNextFrame();
expect(frameInfo.image, isNotNull);
expect(frameInfo.image.width, 100);
@@ -112,7 +113,7 @@ Future<void> testMain() async {
test('provides image loading progress from web', () async {
final Uri uri = Uri.base.resolve('sample_image1.png');
final StringBuffer buffer = StringBuffer();
final HtmlCodec codec = await ui.webOnlyInstantiateImageCodecFromUrl(uri,
final HtmlCodec codec = await ui_web.createImageCodecFromUrl(uri,
chunkCallback: (int loaded, int total) {
buffer.write('$loaded/$total,');
}) as HtmlCodec;

View File

@@ -29,7 +29,7 @@ void main() {
}
Future<void> testMain() async {
await ui.webOnlyInitializePlatform();
await ui_web.bootstrapEngine();
runSemanticsTests();
}

View File

@@ -20,7 +20,7 @@ void main() {
}
Future<void> testMain() async {
await ui.webOnlyInitializePlatform();
await ui_web.bootstrapEngine();
late PersistedPlatformView view;

View File

@@ -13,6 +13,7 @@ import 'package:test/bootstrap/browser.dart';
import 'package:test/test.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;
import '../../common/matchers.dart';
@@ -22,7 +23,7 @@ void main() {
void testMain() {
setUpAll(() async {
await ui.webOnlyInitializePlatform();
await ui_web.bootstrapEngine();
});
group('SceneBuilder', () {

View File

@@ -5,7 +5,7 @@
import 'package:test/bootstrap/browser.dart';
import 'package:test/test.dart';
import 'package:ui/src/engine.dart';
import 'package:ui/ui.dart' hide window;
import 'package:ui/ui_web/src/ui_web.dart' as ui_web;
void main() {
internalBootstrapBrowserTest(() => testMain);
@@ -24,7 +24,7 @@ void testMain() {
')';
setUpAll(() async {
await webOnlyInitializePlatform();
await ui_web.bootstrapEngine();
});
group('Shader Declarations', () {

View File

@@ -6,6 +6,7 @@ import 'package:test/bootstrap/browser.dart';
import 'package:test/test.dart';
import 'package:ui/src/engine.dart';
import 'package:ui/ui.dart';
import 'package:ui/ui_web/src/ui_web.dart' as ui_web;
void main() {
internalBootstrapBrowserTest(() => testMain);
@@ -14,7 +15,7 @@ void main() {
void testMain() {
group('Surface', () {
setUpAll(() async {
await webOnlyInitializePlatform();
await ui_web.bootstrapEngine();
});
setUp(() {

View File

@@ -10,6 +10,7 @@ import 'package:test/bootstrap/browser.dart';
import 'package:test/test.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;
const int kPhysicalKeyA = 0x00070004;
const int kLogicalKeyA = 0x00000000061;
@@ -19,7 +20,7 @@ void main() {
}
Future<void> testMain() async {
await ui.webOnlyInitializePlatform();
await ui_web.bootstrapEngine();
test('onTextScaleFactorChanged preserves the zone', () {
final Zone innerZone = Zone.current.fork();