diff --git a/lib/web_ui/lib/src/engine/canvaskit/image_web_codecs.dart b/lib/web_ui/lib/src/engine/canvaskit/image_web_codecs.dart index 6eb9ed1f7257b..b12f1e18cf991 100644 --- a/lib/web_ui/lib/src/engine/canvaskit/image_web_codecs.dart +++ b/lib/web_ui/lib/src/engine/canvaskit/image_web_codecs.dart @@ -14,6 +14,7 @@ import 'dart:js_interop'; import 'dart:math' as math; import 'dart:typed_data'; +import 'package:js/js.dart'; import 'package:meta/meta.dart'; import 'package:ui/ui.dart' as ui; @@ -439,12 +440,24 @@ bool _shouldReadPixelsUnmodified(VideoFrame videoFrame, ui.ImageByteFormat forma return format == ui.ImageByteFormat.rawRgba && isRgbFrame; } +@JS('Uint8Array') +@staticInterop +class _JSUint8Array { + external factory _JSUint8Array(JSNumber length); +} + Future readVideoFramePixelsUnmodified(VideoFrame videoFrame) async { final int size = videoFrame.allocationSize().toInt(); - final Uint8List destination = Uint8List(size); + + // In dart2wasm, Uint8List is not the same as a JS Uint8Array. So we + // explicitly construct the JS object here. + final JSUint8Array destination = _JSUint8Array(size.toJS) as JSUint8Array; final JsPromise copyPromise = videoFrame.copyTo(destination); await promiseToFuture(copyPromise); - return destination.buffer; + + // In dart2wasm, `toDart` incurs a copy here. On JS backends, this is a + // no-op. + return destination.toDart.buffer; } Future encodeVideoFrameAsPng(VideoFrame videoFrame) async { diff --git a/lib/web_ui/test/canvaskit/canvas_golden_test.dart b/lib/web_ui/test/canvaskit/canvas_golden_test.dart index 5d77675283f84..36cdf783135aa 100644 --- a/lib/web_ui/test/canvaskit/canvas_golden_test.dart +++ b/lib/web_ui/test/canvaskit/canvas_golden_test.dart @@ -802,7 +802,7 @@ void testMain() { test('emoji text with skin tone', () async { await testSampleText('emoji_with_skin_tone', '👋🏿 👋🏾 👋🏽 👋🏼 👋🏻'); - }, skip: isWasm || isSafari || isFirefox); // https://github.com/flutter/flutter/issues/124068 + }, timeout: const Timeout.factor(2)); // Make sure we clear the canvas in between frames. test('empty frame after contentful frame', () async { diff --git a/lib/web_ui/test/canvaskit/image_golden_test.dart b/lib/web_ui/test/canvaskit/image_golden_test.dart index ffc9507620f2e..5f8f83f2f2dd1 100644 --- a/lib/web_ui/test/canvaskit/image_golden_test.dart +++ b/lib/web_ui/test/canvaskit/image_golden_test.dart @@ -887,9 +887,7 @@ void _testCkBrowserImageDecoder() { expect(rgba!.buffer.asUint8List(), expectedColors[i]); } testCollector.collectNow(); - // TODO(jacksongardner): enable on wasm - // see https://github.com/flutter/flutter/issues/118334 - }, skip: isWasm); + }); test('ImageDecoder expires after inactivity', () async { const Duration testExpireDuration = Duration(milliseconds: 100); @@ -934,9 +932,7 @@ void _testCkBrowserImageDecoder() { testCollector.collectNow(); debugRestoreWebDecoderExpireDuration(); - // TODO(jacksongardner): enable on wasm - // see https://github.com/flutter/flutter/issues/118334 - }, skip: isWasm); + }); } Future expectFrameData(ui.FrameInfo frame, List data) async { diff --git a/lib/web_ui/test/engine/channel_buffers_test.dart b/lib/web_ui/test/engine/channel_buffers_test.dart index bd72acab10978..6fc91100aec92 100644 --- a/lib/web_ui/test/engine/channel_buffers_test.dart +++ b/lib/web_ui/test/engine/channel_buffers_test.dart @@ -271,7 +271,7 @@ void testMain() { 'b: seven', '-9', ]); - }, skip: isWasm); // https://github.com/dart-lang/sdk/issues/50778 + }); test('ChannelBuffers.clearListener', () async { final List log = []; @@ -365,7 +365,7 @@ void testMain() { 'callback1: true', 'callback2: true', ]); - }, skip: isWasm); // https://github.com/dart-lang/sdk/issues/50778 + }); } class _TestChannelBuffers extends ui.ChannelBuffers {