mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
[web] Migrate EventListener's to JS types. (flutter/engine#40566)
This commit is contained in:
parent
cfb2ed4e06
commit
bee9f91790
@ -3915,8 +3915,8 @@ Future<bool> _downloadCanvasKitJs(String url) {
|
||||
canvasKitLoadCompleter.complete(false);
|
||||
}
|
||||
|
||||
loadCallback = allowInterop(loadEventHandler);
|
||||
errorCallback = allowInterop(errorEventHandler);
|
||||
loadCallback = createDomEventListener(loadEventHandler);
|
||||
errorCallback = createDomEventListener(errorEventHandler);
|
||||
|
||||
canvasKitScript.addEventListener('load', loadCallback);
|
||||
canvasKitScript.addEventListener('error', errorCallback);
|
||||
|
||||
@ -2,13 +2,14 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:js_interop';
|
||||
|
||||
import 'package:ui/ui.dart' as ui;
|
||||
|
||||
import '../browser_detection.dart';
|
||||
import '../configuration.dart';
|
||||
import '../dom.dart';
|
||||
import '../platform_dispatcher.dart';
|
||||
import '../safe_browser_api.dart';
|
||||
import '../util.dart';
|
||||
import '../window.dart';
|
||||
import 'canvas.dart';
|
||||
@ -67,7 +68,7 @@ class Surface {
|
||||
/// We must cache this function because each time we access the tear-off it
|
||||
/// creates a new object, meaning we won't be able to remove this listener
|
||||
/// later.
|
||||
void Function(DomEvent)? _cachedContextLostListener;
|
||||
DomEventListener? _cachedContextLostListener;
|
||||
|
||||
/// A cached copy of the most recently created `webglcontextrestored`
|
||||
/// listener.
|
||||
@ -75,7 +76,7 @@ class Surface {
|
||||
/// We must cache this function because each time we access the tear-off it
|
||||
/// creates a new object, meaning we won't be able to remove this listener
|
||||
/// later.
|
||||
void Function(DomEvent)? _cachedContextRestoredListener;
|
||||
DomEventListener? _cachedContextRestoredListener;
|
||||
|
||||
SkGrContext? _grContext;
|
||||
int? _glContext;
|
||||
@ -268,7 +269,7 @@ class Surface {
|
||||
htmlCanvas!.style.transform = 'translate(0, -${offset}px)';
|
||||
}
|
||||
|
||||
void _contextRestoredListener(DomEvent event) {
|
||||
JSVoid _contextRestoredListener(DomEvent event) {
|
||||
assert(
|
||||
_contextLost,
|
||||
'Received "webglcontextrestored" event but never received '
|
||||
@ -280,7 +281,7 @@ class Surface {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
void _contextLostListener(DomEvent event) {
|
||||
JSVoid _contextLostListener(DomEvent event) {
|
||||
assert(event.target == htmlCanvas,
|
||||
'Received a context lost event for a disposed canvas');
|
||||
final SurfaceFactory factory = SurfaceFactory.instance;
|
||||
@ -344,8 +345,8 @@ class Surface {
|
||||
// notification. When we receive this notification we force a new context.
|
||||
//
|
||||
// See also: https://www.khronos.org/webgl/wiki/HandlingContextLost
|
||||
_cachedContextRestoredListener = allowInterop(_contextRestoredListener);
|
||||
_cachedContextLostListener = allowInterop(_contextLostListener);
|
||||
_cachedContextRestoredListener = createDomEventListener(_contextRestoredListener);
|
||||
_cachedContextLostListener = createDomEventListener(_contextLostListener);
|
||||
htmlCanvas.addEventListener(
|
||||
'webglcontextlost',
|
||||
_cachedContextLostListener,
|
||||
|
||||
@ -39,7 +39,7 @@ import 'browser_detection.dart';
|
||||
/// `JSUndefined`.
|
||||
extension ObjectToJSAnyExtension on Object {
|
||||
JSAny get toJSAnyShallow {
|
||||
if (isWasm) {
|
||||
if (isWasm) {
|
||||
return toJSAnyDeep;
|
||||
} else {
|
||||
// TODO(joshualitt): remove this cast when we reify JS types on JS
|
||||
@ -334,6 +334,13 @@ extension DomEventTargetExtension on DomEventTarget {
|
||||
}
|
||||
}
|
||||
|
||||
@JS('addEventListener')
|
||||
external JSVoid _addEventListener3(
|
||||
JSString type, DomEventListener listener, JSAny options);
|
||||
void addEventListenerWithOptions(String type, DomEventListener listener,
|
||||
Map<String, Object> options) =>
|
||||
_addEventListener3(type.toJS, listener, options.toJSAnyDeep);
|
||||
|
||||
@JS('removeEventListener')
|
||||
external JSVoid _removeEventListener1(
|
||||
JSString type, DomEventListener listener);
|
||||
@ -356,7 +363,14 @@ extension DomEventTargetExtension on DomEventTarget {
|
||||
bool dispatchEvent(DomEvent event) => _dispatchEvent(event).toDart;
|
||||
}
|
||||
|
||||
typedef DomEventListener = void Function(DomEvent event);
|
||||
typedef DartDomEventListener = JSVoid Function(DomEvent event);
|
||||
|
||||
@JS()
|
||||
@staticInterop
|
||||
class DomEventListener {}
|
||||
|
||||
DomEventListener createDomEventListener(DartDomEventListener listener) =>
|
||||
listener.toJS as DomEventListener;
|
||||
|
||||
@JS()
|
||||
@staticInterop
|
||||
@ -2260,10 +2274,10 @@ extension DomMediaQueryListExtension on DomMediaQueryList {
|
||||
bool get matches => _matches.toDart;
|
||||
|
||||
@JS('addListener')
|
||||
external JSVoid addListener(JSFunction? listener);
|
||||
external JSVoid addListener(DomEventListener? listener);
|
||||
|
||||
@JS('removeListener')
|
||||
external JSVoid removeListener(JSFunction? listener);
|
||||
external JSVoid removeListener(DomEventListener? listener);
|
||||
}
|
||||
|
||||
@JS()
|
||||
@ -2829,8 +2843,10 @@ extension DomScreenOrientationExtension on DomScreenOrientation {
|
||||
// remove the listener. Caller is still responsible for calling [allowInterop]
|
||||
// on the listener before creating the subscription.
|
||||
class DomSubscription {
|
||||
DomSubscription(this.target, String typeString, this.listener)
|
||||
: type = typeString.toJS {
|
||||
DomSubscription(
|
||||
this.target, String typeString, DartDomEventListener dartListener)
|
||||
: type = typeString.toJS,
|
||||
listener = createDomEventListener(dartListener) {
|
||||
target._addEventListener1(type, listener);
|
||||
}
|
||||
|
||||
|
||||
@ -65,7 +65,8 @@ class DebugCanvasReuseOverlay {
|
||||
..append(
|
||||
createDomHTMLButtonElement()
|
||||
..text = 'Reset'
|
||||
..addEventListener('click', (_) => _reset()),
|
||||
..addEventListener('click',
|
||||
createDomEventListener((_) => _reset())),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@ -87,7 +87,7 @@ class HtmlCodec implements ui.Codec {
|
||||
// on the main thread, and may cause dropped framed.
|
||||
late DomEventListener errorListener;
|
||||
DomEventListener? loadListener;
|
||||
errorListener = allowInterop((DomEvent event) {
|
||||
errorListener = createDomEventListener((DomEvent event) {
|
||||
if (loadListener != null) {
|
||||
imgElement.removeEventListener('load', loadListener);
|
||||
}
|
||||
@ -95,7 +95,7 @@ class HtmlCodec implements ui.Codec {
|
||||
completer.completeError(event);
|
||||
});
|
||||
imgElement.addEventListener('error', errorListener);
|
||||
loadListener = allowInterop((DomEvent event) {
|
||||
loadListener = createDomEventListener((DomEvent event) {
|
||||
if (chunkCallback != null) {
|
||||
chunkCallback!(100, 100);
|
||||
}
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:js_interop';
|
||||
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:ui/ui.dart' as ui;
|
||||
import 'package:web_locale_keymap/web_locale_keymap.dart' as locale_keymap;
|
||||
@ -11,7 +13,6 @@ import 'browser_detection.dart';
|
||||
import 'dom.dart';
|
||||
import 'key_map.g.dart';
|
||||
import 'platform_dispatcher.dart';
|
||||
import 'safe_browser_api.dart';
|
||||
import 'semantics.dart';
|
||||
|
||||
typedef _VoidCallback = void Function();
|
||||
@ -100,13 +101,13 @@ ValueGetter<T> _cached<T>(ValueGetter<T> body) {
|
||||
|
||||
class KeyboardBinding {
|
||||
KeyboardBinding._() {
|
||||
_addEventListener('keydown', allowInterop((DomEvent domEvent) {
|
||||
_addEventListener('keydown', (DomEvent domEvent) {
|
||||
final FlutterHtmlKeyboardEvent event = FlutterHtmlKeyboardEvent(domEvent as DomKeyboardEvent);
|
||||
return _converter.handleEvent(event);
|
||||
}));
|
||||
_addEventListener('keyup', allowInterop((DomEvent event) {
|
||||
return _converter.handleEvent(FlutterHtmlKeyboardEvent(event as DomKeyboardEvent));
|
||||
}));
|
||||
_converter.handleEvent(event);
|
||||
});
|
||||
_addEventListener('keyup', (DomEvent event) {
|
||||
_converter.handleEvent(FlutterHtmlKeyboardEvent(event as DomKeyboardEvent));
|
||||
});
|
||||
}
|
||||
|
||||
/// The singleton instance of this object.
|
||||
@ -138,18 +139,17 @@ class KeyboardBinding {
|
||||
);
|
||||
final Map<String, DomEventListener> _listeners = <String, DomEventListener>{};
|
||||
|
||||
void _addEventListener(String eventName, DomEventListener handler) {
|
||||
dynamic loggedHandler(DomEvent event) {
|
||||
void _addEventListener(String eventName, DartDomEventListener handler) {
|
||||
JSVoid loggedHandler(DomEvent event) {
|
||||
if (_debugLogKeyEvents) {
|
||||
print(event.type);
|
||||
}
|
||||
if (EngineSemanticsOwner.instance.receiveGlobalEvent(event)) {
|
||||
return handler(event);
|
||||
handler(event);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
final DomEventListener wrappedHandler = allowInterop(loggedHandler);
|
||||
final DomEventListener wrappedHandler = createDomEventListener(loggedHandler);
|
||||
assert(!_listeners.containsKey(eventName));
|
||||
_listeners[eventName] = wrappedHandler;
|
||||
domWindow.addEventListener(eventName, wrappedHandler, true);
|
||||
|
||||
@ -14,7 +14,7 @@ typedef _PathGetter = String Function();
|
||||
|
||||
typedef _StateGetter = Object? Function();
|
||||
|
||||
typedef _AddPopStateListener = ui.VoidCallback Function(DomEventListener);
|
||||
typedef _AddPopStateListener = ui.VoidCallback Function(DartDomEventListener);
|
||||
|
||||
typedef _StringToString = String Function(String);
|
||||
|
||||
@ -47,7 +47,7 @@ abstract class JsUrlStrategy {
|
||||
extension JsUrlStrategyExtension on JsUrlStrategy {
|
||||
/// Adds a listener to the `popstate` event and returns a function that, when
|
||||
/// invoked, removes the listener.
|
||||
external ui.VoidCallback addPopStateListener(DomEventListener fn);
|
||||
external ui.VoidCallback addPopStateListener(DartDomEventListener fn);
|
||||
|
||||
/// Returns the active path in the browser.
|
||||
external String getPath();
|
||||
|
||||
@ -35,8 +35,7 @@ class HashUrlStrategy extends ui_web.UrlStrategy {
|
||||
|
||||
@override
|
||||
ui.VoidCallback addPopStateListener(ui_web.PopStateListener fn) {
|
||||
final DomEventListener wrappedFn =
|
||||
allowInterop((DomEvent event) => fn((event as DomPopStateEvent).state));
|
||||
final DomEventListener wrappedFn = createDomEventListener(fn);
|
||||
_platformLocation.addPopStateListener(wrappedFn);
|
||||
return () => _platformLocation.removePopStateListener(wrappedFn);
|
||||
}
|
||||
|
||||
@ -10,7 +10,6 @@ import 'dom.dart';
|
||||
import 'html/bitmap_canvas.dart';
|
||||
import 'html/recording_canvas.dart';
|
||||
import 'html_image_codec.dart';
|
||||
import 'safe_browser_api.dart';
|
||||
import 'util.dart';
|
||||
|
||||
/// An implementation of [ui.PictureRecorder] backed by a [RecordingCanvas].
|
||||
@ -74,13 +73,13 @@ class EnginePicture implements ui.Picture {
|
||||
// Ignoring the returned futures from onError and onLoad because we're
|
||||
// communicating through the `onImageLoaded` completer.
|
||||
late final DomEventListener errorListener;
|
||||
errorListener = allowInterop((DomEvent event) {
|
||||
errorListener = createDomEventListener((DomEvent event) {
|
||||
onImageLoaded.completeError(event);
|
||||
imageElement.removeEventListener('error', errorListener);
|
||||
});
|
||||
imageElement.addEventListener('error', errorListener);
|
||||
late final DomEventListener loadListener;
|
||||
loadListener = allowInterop((DomEvent event) {
|
||||
loadListener = createDomEventListener((DomEvent event) {
|
||||
onImageLoaded.complete(HtmlImage(
|
||||
imageElement,
|
||||
width,
|
||||
|
||||
@ -43,8 +43,8 @@ class HighContrastSupport {
|
||||
|
||||
/// Reference to css media query that indicates whether high contrast is on.
|
||||
final DomMediaQueryList _highContrastMediaQuery = domWindow.matchMedia(_highContrastMediaQueryString);
|
||||
late final JSFunction _onHighContrastChangeListener =
|
||||
_onHighContrastChange.toJS;
|
||||
late final DomEventListener _onHighContrastChangeListener =
|
||||
createDomEventListener(_onHighContrastChange);
|
||||
|
||||
bool get isHighContrastEnabled => _highContrastMediaQuery.matches;
|
||||
|
||||
@ -799,11 +799,11 @@ class EnginePlatformDispatcher extends ui.PlatformDispatcher {
|
||||
}
|
||||
updateLocales(); // First time, for good measure.
|
||||
_onLocaleChangedSubscription =
|
||||
DomSubscription(domWindow, 'languagechange', allowInterop((DomEvent _) {
|
||||
DomSubscription(domWindow, 'languagechange', (DomEvent _) {
|
||||
// Update internal config, then propagate the changes.
|
||||
updateLocales();
|
||||
invokeOnLocaleChanged();
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
/// Removes the [_onLocaleChangedSubscription].
|
||||
@ -1029,7 +1029,7 @@ class EnginePlatformDispatcher extends ui.PlatformDispatcher {
|
||||
/// A callback that is invoked whenever [_brightnessMediaQuery] changes value.
|
||||
///
|
||||
/// Updates the [_platformBrightness] with the new user preference.
|
||||
JSFunction? _brightnessMediaQueryListener;
|
||||
DomEventListener? _brightnessMediaQueryListener;
|
||||
|
||||
/// Set the callback function for listening changes in [_brightnessMediaQuery] value.
|
||||
void _addBrightnessMediaQueryListener() {
|
||||
@ -1037,12 +1037,12 @@ class EnginePlatformDispatcher extends ui.PlatformDispatcher {
|
||||
? ui.Brightness.dark
|
||||
: ui.Brightness.light);
|
||||
|
||||
_brightnessMediaQueryListener = (DomEvent event) {
|
||||
_brightnessMediaQueryListener = createDomEventListener((DomEvent event) {
|
||||
final DomMediaQueryListEvent mqEvent =
|
||||
event as DomMediaQueryListEvent;
|
||||
_updatePlatformBrightness(
|
||||
mqEvent.matches! ? ui.Brightness.dark : ui.Brightness.light);
|
||||
}.toJS;
|
||||
});
|
||||
_brightnessMediaQuery.addListener(_brightnessMediaQueryListener);
|
||||
}
|
||||
|
||||
|
||||
@ -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 'dart:js_interop';
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:meta/meta.dart';
|
||||
@ -74,7 +75,7 @@ class SafariPointerEventWorkaround {
|
||||
static SafariPointerEventWorkaround instance = SafariPointerEventWorkaround();
|
||||
|
||||
void workAroundMissingPointerEvents() {
|
||||
domDocument.addEventListener('touchstart', allowInterop((DomEvent event) {}));
|
||||
domDocument.addEventListener('touchstart', createDomEventListener((DomEvent event) {}));
|
||||
}
|
||||
}
|
||||
|
||||
@ -204,10 +205,10 @@ class _Listener {
|
||||
factory _Listener.register({
|
||||
required String event,
|
||||
required DomEventTarget target,
|
||||
required DomEventListener handler,
|
||||
required DartDomEventListener handler,
|
||||
bool capture = false,
|
||||
}) {
|
||||
final DomEventListener jsHandler = allowInterop((DomEvent event) => handler(event));
|
||||
final DomEventListener jsHandler = createDomEventListener(handler);
|
||||
final _Listener listener = _Listener._(
|
||||
event: event,
|
||||
target: target,
|
||||
@ -223,15 +224,14 @@ class _Listener {
|
||||
factory _Listener.registerNative({
|
||||
required String event,
|
||||
required DomEventTarget target,
|
||||
required DomEventListener handler,
|
||||
required DomEventListener jsHandler,
|
||||
bool capture = false,
|
||||
bool passive = false,
|
||||
}) {
|
||||
final Object eventOptions = createPlainJsObject(<String, Object?>{
|
||||
final Map<String, Object> eventOptions = <String, Object>{
|
||||
'capture': capture,
|
||||
'passive': passive,
|
||||
});
|
||||
final DomEventListener jsHandler = allowInterop((DomEvent event) => handler(event));
|
||||
};
|
||||
final _Listener listener = _Listener._(
|
||||
event: event,
|
||||
target: target,
|
||||
@ -239,7 +239,7 @@ class _Listener {
|
||||
useCapture: capture,
|
||||
isNative: true,
|
||||
);
|
||||
addJsEventListener(target, event, jsHandler, eventOptions);
|
||||
target.addEventListenerWithOptions(event, jsHandler, eventOptions);
|
||||
return listener;
|
||||
}
|
||||
|
||||
@ -253,7 +253,7 @@ class _Listener {
|
||||
|
||||
void unregister() {
|
||||
if (isNative) {
|
||||
removeJsEventListener(target, event, handler, useCapture);
|
||||
target.removeEventListener(event, handler, useCapture);
|
||||
} else {
|
||||
target.removeEventListener(event, handler, useCapture);
|
||||
}
|
||||
@ -306,10 +306,10 @@ abstract class _BaseAdapter {
|
||||
void addEventListener(
|
||||
DomEventTarget target,
|
||||
String eventName,
|
||||
DomEventListener handler, {
|
||||
DartDomEventListener handler, {
|
||||
bool useCapture = true,
|
||||
}) {
|
||||
dynamic loggedHandler(DomEvent event) {
|
||||
JSVoid loggedHandler(DomEvent event) {
|
||||
if (_debugLogPointerEvents) {
|
||||
if (domInstanceOfString(event, 'PointerEvent')) {
|
||||
final DomPointerEvent pointerEvent = event as DomPointerEvent;
|
||||
@ -495,11 +495,11 @@ mixin _WheelEventListenerMixin on _BaseAdapter {
|
||||
return data;
|
||||
}
|
||||
|
||||
void _addWheelEventListener(DomEventListener handler) {
|
||||
void _addWheelEventListener(DartDomEventListener handler) {
|
||||
_listeners.add(_Listener.registerNative(
|
||||
event: 'wheel',
|
||||
target: glassPaneElement,
|
||||
handler: (DomEvent event) => handler(event),
|
||||
jsHandler: createDomEventListener(handler),
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@ -9,18 +9,17 @@ import '../engine.dart' show registerHotRestartListener;
|
||||
import 'dom.dart';
|
||||
import 'keyboard_binding.dart';
|
||||
import 'platform_dispatcher.dart';
|
||||
import 'safe_browser_api.dart';
|
||||
import 'services.dart';
|
||||
|
||||
/// Provides keyboard bindings, such as the `flutter/keyevent` channel.
|
||||
class RawKeyboard {
|
||||
RawKeyboard._(this._onMacOs) {
|
||||
_keydownListener = allowInterop((DomEvent event) {
|
||||
_keydownListener = createDomEventListener((DomEvent event) {
|
||||
_handleHtmlEvent(event);
|
||||
});
|
||||
domWindow.addEventListener('keydown', _keydownListener);
|
||||
|
||||
_keyupListener = allowInterop((DomEvent event) {
|
||||
_keyupListener = createDomEventListener((DomEvent event) {
|
||||
_handleHtmlEvent(event);
|
||||
});
|
||||
domWindow.addEventListener('keyup', _keyupListener);
|
||||
|
||||
@ -27,16 +27,6 @@ import 'vector_math.dart';
|
||||
|
||||
export 'package:js/js.dart' show allowInterop;
|
||||
|
||||
/// Creates JavaScript object populated with [properties].
|
||||
///
|
||||
/// This is equivalent to writing `{}` in plain JavaScript.
|
||||
Object createPlainJsObject([Map<String, Object?>? properties]) {
|
||||
if (properties != null) {
|
||||
return js_util.jsify(properties) as Object;
|
||||
} else {
|
||||
return js_util.newObject<Object>();
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if [object] has property [name], false otherwise.
|
||||
///
|
||||
@ -80,37 +70,6 @@ Future<T> promiseToFuture<T>(Object jsPromise) {
|
||||
/// A function that receives a benchmark [value] labeleb by [name].
|
||||
typedef OnBenchmark = void Function(String name, double value);
|
||||
|
||||
/// Adds an event [listener] of type [type] to the [target].
|
||||
///
|
||||
/// [eventOptions] supply additional configuration parameters.
|
||||
///
|
||||
/// This is different from [DomElement.addEventListener] in that the listener
|
||||
/// is added as a plain JavaScript function, as opposed to a Dart function.
|
||||
///
|
||||
/// To remove the listener, call [removeJsEventListener].
|
||||
void addJsEventListener(Object target, String type, Function listener, Object eventOptions) {
|
||||
js_util.callMethod<void>(
|
||||
target,
|
||||
'addEventListener', <dynamic>[
|
||||
type,
|
||||
listener,
|
||||
eventOptions,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/// Removes an event listener that was added using [addJsEventListener].
|
||||
void removeJsEventListener(Object target, String type, Function listener, Object eventOptions) {
|
||||
js_util.callMethod<void>(
|
||||
target,
|
||||
'removeEventListener', <dynamic>[
|
||||
type,
|
||||
listener,
|
||||
eventOptions,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/// Parses a string [source] into a double.
|
||||
///
|
||||
/// Uses the JavaScript `parseFloat` function instead of Dart's [double.parse]
|
||||
@ -1076,7 +1035,7 @@ class OffScreenCanvas {
|
||||
if (offScreenCanvas != null) {
|
||||
offScreenCanvas!.convertToBlob().then((DomBlob value) {
|
||||
final DomFileReader fileReader = createDomFileReader();
|
||||
fileReader.addEventListener('load', allowInterop((DomEvent event) {
|
||||
fileReader.addEventListener('load', createDomEventListener((DomEvent event) {
|
||||
completer.complete(
|
||||
js_util.getProperty<String>(js_util.getProperty<Object>(event, 'target'), 'result'),
|
||||
);
|
||||
|
||||
@ -6,7 +6,6 @@ import 'package:ui/ui.dart' as ui;
|
||||
|
||||
import '../dom.dart';
|
||||
import '../platform_dispatcher.dart';
|
||||
import '../safe_browser_api.dart';
|
||||
import 'semantics.dart';
|
||||
|
||||
/// Adds increment/decrement event handling to a semantics object.
|
||||
@ -25,7 +24,7 @@ class Incrementable extends RoleManager {
|
||||
_element.type = 'range';
|
||||
_element.setAttribute('role', 'slider');
|
||||
|
||||
_element.addEventListener('change', allowInterop((_) {
|
||||
_element.addEventListener('change', createDomEventListener((_) {
|
||||
if (_element.disabled!) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -121,7 +121,7 @@ class Scrollable extends RoleManager {
|
||||
};
|
||||
semanticsObject.owner.addGestureModeListener(_gestureModeListener);
|
||||
|
||||
_scrollListener = allowInterop((_) {
|
||||
_scrollListener = createDomEventListener((_) {
|
||||
_recomputeScrollPosition();
|
||||
});
|
||||
semanticsObject.element.addEventListener('scroll', _scrollListener);
|
||||
|
||||
@ -8,7 +8,6 @@ import 'package:meta/meta.dart';
|
||||
|
||||
import '../browser_detection.dart';
|
||||
import '../dom.dart';
|
||||
import '../safe_browser_api.dart';
|
||||
import 'semantics.dart';
|
||||
|
||||
/// The maximum [semanticsActivationAttempts] before we give up waiting for
|
||||
@ -180,7 +179,7 @@ class DesktopSemanticsEnabler extends SemanticsEnabler {
|
||||
|
||||
// Only listen to "click" because other kinds of events are reported via
|
||||
// PointerBinding.
|
||||
placeholder.addEventListener('click', allowInterop((DomEvent event) {
|
||||
placeholder.addEventListener('click', createDomEventListener((DomEvent event) {
|
||||
tryEnableSemantics(event);
|
||||
}), true);
|
||||
|
||||
@ -374,7 +373,7 @@ class MobileSemanticsEnabler extends SemanticsEnabler {
|
||||
|
||||
// Only listen to "click" because other kinds of events are reported via
|
||||
// PointerBinding.
|
||||
placeholder.addEventListener('click', allowInterop((DomEvent event) {
|
||||
placeholder.addEventListener('click', createDomEventListener((DomEvent event) {
|
||||
tryEnableSemantics(event);
|
||||
}), true);
|
||||
|
||||
|
||||
@ -6,7 +6,6 @@ import 'package:ui/ui.dart' as ui;
|
||||
|
||||
import '../dom.dart';
|
||||
import '../platform_dispatcher.dart';
|
||||
import '../safe_browser_api.dart';
|
||||
import 'semantics.dart';
|
||||
|
||||
/// Listens to HTML "click" gestures detected by the browser.
|
||||
@ -44,7 +43,7 @@ class Tappable extends RoleManager {
|
||||
if (semanticsObject.hasAction(ui.SemanticsAction.tap) &&
|
||||
!semanticsObject.hasFlag(ui.SemanticsFlag.isTextField)) {
|
||||
if (_clickListener == null) {
|
||||
_clickListener = allowInterop((_) {
|
||||
_clickListener = createDomEventListener((_) {
|
||||
if (semanticsObject.owner.gestureMode !=
|
||||
GestureMode.browserGestures) {
|
||||
return;
|
||||
|
||||
@ -9,7 +9,6 @@ import '../browser_detection.dart';
|
||||
import '../dom.dart';
|
||||
import '../embedder.dart';
|
||||
import '../platform_dispatcher.dart';
|
||||
import '../safe_browser_api.dart';
|
||||
import '../text_editing/text_editing.dart';
|
||||
import 'semantics.dart';
|
||||
|
||||
@ -139,13 +138,13 @@ class SemanticsTextEditingStrategy extends DefaultTextEditingStrategy {
|
||||
|
||||
// Subscribe to text and selection changes.
|
||||
subscriptions.add(
|
||||
DomSubscription(activeDomElement, 'input', allowInterop(handleChange)));
|
||||
DomSubscription(activeDomElement, 'input', handleChange));
|
||||
subscriptions.add(
|
||||
DomSubscription(activeDomElement, 'keydown',
|
||||
allowInterop(maybeSendAction)));
|
||||
maybeSendAction));
|
||||
subscriptions.add(
|
||||
DomSubscription(domDocument, 'selectionchange',
|
||||
allowInterop(handleChange)));
|
||||
handleChange));
|
||||
preventDefaultForMouseEvents();
|
||||
}
|
||||
|
||||
@ -298,7 +297,7 @@ class TextField extends RoleManager {
|
||||
void _initializeForBlink() {
|
||||
_initializeEditableElement();
|
||||
activeEditableElement.addEventListener('focus',
|
||||
allowInterop((DomEvent event) {
|
||||
createDomEventListener((DomEvent event) {
|
||||
if (semanticsObject.owner.gestureMode != GestureMode.browserGestures) {
|
||||
return;
|
||||
}
|
||||
@ -339,14 +338,14 @@ class TextField extends RoleManager {
|
||||
num? lastPointerDownOffsetY;
|
||||
|
||||
semanticsObject.element.addEventListener('pointerdown',
|
||||
allowInterop((DomEvent event) {
|
||||
createDomEventListener((DomEvent event) {
|
||||
final DomPointerEvent pointerEvent = event as DomPointerEvent;
|
||||
lastPointerDownOffsetX = pointerEvent.clientX;
|
||||
lastPointerDownOffsetY = pointerEvent.clientY;
|
||||
}), true);
|
||||
|
||||
semanticsObject.element.addEventListener('pointerup',
|
||||
allowInterop((DomEvent event) {
|
||||
createDomEventListener((DomEvent event) {
|
||||
final DomPointerEvent pointerEvent = event as DomPointerEvent;
|
||||
|
||||
if (lastPointerDownOffsetX != null) {
|
||||
@ -396,7 +395,7 @@ class TextField extends RoleManager {
|
||||
semanticsObject.element.removeAttribute('role');
|
||||
|
||||
activeEditableElement.addEventListener('blur',
|
||||
allowInterop((DomEvent event) {
|
||||
createDomEventListener((DomEvent event) {
|
||||
semanticsObject.element.setAttribute('role', 'textbox');
|
||||
activeEditableElement.remove();
|
||||
SemanticsTextEditingStrategy._instance?.deactivate(this);
|
||||
|
||||
@ -2,8 +2,9 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:js_interop';
|
||||
|
||||
import '../dom.dart';
|
||||
import '../safe_browser_api.dart';
|
||||
import 'text_editing.dart';
|
||||
|
||||
/// Provides default functionality for listening to HTML composition events.
|
||||
@ -30,11 +31,11 @@ mixin CompositionAwareMixin {
|
||||
static const String _kCompositionEnd = 'compositionend';
|
||||
|
||||
late final DomEventListener _compositionStartListener =
|
||||
allowInterop(_handleCompositionStart);
|
||||
createDomEventListener(_handleCompositionStart);
|
||||
late final DomEventListener _compositionUpdateListener =
|
||||
allowInterop(_handleCompositionUpdate);
|
||||
createDomEventListener(_handleCompositionUpdate);
|
||||
late final DomEventListener _compositionEndListener =
|
||||
allowInterop(_handleCompositionEnd);
|
||||
createDomEventListener(_handleCompositionEnd);
|
||||
|
||||
/// The currently composing text in the `domElement`.
|
||||
///
|
||||
@ -55,17 +56,17 @@ mixin CompositionAwareMixin {
|
||||
domElement.removeEventListener(_kCompositionEnd, _compositionEndListener);
|
||||
}
|
||||
|
||||
void _handleCompositionStart(DomEvent event) {
|
||||
JSVoid _handleCompositionStart(DomEvent event) {
|
||||
composingText = null;
|
||||
}
|
||||
|
||||
void _handleCompositionUpdate(DomEvent event) {
|
||||
JSVoid _handleCompositionUpdate(DomEvent event) {
|
||||
if (domInstanceOfString(event, 'CompositionEvent')) {
|
||||
composingText = (event as DomCompositionEvent).data;
|
||||
}
|
||||
}
|
||||
|
||||
void _handleCompositionEnd(DomEvent event) {
|
||||
JSVoid _handleCompositionEnd(DomEvent event) {
|
||||
composingText = null;
|
||||
}
|
||||
|
||||
|
||||
@ -194,7 +194,7 @@ class EngineAutofillForm {
|
||||
formElement.noValidate = true;
|
||||
formElement.method = 'post';
|
||||
formElement.action = '#';
|
||||
formElement.addEventListener('submit', allowInterop((DomEvent e) {
|
||||
formElement.addEventListener('submit', createDomEventListener((DomEvent e) {
|
||||
e.preventDefault();
|
||||
}));
|
||||
|
||||
@ -304,7 +304,7 @@ class EngineAutofillForm {
|
||||
final DomElement element = elements![key]!;
|
||||
subscriptions.add(
|
||||
DomSubscription(element, 'input',
|
||||
allowInterop((DomEvent e) {
|
||||
(DomEvent e) {
|
||||
if (items![key] == null) {
|
||||
throw StateError(
|
||||
'AutofillInfo must have a valid uniqueIdentifier.');
|
||||
@ -312,7 +312,7 @@ class EngineAutofillForm {
|
||||
final AutofillInfo autofillInfo = items![key]!;
|
||||
handleChange(element, autofillInfo);
|
||||
}
|
||||
})));
|
||||
}));
|
||||
}
|
||||
|
||||
keys.forEach(addSubscriptionForKey);
|
||||
@ -1231,23 +1231,23 @@ abstract class DefaultTextEditingStrategy with CompositionAwareMixin implements
|
||||
|
||||
// Subscribe to text and selection changes.
|
||||
subscriptions.add(DomSubscription(activeDomElement, 'input',
|
||||
allowInterop(handleChange)));
|
||||
handleChange));
|
||||
|
||||
subscriptions.add(DomSubscription(activeDomElement, 'keydown',
|
||||
allowInterop(maybeSendAction)));
|
||||
maybeSendAction));
|
||||
|
||||
subscriptions.add(DomSubscription(domDocument, 'selectionchange',
|
||||
allowInterop(handleChange)));
|
||||
handleChange));
|
||||
|
||||
activeDomElement.addEventListener('beforeinput',
|
||||
allowInterop(handleBeforeInput));
|
||||
createDomEventListener(handleBeforeInput));
|
||||
|
||||
addCompositionEventHandlers(activeDomElement);
|
||||
|
||||
// Refocus on the activeDomElement after blur, so that user can keep editing the
|
||||
// text field.
|
||||
subscriptions.add(DomSubscription(activeDomElement, 'blur',
|
||||
allowInterop((_) { activeDomElement.focus(); })));
|
||||
(_) { activeDomElement.focus(); }));
|
||||
|
||||
preventDefaultForMouseEvents();
|
||||
}
|
||||
@ -1420,19 +1420,19 @@ abstract class DefaultTextEditingStrategy with CompositionAwareMixin implements
|
||||
/// flickering during selection by mouse.
|
||||
void preventDefaultForMouseEvents() {
|
||||
subscriptions.add(
|
||||
DomSubscription(activeDomElement, 'mousedown', allowInterop((_) {
|
||||
DomSubscription(activeDomElement, 'mousedown', (_) {
|
||||
_.preventDefault();
|
||||
})));
|
||||
}));
|
||||
|
||||
subscriptions.add(
|
||||
DomSubscription(activeDomElement, 'mouseup', allowInterop((_) {
|
||||
DomSubscription(activeDomElement, 'mouseup', (_) {
|
||||
_.preventDefault();
|
||||
})));
|
||||
}));
|
||||
|
||||
subscriptions.add(
|
||||
DomSubscription(activeDomElement, 'mousemove', allowInterop((_) {
|
||||
DomSubscription(activeDomElement, 'mousemove', (_) {
|
||||
_.preventDefault();
|
||||
})));
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1525,25 +1525,25 @@ class IOSTextEditingStrategy extends GloballyPositionedTextEditingStrategy {
|
||||
|
||||
// Subscribe to text and selection changes.
|
||||
subscriptions.add(DomSubscription(activeDomElement, 'input',
|
||||
allowInterop(handleChange)));
|
||||
handleChange));
|
||||
|
||||
subscriptions.add(DomSubscription(activeDomElement, 'keydown',
|
||||
allowInterop(maybeSendAction)));
|
||||
maybeSendAction));
|
||||
|
||||
subscriptions.add(DomSubscription(domDocument, 'selectionchange',
|
||||
allowInterop(handleChange)));
|
||||
handleChange));
|
||||
|
||||
activeDomElement.addEventListener('beforeinput',
|
||||
allowInterop(handleBeforeInput));
|
||||
createDomEventListener(handleBeforeInput));
|
||||
|
||||
addCompositionEventHandlers(activeDomElement);
|
||||
|
||||
// Position the DOM element after it is focused.
|
||||
subscriptions.add(DomSubscription(activeDomElement, 'focus',
|
||||
allowInterop((_) {
|
||||
(_) {
|
||||
// Cancel previous timer if exists.
|
||||
_schedulePlacement();
|
||||
})));
|
||||
}));
|
||||
|
||||
_addTapListener();
|
||||
|
||||
@ -1567,14 +1567,14 @@ class IOSTextEditingStrategy extends GloballyPositionedTextEditingStrategy {
|
||||
// input field was activated. If the time is too short, we re-focus the
|
||||
// input element.
|
||||
subscriptions.add(DomSubscription(activeDomElement, 'blur',
|
||||
allowInterop((_) {
|
||||
(_) {
|
||||
final bool isFastCallback = blurWatch.elapsed < _blurFastCallbackInterval;
|
||||
if (windowHasFocus && isFastCallback) {
|
||||
activeDomElement.focus();
|
||||
} else {
|
||||
owner.sendTextConnectionClosedToFrameworkIfAny();
|
||||
}
|
||||
})));
|
||||
}));
|
||||
}
|
||||
|
||||
@override
|
||||
@ -1610,7 +1610,7 @@ class IOSTextEditingStrategy extends GloballyPositionedTextEditingStrategy {
|
||||
/// [_positionInputElementTimer] timer is restarted. The element will be
|
||||
/// placed to its correct position after [_delayBeforePlacement].
|
||||
void _addTapListener() {
|
||||
subscriptions.add(DomSubscription(activeDomElement, 'click', allowInterop((_) {
|
||||
subscriptions.add(DomSubscription(activeDomElement, 'click', (_) {
|
||||
// Check if the element is already positioned. If not this does not fall
|
||||
// under `The user was using the long press, now they want to enter text
|
||||
// via keyboard` journey.
|
||||
@ -1621,7 +1621,7 @@ class IOSTextEditingStrategy extends GloballyPositionedTextEditingStrategy {
|
||||
// Re-configure the timer to place the element.
|
||||
_schedulePlacement();
|
||||
}
|
||||
})));
|
||||
}));
|
||||
}
|
||||
|
||||
void _schedulePlacement() {
|
||||
@ -1676,24 +1676,24 @@ class AndroidTextEditingStrategy extends GloballyPositionedTextEditingStrategy {
|
||||
|
||||
// Subscribe to text and selection changes.
|
||||
subscriptions.add(
|
||||
DomSubscription(activeDomElement, 'input', allowInterop(handleChange)));
|
||||
DomSubscription(activeDomElement, 'input', handleChange));
|
||||
|
||||
subscriptions.add(
|
||||
DomSubscription(activeDomElement, 'keydown',
|
||||
allowInterop(maybeSendAction)));
|
||||
maybeSendAction));
|
||||
|
||||
subscriptions.add(
|
||||
DomSubscription(domDocument, 'selectionchange',
|
||||
allowInterop(handleChange)));
|
||||
handleChange));
|
||||
|
||||
activeDomElement.addEventListener('beforeinput',
|
||||
allowInterop(handleBeforeInput));
|
||||
createDomEventListener(handleBeforeInput));
|
||||
|
||||
addCompositionEventHandlers(activeDomElement);
|
||||
|
||||
subscriptions.add(
|
||||
DomSubscription(activeDomElement, 'blur',
|
||||
allowInterop((_) {
|
||||
(_) {
|
||||
if (windowHasFocus) {
|
||||
// Chrome on Android will hide the onscreen keyboard when you tap outside
|
||||
// the text box. Instead, we want the framework to tell us to hide the
|
||||
@ -1703,7 +1703,7 @@ class AndroidTextEditingStrategy extends GloballyPositionedTextEditingStrategy {
|
||||
} else {
|
||||
owner.sendTextConnectionClosedToFrameworkIfAny();
|
||||
}
|
||||
})));
|
||||
}));
|
||||
}
|
||||
|
||||
@override
|
||||
@ -1742,14 +1742,14 @@ class FirefoxTextEditingStrategy extends GloballyPositionedTextEditingStrategy {
|
||||
|
||||
// Subscribe to text and selection changes.
|
||||
subscriptions.add(
|
||||
DomSubscription(activeDomElement, 'input', allowInterop(handleChange)));
|
||||
DomSubscription(activeDomElement, 'input', handleChange));
|
||||
|
||||
subscriptions.add(
|
||||
DomSubscription(
|
||||
activeDomElement, 'keydown', allowInterop(maybeSendAction)));
|
||||
activeDomElement, 'keydown', maybeSendAction));
|
||||
|
||||
activeDomElement.addEventListener('beforeinput',
|
||||
allowInterop(handleBeforeInput));
|
||||
createDomEventListener(handleBeforeInput));
|
||||
|
||||
addCompositionEventHandlers(activeDomElement);
|
||||
|
||||
@ -1770,16 +1770,16 @@ class FirefoxTextEditingStrategy extends GloballyPositionedTextEditingStrategy {
|
||||
DomSubscription(
|
||||
activeDomElement,
|
||||
'keyup',
|
||||
allowInterop((DomEvent event) {
|
||||
(DomEvent event) {
|
||||
handleChange(event);
|
||||
})));
|
||||
}));
|
||||
|
||||
// In Firefox the context menu item "Select All" does not work without
|
||||
// listening to onSelect. On the other browsers onSelectionChange is
|
||||
// enough for covering "Select All" functionality.
|
||||
subscriptions.add(
|
||||
DomSubscription(
|
||||
activeDomElement, 'select', allowInterop(handleChange)));
|
||||
activeDomElement, 'select', handleChange));
|
||||
|
||||
// Refocus on the activeDomElement after blur, so that user can keep editing the
|
||||
// text field.
|
||||
@ -1787,9 +1787,9 @@ class FirefoxTextEditingStrategy extends GloballyPositionedTextEditingStrategy {
|
||||
DomSubscription(
|
||||
activeDomElement,
|
||||
'blur',
|
||||
allowInterop((_) {
|
||||
(_) {
|
||||
_postponeFocus();
|
||||
})));
|
||||
}));
|
||||
|
||||
preventDefaultForMouseEvents();
|
||||
}
|
||||
|
||||
@ -4,7 +4,6 @@
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:js/js.dart';
|
||||
import 'package:ui/src/engine/browser_detection.dart';
|
||||
import 'package:ui/src/engine/dom.dart';
|
||||
import 'package:ui/src/engine/window.dart';
|
||||
@ -33,7 +32,7 @@ class FullPageDimensionsProvider extends DimensionsProvider {
|
||||
_domResizeSubscription = DomSubscription(
|
||||
resizeEventTarget,
|
||||
'resize',
|
||||
allowInterop(_onVisualViewportResize),
|
||||
_onVisualViewportResize,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -5,7 +5,6 @@
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
import 'package:ui/src/engine/dom.dart';
|
||||
import 'package:ui/src/engine/safe_browser_api.dart';
|
||||
import 'package:ui/src/engine/view_embedder/hot_restart_cache_handler.dart';
|
||||
|
||||
import 'custom_element_embedding_strategy.dart';
|
||||
@ -65,7 +64,7 @@ mixin _ContextMenu {
|
||||
|
||||
/// Listener for contextmenu events that prevents the browser's context menu
|
||||
/// from being shown.
|
||||
final DomEventListener _disablingContextMenuListener = allowInterop((DomEvent event) {
|
||||
final DomEventListener _disablingContextMenuListener = createDomEventListener((DomEvent event) {
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
|
||||
@ -53,7 +53,7 @@ void testMain() {
|
||||
final JsUrlStrategy jsUrlStrategy = JsUrlStrategy(
|
||||
getPath: allowInterop(() => '/initial'),
|
||||
getState: allowInterop(() => state),
|
||||
addPopStateListener: allowInterop((DomEventListener listener) => allowInterop(() {})),
|
||||
addPopStateListener: allowInterop((DartDomEventListener listener) => allowInterop(() {})),
|
||||
prepareExternalUrl: allowInterop((String value) => ''),
|
||||
pushState: allowInterop((Object? newState, String title, String url) {
|
||||
expect(newState is Map, true);
|
||||
|
||||
@ -13,7 +13,6 @@ import 'package:ui/src/engine.dart' show flutterViewEmbedder;
|
||||
import 'package:ui/src/engine/browser_detection.dart';
|
||||
import 'package:ui/src/engine/dom.dart';
|
||||
import 'package:ui/src/engine/initialization.dart';
|
||||
import 'package:ui/src/engine/safe_browser_api.dart';
|
||||
import 'package:ui/src/engine/services.dart';
|
||||
import 'package:ui/src/engine/text_editing/autofill_hint.dart';
|
||||
import 'package:ui/src/engine/text_editing/input_type.dart';
|
||||
@ -903,7 +902,7 @@ Future<void> testMain() async {
|
||||
defaultTextEditingRoot.querySelector('form')! as DomHTMLFormElement;
|
||||
final Completer<bool> submittedForm = Completer<bool>();
|
||||
formElement.addEventListener(
|
||||
'submit', allowInterop((DomEvent event) =>
|
||||
'submit', createDomEventListener((DomEvent event) =>
|
||||
submittedForm.complete(true)));
|
||||
|
||||
const MethodCall clearClient = MethodCall('TextInput.clearClient');
|
||||
@ -956,7 +955,7 @@ Future<void> testMain() async {
|
||||
defaultTextEditingRoot.querySelector('form')! as DomHTMLFormElement;
|
||||
final Completer<bool> submittedForm = Completer<bool>();
|
||||
formElement.addEventListener(
|
||||
'submit', allowInterop((DomEvent event) =>
|
||||
'submit', createDomEventListener((DomEvent event) =>
|
||||
submittedForm.complete(true)));
|
||||
|
||||
// Clear client is not called. The used requested context to be finalized.
|
||||
|
||||
@ -437,7 +437,7 @@ Future<void> testMain() async {
|
||||
test('dispatches browser event on flutter/service_worker channel', () async {
|
||||
final Completer<void> completer = Completer<void>();
|
||||
domWindow.addEventListener('flutter-first-frame',
|
||||
allowInterop((DomEvent e) => completer.complete()));
|
||||
createDomEventListener((DomEvent e) => completer.complete()));
|
||||
final Zone innerZone = Zone.current.fork();
|
||||
|
||||
innerZone.runGuarded(() {
|
||||
|
||||
@ -397,7 +397,7 @@ Future<HtmlImage> createTestImage({int width = 50, int height = 40}) {
|
||||
ctx.fill();
|
||||
final DomHTMLImageElement imageElement = createDomHTMLImageElement();
|
||||
final Completer<HtmlImage> completer = Completer<HtmlImage>();
|
||||
imageElement.addEventListener('load', allowInterop((DomEvent event) {
|
||||
imageElement.addEventListener('load', createDomEventListener((DomEvent event) {
|
||||
completer.complete(HtmlImage(imageElement, width, height));
|
||||
}));
|
||||
imageElement.src = js_util.callMethod<String>(canvas, 'toDataURL', <dynamic>[]);
|
||||
|
||||
@ -184,7 +184,7 @@ MultiChannel<dynamic> _connectToServer() {
|
||||
final DomWebSocket webSocket = createDomWebSocket(_currentUrl.queryParameters['managerUrl']!);
|
||||
|
||||
final StreamChannelController<dynamic> controller = StreamChannelController<dynamic>(sync: true);
|
||||
webSocket.addEventListener('message', allowInterop((DomEvent message) {
|
||||
webSocket.addEventListener('message', createDomEventListener((DomEvent message) {
|
||||
final String data = (message as DomMessageEvent).data as String;
|
||||
controller.local.sink.add(jsonDecode(data));
|
||||
}));
|
||||
@ -221,7 +221,7 @@ StreamChannel<dynamic> _connectToIframe(String url, int id) {
|
||||
_domSubscriptions[id] = domSubscriptions;
|
||||
_streamSubscriptions[id] = streamSubscriptions;
|
||||
domSubscriptions.add(DomSubscription(domWindow, 'message',
|
||||
allowInterop((DomEvent event) {
|
||||
(DomEvent event) {
|
||||
final DomMessageEvent message = event as DomMessageEvent;
|
||||
// A message on the Window can theoretically come from any website. It's
|
||||
// very unlikely that a malicious site would care about hacking someone's
|
||||
@ -249,13 +249,13 @@ StreamChannel<dynamic> _connectToIframe(String url, int id) {
|
||||
// loading the test.
|
||||
controller.local.sink.add(message.data['data']);
|
||||
}
|
||||
})));
|
||||
}));
|
||||
|
||||
channel.port1.start();
|
||||
domSubscriptions.add(DomSubscription(channel.port1, 'message',
|
||||
allowInterop((DomEvent message) {
|
||||
(DomEvent message) {
|
||||
controller.local.sink.add((message as DomMessageEvent).data['data']);
|
||||
})));
|
||||
}));
|
||||
|
||||
streamSubscriptions.add(controller.local.stream.listen((dynamic message) async {
|
||||
await readyCompleter.future;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user