@@ -202,18 +202,22 @@ bool IsolateMessageHandler::HandleLibMessage(const Array& message) {
202
202
break ;
203
203
}
204
204
case kPingMsg : {
205
- // [ OOB, kPingMsg, responsePort, priority ]
206
- if (message.Length () != 4 ) return true ;
205
+ // [ OOB, kPingMsg, responsePort, priority, response ]
206
+ if (message.Length () != 5 ) return true ;
207
207
const Object& obj2 = Object::Handle (I, message.At (2 ));
208
208
if (!obj2.IsSendPort ()) return true ;
209
209
const SendPort& send_port = SendPort::Cast (obj2);
210
210
const Object& obj3 = Object::Handle (I, message.At (3 ));
211
211
if (!obj3.IsSmi ()) return true ;
212
212
const intptr_t priority = Smi::Cast (obj3).Value ();
213
+ const Object& obj4 = Object::Handle (I, message.At (4 ));
214
+ if (!obj4.IsInstance () && !obj4.IsNull ()) return true ;
215
+ const Instance& response =
216
+ obj4.IsNull () ? Instance::null_instance () : Instance::Cast (obj4);
213
217
if (priority == kImmediateAction ) {
214
218
uint8_t * data = NULL ;
215
219
intptr_t len = 0 ;
216
- SerializeObject (Object::null_instance () , &data, &len, false );
220
+ SerializeObject (response , &data, &len, false );
217
221
PortMap::PostMessage (new Message (send_port.Id (),
218
222
data, len,
219
223
Message::kNormalPriority ));
@@ -268,21 +272,31 @@ bool IsolateMessageHandler::HandleLibMessage(const Array& message) {
268
272
case kAddErrorMsg :
269
273
case kDelErrorMsg : {
270
274
// [ OOB, msg, listener port ]
271
- if (message.Length () != 3 ) return true ;
275
+ if (message.Length () < 3 ) return true ;
272
276
const Object& obj = Object::Handle (I, message.At (2 ));
273
277
if (!obj.IsSendPort ()) return true ;
274
278
const SendPort& listener = SendPort::Cast (obj);
275
279
switch (msg_type) {
276
- case kAddExitMsg :
277
- I->AddExitListener (listener);
280
+ case kAddExitMsg : {
281
+ if (message.Length () != 4 ) return true ;
282
+ // [ OOB, msg, listener port, response object ]
283
+ const Object& response = Object::Handle (I, message.At (3 ));
284
+ if (!response.IsInstance () && !response.IsNull ()) return true ;
285
+ I->AddExitListener (listener,
286
+ response.IsNull () ? Instance::null_instance ()
287
+ : Instance::Cast (response));
278
288
break ;
289
+ }
279
290
case kDelExitMsg :
291
+ if (message.Length () != 3 ) return true ;
280
292
I->RemoveExitListener (listener);
281
293
break ;
282
294
case kAddErrorMsg :
295
+ if (message.Length () != 3 ) return true ;
283
296
I->AddErrorListener (listener);
284
297
break ;
285
298
case kDelErrorMsg :
299
+ if (message.Length () != 3 ) return true ;
286
300
I->RemoveErrorListener (listener);
287
301
break ;
288
302
default :
@@ -1002,21 +1016,23 @@ bool Isolate::RemoveResumeCapability(const Capability& capability) {
1002
1016
1003
1017
// TODO(iposva): Remove duplicated code and start using some hash based
1004
1018
// structure instead of these linear lookups.
1005
- void Isolate::AddExitListener (const SendPort& listener) {
1019
+ void Isolate::AddExitListener (const SendPort& listener,
1020
+ const Instance& response) {
1006
1021
// Ensure a limit for the number of listeners remembered.
1007
- static const intptr_t kMaxListeners = kSmiMax / (6 * kWordSize );
1022
+ static const intptr_t kMaxListeners = kSmiMax / (12 * kWordSize );
1008
1023
1009
1024
const GrowableObjectArray& listeners = GrowableObjectArray::Handle (
1010
1025
this , object_store ()->exit_listeners ());
1011
1026
SendPort& current = SendPort::Handle (this );
1012
1027
intptr_t insertion_index = -1 ;
1013
- for (intptr_t i = 0 ; i < listeners.Length (); i++ ) {
1028
+ for (intptr_t i = 0 ; i < listeners.Length (); i += 2 ) {
1014
1029
current ^= listeners.At (i);
1015
1030
if (current.IsNull ()) {
1016
1031
if (insertion_index < 0 ) {
1017
1032
insertion_index = i;
1018
1033
}
1019
1034
} else if (current.Id () == listener.Id ()) {
1035
+ listeners.SetAt (i + 1 , response);
1020
1036
return ;
1021
1037
}
1022
1038
}
@@ -1028,8 +1044,10 @@ void Isolate::AddExitListener(const SendPort& listener) {
1028
1044
return ;
1029
1045
}
1030
1046
listeners.Add (listener);
1047
+ listeners.Add (response);
1031
1048
} else {
1032
1049
listeners.SetAt (insertion_index, listener);
1050
+ listeners.SetAt (insertion_index + 1 , response);
1033
1051
}
1034
1052
}
1035
1053
@@ -1038,12 +1056,13 @@ void Isolate::RemoveExitListener(const SendPort& listener) {
1038
1056
const GrowableObjectArray& listeners = GrowableObjectArray::Handle (
1039
1057
this , object_store ()->exit_listeners ());
1040
1058
SendPort& current = SendPort::Handle (this );
1041
- for (intptr_t i = 0 ; i < listeners.Length (); i++ ) {
1059
+ for (intptr_t i = 0 ; i < listeners.Length (); i += 2 ) {
1042
1060
current ^= listeners.At (i);
1043
1061
if (!current.IsNull () && (current.Id () == listener.Id ())) {
1044
1062
// Remove the matching listener from the list.
1045
1063
current = SendPort::null ();
1046
1064
listeners.SetAt (i, current);
1065
+ listeners.SetAt (i + 1 , Object::null_instance ());
1047
1066
return ;
1048
1067
}
1049
1068
}
@@ -1056,13 +1075,15 @@ void Isolate::NotifyExitListeners() {
1056
1075
if (listeners.IsNull ()) return ;
1057
1076
1058
1077
SendPort& listener = SendPort::Handle (this );
1059
- for (intptr_t i = 0 ; i < listeners.Length (); i++) {
1078
+ Instance& response = Instance::Handle (this );
1079
+ for (intptr_t i = 0 ; i < listeners.Length (); i += 2 ) {
1060
1080
listener ^= listeners.At (i);
1061
1081
if (!listener.IsNull ()) {
1062
1082
Dart_Port port_id = listener.Id ();
1063
1083
uint8_t * data = NULL ;
1064
1084
intptr_t len = 0 ;
1065
- SerializeObject (Object::null_instance (), &data, &len, false );
1085
+ response ^= listeners.At (i + 1 );
1086
+ SerializeObject (response, &data, &len, false );
1066
1087
Message* msg = new Message (port_id, data, len, Message::kNormalPriority );
1067
1088
PortMap::PostMessage (msg);
1068
1089
}
0 commit comments