Skip to content

Commit

Permalink
fix(ios): fix jsc call c crash
Browse files Browse the repository at this point in the history
  • Loading branch information
etkmao committed Feb 13, 2025
1 parent 4badb95 commit 6404a29
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 7 deletions.
21 changes: 21 additions & 0 deletions driver/js/include/driver/napi/jsc/jsc_ctx.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,27 @@ class ConstructorDataManager {
std::mutex mutex_;
};

class ContextValidManager {
public:
void SaveContextPtr(void* ptr) {
std::lock_guard<std::mutex> lock(mutex_);
ctx_valid_set_.insert(ptr);
}

void ClearContextPtr(void* ptr) {
std::lock_guard<std::mutex> lock(mutex_);
ctx_valid_set_.erase(ptr);
}

bool IsValidContextPtr(void* ptr) {
std::lock_guard<std::mutex> lock(mutex_);
return ctx_valid_set_.find(ptr) != ctx_valid_set_.end();
}
private:
std::set<void*> ctx_valid_set_;
std::mutex mutex_;
};

class JSCCtx : public Ctx {
public:
using string_view = footstone::string_view;
Expand Down
28 changes: 21 additions & 7 deletions driver/js/src/napi/jsc/jsc_ctx.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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_(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() {
Expand All @@ -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,
Expand All @@ -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);
Expand All @@ -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<JSCCtxValue>(context, object));
if (object != global_object) {
auto object_private_data = JSObjectGetPrivate(object);
Expand Down Expand Up @@ -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");
Expand All @@ -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<JSCCtxValue>(constructor_data->prototype)->value_;
JSObjectSetPrototype(ctx, instance, proto);
cb_info.SetReceiver(std::make_shared<JSCCtxValue>(context, instance));
Expand Down Expand Up @@ -397,7 +411,7 @@ std::shared_ptr<CtxValue> JSCCtx::DefineClass(const string_view& name,

std::shared_ptr<CtxValue> JSCCtx::NewInstance(const std::shared_ptr<CtxValue>& cls, int argc, std::shared_ptr<CtxValue> argv[], void* external) {
auto jsc_cls = std::static_pointer_cast<JSCCtxValue>(cls);
JSValueRef values[argc]; // NOLINT(runtime/arrays)
std::vector<JSValueRef> values(argc);
for (size_t i = 0; i < argc; i++) {
auto arg_value = std::static_pointer_cast<JSCCtxValue>(argv[i]);
values[i] = arg_value->value_;
Expand All @@ -415,7 +429,7 @@ std::shared_ptr<CtxValue> JSCCtx::NewInstance(const std::shared_ptr<CtxValue>& 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<JSCCtxValue>(context_, exception));
return nullptr;
Expand Down Expand Up @@ -914,13 +928,13 @@ std::shared_ptr<CtxValue> JSCCtx::CallFunction(const std::shared_ptr<CtxValue>&
return std::make_shared<JSCCtxValue>(context_, ret_value_ref);
}

JSValueRef values[argc]; // NOLINT(runtime/arrays)
std::vector<JSValueRef> values(argc);
for (size_t i = 0; i < argc; i++) {
auto arg_value = std::static_pointer_cast<JSCCtxValue>(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<JSCCtxValue>(context_, exception));
return nullptr;
Expand Down

0 comments on commit 6404a29

Please sign in to comment.