未验证 提交 b6be9377 编写于 作者: J Jason Simmons 提交者: GitHub

Create message response external typed data objects as Uint8Lists (#5101)

PlatformMessageResponseDart will wrap large responses in Dart external typed
data objects in order to avoid copying the data into a new buffer.

Previously these objects were created with the Dart_TypedData_kByteData type.
A weak persistent handle is then associated with the ByteData to provide a
finalizer that deletes the raw buffer.  However, the Dart VM could call
finalizer on the ByteData even if references still existed to the Dart ByteBuffer
object backing the ByteData.  The ByteBuffer would then be referencing a deleted
raw buffer.

This PR prevents that scenario by creating a Dart_TypedData_kUint8 object,
attaching the finalizer to that object, and then wrapping it in a ByteData.
上级 bd3f2f79
......@@ -22,6 +22,10 @@ typedef void SemanticsActionCallback(int id, SemanticsAction action, ByteData ar
/// [Window.onPlatformMessage].
typedef void PlatformMessageResponseCallback(ByteData data);
// The engine returns message responses as a Uint8List which is then wrapped
// in a ByteData.
typedef void _InternalPlatformMessageResponseCallback(Uint8List data);
/// Signature for [Window.onPlatformMessage].
typedef void PlatformMessageCallback(String name, ByteData data, PlatformMessageResponseCallback callback);
......@@ -687,7 +691,7 @@ class Window {
throw new Exception(error);
}
String _sendPlatformMessage(String name,
PlatformMessageResponseCallback callback,
_InternalPlatformMessageResponseCallback callback,
ByteData data) native 'Window_sendPlatformMessage';
/// Called whenever this window receives a message from a platform-specific
......@@ -717,15 +721,15 @@ class Window {
/// Wraps the given [callback] in another callback that ensures that the
/// original callback is called in the zone it was registered in.
static PlatformMessageResponseCallback _zonedPlatformMessageResponseCallback(PlatformMessageResponseCallback callback) {
static _InternalPlatformMessageResponseCallback _zonedPlatformMessageResponseCallback(PlatformMessageResponseCallback callback) {
if (callback == null)
return null;
// Store the zone in which the callback is being registered.
final Zone registrationZone = Zone.current;
return (ByteData data) {
registrationZone.runUnaryGuarded(callback, data);
return (Uint8List data) {
registrationZone.runUnaryGuarded(callback, data.buffer.asByteData());
};
}
}
......
......@@ -28,11 +28,11 @@ void MessageDataFinalizer(void* isolate_callback_data,
Dart_Handle WrapByteData(std::vector<uint8_t> data) {
if (data.size() < kMessageCopyThreshold) {
return ToByteData(data);
return ToTypedData(Dart_TypedData_kUint8, data);
} else {
std::vector<uint8_t>* heap_data = new std::vector<uint8_t>(std::move(data));
Dart_Handle data_handle = Dart_NewExternalTypedData(
Dart_TypedData_kByteData, heap_data->data(), heap_data->size());
Dart_TypedData_kUint8, heap_data->data(), heap_data->size());
DART_CHECK_VALID(data_handle);
Dart_NewWeakPersistentHandle(data_handle, heap_data, heap_data->size(),
MessageDataFinalizer);
......
......@@ -112,8 +112,16 @@ void _RespondToPlatformMessage(Dart_NativeArguments args) {
} // namespace
Dart_Handle ToByteData(const std::vector<uint8_t>& buffer) {
Dart_Handle data_handle =
Dart_NewTypedData(Dart_TypedData_kByteData, buffer.size());
return ToTypedData(Dart_TypedData_kByteData, buffer);
}
Dart_Handle ToTypedData(Dart_TypedData_Type data_type,
const std::vector<uint8_t>& buffer) {
FXL_DCHECK(data_type == Dart_TypedData_kByteData ||
data_type == Dart_TypedData_kInt8 ||
data_type == Dart_TypedData_kUint8);
Dart_Handle data_handle = Dart_NewTypedData(data_type, buffer.size());
if (Dart_IsError(data_handle))
return data_handle;
......
......@@ -24,6 +24,9 @@ class Scene;
Dart_Handle ToByteData(const std::vector<uint8_t>& buffer);
Dart_Handle ToTypedData(Dart_TypedData_Type data_type,
const std::vector<uint8_t>& buffer);
class WindowClient {
public:
virtual std::string DefaultRouteName() = 0;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册