diff --git a/driver/js/include/driver/napi/jsc/jsc_ctx.h b/driver/js/include/driver/napi/jsc/jsc_ctx.h index 075837285d5..d0aa4bee5c2 100644 --- a/driver/js/include/driver/napi/jsc/jsc_ctx.h +++ b/driver/js/include/driver/napi/jsc/jsc_ctx.h @@ -85,6 +85,27 @@ class ConstructorDataManager { std::mutex mutex_; }; +class ContextValidManager { +public: + void SaveContextPtr(void* ptr) { + std::lock_guard lock(mutex_); + ctx_valid_set_.insert(ptr); + } + + void ClearContextPtr(void* ptr) { + std::lock_guard lock(mutex_); + ctx_valid_set_.erase(ptr); + } + + bool IsValidContextPtr(void* ptr) { + std::lock_guard lock(mutex_); + return ctx_valid_set_.find(ptr) != ctx_valid_set_.end(); + } +private: + std::set ctx_valid_set_; + std::mutex mutex_; +}; + class JSCCtx : public Ctx { public: using string_view = footstone::string_view; diff --git a/driver/js/src/napi/jsc/jsc_ctx.cc b/driver/js/src/napi/jsc/jsc_ctx.cc index 5297a0202e9..5c87817cf00 100644 --- a/driver/js/src/napi/jsc/jsc_ctx.cc +++ b/driver/js/src/napi/jsc/jsc_ctx.cc @@ -50,19 +50,23 @@ constexpr char16_t kSetStr[] = u"set"; static std::once_flag global_class_flag; static JSClassRef global_class; static ConstructorDataManager* global_constructor_data_mgr = nullptr; +static ContextValidManager* global_context_valid_mgr = nullptr; JSCCtx::JSCCtx(JSContextGroupRef group, std::weak_ptr vm): vm_(vm) { std::call_once(global_class_flag, []() { JSClassDefinition global = kJSClassDefinitionEmpty; global_class = JSClassCreate(&global); global_constructor_data_mgr = new ConstructorDataManager(); + global_context_valid_mgr = new ContextValidManager(); }); context_ = JSGlobalContextCreateInGroup(group, global_class); + if (global_context_valid_mgr) { + global_context_valid_mgr->SaveContextPtr(context_); + } exception_ = nullptr; is_exception_handled_ = false; - } JSCCtx::~JSCCtx() { @@ -72,7 +76,11 @@ JSCCtx::~JSCCtx() { global_constructor_data_mgr->ClearConstructorDataPtr(item.get()); } } + JSGarbageCollect(context_); JSGlobalContextRelease(context_); + if (global_context_valid_mgr) { + global_context_valid_mgr->ClearContextPtr(context_); + } } JSValueRef InvokeJsCallback(JSContextRef ctx, @@ -81,6 +89,10 @@ JSValueRef InvokeJsCallback(JSContextRef ctx, size_t argument_count, const JSValueRef arguments[], JSValueRef* exception) { + auto context = JSContextGetGlobalContext(ctx); + if (!global_context_valid_mgr || !global_context_valid_mgr->IsValidContextPtr(context)) { + return JSValueMakeUndefined(ctx); + } void* data = JSObjectGetPrivate(function); if (!data) { return JSValueMakeUndefined(ctx); @@ -92,7 +104,6 @@ JSValueRef InvokeJsCallback(JSContextRef ctx, JSObjectRef global_object = JSContextGetGlobalObject(ctx); auto global_external_data = JSObjectGetPrivate(global_object); cb_info.SetSlot(global_external_data); - auto context = JSContextGetGlobalContext(ctx); cb_info.SetReceiver(std::make_shared(context, object)); if (object != global_object) { auto object_private_data = JSObjectGetPrivate(object); @@ -130,6 +141,10 @@ JSObjectRef InvokeConstructorCallback(JSContextRef ctx, size_t argument_count, const JSValueRef arguments[], JSValueRef* exception) { + auto context = JSContextGetGlobalContext(ctx); + if (!global_context_valid_mgr || !global_context_valid_mgr->IsValidContextPtr(context)) { + return constructor; + } void* data = JSObjectGetPrivate(constructor); if (!data) { JSStringRef string_ref = JSCVM::CreateJSCString("InvokeConstructorCallback JSObjectGetPrivate error"); @@ -147,7 +162,6 @@ JSObjectRef InvokeConstructorCallback(JSContextRef ctx, JSObjectRef global_obj = JSContextGetGlobalObject(ctx); auto global_external_data = JSObjectGetPrivate(global_obj); cb_info.SetSlot(global_external_data); - auto context = JSContextGetGlobalContext(ctx); auto proto = std::static_pointer_cast(constructor_data->prototype)->value_; JSObjectSetPrototype(ctx, instance, proto); cb_info.SetReceiver(std::make_shared(context, instance)); @@ -397,7 +411,7 @@ std::shared_ptr JSCCtx::DefineClass(const string_view& name, std::shared_ptr JSCCtx::NewInstance(const std::shared_ptr& cls, int argc, std::shared_ptr argv[], void* external) { auto jsc_cls = std::static_pointer_cast(cls); - JSValueRef values[argc]; // NOLINT(runtime/arrays) + std::vector values(argc); for (size_t i = 0; i < argc; i++) { auto arg_value = std::static_pointer_cast(argv[i]); values[i] = arg_value->value_; @@ -415,7 +429,7 @@ std::shared_ptr JSCCtx::NewInstance(const std::shared_ptr& c constructor_data->object_data_map[clazz] = external; } } - auto ret = JSObjectCallAsConstructor(context_, clazz, argc, values, &exception); + auto ret = JSObjectCallAsConstructor(context_, clazz, argc, values.data(), &exception); if (exception) { SetException(std::make_shared(context_, exception)); return nullptr; @@ -914,13 +928,13 @@ std::shared_ptr JSCCtx::CallFunction(const std::shared_ptr& return std::make_shared(context_, ret_value_ref); } - JSValueRef values[argc]; // NOLINT(runtime/arrays) + std::vector values(argc); for (size_t i = 0; i < argc; i++) { auto arg_value = std::static_pointer_cast(argv[i]); values[i] = arg_value->value_; } - auto ret_value_ref = JSObjectCallAsFunction(context_, function_object, receiver_object, argc, values, &exception); + auto ret_value_ref = JSObjectCallAsFunction(context_, function_object, receiver_object, argc, values.data(), &exception); if (exception) { SetException(std::make_shared(context_, exception)); return nullptr;