add support for JS types (flutter/engine#40310)

This commit is contained in:
joshualitt
2023-03-17 08:27:53 -07:00
committed by GitHub
parent ca850c0c80
commit be4da063e8
10 changed files with 1804 additions and 686 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -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 =
@@ -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,
(_) {},
);
}));
});
}
}

View File

@@ -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';
@@ -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.
@@ -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".
@@ -206,7 +207,7 @@ Future<void> initializeEngineServices({
// implement it properly.
EnginePlatformDispatcher.instance.invokeOnDrawFrame();
}
}));
});
}
};

View File

@@ -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';
@@ -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,

View File

@@ -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';
@@ -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);

View File

@@ -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');
@@ -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');
@@ -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');
@@ -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));
@@ -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));
@@ -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));
@@ -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));

View File

@@ -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');
@@ -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;
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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';
@@ -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.
@@ -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.
@@ -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