Unverified Commit 95be76ab authored by Mouad Debbar's avatar Mouad Debbar Committed by GitHub

[web] Migrate framework away from dart:html and package:js (#128580)

Use `package:web` and `dart:js_interop` instead.

Part of https://github.com/flutter/flutter/issues/127030
parent 52c4db8d
...@@ -48,5 +48,6 @@ const Set<String> kCorePackageAllowList = <String>{ ...@@ -48,5 +48,6 @@ const Set<String> kCorePackageAllowList = <String>{
'test_api', 'test_api',
'vector_math', 'vector_math',
'vm_service', 'vm_service',
'web',
'webdriver', 'webdriver',
}; };
...@@ -2,11 +2,7 @@ ...@@ -2,11 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// For now, we're hiding dart:js_interop's `@JS` to avoid a conflict with import 'dart:js_interop';
// package:js' `@JS`. In the future, we should be able to remove package:js
// altogether and just import dart:js_interop.
import 'dart:js_interop' hide JS;
import 'package:js/js.dart';
// This value is set by the engine. It is used to determine if the application is // This value is set by the engine. It is used to determine if the application is
// using canvaskit. // using canvaskit.
......
...@@ -2,11 +2,7 @@ ...@@ -2,11 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// For now, we're hiding dart:js_interop's `@JS` to avoid a conflict with import 'dart:js_interop';
// package:js' `@JS`. In the future, we should be able to remove package:js
// altogether and just import dart:js_interop.
import 'dart:js_interop' hide JS;
import 'package:js/js.dart';
/// This file includes static interop helpers for Flutter Web. /// This file includes static interop helpers for Flutter Web.
// TODO(joshualitt): This file will eventually be removed, // TODO(joshualitt): This file will eventually be removed,
......
...@@ -9,10 +9,10 @@ dependencies: ...@@ -9,10 +9,10 @@ dependencies:
# To update these, use "flutter update-packages --force-upgrade". # To update these, use "flutter update-packages --force-upgrade".
characters: 1.3.0 characters: 1.3.0
collection: 1.17.2 collection: 1.17.2
js: 0.6.7
material_color_utilities: 0.5.0 material_color_utilities: 0.5.0
meta: 1.9.1 meta: 1.9.1
vector_math: 2.1.4 vector_math: 2.1.4
web: 0.1.3-beta
sky_engine: sky_engine:
sdk: flutter sdk: flutter
...@@ -72,4 +72,4 @@ dev_dependencies: ...@@ -72,4 +72,4 @@ dev_dependencies:
webkit_inspection_protocol: 1.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webkit_inspection_protocol: 1.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
yaml: 3.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 3.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
# PUBSPEC CHECKSUM: dd07 # PUBSPEC CHECKSUM: d32a
...@@ -2,14 +2,9 @@ ...@@ -2,14 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// For now, we're hiding dart:js_interop's `@JS` to avoid a conflict with import 'dart:js_interop';
// package:js' `@JS`. In the future, we should be able to remove package:js
// altogether and just import dart:js_interop.
import 'dart:js_interop' hide JS;
import 'package:flutter/src/services/dom.dart'; import 'package:flutter/src/services/dom.dart';
import 'package:js/js.dart';
import 'package:js/js_util.dart' as js_util;
/// Defines a new property on an Object. /// Defines a new property on an Object.
@JS('Object.defineProperty') @JS('Object.defineProperty')
...@@ -17,13 +12,12 @@ external JSVoid objectDefineProperty(JSAny o, JSString symbol, JSAny desc); ...@@ -17,13 +12,12 @@ external JSVoid objectDefineProperty(JSAny o, JSString symbol, JSAny desc);
void createGetter(JSAny mock, String key, JSAny? Function() get) { void createGetter(JSAny mock, String key, JSAny? Function() get) {
objectDefineProperty( objectDefineProperty(
mock, mock,
key.toJS, key.toJS,
js_util.jsify( <String, JSFunction>{
<String, Object>{ 'get': (() => get()).toJS,
'get': () { return get(); }.toJS }.jsify()!,
} );
) as JSAny);
} }
@JS() @JS()
...@@ -51,13 +45,12 @@ class TestHttpRequest { ...@@ -51,13 +45,12 @@ class TestHttpRequest {
); );
// TODO(srujzs): This is needed for when we reify JS types. Right now, JSAny // TODO(srujzs): This is needed for when we reify JS types. Right now, JSAny
// is a typedef for Object?, but when we reify, it'll be its own type. // is a typedef for Object?, but when we reify, it'll be its own type.
// ignore: unnecessary_cast
final JSAny mock = _mock as JSAny; final JSAny mock = _mock as JSAny;
createGetter(mock, 'headers', () => js_util.jsify(headers) as JSAny); createGetter(mock, 'headers', () => headers.jsify());
createGetter(mock, createGetter(mock,
'responseHeaders', () => js_util.jsify(responseHeaders) as JSAny); 'responseHeaders', () => responseHeaders.jsify());
createGetter(mock, 'status', () => status.toJS); createGetter(mock, 'status', () => status.toJS);
createGetter(mock, 'response', () => js_util.jsify(response) as JSAny); createGetter(mock, 'response', () => response.jsify());
} }
late DomXMLHttpRequestMock _mock; late DomXMLHttpRequestMock _mock;
......
...@@ -5,20 +5,36 @@ ...@@ -5,20 +5,36 @@
@TestOn('browser') // This file contains web-only library. @TestOn('browser') // This file contains web-only library.
library; library;
import 'dart:html' as html; import 'dart:js_interop';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:web/web.dart' as web;
extension on JSString {
external JSBoolean includes(JSString searchString);
}
extension on web.HTMLCollection {
Iterable<web.Element> get iterable => _genIterable(length, (JSNumber i) => item(i));
}
extension on web.CSSRuleList {
Iterable<web.CSSRule> get iterable => _genIterable(length, (JSNumber i) => item(i));
}
typedef ItemGetter<T> = T? Function(JSNumber index);
Iterable<T> _genIterable<T>(JSNumber length, ItemGetter<T> getItem) {
return Iterable<T>.generate(length.toDart.toInt(), (int index) => getItem(index.toJS)!);
}
void main() { void main() {
html.Element? element; web.HTMLElement? element;
PlatformSelectableRegionContextMenu.debugOverrideRegisterViewFactory = (String viewType, Object Function(int viewId) fn, {bool isVisible = true}) { PlatformSelectableRegionContextMenu.debugOverrideRegisterViewFactory = (String viewType, Object Function(int viewId) fn, {bool isVisible = true}) {
element = fn(0) as html.Element; element = fn(0) as web.HTMLElement;
// The element needs to be attached to the document body to receive mouse // The element needs to be attached to the document body to receive mouse
// events. // events.
html.document.body!.append(element!); web.document.body!.append(element);
}; };
// This force register the dom element. // This force register the dom element.
PlatformSelectableRegionContextMenu(child: const Placeholder()); PlatformSelectableRegionContextMenu(child: const Placeholder());
...@@ -26,19 +42,24 @@ void main() { ...@@ -26,19 +42,24 @@ void main() {
test('DOM element is set up correctly', () async { test('DOM element is set up correctly', () async {
expect(element, isNotNull); expect(element, isNotNull);
expect(element!.style.width, '100%'); expect(element!.style.width, '100%'.toJS);
expect(element!.style.height, '100%'); expect(element!.style.height, '100%'.toJS);
expect(element!.classes.length, 1); expect(element!.classList.length, 1.toJS);
final String className = element!.classes.first; final JSString className = element!.className;
expect(html.document.head!.children, isNotEmpty); expect(web.document.head!.children.iterable, isNotEmpty);
bool foundStyle = false; bool foundStyle = false;
for (final html.Element element in html.document.head!.children) { for (final web.Element element in web.document.head!.children.iterable) {
if (element is! html.StyleElement) { if (element.tagName != 'STYLE'.toJS) {
continue; continue;
} }
final html.CssStyleSheet sheet = element.sheet! as html.CssStyleSheet; final web.CSSRuleList? rules = (element as web.HTMLStyleElement).sheet?.rules;
foundStyle = sheet.rules!.any((html.CssRule rule) => rule.cssText!.contains(className)); if (rules != null) {
foundStyle = rules.iterable.any((web.CSSRule rule) => rule.cssText.includes(className).toDart);
}
if (foundStyle) {
break;
}
} }
expect(foundStyle, isTrue); expect(foundStyle, isTrue);
}); });
...@@ -62,11 +83,13 @@ void main() { ...@@ -62,11 +83,13 @@ void main() {
// Dispatch right click. // Dispatch right click.
element!.dispatchEvent( element!.dispatchEvent(
html.MouseEvent( web.MouseEvent(
'mousedown', 'mousedown'.toJS,
button: 2, web.MouseEventInit(
clientX: 200, button: 2.toJS,
clientY: 300, clientX: 200.toJS,
clientY: 300.toJS,
),
), ),
); );
final RenderSelectionSpy renderSelectionSpy = tester.renderObject<RenderSelectionSpy>(find.byKey(spy)); final RenderSelectionSpy renderSelectionSpy = tester.renderObject<RenderSelectionSpy>(find.byKey(spy));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment