From bf91e3563aaafbcba0c289d55fb32943cc49d3b8 Mon Sep 17 00:00:00 2001 From: wwwcg Date: Wed, 17 Apr 2024 15:40:51 +0800 Subject: [PATCH 1/7] chore(ios): improve parameter mismatch tips --- .../ios/base/modules/HippyModuleMethod.mm | 33 +++++++++---------- modules/ios/base/HippyLog.mm | 2 +- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/framework/ios/base/modules/HippyModuleMethod.mm b/framework/ios/base/modules/HippyModuleMethod.mm index 0ac4f61637e..fd6f4edb7de 100644 --- a/framework/ios/base/modules/HippyModuleMethod.mm +++ b/framework/ios/base/modules/HippyModuleMethod.mm @@ -464,23 +464,22 @@ - (id)invokeWithBridge:(HippyBridge *)bridge module:(id)module arguments:(NSArra %@ on a module of class %@", [self methodName], [module class]); // Safety check - if (arguments.count != _argumentBlocks.count) { - NSInteger actualCount = arguments.count; - NSInteger expectedCount = _argumentBlocks.count; - - // Subtract the implicit Promise resolver and rejecter functions for implementations of async functions - if (self.functionType == HippyFunctionTypePromise) { - actualCount -= 2; - expectedCount -= 2; - } - - HippyLogError(@"%@.%@ was called with %ld arguments, but expects %ld. \ - If you haven\'t changed this method " - @"yourself, this usually means that \ - your versions of the native code and JavaScript code are out " - @"of sync. \ - Updating both should make this error go away.", - HippyBridgeModuleNameForClass(_moduleClass), self.JSMethodName, (long)actualCount, (long)expectedCount); + NSInteger actualCount = arguments.count; + NSInteger expectedCount = _argumentBlocks.count; + BOOL isArgumentsMismatch = NO; + if (actualCount > expectedCount || + (self.functionType == HippyFunctionTypePromise && actualCount < expectedCount - 2)) { + isArgumentsMismatch = YES; + } + if (isArgumentsMismatch) { + HippyLogError(@"%@.%@ was called with %lld arguments but expects %lld arguments. " + @"If you haven\'t changed this method yourself, this usually means that " + @"your versions of the native code and JavaScript code are out of sync. " + @"Updating both should make this error go away.", + HippyBridgeModuleNameForClass(_moduleClass), + self.JSMethodName, + (long long)actualCount, + (long long)expectedCount); } } diff --git a/modules/ios/base/HippyLog.mm b/modules/ios/base/HippyLog.mm index 16dbe0790f6..33d4489932d 100644 --- a/modules/ios/base/HippyLog.mm +++ b/modules/ios/base/HippyLog.mm @@ -184,7 +184,7 @@ void HippyLogNativeInternal(HippyLogLevel level, const char *fileName, int lineN // Call log function if (logFunction) { - logFunction(level, HippyLogSourceNative, fileName ? @(fileName) : nil, lineNumber > 0 ? @(lineNumber) : nil, message); + logFunction(level, HippyLogSourceNative, fileName ? @(fileName) : nil, @(lineNumber), message); } #if HIPPY_DEBUG From 271bb9149526c91a5b0b93567967d871627a0d71 Mon Sep 17 00:00:00 2001 From: wwwcg Date: Thu, 18 Apr 2024 16:06:44 +0800 Subject: [PATCH 2/7] refactor(ios): Improve compatibility of imageProvider --- framework/ios/base/bridge/HippyBridge.h | 10 ++--- framework/ios/base/bridge/HippyBridge.mm | 42 ++++++++++--------- .../imageloader/HippyImageLoaderModule.mm | 2 +- .../component/image/HippyImageViewManager.mm | 2 +- .../component/view/HippyViewManager.mm | 2 +- 5 files changed, 30 insertions(+), 28 deletions(-) diff --git a/framework/ios/base/bridge/HippyBridge.h b/framework/ios/base/bridge/HippyBridge.h index 9b37f2a9ffd..a19b26df1af 100644 --- a/framework/ios/base/bridge/HippyBridge.h +++ b/framework/ios/base/bridge/HippyBridge.h @@ -170,12 +170,12 @@ HIPPY_EXTERN NSString *HippyBridgeModuleNameForClass(Class bridgeModuleClass); /// - Parameter imageLoader: id - (void)setCustomImageLoader:(id)imageLoader; -/** - * Image provider method - * Users adds or obtains image providers in the following methods - */ +/// Get all classes that confirms to HippyImageProviderProtocol +@property (nonatomic, strong, nonnull, readonly) NSArray> *imageProviders; + +/// Add a custom ImageProvider class. +/// - Parameter cls: class confirms to HippyImageProviderProtocol - (void)addImageProviderClass:(Class)cls; -- (NSArray> *)imageProviderClasses; #pragma mark - diff --git a/framework/ios/base/bridge/HippyBridge.mm b/framework/ios/base/bridge/HippyBridge.mm index c6b6b166692..815e7208f1b 100644 --- a/framework/ios/base/bridge/HippyBridge.mm +++ b/framework/ios/base/bridge/HippyBridge.mm @@ -133,7 +133,6 @@ static inline void registerLogDelegateToHippyCore() { @interface HippyBridge() { - NSMutableArray> *_imageProviders; __weak id _methodInterceptor; HippyModulesSetup *_moduleSetup; __weak NSOperation *_lastOperation; @@ -176,6 +175,7 @@ @implementation HippyBridge @synthesize renderManager = _renderManager; @synthesize imageLoader = _imageLoader; +@synthesize imageProviders = _imageProviders; dispatch_queue_t HippyJSThread; @@ -371,25 +371,6 @@ - (HippyModuleData *)moduleDataForName:(NSString *)moduleName { return nil; } -- (void)addImageProviderClass:(Class)cls { - HippyAssertParam(cls); - @synchronized (self) { - if (!_imageProviders) { - _imageProviders = [NSMutableArray array]; - } - [_imageProviders addObject:cls]; - } -} - -- (NSArray> *)imageProviderClasses { - @synchronized (self) { - if (!_imageProviders) { - _imageProviders = [NSMutableArray array]; - } - return [_imageProviders copy]; - } -} - - (NSArray *)modulesConformingToProtocol:(Protocol *)protocol { NSMutableArray *modules = [NSMutableArray new]; for (Class moduleClass in self.moduleClasses) { @@ -432,6 +413,27 @@ - (void)setCustomImageLoader:(id)imageLoader { } } +- (NSArray> *)imageProviders { + @synchronized (self) { + if (!_imageProviders) { + NSMutableArray *moduleClasses = [NSMutableArray new]; + for (Class moduleClass in self.moduleClasses) { + if ([moduleClass conformsToProtocol:@protocol(HippyImageProviderProtocol)]) { + [moduleClasses addObject:moduleClass]; + } + } + _imageProviders = moduleClasses; + } + return [_imageProviders copy]; + } +} + +- (void)addImageProviderClass:(Class)cls { + HippyAssertParam(cls); + @synchronized (self) { + _imageProviders = [self.imageProviders arrayByAddingObject:cls]; + } +} #pragma mark - Debug Reload diff --git a/framework/ios/module/imageloader/HippyImageLoaderModule.mm b/framework/ios/module/imageloader/HippyImageLoaderModule.mm index a908df9ad1f..37926663ad8 100644 --- a/framework/ios/module/imageloader/HippyImageLoaderModule.mm +++ b/framework/ios/module/imageloader/HippyImageLoaderModule.mm @@ -47,7 +47,7 @@ @implementation HippyImageLoaderModule @synthesize bridge = _bridge; - (id)imageProviderForData:(NSData *)data { - NSArray> *providers = [self.bridge imageProviderClasses]; + NSArray> *providers = [self.bridge imageProviders]; for (Class cls in providers) { if ([cls canHandleData:data]) { id object = [[(Class)cls alloc] init]; diff --git a/renderer/native/ios/renderer/component/image/HippyImageViewManager.mm b/renderer/native/ios/renderer/component/image/HippyImageViewManager.mm index 9f925f814db..629be77135e 100644 --- a/renderer/native/ios/renderer/component/image/HippyImageViewManager.mm +++ b/renderer/native/ios/renderer/component/image/HippyImageViewManager.mm @@ -134,7 +134,7 @@ - (void)loadImageSource:(NSString *)path forView:(HippyImageView *)view { HippyBridge *bridge = strongSelf.bridge; if (bridge) { id imageProvider = nil; - for (Class cls in [bridge imageProviderClasses]) { + for (Class cls in [bridge imageProviders]) { if ([cls canHandleData:data]) { imageProvider = [[(Class)cls alloc] init]; break; diff --git a/renderer/native/ios/renderer/component/view/HippyViewManager.mm b/renderer/native/ios/renderer/component/view/HippyViewManager.mm index 3b28c925fee..9d5c38ee6bd 100644 --- a/renderer/native/ios/renderer/component/view/HippyViewManager.mm +++ b/renderer/native/ios/renderer/component/view/HippyViewManager.mm @@ -296,7 +296,7 @@ - (void)loadImageSource:(NSString *)path forView:(HippyView *)view { HippyBridge *bridge = strongSelf.bridge; if (bridge) { id imageProvider = nil; - for (Class cls in [bridge imageProviderClasses]) { + for (Class cls in [bridge imageProviders]) { if ([cls canHandleData:data]) { imageProvider = [[(Class)cls alloc] init]; break; From 0d3d6e0cfbb94e060d1728abc14cbb8ed726573c Mon Sep 17 00:00:00 2001 From: wwwcg Date: Thu, 28 Mar 2024 20:51:29 +0800 Subject: [PATCH 3/7] fix(ios): add ResponseSenderBlock type support for component parameter --- .../ios/base/modules/HippyModuleMethod.mm | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/framework/ios/base/modules/HippyModuleMethod.mm b/framework/ios/base/modules/HippyModuleMethod.mm index fd6f4edb7de..65bf27b0df2 100644 --- a/framework/ios/base/modules/HippyModuleMethod.mm +++ b/framework/ios/base/modules/HippyModuleMethod.mm @@ -293,14 +293,26 @@ - (void)processMethodSignature { } } } else if ([typeName isEqualToString:@"HippyResponseSenderBlock"]) { - HIPPY_ARG_BLOCK(if (HIPPY_DEBUG && json && ![json isKindOfClass:[NSNumber class]]) { - HippyLogArgumentError(weakSelf, index, json, "should be a function"); - return NO; - } - __weak HippyBridge *weakBridge = bridge; - Hippy_BLOCK_ARGUMENT(^(NSArray *args) { - enqueueBlockCallback(weakBridge, weakSelf, json, args); - });) + HIPPY_ARG_BLOCK( + if (!json) { + HippyLogArgumentError(weakSelf, index, json, "should be a response sender function"); + return NO; + } + id blockArg = nil; + if (![json isKindOfClass:[NSNumber class]]) { + // In Hippy3.0, Dom Nodes call function by method name directly, + // so it is not a Number anymore. + // See NativeRenderManager::CallFunction() for more. + // TODO: add more type check for safe + blockArg = json; + } else { + __weak HippyBridge *weakBridge = bridge; + blockArg = ^(NSArray *args){ + enqueueBlockCallback(weakBridge, weakSelf, json, args); + }; + } + Hippy_BLOCK_ARGUMENT(blockArg); + ) } else if ([typeName isEqualToString:@"HippyResponseErrorBlock"]) { HIPPY_ARG_BLOCK(if (HIPPY_DEBUG && json && ![json isKindOfClass:[NSNumber class]]) { HippyLogArgumentError(weakSelf, index, json, "should be a function"); @@ -325,6 +337,7 @@ - (void)processMethodSignature { // In Hippy3.0, Dom Nodes call function by method name directly, // so it is not a Number anymore. // See NativeRenderManager::CallFunction() for more. + // TODO: add more type check for safe blockArg = json; } else { __weak HippyBridge *weakBridge = bridge; From a18ea5a90dca6962a281f994477be9f250c627eb Mon Sep 17 00:00:00 2001 From: wwwcg Date: Fri, 19 Apr 2024 17:10:50 +0800 Subject: [PATCH 4/7] refactor(ios): increase robustness of HippyUrl process --- driver/js/src/napi/jsc/jsc_ctx.cc | 1 + framework/ios/base/bridge/HippyBridge.h | 4 +- hippy.podspec | 1 + modules/ios/base/HippyDefines.h | 10 +++ modules/ios/base/HippyUtils.m | 10 +-- modules/vfs/ios/VFSUriLoader.mm | 7 +- tests/ios/HippyUtilsTest.m | 90 +++++++++++++++++++++++++ 7 files changed, 109 insertions(+), 14 deletions(-) create mode 100644 tests/ios/HippyUtilsTest.m diff --git a/driver/js/src/napi/jsc/jsc_ctx.cc b/driver/js/src/napi/jsc/jsc_ctx.cc index c7d1be501ce..25f1d9f8a83 100644 --- a/driver/js/src/napi/jsc/jsc_ctx.cc +++ b/driver/js/src/napi/jsc/jsc_ctx.cc @@ -1149,6 +1149,7 @@ std::shared_ptr JSCCtx::RunScript(const string_view& data, if (exception) { SetException(std::make_shared(context_, exception)); + FOOTSTONE_LOG(ERROR) << GetExceptionMessage(exception_); return nullptr; } diff --git a/framework/ios/base/bridge/HippyBridge.h b/framework/ios/base/bridge/HippyBridge.h index a19b26df1af..4b5b9e18212 100644 --- a/framework/ios/base/bridge/HippyBridge.h +++ b/framework/ios/base/bridge/HippyBridge.h @@ -94,7 +94,7 @@ HIPPY_EXTERN NSString *HippyBridgeModuleNameForClass(Class bridgeModuleClass); /// /// Note: 多个bridge使用相同的共享engineKey时,只有全部bridge实例销毁时engine资源才将释放,因此,请注意合理使用,避免出现意外的内存泄漏。 /// 传空时默认不共享,SDK内部默认分配一随机key。 -- (instancetype)initWithDelegate:(id)delegate +- (instancetype)initWithDelegate:(nullable id)delegate moduleProvider:(nullable HippyBridgeModuleProviderBlock)block launchOptions:(nullable NSDictionary *)launchOptions executorKey:(nullable NSString *)executorKey; @@ -112,7 +112,7 @@ HIPPY_EXTERN NSString *HippyBridgeModuleNameForClass(Class bridgeModuleClass); /// /// Note: 多个bridge使用相同的共享engineKey时,只有全部bridge实例销毁时engine资源才将释放,因此,请注意合理使用,避免出现意外的内存泄漏。 /// 传空时默认不共享,SDK内部默认分配一随机key。 -- (instancetype)initWithDelegate:(id)delegate +- (instancetype)initWithDelegate:(nullable id)delegate bundleURL:(nullable NSURL *)bundleURL moduleProvider:(nullable HippyBridgeModuleProviderBlock)block launchOptions:(nullable NSDictionary *)launchOptions diff --git a/hippy.podspec b/hippy.podspec index 1d5142f4c90..3b48f1bbab1 100644 --- a/hippy.podspec +++ b/hippy.podspec @@ -167,6 +167,7 @@ Pod::Spec.new do |s| 'GCC_ENABLE_CPP_EXCEPTIONS' => false, 'GCC_ENABLE_CPP_RTTI' => false, } + iosvfs.dependency 'hippy/Base' iosvfs.dependency 'hippy/VFS' iosvfs.dependency 'hippy/Footstone' iosvfs.dependency 'hippy/FootstoneUtils' diff --git a/modules/ios/base/HippyDefines.h b/modules/ios/base/HippyDefines.h index 2b12aff1569..46b32e34a82 100644 --- a/modules/ios/base/HippyDefines.h +++ b/modules/ios/base/HippyDefines.h @@ -85,6 +85,16 @@ method NS_UNAVAILABLE { _Pragma("clang diagnostic pop") +#pragma mark - Clang Warnings + +// warning list ref:https://clang.llvm.org/docs/DiagnosticsReference.html +#define HIPPY_CLANG_WARN_CONCAT(warning_name) HIPPY_STR_EXPAND(clang diagnostic ignored warning_name) +#define HIPPY_IGNORE_WARNING_BEGIN(warningName) _Pragma("clang diagnostic push") _Pragma(HIPPY_CLANG_WARN_CONCAT(#warningName)) +#define HIPPY_IGNORE_WARNING_END _Pragma("clang diagnostic pop") + + +#pragma mark - + #define HIPPY_VERSION_3_0 300 diff --git a/modules/ios/base/HippyUtils.m b/modules/ios/base/HippyUtils.m index e257b5a0cc7..448fea984c1 100644 --- a/modules/ios/base/HippyUtils.m +++ b/modules/ios/base/HippyUtils.m @@ -438,15 +438,7 @@ static void HPGetRGBAColorComponents(CGColorRef color, CGFloat rgba[4]) { if (nil == uriData) { return nil; } - CFURLRef urlRef = NULL; - if ([URLString hasPrefix:@"http"] || - [URLString hasPrefix:@"data:"] || - [URLString hasPrefix:@"file:"]) { - urlRef = CFURLCreateWithBytes(NULL, [uriData bytes], [uriData length], kCFStringEncodingUTF8, (__bridge CFURLRef)baseURL); - } - else { - urlRef = CFURLCreateWithFileSystemPath(NULL, (__bridge CFStringRef)URLString, kCFURLPOSIXPathStyle, NO); - } + CFURLRef urlRef = CFURLCreateWithBytes(NULL, [uriData bytes], [uriData length], kCFStringEncodingUTF8, (__bridge CFURLRef)baseURL); NSURL *source_url = CFBridgingRelease(urlRef); return source_url; } diff --git a/modules/vfs/ios/VFSUriLoader.mm b/modules/vfs/ios/VFSUriLoader.mm index 0825443c4ba..d4c6ccda1c2 100644 --- a/modules/vfs/ios/VFSUriLoader.mm +++ b/modules/vfs/ios/VFSUriLoader.mm @@ -25,10 +25,9 @@ #import "TypeConverter.h" #import "VFSUriLoader.h" #import "VFSUriHandler.h" - +#import "HippyAssert.h" #include #include - #include "footstone/string_view_utils.h" NSString *const VFSErrorDomain = @"VFSErrorDomain"; @@ -91,7 +90,9 @@ NSOperationQueue *operationQueue, VFSHandlerProgressBlock progress, VFSHandlerCompletionBlock completion) { - NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlString]]; + NSURL *url = HippyURLWithString(urlString, nil); + HippyAssert(url, @"Invalid URL! %@", urlString); + NSURLRequest *request = [NSURLRequest requestWithURL:url]; RequestUntrustedContent(request, extraInfo, operationQueue, progress, completion); } diff --git a/tests/ios/HippyUtilsTest.m b/tests/ios/HippyUtilsTest.m new file mode 100644 index 00000000000..fb41d388923 --- /dev/null +++ b/tests/ios/HippyUtilsTest.m @@ -0,0 +1,90 @@ +/*! + * iOS SDK + * + * Tencent is pleased to support the open source community by making + * Hippy available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import + +@interface HippyUtilsTest : XCTestCase + +@end + +@implementation HippyUtilsTest + +- (void)setUp { + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. +} + +- (void)testSDKVersionExists { + NSString *ver = [HippyUtils sdkVersion]; + XCTAssertNotNil(ver); +} + +- (void)testHippyURLWithString { + HIPPY_IGNORE_WARNING_BEGIN(-Wnonnull) + XCTAssertNil(HippyURLWithString(nil, nil)); + HIPPY_IGNORE_WARNING_END + XCTAssert([[HippyURLWithString(@"", nil) absoluteString] length] == 0); + + NSArray *testPaths = @[ + @"http://hippyjs.org", + @"https://hippyjs.org", + @"file:///testAbsulotePath/subPath", + @"hpfile://./testHippyRelativePath/subPath", + @"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAA", + // Some exceptions, such as Spaces or newlines + @"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAA\n\n ", + ]; + for (NSString *path in testPaths) { + NSURL *url = HippyURLWithString(path, nil); + XCTAssertNotNil(url); + NSURLComponents *components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO]; + XCTAssertNotNil(components.scheme); + XCTAssertNotNil(components.path); + } + testPaths = @[ + @"测试中文", + ]; + for (NSString *path in testPaths) { + NSURL *url = HippyURLWithString(path, nil); + XCTAssertNotNil(url); + NSURLComponents *components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO]; + XCTAssertNil(components.scheme); + XCTAssertNotNil(components.path); + } + + NSString *baseUrl = @"https://hippyjs.org/#/"; + testPaths = @[ + @"hello/hippy", + ]; + for (NSString *path in testPaths) { + NSURL *url = HippyURLWithString(path, baseUrl); + XCTAssert([url.absoluteString isEqualToString:@"https://hippyjs.org/hello/hippy"]); + } + +} + + +@end From f50455fa7a43682254a60cb3244d526e596df765 Mon Sep 17 00:00:00 2001 From: wwwcg Date: Mon, 22 Apr 2024 22:01:00 +0800 Subject: [PATCH 5/7] feat(ios): unify HippyBridge's notifications and improve compatibility --- .../RenderPage/HippyDemoViewController.mm | 4 +- .../examples/ios-demo/HippyDemo/TestModule.mm | 4 +- framework/ios/base/bridge/HippyBridge.h | 101 +++++++++++++++-- framework/ios/base/bridge/HippyBridge.mm | 106 ++++++++++++++---- renderer/native/ios/renderer/HippyRootView.h | 5 - renderer/native/ios/renderer/HippyRootView.mm | 22 +--- 6 files changed, 187 insertions(+), 55 deletions(-) diff --git a/framework/examples/ios-demo/HippyDemo/RenderPage/HippyDemoViewController.mm b/framework/examples/ios-demo/HippyDemo/RenderPage/HippyDemoViewController.mm index 43481a05867..4b4ac52033e 100644 --- a/framework/examples/ios-demo/HippyDemo/RenderPage/HippyDemoViewController.mm +++ b/framework/examples/ios-demo/HippyDemo/RenderPage/HippyDemoViewController.mm @@ -198,7 +198,9 @@ - (void)mountConnector:(HippyBridge *)hippyBridge { } else { NSURL *vendorBundleURL = [self vendorBundleURL]; NSURL *indexBundleURL = [self indexBundleURL]; - [hippyBridge loadBundleURL:vendorBundleURL completion:^(NSURL * _Nullable, NSError * _Nullable) { + [hippyBridge loadBundleURL:vendorBundleURL + bundleType:HippyBridgeBundleTypeVendor + completion:^(NSURL * _Nullable, NSError * _Nullable) { NSLog(@"url %@ load finish", vendorBundleURL); }]; hippyBridge.sandboxDirectory = [indexBundleURL URLByDeletingLastPathComponent]; diff --git a/framework/examples/ios-demo/HippyDemo/TestModule.mm b/framework/examples/ios-demo/HippyDemo/TestModule.mm index 04879102526..69a0e711364 100644 --- a/framework/examples/ios-demo/HippyDemo/TestModule.mm +++ b/framework/examples/ios-demo/HippyDemo/TestModule.mm @@ -95,7 +95,9 @@ - (void)mountConnector:(HippyBridge *)connector onView:(UIView *)view { rootView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; [_connector setRootView:rootView]; NSNumber *rootTag = [rootView hippyTag]; - [connector loadBundleURL:bundleUrl completion:^(NSURL * _Nullable, NSError * _Nullable) { + [connector loadBundleURL:bundleUrl + bundleType:HippyBridgeBundleTypeBusiness + completion:^(NSURL * _Nullable bundleURL, NSError * _Nullable error) { NSLog(@"url %@ load finish", bundleStr); [connector loadInstanceForRootView:rootTag withProperties:@{@"isSimulator": @(isSimulator)}]; }]; diff --git a/framework/ios/base/bridge/HippyBridge.h b/framework/ios/base/bridge/HippyBridge.h index 4b5b9e18212..d5697ad44db 100644 --- a/framework/ios/base/bridge/HippyBridge.h +++ b/framework/ios/base/bridge/HippyBridge.h @@ -42,20 +42,88 @@ NS_ASSUME_NONNULL_BEGIN * 注意:为兼容2.0版本,保持的相同的下划线前缀命名,不可修改 */ HIPPY_EXTERN NSString *const _HippySDKVersion; + /** * This notification triggers a reload of all bridges currently running. * Deprecated, use HippyBridge::requestReload instead. */ HIPPY_EXTERN NSString *const HippyReloadNotification; + +// Keys of userInfo for the following notifications +HIPPY_EXTERN NSString *const kHippyNotiBridgeKey; +HIPPY_EXTERN NSString *const kHippyNotiBundleUrlKey; +HIPPY_EXTERN NSString *const kHippyNotiBundleTypeKey; +HIPPY_EXTERN NSString *const kHippyNotiErrorKey; + +/// Bundle Type of Vendor (or Common Bundle), +/// used in kHippyNotiBundleTypeKey +HIPPY_EXTERN const NSUInteger HippyBridgeBundleTypeVendor; +/// Bundle Type Business, +/// used in kHippyNotiBundleTypeKey +HIPPY_EXTERN const NSUInteger HippyBridgeBundleTypeBusiness; + +/** + * This notification fires when the bridge starts loading and executing the JS bundle. + * @discussion + * Notification.object: instance of HippyBridge + * Notification.userInfo: + * @{ + * kHippyNotiBridgeKey : $(instance of HippyBridge), + * kHippyNotiBundleUrlKey : $(bundleURL), + * kHippyNotiBundleTypeKey : $(bundleType), + * } + * + * 备注:bundle包开始加载的通知, 注意与Hippy2不同的是,不仅指代`Common包`,`Business包`同样会发送该通知, + * 可通过userInfo中bundleType参数进行区分,see: HippyBridgeBundleTypeVendor + */ +HIPPY_EXTERN NSString *const HippyJavaScriptWillStartLoadingNotification; + +/** + * This notification fires when bridge has fetched JS bundle's source code. + * @discussion + * Notification.object: instance of HippyBridge + * Notification.userInfo: + * @{ + * kHippyNotiBridgeKey : $(instance of HippyBridge), + * kHippyNotiBundleUrlKey : $(bundleURL), + * kHippyNotiBundleTypeKey : $(bundleType), + * kHippyNotiErrorKey : $(error), // NSError object + * } + * + * 备注:获取到Bundle包的source code data时的通知 + */ +HIPPY_EXTERN NSString *const HippyJavaScripDidLoadSourceCodeNotification; + /** * This notification fires when the bridge has finished loading the JS bundle. + * @discussion + * Notification.object: instance of HippyBridge + * Notification.userInfo: + * @{ + * kHippyNotiBridgeKey : $(instance of HippyBridge), + * kHippyNotiBundleUrlKey : $(bundleURL), + * kHippyNotiBundleTypeKey : $(bundleType), + * } + * + * 备注:Bundle包`加载和执行`结束的通知 */ HIPPY_EXTERN NSString *const HippyJavaScriptDidLoadNotification; /** * This notification fires when the bridge failed to load the JS bundle. The * `error` key can be used to determine the error that occured. + * @discussion + * Notification.object: instance of HippyBridge + * Notification.userInfo: + * @{ + * kHippyNotiBridgeKey : $(instance of HippyBridge), + * kHippyNotiBundleUrlKey : $(bundleURL), + * kHippyNotiBundleTypeKey : $(bundleType), + * kHippyNotiErrorKey : $(error), // NSError object + * } + * + * 备注:Bundle包`加载和执行`失败的通知 */ HIPPY_EXTERN NSString *const HippyJavaScriptDidFailToLoadNotification; @@ -74,6 +142,8 @@ HIPPY_EXTERN NSString *HippyBridgeModuleNameForClass(Class bridgeModuleClass); +#pragma mark - + /// Async bridge used to communicate with the JavaScript application. @interface HippyBridge : NSObject @@ -143,14 +213,6 @@ HIPPY_EXTERN NSString *HippyBridgeModuleNameForClass(Class bridgeModuleClass); */ @property (nonatomic, strong, readonly) NSURL *debugURL; -/** - * Load js bundles from urls - * - * @param bundleURL bundles url - * @discussion HippyBridge makes sure bundles will be loaded in order. - */ -- (void)loadBundleURL:(NSURL *)bundleURL - completion:(void (^_Nullable)(NSURL * _Nullable, NSError * _Nullable))completion; #pragma mark - Image Related @@ -338,6 +400,29 @@ HIPPY_EXTERN NSString *HippyBridgeModuleNameForClass(Class bridgeModuleClass); - (void)setOSNightMode:(BOOL)isOSNightMode withRootViewTag:(NSNumber *)rootViewTag; + +#pragma mark - Advanced Usages + +/* 说明: + * 以下方法一般情况下无需调用,仅供高级定制化使用。 + * Following methods are only used for advanced customization, no need to be invoked in general. + */ + +typedef NSUInteger HippyBridgeBundleType; +typedef void (^HippyBridgeBundleLoadCompletionBlock)(NSURL * _Nullable bundleURL, NSError * _Nullable error); + +/// Load and Execute bundle from the given bundle URL +/// - Parameters: +/// - bundleURL: bundle url +/// - bundleType: type of bundle, e.g.: whether is `Vendor Bundle`(Common Bundle) or `Business Bundle` +/// - completion: Completion block +/// +/// - Disscusion: HippyBridge makes sure bundles will be loaded and execute in order. +- (void)loadBundleURL:(NSURL *)bundleURL + bundleType:(HippyBridgeBundleType)bundleType + completion:(HippyBridgeBundleLoadCompletionBlock)completion; + + @end diff --git a/framework/ios/base/bridge/HippyBridge.mm b/framework/ios/base/bridge/HippyBridge.mm index 815e7208f1b..7b6afcc8449 100644 --- a/framework/ios/base/bridge/HippyBridge.mm +++ b/framework/ios/base/bridge/HippyBridge.mm @@ -79,11 +79,22 @@ #include "devtools/devtools_data_source.h" #endif + +NSString *const _HippySDKVersion = @HIPPY_STR(HIPPY_VERSION); NSString *const HippyReloadNotification = @"HippyReloadNotification"; +NSString *const HippyJavaScriptWillStartLoadingNotification = @"HippyJavaScriptWillStartLoadingNotification"; +NSString *const HippyJavaScripDidLoadSourceCodeNotification = @"HippyJavaScripDidLoadSourceCodeNotification"; NSString *const HippyJavaScriptDidLoadNotification = @"HippyJavaScriptDidLoadNotification"; NSString *const HippyJavaScriptDidFailToLoadNotification = @"HippyJavaScriptDidFailToLoadNotification"; NSString *const HippyDidInitializeModuleNotification = @"HippyDidInitializeModuleNotification"; -NSString *const _HippySDKVersion = @HIPPY_STR(HIPPY_VERSION); + +NSString *const kHippyNotiBridgeKey = @"bridge"; +NSString *const kHippyNotiBundleUrlKey = @"bundleURL"; +NSString *const kHippyNotiBundleTypeKey = @"bundleType"; +NSString *const kHippyNotiErrorKey = @"error"; + +const NSUInteger HippyBridgeBundleTypeVendor = 1; +const NSUInteger HippyBridgeBundleTypeBusiness = 2; static NSString *const HippyNativeGlobalKeyOS = @"OS"; @@ -481,7 +492,7 @@ - (void)setUp { _javaScriptExecutor.contextName = _contextName; } _displayLink = [[HippyDisplayLink alloc] init]; - + // Setup all extra and internal modules [_moduleSetup setupModulesWithCompletionBlock:^{ HippyBridge *strongSelf = weakSelf; @@ -503,36 +514,61 @@ - (void)setUp { /// 加载初始化bridge时传入的Bundle URL - (void)loadPendingVendorBundleURLIfNeeded { if (self.pendingLoadingVendorBundleURL) { - [self loadBundleURL:self.pendingLoadingVendorBundleURL completion:^(NSURL * _Nullable url, NSError * _Nullable error) { + [self loadBundleURL:self.pendingLoadingVendorBundleURL + bundleType:HippyBridgeBundleTypeVendor + completion:^(NSURL * _Nullable bundleURL, NSError * _Nullable error) { if (error) { - HippyLogError(@"[Hippy_OC_Log][HippyBridge], bundle loaded error:%@, %@", url, error.description); + HippyLogError(@"[Hippy_OC_Log][HippyBridge], bundle loaded error:%@, %@", bundleURL, error.description); } else { - HippyLogInfo(@"[Hippy_OC_Log][HippyBridge], bundle loaded success:%@", url); + HippyLogInfo(@"[Hippy_OC_Log][HippyBridge], bundle loaded success:%@", bundleURL); } }]; } } +#define BUNDLE_LOAD_NOTI_SUCCESS_USER_INFO \ + @{ kHippyNotiBridgeKey: strongSelf, \ + kHippyNotiBundleUrlKey: bundleURL, \ + kHippyNotiBundleTypeKey : @(bundleType) } + +#define BUNDLE_LOAD_NOTI_ERROR_USER_INFO \ + @{ kHippyNotiBridgeKey: strongSelf, \ + kHippyNotiBundleUrlKey: bundleURL, \ + kHippyNotiBundleTypeKey : @(bundleType), \ + kHippyNotiErrorKey : error } - (void)loadBundleURL:(NSURL *)bundleURL - completion:(void (^_Nullable)(NSURL * _Nullable, NSError * _Nullable))completion { + bundleType:(HippyBridgeBundleType)bundleType + completion:(nonnull HippyBridgeBundleLoadCompletionBlock)completion { if (!bundleURL) { if (completion) { static NSString *bundleError = @"bundle url is nil"; - NSError *error = [NSError errorWithDomain:@"Bridge Bundle Loading Domain" code:1 userInfo:@{NSLocalizedFailureReasonErrorKey: bundleError}]; + NSError *error = [NSError errorWithDomain:@"Bridge Bundle Loading Domain" + code:1 + userInfo:@{NSLocalizedFailureReasonErrorKey: bundleError}]; completion(nil, error); } return; } - HippyLogInfo(@"[HP PERF] Begin loading bundle(%s) at %s", HP_CSTR_NOT_NULL(bundleURL.absoluteString.lastPathComponent.UTF8String), HP_CSTR_NOT_NULL(bundleURL.absoluteString.UTF8String)); + HippyLogInfo(@"[HP PERF] Begin loading bundle(%s) at %s", + HP_CSTR_NOT_NULL(bundleURL.absoluteString.lastPathComponent.UTF8String), + HP_CSTR_NOT_NULL(bundleURL.absoluteString.UTF8String)); [_bundleURLs addObject:bundleURL]; + + __weak __typeof(self)weakSelf = self; dispatch_async(HippyBridgeQueue(), ^{ - [self beginLoadingBundle:bundleURL completion:completion]; + __strong __typeof(weakSelf)strongSelf = weakSelf; + NSDictionary *userInfo = BUNDLE_LOAD_NOTI_SUCCESS_USER_INFO; + [[NSNotificationCenter defaultCenter] postNotificationName:HippyJavaScriptWillStartLoadingNotification + object:strongSelf + userInfo:userInfo]; + [strongSelf beginLoadingBundle:bundleURL bundleType:bundleType completion:completion]; }); } - (void)beginLoadingBundle:(NSURL *)bundleURL - completion:(void (^)(NSURL * _Nullable, NSError * _Nullable))completion { + bundleType:(HippyBridgeBundleType)bundleType + completion:(HippyBridgeBundleLoadCompletionBlock)completion { dispatch_group_t group = dispatch_group_create(); __weak HippyBridge *weakSelf = self; __block NSData *script = nil; @@ -545,23 +581,35 @@ - (void)beginLoadingBundle:(NSURL *)bundleURL bundleURL:bundleURL queue:bundleQueue]; fetchOp.onLoad = ^(NSData *source, NSError *error) { + __strong __typeof(weakSelf)strongSelf = weakSelf; + if (!strongSelf) { + dispatch_group_leave(group); + return; + } + NSDictionary *userInfo; if (error) { HippyBridgeFatal(error, weakSelf); + userInfo = BUNDLE_LOAD_NOTI_ERROR_USER_INFO; } else { script = source; + userInfo = BUNDLE_LOAD_NOTI_SUCCESS_USER_INFO; } + [[NSNotificationCenter defaultCenter] postNotificationName:HippyJavaScripDidLoadSourceCodeNotification + object:strongSelf + userInfo:userInfo]; dispatch_group_leave(group); }; dispatch_group_enter(group); HippyBundleExecutionOperation *executeOp = [[HippyBundleExecutionOperation alloc] initWithBlock:^{ - HippyBridge *strongSelf = weakSelf; + __strong __typeof(weakSelf)strongSelf = weakSelf; if (!strongSelf || !strongSelf.valid) { dispatch_group_leave(group); return; } __weak __typeof(strongSelf)weakSelf = strongSelf; [strongSelf executeJSCode:script sourceURL:bundleURL onCompletion:^(id result, NSError *error) { + __strong __typeof(weakSelf)strongSelf = weakSelf; HippyLogInfo(@"End loading bundle(%s) at %s", HP_CSTR_NOT_NULL(bundleURL.absoluteString.lastPathComponent.UTF8String), HP_CSTR_NOT_NULL(bundleURL.absoluteString.UTF8String)); @@ -569,7 +617,6 @@ - (void)beginLoadingBundle:(NSURL *)bundleURL if (completion) { completion(bundleURL, error); } - HippyBridge *strongSelf = weakSelf; if (!strongSelf || !strongSelf.valid) { dispatch_group_leave(group); return; @@ -577,6 +624,25 @@ - (void)beginLoadingBundle:(NSURL *)bundleURL if (error) { HippyBridgeFatal(error, strongSelf); } + __weak __typeof(self)weakSelf = strongSelf; + dispatch_async(dispatch_get_main_queue(), ^{ + __strong __typeof(weakSelf)strongSelf = weakSelf; + if (!strongSelf) { + return; + } + NSNotificationName notiName; + NSDictionary *userInfo; + if (error) { + notiName = HippyJavaScriptDidFailToLoadNotification; + userInfo = BUNDLE_LOAD_NOTI_ERROR_USER_INFO; + } else { + notiName = HippyJavaScriptDidLoadNotification; + userInfo = BUNDLE_LOAD_NOTI_SUCCESS_USER_INFO; + } + [[NSNotificationCenter defaultCenter] postNotificationName:notiName + object:strongSelf + userInfo:userInfo]; + }); dispatch_group_leave(group); }]; } queue:bundleQueue]; @@ -660,6 +726,10 @@ - (void)setInspectable:(BOOL)isInspectable { [self.javaScriptExecutor setInspecable:isInspectable]; } + +#pragma mark - Private + +/// Execute JS Bundle - (void)executeJSCode:(NSData *)script sourceURL:(NSURL *)sourceURL onCompletion:(HippyJavaScriptCallback)completion { @@ -682,14 +752,6 @@ - (void)executeJSCode:(NSData *)script if (error) { [strongSelf stopLoadingWithError:error scriptSourceURL:sourceURL]; } - else { - dispatch_async(dispatch_get_main_queue(), ^{ - NSDictionary *userInfo = @{@"bridge": self, sourceURL: sourceURL}; - [[NSNotificationCenter defaultCenter] postNotificationName:HippyJavaScriptDidLoadNotification - object:self - userInfo:userInfo]; - }); - } completion(result, error); }]; } @@ -708,10 +770,6 @@ - (void)stopLoadingWithError:(NSError *)error scriptSourceURL:(NSURL *)sourceURL } } }]; - NSDictionary *userInfo = @{@"bridge": self, @"error": error, @"sourceURL": sourceURL}; - [[NSNotificationCenter defaultCenter] postNotificationName:HippyJavaScriptDidFailToLoadNotification - object:self - userInfo:userInfo]; if ([error userInfo][HippyJSStackTraceKey]) { [self.redBox showErrorMessage:[error localizedDescription] withStack:[error userInfo][HippyJSStackTraceKey]]; } diff --git a/renderer/native/ios/renderer/HippyRootView.h b/renderer/native/ios/renderer/HippyRootView.h index 33a8aba604d..fa56135a43c 100644 --- a/renderer/native/ios/renderer/HippyRootView.h +++ b/renderer/native/ios/renderer/HippyRootView.h @@ -47,11 +47,6 @@ typedef NS_ENUM(NSInteger, HippyRootViewSizeFlexibility) { /// is a good indicator that the application is ready to use. extern NSString *const HippyContentDidAppearNotification; -/// Business bundle loading completion notification -/// This notification is for compatibility with hippy2 and is not recommended for further use -extern NSString *const HippySecondaryBundleDidLoadNotification; - - /// Native view used to host Hippy-managed views within the app. /// Can be used just like any ordinary UIView. diff --git a/renderer/native/ios/renderer/HippyRootView.mm b/renderer/native/ios/renderer/HippyRootView.mm index f9ed9123ed5..e8ca67e0b91 100644 --- a/renderer/native/ios/renderer/HippyRootView.mm +++ b/renderer/native/ios/renderer/HippyRootView.mm @@ -35,11 +35,6 @@ // Sent when the first subviews are added to the root view NSString *const HippyContentDidAppearNotification = @"HippyContentDidAppearNotification"; -// In hippy2 there are two concepts: common package and business package; -// After the success of the business package loading will send a `SecondaryBundleDidLoad` notification; -// For compatibility, hippy3 retains this notice and its actual meaning. -NSString *const HippySecondaryBundleDidLoadNotification = @"HippySecondaryBundleDidLoadNotification"; - NSNumber *AllocRootViewTag(void) { static NSString * const token = @"allocateRootTag"; @synchronized (token) { @@ -156,7 +151,9 @@ - (instancetype)initWithBridge:(HippyBridge *)bridge } } else { __weak __typeof(self)weakSelf = self; - [bridge loadBundleURL:businessURL completion:^(NSURL * _Nullable url, NSError * _Nullable error) { + [bridge loadBundleURL:businessURL + bundleType:HippyBridgeBundleTypeBusiness + completion:^(NSURL * _Nullable url, NSError * _Nullable error) { // Execute loadInstance first and then do call back, maintain compatibility with hippy2 dispatch_async(dispatch_get_main_queue(), ^{ __strong __typeof(weakSelf)strongSelf = weakSelf; @@ -166,13 +163,6 @@ - (instancetype)initWithBridge:(HippyBridge *)bridge if (!error && !strongSelf.disableAutoRunApplication) { [strongSelf runHippyApplication]; } - // 抛出业务包(BusinessBundle aka SecondaryBundle)加载完成通知, for hippy2兼容 - NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] initWithDictionary:@{ @"url": url, - @"bridge": strongSelf.bridge }]; - if (error) [userInfo setObject:error forKey:@"error"]; - [[NSNotificationCenter defaultCenter] postNotificationName:HippySecondaryBundleDidLoadNotification - object:strongSelf.bridge userInfo:userInfo]; - if ([delegate respondsToSelector:@selector(rootView:didLoadFinish:)]) { [delegate rootView:strongSelf didLoadFinish:(error == nil)]; } @@ -285,15 +275,15 @@ - (void)javaScriptDidLoad:(NSNotification *)notification { // Use the bridge that's sent in the notification payload // Call runHippyApplication only if the RootView is initialized without a business bundle. - HippyBridge *bridge = notification.userInfo[@"bridge"]; + HippyBridge *bridge = notification.userInfo[kHippyNotiBridgeKey]; if (!self.disableAutoRunApplication && bridge == self.bridge && !_hasBusinessBundleToLoad) { [self runHippyApplication]; } } - (void)javaScriptDidFailToLoad:(NSNotification *)notification { - HippyBridge *bridge = notification.userInfo[@"bridge"]; - NSError *error = notification.userInfo[@"error"]; + HippyBridge *bridge = notification.userInfo[kHippyNotiBridgeKey]; + NSError *error = notification.userInfo[kHippyNotiErrorKey]; if (bridge == self.bridge && error) { NSError *retError = HippyErrorFromErrorAndModuleName(error, self.bridge.moduleName); HippyFatal(retError); From beb965dc7a9e1269308bdd6b157b7bc3581a7273 Mon Sep 17 00:00:00 2001 From: wwwcg Date: Tue, 23 Apr 2024 15:56:52 +0800 Subject: [PATCH 6/7] chore(ios): add SecondaryBundleDidLoadNotification for compatibility --- renderer/native/ios/renderer/HippyRootView.h | 4 ++++ renderer/native/ios/renderer/HippyRootView.mm | 17 +++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/renderer/native/ios/renderer/HippyRootView.h b/renderer/native/ios/renderer/HippyRootView.h index fa56135a43c..8860247c635 100644 --- a/renderer/native/ios/renderer/HippyRootView.h +++ b/renderer/native/ios/renderer/HippyRootView.h @@ -47,6 +47,10 @@ typedef NS_ENUM(NSInteger, HippyRootViewSizeFlexibility) { /// is a good indicator that the application is ready to use. extern NSString *const HippyContentDidAppearNotification; +/// Business bundle loading completion notification +/// This notification is for compatibility with hippy2 and is not recommended for further use +extern NSString *const HippySecondaryBundleDidLoadNotification DEPRECATED_MSG_ATTRIBUTE("use HippyJavaScriptDidLoadNotification"); + /// Native view used to host Hippy-managed views within the app. /// Can be used just like any ordinary UIView. diff --git a/renderer/native/ios/renderer/HippyRootView.mm b/renderer/native/ios/renderer/HippyRootView.mm index e8ca67e0b91..b99d9553c45 100644 --- a/renderer/native/ios/renderer/HippyRootView.mm +++ b/renderer/native/ios/renderer/HippyRootView.mm @@ -35,6 +35,12 @@ // Sent when the first subviews are added to the root view NSString *const HippyContentDidAppearNotification = @"HippyContentDidAppearNotification"; +// In hippy2 there are two concepts: common package and business package; +// After the success of the business package loading will send a `SecondaryBundleDidLoad` notification; +// For compatibility, hippy3 retains this notice and its actual meaning. +NSString *const HippySecondaryBundleDidLoadNotification = @"HippySecondaryBundleDidLoadNotification"; + + NSNumber *AllocRootViewTag(void) { static NSString * const token = @"allocateRootTag"; @synchronized (token) { @@ -163,6 +169,17 @@ - (instancetype)initWithBridge:(HippyBridge *)bridge if (!error && !strongSelf.disableAutoRunApplication) { [strongSelf runHippyApplication]; } + + // 抛出业务包(BusinessBundle aka SecondaryBundle)加载完成通知,for hippy2兼容 + NSMutableDictionary *userInfo = @{ kHippyNotiBundleUrlKey: url, + kHippyNotiBridgeKey: strongSelf.bridge }.mutableCopy; + if (error) { [userInfo setObject:error forKey:kHippyNotiErrorKey]; } + HIPPY_IGNORE_WARNING_BEGIN(-Wdeprecated) + [[NSNotificationCenter defaultCenter] postNotificationName:HippySecondaryBundleDidLoadNotification + object:strongSelf.bridge + userInfo:userInfo]; + HIPPY_IGNORE_WARNING_END + if ([delegate respondsToSelector:@selector(rootView:didLoadFinish:)]) { [delegate rootView:strongSelf didLoadFinish:(error == nil)]; } From 1ccd56194bd4d8e406fc8d7c6e25f3c3d5e55c98 Mon Sep 17 00:00:00 2001 From: wwwcg Date: Tue, 23 Apr 2024 17:34:47 +0800 Subject: [PATCH 7/7] chore(ios): optimize parameter check tips --- framework/ios/base/modules/HippyModuleMethod.mm | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/framework/ios/base/modules/HippyModuleMethod.mm b/framework/ios/base/modules/HippyModuleMethod.mm index 65bf27b0df2..2a2ea61d786 100644 --- a/framework/ios/base/modules/HippyModuleMethod.mm +++ b/framework/ios/base/modules/HippyModuleMethod.mm @@ -480,9 +480,15 @@ - (id)invokeWithBridge:(HippyBridge *)bridge module:(id)module arguments:(NSArra NSInteger actualCount = arguments.count; NSInteger expectedCount = _argumentBlocks.count; BOOL isArgumentsMismatch = NO; - if (actualCount > expectedCount || - (self.functionType == HippyFunctionTypePromise && actualCount < expectedCount - 2)) { + if (actualCount > expectedCount) { isArgumentsMismatch = YES; + } else if (self.functionType == HippyFunctionTypePromise && actualCount < expectedCount - 2) { + for (NSInteger index = actualCount; index < expectedCount - 2; index++) { + id arg = self.arguments[index]; + if (arg.nullability != HippyNullable) { + isArgumentsMismatch = YES; + } + } } if (isArgumentsMismatch) { HippyLogError(@"%@.%@ was called with %lld arguments but expects %lld arguments. " @@ -499,8 +505,7 @@ - (id)invokeWithBridge:(HippyBridge *)bridge module:(id)module arguments:(NSArra // Set arguments NSUInteger index = 0; for (id json in arguments) { - // release模式下,如果前端给的参数多于终端所需参数,那会造成数组越界,引起整个逻辑return。 - //这里做个修改,如果前端给的参数过多,那忽略多余的参数。 + // 如果前端给的参数过多,忽略多余的参数 if ([_argumentBlocks count] <= index) { break; }