Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

[web] Avoid using js_util.{jsify,dartify}() in dart2wasm for converting to JS wrappers #51375

Merged
merged 7 commits into from
Mar 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -40598,6 +40598,7 @@ ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/shadow.dart + ../../../flutte
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/canvas.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/codecs.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/dart_js_conversion.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/filters.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/font_collection.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/image.dart + ../../../flutter/LICENSE
Expand Down Expand Up @@ -40634,6 +40635,7 @@ ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/shaders.da
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/surface.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/vertices.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_stub.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_stub/dart_js_conversion.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_stub/renderer.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/svg.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/test_embedding.dart + ../../../flutter/LICENSE
Expand Down Expand Up @@ -43471,6 +43473,7 @@ FILE: ../../../flutter/lib/web_ui/lib/src/engine/shadow.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/canvas.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/codecs.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/dart_js_conversion.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/filters.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/font_collection.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/image.dart
Expand Down Expand Up @@ -43507,6 +43510,7 @@ FILE: ../../../flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/shaders.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/surface.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/vertices.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_stub.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_stub/dart_js_conversion.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_stub/renderer.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/svg.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/test_embedding.dart
Expand Down
6 changes: 3 additions & 3 deletions lib/web_ui/lib/src/engine/canvaskit/native_memory.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ import 'package:ui/src/engine.dart';
/// 4. GC decides to perform a GC cycle and collects CkPaint.
/// 5. The finalizer function is called with the SkPaint as the sole argument.
/// 6. We call `delete` on SkPaint.
DomFinalizationRegistry _finalizationRegistry = createDomFinalizationRegistry(
DomFinalizationRegistry _finalizationRegistry = DomFinalizationRegistry(
(JSBoxedDartObject boxedUniq) {
final UniqueRef<Object> uniq = boxedUniq.toDart as UniqueRef<Object>;
final UniqueRef<Object> uniq = boxedUniq.fromJSWrapper as UniqueRef<Object>;
uniq.collect();
}.toJS
);
Expand All @@ -34,7 +34,7 @@ NativeMemoryFinalizationRegistry nativeMemoryFinalizationRegistry = NativeMemory
class NativeMemoryFinalizationRegistry {
void register(Object owner, UniqueRef<Object> ref) {
if (browserSupportsFinalizationRegistry) {
_finalizationRegistry.register(owner, ref.toJSBox);
_finalizationRegistry.register(owner.toJSWrapper, ref.toJSWrapper);
}
}
}
Expand Down
52 changes: 29 additions & 23 deletions lib/web_ui/lib/src/engine/dom.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import 'dart:typed_data';

import 'package:js/js_util.dart' as js_util;
import 'package:meta/meta.dart';
import 'package:ui/src/engine/skwasm/skwasm_stub.dart' if (dart.library.ffi) 'package:ui/src/engine/skwasm/skwasm_impl.dart';

import 'browser_detection.dart';

Expand Down Expand Up @@ -37,6 +38,15 @@ import 'browser_detection.dart';
/// used carefully and only on types that are known to not contains `JSNull` and
/// `JSUndefined`.
extension ObjectToJSAnyExtension on Object {
// Once `Object.toJSBox` is faster (see
// https://github.com/dart-lang/sdk/issues/55183) we can remove this
// backend-specific workaround.
@pragma('wasm:prefer-inline')
@pragma('dart2js:tryInline')
JSAny get toJSWrapper => dartToJsWrapper(this);

@pragma('wasm:prefer-inline')
@pragma('dart2js:tryInline')
JSAny get toJSAnyShallow {
if (isWasm) {
return toJSAnyDeep;
Expand All @@ -45,10 +55,18 @@ extension ObjectToJSAnyExtension on Object {
}
}

@pragma('wasm:prefer-inline')
@pragma('dart2js:tryInline')
JSAny get toJSAnyDeep => js_util.jsify(this) as JSAny;
}

extension JSAnyToObjectExtension on JSAny {
@pragma('wasm:prefer-inline')
@pragma('dart2js:tryInline')
Object get fromJSWrapper => jsWrapperToDart(this);

@pragma('wasm:prefer-inline')
@pragma('dart2js:tryInline')
Object get toObjectShallow {
if (isWasm) {
return toObjectDeep;
Expand All @@ -57,6 +75,8 @@ extension JSAnyToObjectExtension on JSAny {
}
}

@pragma('wasm:prefer-inline')
@pragma('dart2js:tryInline')
Object get toObjectDeep => js_util.dartify(this)!;
}

Expand Down Expand Up @@ -3648,38 +3668,24 @@ extension DomTextDecoderExtension on DomTextDecoder {

@JS('window.FinalizationRegistry')
@staticInterop
class DomFinalizationRegistry {}

@JS('window.FinalizationRegistry')
external JSAny? get _finalizationRegistryConstructor;

// Note: We don't use a factory constructor here because there is an issue in
// dart2js that causes a crash in the Google3 build if we do use a factory
// constructor. See b/284478971
DomFinalizationRegistry createDomFinalizationRegistry(JSFunction cleanup) =>
js_util.callConstructor(
_finalizationRegistryConstructor!.toObjectShallow, <Object>[cleanup]);
class DomFinalizationRegistry {
external factory DomFinalizationRegistry(JSFunction cleanup);
}

extension DomFinalizationRegistryExtension on DomFinalizationRegistry {
@JS('register')
external JSVoid _register1(JSAny target, JSAny value);
external JSVoid register(JSAny target, JSAny value);

@JS('register')
external JSVoid _register2(JSAny target, JSAny value, JSAny token);
void register(Object target, Object value, [Object? token]) {
if (token != null) {
_register2(
target.toJSAnyShallow, value.toJSAnyShallow, token.toJSAnyShallow);
} else {
_register1(target.toJSAnyShallow, value.toJSAnyShallow);
}
}
external JSVoid registerWithToken(JSAny target, JSAny value, JSAny token);

@JS('unregister')
external JSVoid _unregister(JSAny token);
void unregister(Object token) => _unregister(token.toJSAnyShallow);
external JSVoid unregister(JSAny token);
}

@JS('window.FinalizationRegistry')
external JSAny? get _finalizationRegistryConstructor;

/// Whether the current browser supports `FinalizationRegistry`.
bool browserSupportsFinalizationRegistry =
_finalizationRegistryConstructor != null;
Expand Down
1 change: 1 addition & 0 deletions lib/web_ui/lib/src/engine/skwasm/skwasm_impl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import 'dart:ffi';

export 'skwasm_impl/canvas.dart';
export 'skwasm_impl/codecs.dart';
export 'skwasm_impl/dart_js_conversion.dart';
export 'skwasm_impl/filters.dart';
export 'skwasm_impl/font_collection.dart';
export 'skwasm_impl/image.dart';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:_wasm';
import 'dart:js_interop';

@pragma('wasm:prefer-inline')
@pragma('dart2js:tryInline')
JSAny dartToJsWrapper(Object object) =>
WasmAnyRef.fromObject(object).externalize().toJS;

@pragma('wasm:prefer-inline')
@pragma('dart2js:tryInline')
Object jsWrapperToDart(JSAny jsWrapper) =>
externRefForJSAny(jsWrapper).internalize()!.toObject();
9 changes: 6 additions & 3 deletions lib/web_ui/lib/src/engine/skwasm/skwasm_impl/memory.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,22 @@ typedef DisposeFunction<T extends NativeType> = void Function(Pointer<T>);

class SkwasmFinalizationRegistry<T extends NativeType> {
SkwasmFinalizationRegistry(this.dispose)
: registry = createDomFinalizationRegistry(((JSNumber address) =>
: registry = DomFinalizationRegistry(((JSNumber address) =>
dispose(Pointer<T>.fromAddress(address.toDartDouble.toInt()))
).toJS);

final DomFinalizationRegistry registry;
final DisposeFunction<T> dispose;

void register(SkwasmObjectWrapper<T> wrapper) {
registry.register(wrapper, wrapper.handle.address, wrapper);
final JSAny jsWrapper = wrapper.toJSWrapper;
registry.registerWithToken(
jsWrapper, wrapper.handle.address.toJS, jsWrapper);
}

void evict(SkwasmObjectWrapper<T> wrapper) {
registry.unregister(wrapper);
final JSAny jsWrapper = wrapper.toJSWrapper;
registry.unregister(jsWrapper);
dispose(wrapper.handle);
}
}
1 change: 1 addition & 0 deletions lib/web_ui/lib/src/engine/skwasm/skwasm_stub.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@
// ignore: unnecessary_library_directive
library skwasm_stub;

export 'skwasm_stub/dart_js_conversion.dart';
export 'skwasm_stub/renderer.dart';
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:js_interop';

@pragma('wasm:prefer-inline')
@pragma('dart2js:tryInline')
JSAny dartToJsWrapper(Object object) => object as JSAny;

@pragma('wasm:prefer-inline')
@pragma('dart2js:tryInline')
Object jsWrapperToDart(JSAny jsWrapper) => jsWrapper;
4 changes: 2 additions & 2 deletions lib/web_ui/test/canvaskit/canvaskit_api_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1928,8 +1928,8 @@ void _paragraphTests() {
// FinalizationRegistry because it depends on GC, which cannot be controlled,
// So the test simply tests that a FinalizationRegistry can be constructed
// and its `register` method can be called.
final DomFinalizationRegistry registry = createDomFinalizationRegistry((String arg) {}.toJS);
registry.register(Object(), Object());
final DomFinalizationRegistry registry = DomFinalizationRegistry((String arg) {}.toJS);
registry.register(Object().toJSWrapper, Object().toJSWrapper);
});
}

Expand Down