-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[firebase_storage]: Upload fails with Uint8List is not a subtype of type 'JSValue' in type cast on Wasm #13458
Comments
@kevmoo CC |
Would you include a stack trace? Do you see anything in the chrome console? |
|
Uh oh, the issue affects image and file uploads as well. This isn't limited to data types. Image uploads don't work either. |
Hi @rayliverified , thanks for submitting this issue. I'm looking into it. |
I'm able to reproduce this issue. Steps to reproduce: Reproducible code: import 'dart:async';
import 'dart:convert';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'firebase_options.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(MyApp());
}
/// Enum representing the upload task types the example app supports.
enum UploadType {
/// Uploads a randomly generated string (as a file) to Storage.
string,
/// Uploads a file from the device.
file,
/// Clears any tasks from the list.
clear,
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool _isUploading = false;
Future<void> uploadToFirebaseStorage() async {
setState(() {
_isUploading = true;
});
try {
// Simulating API response
final response = '{"key": "value", "number": 42}';
final data = jsonDecode(response);
final ref = FirebaseStorage.instance
.ref()
.child('flutter-tests')
.child('/file.json');
await ref.putData(
Uint8List.fromList(utf8.encode(jsonEncode(data))),
);
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Upload successful!')),
);
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Upload failed: $e')),
);
} finally {
setState(() {
_isUploading = false;
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: _isUploading ? null : uploadToFirebaseStorage,
child: _isUploading
? const CircularProgressIndicator()
: const Text('Upload to Firebase Storage'),
),
],
),
),
);
}
} |
We need more testing here! There is a dynamic flowing through that needs to be turned into a JS type. For the ambitious, here's a patch to try to apply and validate. diff --git a/packages/firebase_storage/firebase_storage_web/lib/src/interop/storage.dart b/packages/firebase_storage/firebase_storage_web/lib/src/interop/storage.dart
index d0c0ba5c2..e5e9c3416 100644
--- a/packages/firebase_storage/firebase_storage_web/lib/src/interop/storage.dart
+++ b/packages/firebase_storage/firebase_storage_web/lib/src/interop/storage.dart
@@ -179,7 +179,7 @@ class StorageReference
/// Uploads data [blob] to the actual location with optional [metadata].
/// Returns the [UploadTask] which can be used to monitor and manage
/// the upload.
- UploadTask put(dynamic blob, [UploadMetadata? metadata]) {
+ UploadTask put(JSObject blob, [UploadMetadata? metadata]) {
storage_interop.UploadTaskJsImpl taskImpl;
if (metadata != null) {
taskImpl = storage_interop.uploadBytesResumable(
diff --git a/packages/firebase_storage/firebase_storage_web/lib/src/interop/storage_interop.dart b/packages/firebase_storage/firebase_storage_web/lib/src/interop/storage_interop.dart
index 064610e90..d8c9a9d52 100644
--- a/packages/firebase_storage/firebase_storage_web/lib/src/interop/storage_interop.dart
+++ b/packages/firebase_storage/firebase_storage_web/lib/src/interop/storage_interop.dart
@@ -67,7 +67,7 @@ external JSPromise /* FullMetadataJsImpl */ updateMetadata(
@JS()
@staticInterop
external UploadTaskJsImpl uploadBytesResumable(
- ReferenceJsImpl ref, JSAny /* Blob | Uint8Array | ArrayBuffer */ data,
+ ReferenceJsImpl ref, JSObject /* Blob | Uint8Array | ArrayBuffer */ data,
[UploadMetadataJsImpl? metadata]);
@JS()
diff --git a/packages/firebase_storage/firebase_storage_web/lib/src/reference_web.dart b/packages/firebase_storage/firebase_storage_web/lib/src/reference_web.dart
index 2ba54062b..7069ce5c1 100644
--- a/packages/firebase_storage/firebase_storage_web/lib/src/reference_web.dart
+++ b/packages/firebase_storage/firebase_storage_web/lib/src/reference_web.dart
@@ -4,6 +4,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:convert';
+import 'dart:js_interop';
import 'dart:typed_data';
import 'package:firebase_storage_platform_interface/firebase_storage_platform_interface.dart';
@@ -143,7 +144,7 @@ class ReferenceWeb extends ReferencePlatform {
return TaskWeb(
this,
_ref.put(
- data,
+ data.toJS,
settableMetadataToFbUploadMetadata(
_cache.store(metadata),
),
@@ -155,9 +156,7 @@ class ReferenceWeb extends ReferencePlatform {
///
/// Optionally, you can also set metadata onto the uploaded object.
@override
- TaskPlatform putBlob(dynamic data, [SettableMetadata? metadata]) {
- assert(data is web.Blob, 'data must be a package:web Blob object.');
-
+ TaskPlatform putBlob(covariant web.Blob data, [SettableMetadata? metadata]) {
return TaskWeb(
this,
_ref.put( |
Is there an existing issue for this?
Which plugins are affected?
Storage
Which platforms are affected?
Web
Description
Upload fails on Wasm with type error internally.
Sample Repo: https://github.com/rayliverified/flutter_storage_example
Reproducing the issue
Firebase Core version
3.7.0
Flutter Version
3.24.3
Relevant Log Output
No response
Flutter dependencies
Expand
Flutter dependencies
snippetAdditional context and comments
No response
The text was updated successfully, but these errors were encountered: