[VM/Runtime] - Account for TransferableTypedData in Api Messages
Account for TransferableTypedData when receiving messages in
native ports and not crash.
TEST=added new API test
Bug:47686
Change-Id: I2dfad694532f544df3000cd97015089ebb5176fa
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/222031
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Siva Annamalai <asiva@google.com>
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 5a9050a..426bb94 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -7854,7 +7854,8 @@
"'foo1:///.dart_tool");
}
-void NewNativePort_send123(Dart_Port dest_port_id, Dart_CObject* message) {
+static void NewNativePort_send123(Dart_Port dest_port_id,
+ Dart_CObject* message) {
// Gets a send port message.
EXPECT_NOTNULL(message);
EXPECT_EQ(Dart_CObject_kArray, message->type);
@@ -7869,7 +7870,8 @@
response);
}
-void NewNativePort_send321(Dart_Port dest_port_id, Dart_CObject* message) {
+static void NewNativePort_send321(Dart_Port dest_port_id,
+ Dart_CObject* message) {
// Gets a null message.
EXPECT_NOTNULL(message);
EXPECT_EQ(Dart_CObject_kArray, message->type);
@@ -7978,8 +7980,8 @@
EXPECT(Dart_CloseNativePort(port_id2));
}
-void NewNativePort_sendInteger123(Dart_Port dest_port_id,
- Dart_CObject* message) {
+static void NewNativePort_sendInteger123(Dart_Port dest_port_id,
+ Dart_CObject* message) {
// Gets a send port message.
EXPECT_NOTNULL(message);
EXPECT_EQ(Dart_CObject_kArray, message->type);
@@ -7990,8 +7992,8 @@
123);
}
-void NewNativePort_sendInteger321(Dart_Port dest_port_id,
- Dart_CObject* message) {
+static void NewNativePort_sendInteger321(Dart_Port dest_port_id,
+ Dart_CObject* message) {
// Gets a null message.
EXPECT_NOTNULL(message);
EXPECT_EQ(Dart_CObject_kArray, message->type);
@@ -8053,8 +8055,74 @@
EXPECT(Dart_CloseNativePort(port_id2));
}
-void NewNativePort_nativeReceiveNull(Dart_Port dest_port_id,
- Dart_CObject* message) {
+static void NewNativePort_Transferrable1(Dart_Port dest_port_id,
+ Dart_CObject* message) {
+ // Gets a send port message.
+ EXPECT_NOTNULL(message);
+ EXPECT_EQ(Dart_CObject_kTypedData, message->type);
+ EXPECT_EQ(Dart_TypedData_kUint8, message->value.as_typed_data.type);
+ EXPECT_EQ(10, message->value.as_typed_data.length);
+ EXPECT_EQ(42, message->value.as_typed_data.values[0]);
+ free(message->value.as_typed_data.values);
+}
+
+static void NewNativePort_Transferrable2(Dart_Port dest_port_id,
+ Dart_CObject* message) {
+ // Gets a send port message.
+ EXPECT_NOTNULL(message);
+ EXPECT_EQ(Dart_CObject_kArray, message->type);
+ EXPECT_EQ(1, message->value.as_array.length);
+ Dart_CObject* cobj = message->value.as_array.values[0];
+ EXPECT_EQ(Dart_CObject_kTypedData, cobj->type);
+ EXPECT_EQ(Dart_TypedData_kUint8, cobj->value.as_typed_data.type);
+ EXPECT_EQ(10, cobj->value.as_typed_data.length);
+ EXPECT_EQ(42, cobj->value.as_typed_data.values[0]);
+ free(cobj->value.as_typed_data.values);
+}
+
+TEST_CASE(DartAPI_NativePortPostTransferrableTypedData) {
+ const char* kScriptChars =
+ "import 'dart:typed_data';\n"
+ "import 'dart:isolate';\n"
+ "void callPort(SendPort port1, SendPort port2) {\n"
+ " final td1 ="
+ " TransferableTypedData.fromList([Uint8List(10)..[0] = 42]);\n"
+ " final td2 ="
+ " TransferableTypedData.fromList([Uint8List(10)..[0] = 42]);\n"
+ " port1.send(td1);\n"
+ " port2.send([td2]);\n"
+ "}\n";
+ Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
+ Dart_EnterScope();
+
+ Dart_Port port_id1 =
+ Dart_NewNativePort("Port123", NewNativePort_Transferrable1, true);
+ Dart_Port port_id2 =
+ Dart_NewNativePort("Port321", NewNativePort_Transferrable2, true);
+
+ Dart_Handle send_port1 = Dart_NewSendPort(port_id1);
+ EXPECT_VALID(send_port1);
+ Dart_Handle send_port2 = Dart_NewSendPort(port_id2);
+ EXPECT_VALID(send_port2);
+
+ // Test first port.
+ Dart_Handle dart_args[2];
+ dart_args[0] = send_port1;
+ dart_args[1] = send_port2;
+ Dart_Handle result = Dart_Invoke(lib, NewString("callPort"), 2, dart_args);
+ EXPECT_VALID(result);
+ result = Dart_RunLoop();
+ EXPECT_VALID(result);
+
+ Dart_ExitScope();
+
+ // Delete the native ports.
+ EXPECT(Dart_CloseNativePort(port_id1));
+ EXPECT(Dart_CloseNativePort(port_id2));
+}
+
+static void NewNativePort_nativeReceiveNull(Dart_Port dest_port_id,
+ Dart_CObject* message) {
EXPECT_NOTNULL(message);
if ((message->type == Dart_CObject_kArray) &&
@@ -8104,8 +8172,8 @@
EXPECT(Dart_CloseNativePort(port_id1));
}
-void NewNativePort_nativeReceiveInteger(Dart_Port dest_port_id,
- Dart_CObject* message) {
+static void NewNativePort_nativeReceiveInteger(Dart_Port dest_port_id,
+ Dart_CObject* message) {
EXPECT_NOTNULL(message);
if ((message->type == Dart_CObject_kArray) &&
diff --git a/runtime/vm/message_snapshot.cc b/runtime/vm/message_snapshot.cc
index 4733db0..afc2bc3 100644
--- a/runtime/vm/message_snapshot.cc
+++ b/runtime/vm/message_snapshot.cc
@@ -2133,6 +2133,19 @@
reinterpret_cast<uint8_t*>(finalizable_data.data), length));
}
}
+
+ void ReadNodesApi(ApiMessageDeserializer* d) {
+ intptr_t count = d->ReadUnsigned();
+ for (intptr_t i = 0; i < count; i++) {
+ Dart_CObject* data = d->Allocate(Dart_CObject_kTypedData);
+ data->value.as_typed_data.length = d->ReadUnsigned();
+ data->value.as_typed_data.type = Dart_TypedData_kUint8;
+ FinalizableData finalizable_data = d->finalizable_data()->Get();
+ data->value.as_typed_data.values =
+ reinterpret_cast<uint8_t*>(finalizable_data.data);
+ d->AssignRef(data);
+ }
+ }
};
class Simd128MessageSerializationCluster : public MessageSerializationCluster {