From 66d516bf76a75db16aeace766a1b59f1de726935 Mon Sep 17 00:00:00 2001 From: wwwcg Date: Fri, 25 Aug 2023 11:24:50 +0800 Subject: [PATCH] fix(ios): fix context leak when using shared engine (#3451) * chore(ios): fix demo release build error * fix(ios): js context leak when using shared engine --------- Co-authored-by: OpenHippy <124017524+open-hippy@users.noreply.github.com> --- examples/ios-demo/HippyDemo/ViewController.m | 2 +- ios/sdk/base/executors/HippyJSCExecutor.mm | 26 +++++++++++--------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/examples/ios-demo/HippyDemo/ViewController.m b/examples/ios-demo/HippyDemo/ViewController.m index 8cefdd6bf49..d5dbdd408bd 100644 --- a/examples/ios-demo/HippyDemo/ViewController.m +++ b/examples/ios-demo/HippyDemo/ViewController.m @@ -25,7 +25,7 @@ #import "HippyLog.h" #import "HippyBundleURLProvider.h" #import "DemoConfigs.h" -#import +#import "HippyBridge.h" #import diff --git a/ios/sdk/base/executors/HippyJSCExecutor.mm b/ios/sdk/base/executors/HippyJSCExecutor.mm index c28d022afbb..42e1558045c 100644 --- a/ios/sdk/base/executors/HippyJSCExecutor.mm +++ b/ios/sdk/base/executors/HippyJSCExecutor.mm @@ -165,12 +165,9 @@ - (void)setBridge:(HippyBridge *)bridge { - (instancetype)initWithExecurotKey:(NSString *)execurotkey bridge:(HippyBridge *)bridge { if (self = [super init]) { _valid = YES; - // maybe bug in JavaScriptCore: - // JSContextRef held by JSContextGroupRef cannot be deallocated, - // unless JSContextGroupRef is deallocated self.executorkey = execurotkey; self.bridge = bridge; - std::shared_ptr engine = [[HippyJSEnginesMapper defaultInstance] createJSEngineForKey:self.executorkey]; + std::shared_ptr engine = [[HippyJSEnginesMapper defaultInstance] createJSEngineForKey:self.uniqueExecutorkeyForEngine]; std::unique_ptr map = [self registerMap]; const char *pName = [execurotkey UTF8String] ?: ""; std::shared_ptr scope = engine->AsyncCreateScope(pName, {}, std::move(map)); @@ -216,7 +213,7 @@ static unicode_string_view NSStringToU8(NSString* str) { std::shared_ptr scope = wrapper->scope.lock(); if (scope) { std::shared_ptr context = std::static_pointer_cast(scope->GetContext()); - JSContext *jsContext = [JSContext contextWithJSGlobalContextRef:context->GetCtxRef()]; + JSContext *jsContext = [strongSelf JSContext]; auto global_object = context->GetGlobalObject(); auto user_global_object_key = context->CreateString("global"); context->SetProperty(global_object, user_global_object_key, global_object, hippy::napi::PropertyAttribute::DontDelete); @@ -455,12 +452,10 @@ - (void)invalidate { _JSContext.name = @"HippyJSContext(delete)"; _JSContext = nil; _JSGlobalContextRef = NULL; - NSString *executorKey = self.executorkey; + NSString *uniqueExecutorKey = self.uniqueExecutorkeyForEngine; dispatch_async(dispatch_get_main_queue(), ^{ - HippyLogInfo(@"[Hippy_OC_Log][Life_Circle],HippyJSCExecutor remove engine %@", executorKey); - if (executorKey) { - [[HippyJSEnginesMapper defaultInstance] removeEngineForKey:executorKey]; - } + HippyLogInfo(@"[Hippy_OC_Log][Life_Circle],HippyJSCExecutor remove engine %@", uniqueExecutorKey); + [[HippyJSEnginesMapper defaultInstance] removeEngineForKey:uniqueExecutorKey]; }); } @@ -472,6 +467,13 @@ - (NSString *)executorkey { return _executorkey ?: [NSString stringWithFormat:@"%p", self]; } +- (NSString *)uniqueExecutorkeyForEngine { + // core-engine reuse can lead to leak of context, + // which we avoid by using a unique executor key. + return [NSString stringWithFormat:@"%@%p", self.executorkey, self]; +} + + HIPPY_EXPORT_METHOD(setContextName:(NSString *)contextName) { __weak HippyJSCExecutor *weakSelf = self; [self executeBlockOnJavaScriptQueue:^{ @@ -778,7 +780,7 @@ static void handleJsExcepiton(std::shared_ptr scope) { } - (void)executeBlockOnJavaScriptQueue:(dispatch_block_t)block { - auto engine = [[HippyJSEnginesMapper defaultInstance] JSEngineForKey:self.executorkey]; + auto engine = [[HippyJSEnginesMapper defaultInstance] JSEngineForKey:self.uniqueExecutorkeyForEngine]; if (engine) { dispatch_block_t autoReleaseBlock = ^(void){ if (block) { @@ -798,7 +800,7 @@ - (void)executeBlockOnJavaScriptQueue:(dispatch_block_t)block { } - (void)executeAsyncBlockOnJavaScriptQueue:(dispatch_block_t)block { - auto engine = [[HippyJSEnginesMapper defaultInstance] JSEngineForKey:self.executorkey]; + auto engine = [[HippyJSEnginesMapper defaultInstance] JSEngineForKey:self.uniqueExecutorkeyForEngine]; if (engine) { std::shared_ptr task = std::make_shared(); dispatch_block_t autoReleaseBlock = ^(void){