dart-lang / sdk

The Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.
https://dart.dev
BSD 3-Clause "New" or "Revised" License
10.19k stars 1.56k forks source link

Invalid argument(s): Dart_TypedDataAcquireData expects argument 'object' to be of type 'TypedData'. #39901

Open MarcelGarus opened 4 years ago

MarcelGarus commented 4 years ago

I encountered the error Invalid argument(s): Dart_TypedDataAcquireData expects argument 'object' to be of type 'TypedData'. with the following stack trace when adding a Uint8List to a socket:

#0      _NativeSocket.nativeWrite (dart:io-patch/socket_patch.dart:1222:32)
#1      _NativeSocket.write (dart:io-patch/socket_patch.dart:786:9)
#2      _RawSocket.write (dart:io-patch/socket_patch.dart:1442:15)
#3      _Socket._write (dart:io-patch/socket_patch.dart:1862:19)
#4      _SocketStreamConsumer.write (dart:io-patch/socket_patch.dart:1617:22)
#5      _SocketStreamConsumer.addStream.<anonymous closure> (dart:io-patch/socket_patch.dart:1592:11)
#6      _RootZone.runUnaryGuarded (dart:async/zone.dart:1316:10)
#7      _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:338:11)
#8      _BufferingStreamSubscription._add (dart:async/stream_impl.dart:265:7)
#9      _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:766:19)
#10     _StreamController._add (dart:async/stream_controller.dart:642:7)
#11     _StreamController.add (dart:async/stream_controller.dart:588:5)
#12     _StreamSinkImpl.add (dart:io/io_sink.dart:158:17)
#13     _Socket.add (dart:io-patch/socket_patch.dart:1714:38)
#14     EncryptedConnection.send (package:portals/src/client_connection.dart:110:42)
#15     EncryptedConnection.ensureEncryptionAndMeasureLatency (package:portals/src/client_connection.dart:123:5)
<asynchronous suspension>
#16     EncryptedConnection.establish (package:portals/src/client_connection.dart:99:22)
#17     DilatedConnection.establishConnection (package:portals/src/client_connection.dart:58:35)
<asynchronous suspension>
#18     Portal._setupLink (package:portals/src/portal.dart:89:19)
<asynchronous suspension>
#19     Portal.waitForLink (package:portals/src/portal.dart:60:18)
#20     main (package:portals/main.dart:14:28)
<asynchronous suspension>
#21     _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:307:19)
#22     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:174:12)

Turns out, I passed in an EncryptedMessage from the pinenacl package, which extends Uint8List. Apparently, Sockets only accept pure Uint8Lists and not objects that extend one.

As sockets are pretty low-level, that may make sense implementation-wise, but it's dangerous because it goes against the object-oriented paradigms of Dart. If this behavior is intended, at least the analyzer should warn me and it should be made clear in the documentation.

I'm using Dart 2.7.0 on Windows.

sortie commented 4 years ago

It appears to be the native calls in the socket patch that doesn't support custom List<int> implementations.

  nativeWrite(List<int> buffer, int offset, int bytes)
      native "Socket_WriteList";

I supposing Dart_TypedDataAcquireData can't serialize a custom List<int> implementation when calling into the C++ code.

@lrhn Might you have an opinion on this? I'm thinking the proper fix is to find all native calls expecting a List and to wrap the callers, so they turn the List into a native List. Either that or having the native call support automatically do this.

ahmadSaeedGoda commented 2 years ago

coming from 2022 Feb. using Dart SDK version: 2.12.0 (stable) (Thu Feb 25 19:50:53 2021 +0100) on "linux_x64" to ask for any updates on this!

Can you please advise?