[web] Migrate Flutter Web DOM usage to JS static interop - 11. (#33190)
diff --git a/lib/web_ui/lib/src/engine/dom.dart b/lib/web_ui/lib/src/engine/dom.dart
index b7d94b5..c461219 100644
--- a/lib/web_ui/lib/src/engine/dom.dart
+++ b/lib/web_ui/lib/src/engine/dom.dart
@@ -15,6 +15,8 @@
/// class name with `Dom`.
/// NOTE: After the new static interop DOM API is released in the Dart SDK,
/// these classes will be replaced by typedefs.
+/// NOTE: Currently, optional parameters do not behave as expected.
+/// For the time being, avoid passing optional parameters directly to JS.
@JS()
@staticInterop
@@ -59,7 +61,9 @@
extension DomDocumentExtension on DomDocument {
external DomElement? querySelector(String selectors);
external /* List<Node> */ List<Object?> querySelectorAll(String selectors);
- external DomElement createElement(String name, [dynamic options]);
+ DomElement createElement(String name, [Object? options]) =>
+ js_util.callMethod(this, 'createElement',
+ <Object>[name, if (options != null) options]) as DomElement;
external DomHTMLScriptElement? get currentScript;
external DomElement createElementNS(
String namespaceURI, String qualifiedName);
@@ -82,10 +86,21 @@
class DomEventTarget {}
extension DomEventTargetExtension on DomEventTarget {
- external void addEventListener(String type, DomEventListener? listener,
- [bool? useCapture]);
- external void removeEventListener(String type, DomEventListener? listener,
- [bool? useCapture]);
+ void addEventListener(String type, DomEventListener? listener,
+ [bool? useCapture]) {
+ if (listener != null) {
+ js_util.callMethod(this, 'addEventListener',
+ <Object>[type, listener, if (useCapture != null) useCapture]);
+ }
+ }
+
+ void removeEventListener(String type, DomEventListener? listener,
+ [bool? useCapture]) {
+ if (listener != null) {
+ js_util.callMethod(this, 'removeEventListener',
+ <Object>[type, listener, if (useCapture != null) useCapture]);
+ }
+ }
}
typedef DomEventListener = void Function(DomEvent event);
@@ -139,6 +154,7 @@
external /* List<DomElement> */ List<Object?> get children;
external String get id;
external set id(String id);
+ external set spellcheck(bool? value);
external DomCSSStyleDeclaration get style;
external void append(DomNode node);
external String? getAttribute(String attributeName);
@@ -152,14 +168,22 @@
class DomCSSStyleDeclaration {}
extension DomCSSStyleDeclarationExtension on DomCSSStyleDeclaration {
- set width(String value) => setProperty('width', value);
- set height(String value) => setProperty('height', value);
- set position(String value) => setProperty('position', value);
- set clip(String value) => setProperty('clip', value);
- set clipPath(String value) => setProperty('clip-path', value);
- set transform(String value) => setProperty('transform', value);
- set transformOrigin(String value) => setProperty('transform-origin', value);
- set opacity(String value) => setProperty('opacity', value);
+ set width(String value) => setProperty('width', value, '');
+ set height(String value) => setProperty('height', value, '');
+ set position(String value) => setProperty('position', value, '');
+ set clip(String value) => setProperty('clip', value, '');
+ set clipPath(String value) => setProperty('clip-path', value, '');
+ set transform(String value) => setProperty('transform', value, '');
+ set transformOrigin(String value) =>
+ setProperty('transform-origin', value, '');
+ set opacity(String value) => setProperty('opacity', value, '');
+ set color(String value) => setProperty('color', value, '');
+ set top(String value) => setProperty('top', value, '');
+ set left(String value) => setProperty('left', value, '');
+ set right(String value) => setProperty('right', value, '');
+ set bottom(String value) => setProperty('bottom', value, '');
+ set backgroundColor(String value) =>
+ setProperty('background-color', value, '');
String get width => getPropertyValue('width');
String get height => getPropertyValue('height');
String get position => getPropertyValue('position');
@@ -168,10 +192,21 @@
String get transform => getPropertyValue('transform');
String get transformOrigin => getPropertyValue('transform-origin');
String get opacity => getPropertyValue('opacity');
+ String get color => getPropertyValue('color');
+ String get top => getPropertyValue('top');
+ String get left => getPropertyValue('left');
+ String get right => getPropertyValue('right');
+ String get bottom => getPropertyValue('bottom');
+ String get backgroundColor => getPropertyValue('background-color');
external String getPropertyValue(String property);
- external void setProperty(String propertyName, String value,
- [String priority]);
+ void setProperty(String propertyName, String value, [String? priority]) {
+ priority ??= '';
+ js_util.callMethod(
+ this, 'setProperty', <Object>[propertyName, value, priority]);
+ }
+
+ external String removeProperty(String property);
}
@JS()
@@ -253,7 +288,8 @@
external set width(int? value);
external int? get height;
external set height(int? value);
- external String toDataURL([String? type]);
+ String toDataURL([String? type]) =>
+ js_util.callMethod(this, 'toDataURL', <Object>[if (type != null) type]);
Object? getContext(String contextType, [Map<dynamic, dynamic>? attributes]) {
return js_util.callMethod(this, 'getContext', <Object?>[
@@ -307,7 +343,8 @@
external String get responseType;
external int? get status;
external set responseType(String value);
- external void open(String method, String url, [bool? async]);
+ void open(String method, String url, [bool? async]) => js_util.callMethod(
+ this, 'open', <Object>[method, url, if (async != null) async]);
external void send();
}
diff --git a/lib/web_ui/lib/src/engine/embedder.dart b/lib/web_ui/lib/src/engine/embedder.dart
index 9c30eb6..0116e1a 100644
--- a/lib/web_ui/lib/src/engine/embedder.dart
+++ b/lib/web_ui/lib/src/engine/embedder.dart
@@ -200,7 +200,7 @@
hasAutofillOverlay: browserHasAutofillOverlay(),
);
- final html.BodyElement bodyElement = html.document.body!;
+ final DomHTMLBodyElement bodyElement = domDocument.body!;
bodyElement.setAttribute(
'flt-renderer',
@@ -270,8 +270,8 @@
// IMPORTANT: the glass pane element must come after the scene element in the DOM node list so
// it can intercept input events.
_glassPaneElement?.remove();
- final html.Element glassPaneElement = html.document.createElement(_glassPaneTagName);
- _glassPaneElement = glassPaneElement;
+ final DomElement glassPaneElement = domDocument.createElement(_glassPaneTagName);
+ _glassPaneElement = glassPaneElement as html.Element;
glassPaneElement.style
..position = 'absolute'
..top = '0'
@@ -285,7 +285,8 @@
// Create a [HostNode] under the glass pane element, and attach everything
// there, instead of directly underneath the glass panel.
- final HostNode glassPaneElementHostNode = _createHostNode(glassPaneElement);
+ final HostNode glassPaneElementHostNode = _createHostNode(glassPaneElement
+ as html.Element);
_glassPaneShadow = glassPaneElementHostNode;
// Don't allow the scene to receive pointer events.
@@ -335,8 +336,8 @@
_sceneHostElement!.style.opacity = '0.3';
}
- PointerBinding.initInstance(glassPaneElement);
- KeyboardBinding.initInstance(glassPaneElement);
+ PointerBinding.initInstance(glassPaneElement as html.Element);
+ KeyboardBinding.initInstance(glassPaneElement as html.Element);
if (html.window.visualViewport == null && isWebKit) {
// Older Safari versions sometimes give us bogus innerWidth/innerHeight
diff --git a/lib/web_ui/lib/src/engine/html/backdrop_filter.dart b/lib/web_ui/lib/src/engine/html/backdrop_filter.dart
index 73e7d71..065f58f 100644
--- a/lib/web_ui/lib/src/engine/html/backdrop_filter.dart
+++ b/lib/web_ui/lib/src/engine/html/backdrop_filter.dart
@@ -7,6 +7,7 @@
import 'package:ui/ui.dart' as ui;
import '../browser_detection.dart';
+import '../dom.dart';
import '../util.dart';
import '../vector_math.dart';
import 'shaders/shader.dart';
@@ -25,9 +26,9 @@
/// [rootElement] is used to host child in front of [filterElement] that
/// is transformed to cover background.
@override
- html.Element? get childContainer => _childContainer;
- html.Element? _childContainer;
- html.Element? _filterElement;
+ html.Element? get childContainer => _childContainer as html.Element?;
+ DomElement? _childContainer;
+ DomElement? _filterElement;
ui.Rect? _activeClipBounds;
// Cached inverted transform for [transform].
late Matrix4 _invertedTransform;
@@ -44,18 +45,19 @@
@override
html.Element createElement() {
- final html.Element element = defaultCreateElement('flt-backdrop')
- ..style.transformOrigin = '0 0 0';
- _childContainer = html.Element.tag('flt-backdrop-interior');
+ final DomElement element = defaultCreateElement('flt-backdrop') as
+ DomElement;
+ element.style.transformOrigin = '0 0 0';
+ _childContainer = createDomElement('flt-backdrop-interior');
_childContainer!.style.position = 'absolute';
if (debugExplainSurfaceStats) {
// This creates an additional interior element. Count it too.
surfaceStatsFor(this).allocatedDomNodeCount++;
}
- _filterElement = defaultCreateElement('flt-backdrop-filter');
+ _filterElement = defaultCreateElement('flt-backdrop-filter') as DomElement;
_filterElement!.style.transformOrigin = '0 0 0';
element..append(_filterElement!)..append(_childContainer!);
- return element;
+ return element as html.Element;
}
@override
@@ -102,7 +104,7 @@
}
parentSurface = parentSurface.parent;
}
- final html.CssStyleDeclaration filterElementStyle = _filterElement!.style;
+ final DomCSSStyleDeclaration filterElementStyle = _filterElement!.style;
filterElementStyle
..position = 'absolute'
..left = '${left}px'
diff --git a/lib/web_ui/lib/src/engine/html/offset.dart b/lib/web_ui/lib/src/engine/html/offset.dart
index a23b512..ff75d47 100644
--- a/lib/web_ui/lib/src/engine/html/offset.dart
+++ b/lib/web_ui/lib/src/engine/html/offset.dart
@@ -6,6 +6,7 @@
import 'package:ui/ui.dart' as ui;
+import '../dom.dart';
import '../util.dart';
import '../vector_math.dart';
import 'surface.dart';
@@ -41,10 +42,10 @@
@override
html.Element createElement() {
- final html.Element element = html.document.createElement('flt-offset');
+ final DomElement element = domDocument.createElement('flt-offset');
setElementStyle(element, 'position', 'absolute');
setElementStyle(element, 'transform-origin', '0 0 0');
- return element;
+ return element as html.Element;
}
@override
diff --git a/lib/web_ui/lib/src/engine/html/opacity.dart b/lib/web_ui/lib/src/engine/html/opacity.dart
index 4348fc3..9fbc00b 100644
--- a/lib/web_ui/lib/src/engine/html/opacity.dart
+++ b/lib/web_ui/lib/src/engine/html/opacity.dart
@@ -6,6 +6,7 @@
import 'package:ui/ui.dart' as ui;
+import '../dom.dart';
import '../util.dart';
import '../vector_math.dart';
import 'surface.dart';
@@ -43,15 +44,15 @@
@override
html.Element createElement() {
- final html.Element element = html.document.createElement('flt-opacity');
+ final DomElement element = domDocument.createElement('flt-opacity');
setElementStyle(element, 'position', 'absolute');
setElementStyle(element, 'transform-origin', '0 0 0');
- return element;
+ return element as html.Element;
}
@override
void apply() {
- final html.Element element = rootElement!;
+ final DomElement element = rootElement! as DomElement;
setElementStyle(element, 'opacity', '${alpha / 255}');
element.style.transform = 'translate(${offset.dx}px, ${offset.dy}px)';
}
diff --git a/lib/web_ui/lib/src/engine/html/transform.dart b/lib/web_ui/lib/src/engine/html/transform.dart
index d3e1f8f..41b3d93 100644
--- a/lib/web_ui/lib/src/engine/html/transform.dart
+++ b/lib/web_ui/lib/src/engine/html/transform.dart
@@ -7,6 +7,7 @@
import 'package:ui/ui.dart' as ui;
+import '../dom.dart';
import '../util.dart';
import '../vector_math.dart';
import 'surface.dart';
@@ -42,10 +43,10 @@
@override
html.Element createElement() {
- final html.Element element = html.document.createElement('flt-transform');
+ final DomElement element = domDocument.createElement('flt-transform');
setElementStyle(element, 'position', 'absolute');
setElementStyle(element, 'transform-origin', '0 0 0');
- return element;
+ return element as html.Element;
}
@override
diff --git a/lib/web_ui/lib/src/engine/mouse_cursor.dart b/lib/web_ui/lib/src/engine/mouse_cursor.dart
index 3e5979b..1d05a24 100644
--- a/lib/web_ui/lib/src/engine/mouse_cursor.dart
+++ b/lib/web_ui/lib/src/engine/mouse_cursor.dart
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+import 'dom.dart';
import 'embedder.dart';
import 'util.dart';
@@ -67,7 +68,7 @@
void activateSystemCursor(String? kind) {
setElementStyle(
- flutterViewEmbedder.glassPaneElement!,
+ flutterViewEmbedder.glassPaneElement! as DomElement,
'cursor',
_mapKindToCssValue(kind),
);
diff --git a/lib/web_ui/lib/src/engine/text/paragraph.dart b/lib/web_ui/lib/src/engine/text/paragraph.dart
index b76328b..3316d8c 100644
--- a/lib/web_ui/lib/src/engine/text/paragraph.dart
+++ b/lib/web_ui/lib/src/engine/text/paragraph.dart
@@ -8,6 +8,7 @@
import 'package:ui/ui.dart' as ui;
import '../browser_detection.dart';
+import '../dom.dart';
import '../embedder.dart';
import '../util.dart';
import 'layout_service.dart';
@@ -743,7 +744,7 @@
if (textDecoration != null) {
if (browserEngine == BrowserEngine.webkit) {
setElementStyle(
- element, '-webkit-text-decoration', textDecoration);
+ element as DomElement, '-webkit-text-decoration', textDecoration);
} else {
cssStyle.textDecoration = textDecoration;
}
diff --git a/lib/web_ui/lib/src/engine/util.dart b/lib/web_ui/lib/src/engine/util.dart
index d2fe1c5..eb46f40 100644
--- a/lib/web_ui/lib/src/engine/util.dart
+++ b/lib/web_ui/lib/src/engine/util.dart
@@ -656,7 +656,7 @@
/// [name] is the name of the property. [value] is the value of the property.
/// If [value] is null, removes the style property.
void setElementStyle(
- html.Element element, String name, String? value) {
+ DomElement element, String name, String? value) {
if (value == null) {
element.style.removeProperty(name);
} else {
diff --git a/lib/web_ui/test/engine/util_test.dart b/lib/web_ui/test/engine/util_test.dart
index 5509919..57b2ac5 100644
--- a/lib/web_ui/test/engine/util_test.dart
+++ b/lib/web_ui/test/engine/util_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:test/bootstrap/browser.dart';
@@ -107,13 +106,13 @@
});
test('can set style properties on elements', () {
- final html.Element element = html.document.createElement('div');
+ final DomElement element = domDocument.createElement('div');
setElementStyle(element, 'color', 'red');
expect(element.style.color, 'red');
});
test('can remove style properties from elements', () {
- final html.Element element = html.document.createElement('div');
+ final DomElement element = domDocument.createElement('div');
setElementStyle(element, 'color', 'blue');
expect(element.style.color, 'blue');
setElementStyle(element, 'color', null);