Skip to content

Commit

Permalink
add support for JS types (flutter#40310)
Browse files Browse the repository at this point in the history
  • Loading branch information
joshualitt authored Mar 17, 2023
1 parent 476985a commit 59e21ff
Show file tree
Hide file tree
Showing 10 changed files with 1,803 additions and 685 deletions.
2,407 changes: 1,760 additions & 647 deletions lib/web_ui/lib/src/engine/dom.dart

Large diffs are not rendered by default.

5 changes: 2 additions & 3 deletions lib/web_ui/lib/src/engine/font_change_util.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import 'dart:typed_data';

import 'dom.dart';
import 'platform_dispatcher.dart';
import 'safe_browser_api.dart';
import 'services.dart';

final ByteData? _fontChangeMessage =
Expand All @@ -23,13 +22,13 @@ FutureOr<void> sendFontChangeMessage() async {
if (!_fontChangeScheduled) {
_fontChangeScheduled = true;
// Batch updates into next animationframe.
domWindow.requestAnimationFrame(allowInterop((num _) {
domWindow.requestAnimationFrame((_) {
_fontChangeScheduled = false;
EnginePlatformDispatcher.instance.invokeOnPlatformMessage(
'flutter/system',
_fontChangeMessage,
(_) {},
);
}));
});
}
}
7 changes: 4 additions & 3 deletions lib/web_ui/lib/src/engine/initialization.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import 'dart:async';
import 'dart:developer' as developer;
import 'dart:js_interop';

import 'package:ui/src/engine/assets.dart';
import 'package:ui/src/engine/browser_detection.dart';
Expand Down Expand Up @@ -174,7 +175,7 @@ Future<void> initializeEngineServices({
// fires.
if (!waitingForAnimation) {
waitingForAnimation = true;
domWindow.requestAnimationFrame(allowInterop((num highResTime) {
domWindow.requestAnimationFrame((JSNumber highResTime) {
frameTimingsOnVsync();

// Reset immediately, because `frameHandler` can schedule more frames.
Expand All @@ -185,7 +186,7 @@ Future<void> initializeEngineServices({
// milliseconds as a double value, with sub-millisecond information
// hidden in the fraction. So we first multiply it by 1000 to uncover
// microsecond precision, and only then convert to `int`.
final int highResTimeMicroseconds = (1000 * highResTime).toInt();
final int highResTimeMicroseconds = (1000 * highResTime.toDart).toInt();

// In Flutter terminology "building a frame" consists of "beginning
// frame" and "drawing frame".
Expand All @@ -206,7 +207,7 @@ Future<void> initializeEngineServices({
// implement it properly.
EnginePlatformDispatcher.instance.invokeOnDrawFrame();
}
}));
});
}
};

Expand Down
11 changes: 6 additions & 5 deletions lib/web_ui/lib/src/engine/platform_dispatcher.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import 'dart:async';
import 'dart:convert';
import 'dart:js_interop';
import 'dart:typed_data';

import 'package:ui/src/engine/canvaskit/renderer.dart';
Expand Down Expand Up @@ -934,17 +935,17 @@ class EnginePlatformDispatcher extends ui.PlatformDispatcher {
void _addFontSizeObserver() {
const String styleAttribute = 'style';

_fontSizeObserver = createDomMutationObserver(allowInterop(
(List<dynamic> mutations, DomMutationObserver _) {
for (final dynamic mutation in mutations) {
final DomMutationRecord record = mutation as DomMutationRecord;
_fontSizeObserver = createDomMutationObserver(
(JSArray mutations, DomMutationObserver _) {
for (final JSAny? mutation in mutations.toDart) {
final DomMutationRecord record = mutation! as DomMutationRecord;
if (record.type == 'attributes' &&
record.attributeName == styleAttribute) {
final double newTextScaleFactor = findBrowserTextScaleFactor();
_updateTextScaleFactor(newTextScaleFactor);
}
}
}));
});
_fontSizeObserver!.observe(
domDocument.documentElement!,
attributes: true,
Expand Down
7 changes: 4 additions & 3 deletions lib/web_ui/test/engine/surface/scene_builder_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
@TestOn('chrome || firefox')

import 'dart:async';
import 'dart:js_interop';
import 'dart:js_util' as js_util;

import 'package:test/bootstrap/browser.dart';
Expand Down Expand Up @@ -500,12 +501,12 @@ void testMain() {

// Watches DOM mutations and counts deletions and additions to the child
// list of the `<flt-scene>` element.
final DomMutationObserver observer = createDomMutationObserver(allowInterop((List<dynamic> mutations, _) {
for (final DomMutationRecord record in mutations.cast<DomMutationRecord>()) {
final DomMutationObserver observer = createDomMutationObserver((JSArray mutations, _) {
for (final DomMutationRecord record in mutations.toDart.cast<DomMutationRecord>()) {
actualDeletions.addAll(record.removedNodes!);
actualAdditions.addAll(record.addedNodes!);
}
}));
});
observer.observe(
SurfaceSceneBuilder.debugLastFrameScene!.rootElement!, childList: true);

Expand Down
28 changes: 14 additions & 14 deletions lib/web_ui/test/text/font_collection_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ void testMain() {
await fontManager.downloadAllFonts();
fontManager.registerDownloadedFonts();
domDocument.fonts!
.forEach(allowInterop((DomFontFace f, DomFontFace f2, DomFontFaceSet s) {
.forEach((DomFontFace f, DomFontFace f2, DomFontFaceSet s) {
fontFamilyList.add(f.family!);
}));
});

expect(fontFamilyList.length, equals(1));
expect(fontFamilyList.first, 'Ahem');
Expand All @@ -51,9 +51,9 @@ void testMain() {
await fontManager.downloadAllFonts();
fontManager.registerDownloadedFonts();
domDocument.fonts!
.forEach(allowInterop((DomFontFace f, DomFontFace f2, DomFontFaceSet s) {
.forEach((DomFontFace f, DomFontFace f2, DomFontFaceSet s) {
fontFamilyList.add(f.family!);
}));
});

expect(fontFamilyList.length, equals(1));
expect(fontFamilyList.first, 'Ahem ahem ahem');
Expand All @@ -70,9 +70,9 @@ void testMain() {
await fontManager.downloadAllFonts();
fontManager.registerDownloadedFonts();
domDocument.fonts!
.forEach(allowInterop((DomFontFace f, DomFontFace f2, DomFontFaceSet s) {
.forEach((DomFontFace f, DomFontFace f2, DomFontFaceSet s) {
fontFamilyList.add(f.family!);
}));
});

expect(fontFamilyList.length, equals(1));
expect(fontFamilyList.first, 'AhEm');
Expand All @@ -89,9 +89,9 @@ void testMain() {
await fontManager.downloadAllFonts();
fontManager.registerDownloadedFonts();
domDocument.fonts!
.forEach(allowInterop((DomFontFace f, DomFontFace f2, DomFontFaceSet s) {
.forEach((DomFontFace f, DomFontFace f2, DomFontFaceSet s) {
fontFamilyList.add(f.family!);
}));
});

if (browserEngine != BrowserEngine.firefox) {
expect(fontFamilyList.length, equals(2));
Expand All @@ -114,9 +114,9 @@ void testMain() {
await fontManager.downloadAllFonts();
fontManager.registerDownloadedFonts();
domDocument.fonts!
.forEach(allowInterop((DomFontFace f, DomFontFace f2, DomFontFaceSet s) {
.forEach((DomFontFace f, DomFontFace f2, DomFontFaceSet s) {
fontFamilyList.add(f.family!);
}));
});

if (browserEngine != BrowserEngine.firefox) {
expect(fontFamilyList.length, equals(2));
Expand All @@ -139,9 +139,9 @@ void testMain() {
await fontManager.downloadAllFonts();
fontManager.registerDownloadedFonts();
domDocument.fonts!
.forEach(allowInterop((DomFontFace f, DomFontFace f2, DomFontFaceSet s) {
.forEach((DomFontFace f, DomFontFace f2, DomFontFaceSet s) {
fontFamilyList.add(f.family!);
}));
});

if (browserEngine != BrowserEngine.firefox) {
expect(fontFamilyList.length, equals(2));
Expand All @@ -165,9 +165,9 @@ void testMain() {
await fontManager.downloadAllFonts();
fontManager.registerDownloadedFonts();
domDocument.fonts!
.forEach(allowInterop((DomFontFace f, DomFontFace f2, DomFontFaceSet s) {
.forEach((DomFontFace f, DomFontFace f2, DomFontFaceSet s) {
fontFamilyList.add(f.family!);
}));
});

if (browserEngine != BrowserEngine.firefox) {
expect(fontFamilyList.length, equals(2));
Expand Down
6 changes: 3 additions & 3 deletions lib/web_ui/test/text/font_loading_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ Future<void> testMain() async {
final ByteBuffer response = await httpFetchByteBuffer(testFontUrl);
await ui.loadFontFromList(response.asUint8List(), fontFamily: 'Blehm');
final Completer<void> completer = Completer<void>();
domWindow.requestAnimationFrame(allowInterop((_) { completer.complete();}) );
domWindow.requestAnimationFrame((_) { completer.complete();});
await completer.future;
window.onPlatformMessage = oldHandler;
expect(actualName, 'flutter/system');
Expand All @@ -94,11 +94,11 @@ Future<void> testMain() async {

bool _containsFontFamily(String family) {
bool found = false;
domDocument.fonts!.forEach(allowInterop((DomFontFace fontFace,
domDocument.fonts!.forEach((DomFontFace fontFace,
DomFontFace fontFaceAgain, DomFontFaceSet fontFaceSet) {
if (fontFace.family == family) {
found = true;
}
}));
});
return found;
}
1 change: 1 addition & 0 deletions web_sdk/sdk_rewriter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import 'dart:convert' hide Codec;
import 'dart:developer' as developer;
import 'dart:js_util' as js_util;
import 'dart:_js_annotations';
import 'dart:js_interop' hide JS;
import 'dart:math' as math;
import 'dart:typed_data';
import 'dart:ui' as ui;
Expand Down
1 change: 1 addition & 0 deletions web_sdk/test/sdk_rewriter_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import 'dart:convert' hide Codec;
import 'dart:developer' as developer;
import 'dart:js_util' as js_util;
import 'dart:_js_annotations';
import 'dart:js_interop' hide JS;
import 'dart:math' as math;
import 'dart:typed_data';
import 'dart:ui' as ui;
Expand Down
15 changes: 8 additions & 7 deletions web_sdk/web_engine_tester/lib/static/host.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ library test.host;

import 'dart:async';
import 'dart:convert';
import 'dart:js_interop';

import 'package:js/js.dart';
import 'package:stack_trace/stack_trace.dart';
Expand All @@ -22,7 +23,7 @@ import 'package:ui/src/engine/dom.dart';
class _TestRunner {}

extension _TestRunnerExtension on _TestRunner {
external void waitUntilDone();
external JSVoid waitUntilDone();
}

/// Returns the current content shell runner, or `null` if none exists.
Expand All @@ -37,19 +38,19 @@ external _TestRunner? get testRunner; // ignore: library_private_types_in_public
@anonymous
@staticInterop
class _JSApi {
external factory _JSApi({void Function() resume, void Function() restartCurrent});
external factory _JSApi({JSFunction resume, JSFunction restartCurrent});
}

extension _JSApiExtension on _JSApi {
/// Causes the test runner to resume running, as though the user had clicked
/// the "play" button.
// ignore: unused_element
external Function get resume;
external JSFunction get resume;

/// Causes the test runner to restart the current test once it finishes
/// running.
// ignore: unused_element
external Function get restartCurrent;
external JSFunction get restartCurrent;
}

/// Sets the top-level `dartTest` object so that it's visible to JS.
Expand Down Expand Up @@ -159,15 +160,15 @@ void main() {
Timer.periodic(const Duration(seconds: 1),
(_) => serverChannel.sink.add(<String, String>{'command': 'ping'}));

_jsApi = _JSApi(resume: allowInterop(() {
_jsApi = _JSApi(resume: () {
if (!domDocument.body!.classList.contains('paused')) {
return;
}
domDocument.body!.classList.remove('paused');
serverChannel.sink.add(<String, String>{'command': 'resume'});
}), restartCurrent: allowInterop(() {
}.toJS, restartCurrent: () {
serverChannel.sink.add(<String, String>{'command': 'restart'});
}));
}.toJS);
},
(dynamic error, StackTrace stackTrace) {
print('$error\n${Trace.from(stackTrace).terse}'); // ignore: avoid_print
Expand Down

0 comments on commit 59e21ff

Please sign in to comment.