@@ -126,11 +126,18 @@ class DeserializerDelegate : public ValueDeserializer::Delegate {
126126} // anonymous namespace
127127
128128MaybeLocal<Value> Message::Deserialize (Environment* env,
129- Local<Context> context) {
129+ Local<Context> context,
130+ Local<Value>* port_list) {
131+ Context::Scope context_scope (context);
132+
130133 CHECK (!IsCloseMessage ());
134+ if (port_list != nullptr && !transferables_.empty ()) {
135+ // Need to create this outside of the EscapableHandleScope, but inside
136+ // the Context::Scope.
137+ *port_list = Array::New (env->isolate ());
138+ }
131139
132140 EscapableHandleScope handle_scope (env->isolate ());
133- Context::Scope context_scope (context);
134141
135142 // Create all necessary objects for transferables, e.g. MessagePort handles.
136143 std::vector<BaseObjectPtr<BaseObject>> host_objects (transferables_.size ());
@@ -146,10 +153,27 @@ MaybeLocal<Value> Message::Deserialize(Environment* env,
146153 });
147154
148155 for (uint32_t i = 0 ; i < transferables_.size (); ++i) {
156+ HandleScope handle_scope (env->isolate ());
149157 TransferData* data = transferables_[i].get ();
150158 host_objects[i] = data->Deserialize (
151159 env, context, std::move (transferables_[i]));
152160 if (!host_objects[i]) return {};
161+ if (port_list != nullptr ) {
162+ // If we gather a list of all message ports, and this transferred object
163+ // is a message port, add it to that list. This is a bit of an odd case
164+ // of special handling for MessagePorts (as opposed to applying to all
165+ // transferables), but it's required for spec compliancy.
166+ DCHECK ((*port_list)->IsArray ());
167+ Local<Array> port_list_array = port_list->As <Array>();
168+ Local<Object> obj = host_objects[i]->object ();
169+ if (env->message_port_constructor_template ()->HasInstance (obj)) {
170+ if (port_list_array->Set (context,
171+ port_list_array->Length (),
172+ obj).IsNothing ()) {
173+ return {};
174+ }
175+ }
176+ }
153177 }
154178 transferables_.clear ();
155179
@@ -664,7 +688,8 @@ MessagePort* MessagePort::New(
664688}
665689
666690MaybeLocal<Value> MessagePort::ReceiveMessage (Local<Context> context,
667- MessageProcessingMode mode) {
691+ MessageProcessingMode mode,
692+ Local<Value>* port_list) {
668693 std::shared_ptr<Message> received;
669694 {
670695 // Get the head of the message queue.
@@ -696,7 +721,7 @@ MaybeLocal<Value> MessagePort::ReceiveMessage(Local<Context> context,
696721
697722 if (!env ()->can_call_into_js ()) return MaybeLocal<Value>();
698723
699- return received->Deserialize (env (), context);
724+ return received->Deserialize (env (), context, port_list );
700725}
701726
702727void MessagePort::OnMessage (MessageProcessingMode mode) {
@@ -735,14 +760,15 @@ void MessagePort::OnMessage(MessageProcessingMode mode) {
735760 Local<Function> emit_message = PersistentToLocal::Strong (emit_message_fn_);
736761
737762 Local<Value> payload;
763+ Local<Value> port_list = Undefined (env ()->isolate ());
738764 Local<Value> message_error;
739- Local<Value> argv[2 ];
765+ Local<Value> argv[3 ];
740766
741767 {
742768 // Catch any exceptions from parsing the message itself (not from
743769 // emitting it) as 'messageeror' events.
744770 TryCatchScope try_catch (env ());
745- if (!ReceiveMessage (context, mode).ToLocal (&payload)) {
771+ if (!ReceiveMessage (context, mode, &port_list ).ToLocal (&payload)) {
746772 if (try_catch.HasCaught () && !try_catch.HasTerminated ())
747773 message_error = try_catch.Exception ();
748774 goto reschedule;
@@ -757,13 +783,15 @@ void MessagePort::OnMessage(MessageProcessingMode mode) {
757783 }
758784
759785 argv[0 ] = payload;
760- argv[1 ] = env ()->message_string ();
786+ argv[1 ] = port_list;
787+ argv[2 ] = env ()->message_string ();
761788
762789 if (MakeCallback (emit_message, arraysize (argv), argv).IsEmpty ()) {
763790 reschedule:
764791 if (!message_error.IsEmpty ()) {
765792 argv[0 ] = message_error;
766- argv[1 ] = env ()->messageerror_string ();
793+ argv[1 ] = Undefined (env ()->isolate ());
794+ argv[2 ] = env ()->messageerror_string ();
767795 USE (MakeCallback (emit_message, arraysize (argv), argv));
768796 }
769797
0 commit comments