@@ -28,7 +28,6 @@ using v8::Maybe; |
28 | 28 | using v8::MaybeLocal; |
29 | 29 | using v8::Nothing; |
30 | 30 | using v8::Object; |
31 | | -using v8::ObjectTemplate; |
32 | 31 | using v8::SharedArrayBuffer; |
33 | 32 | using v8::String; |
34 | 33 | using v8::Symbol; |
@@ -188,6 +187,20 @@ uint32_t Message::AddWASMModule(WasmModuleObject::TransferrableModule&& mod) { |
188 | 187 |
|
189 | 188 | namespace { |
190 | 189 |
|
| 190 | +MaybeLocal<Function> GetEmitMessageFunction(Local<Context> context) { |
| 191 | + Isolate* isolate = context->GetIsolate(); |
| 192 | + Local<Object> per_context_bindings; |
| 193 | + Local<Value> emit_message_val; |
| 194 | + if (!GetPerContextExports(context).ToLocal(&per_context_bindings) || |
| 195 | + !per_context_bindings->Get(context, |
| 196 | + FIXED_ONE_BYTE_STRING(isolate, "emitMessage")) |
| 197 | + .ToLocal(&emit_message_val)) { |
| 198 | + return MaybeLocal<Function>(); |
| 199 | + } |
| 200 | + CHECK(emit_message_val->IsFunction()); |
| 201 | + return emit_message_val.As<Function>(); |
| 202 | +} |
| 203 | + |
191 | 204 | MaybeLocal<Function> GetDOMException(Local<Context> context) { |
192 | 205 | Isolate* isolate = context->GetIsolate(); |
193 | 206 | Local<Object> per_context_bindings; |
@@ -498,20 +511,31 @@ MessagePort::MessagePort(Environment* env, |
498 | 511 | MessagePort* channel = ContainerOf(&MessagePort::async_, handle); |
499 | 512 | channel->OnMessage(); |
500 | 513 | }; |
| 514 | + |
501 | 515 | CHECK_EQ(uv_async_init(env->event_loop(), |
502 | 516 | &async_, |
503 | 517 | onmessage), 0); |
504 | | - async_.data = static_cast<void*>(this); |
| 518 | + async_.data = nullptr; // Reset later to indicate success of the constructor. |
| 519 | + auto cleanup = OnScopeLeave([&]() { |
| 520 | + if (async_.data == nullptr) Close(); |
| 521 | + }); |
505 | 522 |
|
506 | 523 | Local<Value> fn; |
507 | 524 | if (!wrap->Get(context, env->oninit_symbol()).ToLocal(&fn)) |
508 | 525 | return; |
509 | 526 |
|
510 | 527 | if (fn->IsFunction()) { |
511 | 528 | Local<Function> init = fn.As<Function>(); |
512 | | - USE(init->Call(context, wrap, 0, nullptr)); |
| 529 | + if (init->Call(context, wrap, 0, nullptr).IsEmpty()) |
| 530 | + return; |
513 | 531 | } |
514 | 532 |
|
| 533 | + Local<Function> emit_message_fn; |
| 534 | + if (!GetEmitMessageFunction(context).ToLocal(&emit_message_fn)) |
| 535 | + return; |
| 536 | + emit_message_fn_.Reset(env->isolate(), emit_message_fn); |
| 537 | + |
| 538 | + async_.data = static_cast<void*>(this); |
515 | 539 | Debug(this, "Created message port"); |
516 | 540 | } |
517 | 541 |
|
@@ -559,6 +583,11 @@ MessagePort* MessagePort::New( |
559 | 583 | return nullptr; |
560 | 584 | MessagePort* port = new MessagePort(env, context, instance); |
561 | 585 | CHECK_NOT_NULL(port); |
| 586 | + if (port->IsHandleClosing()) { |
| 587 | + // Construction failed with an exception. |
| 588 | + return nullptr; |
| 589 | + } |
| 590 | + |
562 | 591 | if (data) { |
563 | 592 | port->Detach(); |
564 | 593 | port->data_ = std::move(data); |
@@ -651,16 +680,8 @@ void MessagePort::OnMessage() { |
651 | 680 | continue; |
652 | 681 | } |
653 | 682 |
|
654 | | - Local<Object> event; |
655 | | - Local<Value> cb_args[1]; |
656 | | - if (!env()->message_event_object_template()->NewInstance(context) |
657 | | - .ToLocal(&event) || |
658 | | - event->Set(context, env()->data_string(), payload).IsNothing() || |
659 | | - event->Set(context, env()->target_string(), object()).IsNothing() || |
660 | | - (cb_args[0] = event, false) || |
661 | | - MakeCallback(env()->onmessage_string(), |
662 | | - arraysize(cb_args), |
663 | | - cb_args).IsEmpty()) { |
| 683 | + Local<Function> emit_message = PersistentToLocal::Strong(emit_message_fn_); |
| 684 | + if (MakeCallback(emit_message, 1, &payload).IsEmpty()) { |
664 | 685 | // Re-schedule OnMessage() execution in case of failure. |
665 | 686 | if (data_) |
666 | 687 | TriggerAsync(); |
@@ -929,6 +950,7 @@ void MessagePort::Entangle(MessagePort* a, MessagePortData* b) { |
929 | 950 |
|
930 | 951 | void MessagePort::MemoryInfo(MemoryTracker* tracker) const { |
931 | 952 | tracker->TrackField("data", data_); |
| 953 | + tracker->TrackField("emit_message_fn", emit_message_fn_); |
932 | 954 | } |
933 | 955 |
|
934 | 956 | Local<FunctionTemplate> GetMessagePortConstructorTemplate(Environment* env) { |
@@ -938,8 +960,6 @@ Local<FunctionTemplate> GetMessagePortConstructorTemplate(Environment* env) { |
938 | 960 | if (!templ.IsEmpty()) |
939 | 961 | return templ; |
940 | 962 |
|
941 | | - Isolate* isolate = env->isolate(); |
942 | | - |
943 | 963 | { |
944 | 964 | Local<FunctionTemplate> m = env->NewFunctionTemplate(MessagePort::New); |
945 | 965 | m->SetClassName(env->message_port_constructor_string()); |
@@ -950,13 +970,6 @@ Local<FunctionTemplate> GetMessagePortConstructorTemplate(Environment* env) { |
950 | 970 | env->SetProtoMethod(m, "start", MessagePort::Start); |
951 | 971 |
|
952 | 972 | env->set_message_port_constructor_template(m); |
953 | | - |
954 | | - Local<FunctionTemplate> event_ctor = FunctionTemplate::New(isolate); |
955 | | - event_ctor->SetClassName(FIXED_ONE_BYTE_STRING(isolate, "MessageEvent")); |
956 | | - Local<ObjectTemplate> e = event_ctor->InstanceTemplate(); |
957 | | - e->Set(env->data_string(), Null(isolate)); |
958 | | - e->Set(env->target_string(), Null(isolate)); |
959 | | - env->set_message_event_object_template(e); |
960 | 973 | } |
961 | 974 |
|
962 | 975 | return GetMessagePortConstructorTemplate(env); |
@@ -975,7 +988,13 @@ static void MessageChannel(const FunctionCallbackInfo<Value>& args) { |
975 | 988 | Context::Scope context_scope(context); |
976 | 989 |
|
977 | 990 | MessagePort* port1 = MessagePort::New(env, context); |
| 991 | + if (port1 == nullptr) return; |
978 | 992 | MessagePort* port2 = MessagePort::New(env, context); |
| 993 | + if (port2 == nullptr) { |
| 994 | + port1->Close(); |
| 995 | + return; |
| 996 | + } |
| 997 | + |
979 | 998 | MessagePort::Entangle(port1, port2); |
980 | 999 |
|
981 | 1000 | args.This()->Set(context, env->port1_string(), port1->object()) |
|