[web] Migrate Flutter Web DOM usage to JS static interop - 38. (#33374)
diff --git a/lib/web_ui/lib/initialization.dart b/lib/web_ui/lib/initialization.dart
index 75f1f24..8ee067b 100644
--- a/lib/web_ui/lib/initialization.dart
+++ b/lib/web_ui/lib/initialization.dart
@@ -4,6 +4,8 @@
// TODO(yjbanov): rename this file to web_only_api.dart.
// https://github.com/flutter/flutter/issues/100394
+// Rather than extending this file with new APIs, we
+// should instead use js interop.
// This file contains extra web-only API that non-web engines do not have.
//
@@ -129,13 +131,13 @@
engine.pluginMessageCallHandler = handler;
}
-/// A function which takes a unique `id` and creates an HTML element.
-typedef PlatformViewFactory = html.Element Function(int viewId);
-
/// A registry for factories that create platform views.
class PlatformViewRegistry {
- /// Register [viewTypeId] as being creating by the given [factory].
- bool registerViewFactory(String viewTypeId, PlatformViewFactory viewFactory,
+ /// Register [viewTypeId] as being creating by the given [viewFactory].
+ /// [viewFactory] can be any function that takes an integer and returns an
+ /// `HTMLElement` DOM object.
+ bool registerViewFactory(String viewTypeId,
+ Object Function(int viewId) viewFactory,
{bool isVisible = true}) {
// TODO(web): Deprecate this once there's another way of calling `registerFactory` (js interop?)
return engine.platformViewManager
diff --git a/lib/web_ui/lib/src/engine/browser_detection.dart b/lib/web_ui/lib/src/engine/browser_detection.dart
index 59dc018..8718be3 100644
--- a/lib/web_ui/lib/src/engine/browser_detection.dart
+++ b/lib/web_ui/lib/src/engine/browser_detection.dart
@@ -185,7 +185,7 @@
return OperatingSystem.iOs;
} else if (userAgent.contains('Android')) {
// The Android OS reports itself as "Linux armv8l" in
- // [html.window.navigator.platform]. So we have to check the user-agent to
+ // [domWindow.navigator.platform]. So we have to check the user-agent to
// determine if the OS is Android or not.
return OperatingSystem.android;
} else if (platform.startsWith('Linux')) {
diff --git a/lib/web_ui/lib/src/engine/dom.dart b/lib/web_ui/lib/src/engine/dom.dart
index 88dcd3e..4775a89 100644
--- a/lib/web_ui/lib/src/engine/dom.dart
+++ b/lib/web_ui/lib/src/engine/dom.dart
@@ -47,8 +47,11 @@
if (pseudoElt != null) pseudoElt
]) as DomCSSStyleDeclaration;
external DomScreen? get screen;
+ external int requestAnimationFrame(DomRequestAnimationFrameCallback callback);
}
+typedef DomRequestAnimationFrameCallback = void Function(num highResTime);
+
@JS()
@staticInterop
class DomConsole {}
diff --git a/lib/web_ui/lib/src/engine/embedder.dart b/lib/web_ui/lib/src/engine/embedder.dart
index 0aa7f84..a343133 100644
--- a/lib/web_ui/lib/src/engine/embedder.dart
+++ b/lib/web_ui/lib/src/engine/embedder.dart
@@ -345,7 +345,7 @@
//
// VisualViewport API is not enabled in Firefox as well. On the other hand
// Firefox returns correct values for innerHeight, innerWidth.
- // Firefox also triggers html.window.onResize therefore this timer does
+ // Firefox also triggers domWindow.onResize therefore this timer does
// not need to be set up for Firefox.
final int initialInnerWidth = domWindow.innerWidth!;
// Counts how many times screen size was checked. It is checked up to 5
@@ -539,7 +539,7 @@
String get currentHtml => _rootApplicationElement?.outerHTML ?? '';
}
-// Applies the required global CSS to an incoming [html.CssStyleSheet] `sheet`.
+// Applies the required global CSS to an incoming [DomCSSStyleSheet] `sheet`.
void applyGlobalCssRulesToSheet(
DomCSSStyleSheet sheet, {
required BrowserEngine browserEngine,
diff --git a/lib/web_ui/lib/src/engine/font_change_util.dart b/lib/web_ui/lib/src/engine/font_change_util.dart
index 14cfcf0..c4b8767 100644
--- a/lib/web_ui/lib/src/engine/font_change_util.dart
+++ b/lib/web_ui/lib/src/engine/font_change_util.dart
@@ -3,10 +3,11 @@
// found in the LICENSE file.
import 'dart:async';
-import 'dart:html' as html;
import 'dart:typed_data';
+import 'dom.dart';
import 'platform_dispatcher.dart';
+import 'safe_browser_api.dart';
import 'services.dart';
final ByteData? _fontChangeMessage =
@@ -22,13 +23,13 @@
if (!_fontChangeScheduled) {
_fontChangeScheduled = true;
// Batch updates into next animationframe.
- html.window.requestAnimationFrame((num _) {
+ domWindow.requestAnimationFrame(allowInterop((num _) {
_fontChangeScheduled = false;
EnginePlatformDispatcher.instance.invokeOnPlatformMessage(
'flutter/system',
_fontChangeMessage,
(_) {},
);
- });
+ }));
}
}
diff --git a/lib/web_ui/lib/src/engine/initialization.dart b/lib/web_ui/lib/src/engine/initialization.dart
index f1210d8..71da02a 100644
--- a/lib/web_ui/lib/src/engine/initialization.dart
+++ b/lib/web_ui/lib/src/engine/initialization.dart
@@ -4,7 +4,6 @@
import 'dart:async';
import 'dart:developer' as developer;
-import 'dart:html' as html;
import 'package:ui/src/engine/assets.dart';
import 'package:ui/src/engine/browser_detection.dart';
@@ -22,6 +21,8 @@
import 'package:ui/src/engine/window.dart';
import 'package:ui/ui.dart' as ui;
+import 'dom.dart';
+
/// The mode the app is running in.
/// Keep these in sync with the same constants on the framework-side under foundation/constants.dart.
const bool kReleaseMode =
@@ -178,7 +179,7 @@
// fires.
if (!waitingForAnimation) {
waitingForAnimation = true;
- html.window.requestAnimationFrame((num highResTime) {
+ domWindow.requestAnimationFrame(allowInterop((num highResTime) {
frameTimingsOnVsync();
// Reset immediately, because `frameHandler` can schedule more frames.
@@ -210,7 +211,7 @@
// implement it properly.
EnginePlatformDispatcher.instance.invokeOnDrawFrame();
}
- });
+ }));
}
};
diff --git a/lib/web_ui/lib/src/engine/safe_browser_api.dart b/lib/web_ui/lib/src/engine/safe_browser_api.dart
index b2b29a4..3b918a1 100644
--- a/lib/web_ui/lib/src/engine/safe_browser_api.dart
+++ b/lib/web_ui/lib/src/engine/safe_browser_api.dart
@@ -64,7 +64,7 @@
'Attempted to set property "$name" on a JavaScript object. This property '
'has not been checked for safety. Possible solutions to this problem:\n'
' - Do not set this property.\n'
- ' - Use a `dart:html` API that does the same thing.\n'
+ ' - Use a `js_util` API that does the same thing.\n'
' - Ensure that the property is safe then add it to _safeJsProperties set.',
);
return js_util.setProperty<T>(object, name, value);
diff --git a/lib/web_ui/lib/ui.dart b/lib/web_ui/lib/ui.dart
index baa2a5c..a01d539 100644
--- a/lib/web_ui/lib/ui.dart
+++ b/lib/web_ui/lib/ui.dart
@@ -10,7 +10,6 @@
import 'dart:async';
import 'dart:collection' as collection;
import 'dart:convert';
-import 'dart:html' as html;
import 'dart:math' as math;
import 'dart:typed_data';
diff --git a/lib/web_ui/test/canvaskit/embedded_views_test.dart b/lib/web_ui/test/canvaskit/embedded_views_test.dart
index 30b332f..2a796d3 100644
--- a/lib/web_ui/test/canvaskit/embedded_views_test.dart
+++ b/lib/web_ui/test/canvaskit/embedded_views_test.dart
@@ -27,7 +27,7 @@
test('embeds interactive platform views', () async {
ui.platformViewRegistry.registerViewFactory(
'test-platform-view',
- (int viewId) => html.DivElement()..id = 'view-0',
+ (int viewId) => createDomHTMLDivElement()..id = 'view-0',
);
await createPlatformView(0, 'test-platform-view');
@@ -63,7 +63,7 @@
test('clips platform views with RRects', () async {
ui.platformViewRegistry.registerViewFactory(
'test-platform-view',
- (int viewId) => html.DivElement()..id = 'view-0',
+ (int viewId) => createDomHTMLDivElement()..id = 'view-0',
);
await createPlatformView(0, 'test-platform-view');
@@ -103,7 +103,7 @@
test('correctly transforms platform views', () async {
ui.platformViewRegistry.registerViewFactory(
'test-platform-view',
- (int viewId) => html.DivElement()..id = 'view-0',
+ (int viewId) => createDomHTMLDivElement()..id = 'view-0',
);
await createPlatformView(0, 'test-platform-view');
@@ -135,7 +135,7 @@
test('correctly offsets platform views', () async {
ui.platformViewRegistry.registerViewFactory(
'test-platform-view',
- (int viewId) => html.DivElement()..id = 'view-0',
+ (int viewId) => createDomHTMLDivElement()..id = 'view-0',
);
await createPlatformView(0, 'test-platform-view');
@@ -175,7 +175,7 @@
test('correctly offsets when clip chain length is changed', () async {
ui.platformViewRegistry.registerViewFactory(
'test-platform-view',
- (int viewId) => html.DivElement()..id = 'view-0',
+ (int viewId) => createDomHTMLDivElement()..id = 'view-0',
);
await createPlatformView(0, 'test-platform-view');
@@ -228,7 +228,7 @@
window.debugOverrideDevicePixelRatio(4);
ui.platformViewRegistry.registerViewFactory(
'test-platform-view',
- (int viewId) => html.DivElement()..id = 'view-0',
+ (int viewId) => createDomHTMLDivElement()..id = 'view-0',
);
await createPlatformView(0, 'test-platform-view');
@@ -255,7 +255,7 @@
window.debugOverrideDevicePixelRatio(4);
ui.platformViewRegistry.registerViewFactory(
'test-platform-view',
- (int viewId) => html.DivElement()..id = 'view-0',
+ (int viewId) => createDomHTMLDivElement()..id = 'view-0',
);
await createPlatformView(0, 'test-platform-view');
@@ -297,7 +297,7 @@
for (int i = 0; i < 16; i++) {
ui.platformViewRegistry.registerViewFactory(
'test-platform-view',
- (int viewId) => html.DivElement()..id = 'view-$i',
+ (int viewId) => createDomHTMLDivElement()..id = 'view-$i',
);
await createPlatformView(i, 'test-platform-view');
platformViewIds.add(i);
@@ -453,7 +453,7 @@
for (int i = 0; i < 20; i++) {
ui.platformViewRegistry.registerViewFactory(
'test-platform-view',
- (int viewId) => html.DivElement()..id = 'view-$i',
+ (int viewId) => createDomHTMLDivElement()..id = 'view-$i',
);
await createPlatformView(i, 'test-platform-view');
platformViewIds.add(i);
@@ -583,7 +583,7 @@
test('embeds and disposes of a platform view', () async {
ui.platformViewRegistry.registerViewFactory(
'test-platform-view',
- (int viewId) => html.DivElement()..id = 'view-0',
+ (int viewId) => createDomHTMLDivElement()..id = 'view-0',
);
await createPlatformView(0, 'test-platform-view');
@@ -626,7 +626,7 @@
test('removed the DOM node of an unrendered platform view', () async {
ui.platformViewRegistry.registerViewFactory(
'test-platform-view',
- (int viewId) => html.DivElement()..id = 'view-0',
+ (int viewId) => createDomHTMLDivElement()..id = 'view-0',
);
await createPlatformView(0, 'test-platform-view');
@@ -688,7 +688,7 @@
() async {
ui.platformViewRegistry.registerViewFactory(
'test-platform-view',
- (int viewId) => html.DivElement()..id = 'test-view',
+ (int viewId) => createDomHTMLDivElement()..id = 'test-view',
);
await createPlatformView(0, 'test-platform-view');
@@ -725,7 +725,7 @@
() async {
ui.platformViewRegistry.registerViewFactory(
'test-platform-view',
- (int viewId) => html.DivElement()..id = 'view-0',
+ (int viewId) => createDomHTMLDivElement()..id = 'view-0',
);
await createPlatformView(0, 'test-platform-view');
@@ -748,7 +748,7 @@
HtmlViewEmbedder.debugDisableOverlays = true;
ui.platformViewRegistry.registerViewFactory(
'test-platform-view',
- (int viewId) => html.DivElement()..id = 'view-0',
+ (int viewId) => createDomHTMLDivElement()..id = 'view-0',
);
await createPlatformView(0, 'test-platform-view');
@@ -778,7 +778,7 @@
ui.platformViewRegistry.registerViewFactory(
'test-platform-view',
- (int viewId) => html.DivElement()..id = 'view-0',
+ (int viewId) => createDomHTMLDivElement()..id = 'view-0',
);
await createPlatformView(0, 'test-platform-view');
await createPlatformView(1, 'test-platform-view');
@@ -824,7 +824,7 @@
HtmlViewEmbedder.debugDisableOverlays = true;
ui.platformViewRegistry.registerViewFactory(
'test-platform-view',
- (int viewId) => html.DivElement()..id = 'view-0',
+ (int viewId) => createDomHTMLDivElement()..id = 'view-0',
);
await createPlatformView(0, 'test-platform-view');
await createPlatformView(1, 'test-platform-view');
@@ -863,11 +863,11 @@
ui.platformViewRegistry.registerViewFactory(
'test-visible-view',
(int viewId) =>
- html.DivElement()..className = 'visible-platform-view');
+ createDomHTMLDivElement()..className = 'visible-platform-view');
ui.platformViewRegistry.registerViewFactory(
'test-invisible-view',
(int viewId) =>
- html.DivElement()..className = 'invisible-platform-view',
+ createDomHTMLDivElement()..className = 'invisible-platform-view',
isVisible: false,
);
await createPlatformView(0, 'test-visible-view');
diff --git a/lib/web_ui/test/canvaskit/image_golden_test.dart b/lib/web_ui/test/canvaskit/image_golden_test.dart
index ca4626f..06cb0ff 100644
--- a/lib/web_ui/test/canvaskit/image_golden_test.dart
+++ b/lib/web_ui/test/canvaskit/image_golden_test.dart
@@ -3,7 +3,6 @@
// found in the LICENSE file.
import 'dart:async';
-import 'dart:html' as html;
import 'dart:typed_data';
import 'package:js/js.dart';
@@ -533,7 +532,7 @@
test('the same image can be rendered on difference surfaces', () async {
ui.platformViewRegistry.registerViewFactory(
'test-platform-view',
- (int viewId) => html.DivElement()..id = 'view-0',
+ (int viewId) => createDomHTMLDivElement()..id = 'view-0',
);
await createPlatformView(0, 'test-platform-view');
diff --git a/lib/web_ui/test/engine/semantics/semantics_test.dart b/lib/web_ui/test/engine/semantics/semantics_test.dart
index 972d24e..2a8eb8e 100644
--- a/lib/web_ui/test/engine/semantics/semantics_test.dart
+++ b/lib/web_ui/test/engine/semantics/semantics_test.dart
@@ -1806,7 +1806,7 @@
ui.platformViewRegistry.registerViewFactory(
'test-platform-view',
- (int viewId) => html.DivElement()
+ (int viewId) => createDomHTMLDivElement()
..id = 'view-0'
..style.width = '100%'
..style.height = '100%',
diff --git a/lib/web_ui/test/engine/surface/platform_view_test.dart b/lib/web_ui/test/engine/surface/platform_view_test.dart
index 9c763a4..86c506a 100644
--- a/lib/web_ui/test/engine/surface/platform_view_test.dart
+++ b/lib/web_ui/test/engine/surface/platform_view_test.dart
@@ -3,7 +3,6 @@
// found in the LICENSE file.
import 'dart:async';
-import 'dart:html' as html;
import 'package:test/bootstrap/browser.dart';
import 'package:test/test.dart';
@@ -28,11 +27,11 @@
setUp(() async {
platformViewRegistry.registerViewFactory(
'test-0',
- (int viewId) => html.DivElement(),
+ (int viewId) => createDomHTMLDivElement(),
);
platformViewRegistry.registerViewFactory(
'test-1',
- (int viewId) => html.DivElement(),
+ (int viewId) => createDomHTMLDivElement(),
);
// Ensure the views are created...
await Future.wait(<Future<void>>[