Skip to content

Commit

Permalink
Convert RCTImageLoader to TurboModules [4/N]
Browse files Browse the repository at this point in the history
Summary:
This diff adds a JS spec for RCTImageLoader, and conforms to it in ObjC++. Since RCTImageLoader isn't called from JS, the js spec is empty. Since `/CoreModules/` is the only dir in OSS which supports TM, move the ObjC++ impl there.

The change in `NativeExceptionsManager.js` fixes a weird bug I was hitting in codegen, where the codegen cpp file wouldn't compile due to unused variable.

Reviewed By: JoshuaGross

Differential Revision: D16495674

fbshipit-source-id: 191897b87730a6b0b96022eedc6412551fae04a6
  • Loading branch information
Peter Argany authored and facebook-github-bot committed Aug 15, 2019
1 parent 6c3b01d commit 30c1196
Show file tree
Hide file tree
Showing 10 changed files with 104 additions and 55 deletions.
3 changes: 2 additions & 1 deletion Libraries/Core/NativeExceptionsManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ export type ExceptionData = {
stack: Array<StackFrame>,
id: number,
isFatal: boolean,
extraData?: ?{},
// flowlint-next-line unclear-type:off
extraData?: Object,
};

export interface Spec extends TurboModule {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -855,12 +855,6 @@ + (RCTManagedPointer *)JS_NativeExceptionsManager_StackFrame:(id)json
return facebook::react::managedPointer<JS::NativeExceptionsManager::StackFrame>(json);
}
@end
@implementation RCTCxxConvert (NativeExceptionsManager_ExceptionDataExtraData)
+ (RCTManagedPointer *)JS_NativeExceptionsManager_ExceptionDataExtraData:(id)json
{
return facebook::react::managedPointer<JS::NativeExceptionsManager::ExceptionDataExtraData>(json);
}
@end
@implementation RCTCxxConvert (NativeExceptionsManager_ExceptionData)
+ (RCTManagedPointer *)JS_NativeExceptionsManager_ExceptionData:(id)json
{
Expand Down Expand Up @@ -1082,6 +1076,19 @@ + (RCTManagedPointer *)JS_NativeFrameRateLogger_SpecSetGlobalOptionsOptions:(id)



}

} // namespace react
} // namespace facebook
namespace facebook {
namespace react {



NativeImageLoaderSpecJSI::NativeImageLoaderSpecJSI(id<RCTTurboModule> instance, std::shared_ptr<JSCallInvoker> jsInvoker)
: ObjCTurboModule("ImageLoader", instance, jsInvoker) {


}

} // namespace react
Expand Down
37 changes: 18 additions & 19 deletions Libraries/FBReactNativeSpec/FBReactNativeSpec/FBReactNativeSpec.h
Original file line number Diff line number Diff line change
Expand Up @@ -880,21 +880,6 @@ namespace JS {
+ (RCTManagedPointer *)JS_NativeExceptionsManager_StackFrame:(id)json;
@end

namespace JS {
namespace NativeExceptionsManager {
struct ExceptionDataExtraData {

ExceptionDataExtraData(NSDictionary *const v) : _v(v) {}
private:
NSDictionary *_v;
};
}
}

@interface RCTCxxConvert (NativeExceptionsManager_ExceptionDataExtraData)
+ (RCTManagedPointer *)JS_NativeExceptionsManager_ExceptionDataExtraData:(id)json;
@end

namespace JS {
namespace NativeExceptionsManager {
struct ExceptionData {
Expand All @@ -905,7 +890,7 @@ namespace JS {
facebook::react::LazyVector<JS::NativeExceptionsManager::StackFrame> stack() const;
double id_() const;
bool isFatal() const;
folly::Optional<JS::NativeExceptionsManager::ExceptionDataExtraData> extraData() const;
id<NSObject> _Nullable extraData() const;

ExceptionData(NSDictionary *const v) : _v(v) {}
private:
Expand Down Expand Up @@ -1099,6 +1084,21 @@ namespace facebook {
};
} // namespace react
} // namespace facebook
@protocol NativeImageLoaderSpec <RCTBridgeModule, RCTTurboModule>
@end
namespace facebook {
namespace react {
/**
* ObjC++ class for module 'ImageLoader'
*/

class JSI_EXPORT NativeImageLoaderSpecJSI : public ObjCTurboModule {
public:
NativeImageLoaderSpecJSI(id<RCTTurboModule> instance, std::shared_ptr<JSCallInvoker> jsInvoker);

};
} // namespace react
} // namespace facebook

namespace JS {
namespace NativeImagePickerIOS {
Expand Down Expand Up @@ -2682,7 +2682,6 @@ inline folly::Optional<bool> JS::NativeExceptionsManager::StackFrame::collapse()
id const p = _v[@"collapse"];
return RCTBridgingToOptionalBool(p);
}

inline NSString *JS::NativeExceptionsManager::ExceptionData::message() const
{
id const p = _v[@"message"];
Expand Down Expand Up @@ -2718,10 +2717,10 @@ inline bool JS::NativeExceptionsManager::ExceptionData::isFatal() const
id const p = _v[@"isFatal"];
return RCTBridgingToBool(p);
}
inline folly::Optional<JS::NativeExceptionsManager::ExceptionDataExtraData> JS::NativeExceptionsManager::ExceptionData::extraData() const
inline id<NSObject> _Nullable JS::NativeExceptionsManager::ExceptionData::extraData() const
{
id const p = _v[@"extraData"];
return (p == nil ? folly::none : folly::make_optional(JS::NativeExceptionsManager::ExceptionDataExtraData(p)));
return p;
}
inline folly::Optional<bool> JS::NativeFrameRateLogger::SpecSetGlobalOptionsOptions::debug() const
{
Expand Down
20 changes: 20 additions & 0 deletions Libraries/Image/NativeImageLoader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
* @format
*/

'use strict';

import type {TurboModule} from '../TurboModule/RCTExport';
import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry';

export interface Spec extends TurboModule {
+getConstants: () => {||};
}

export default TurboModuleRegistry.getEnforcing<Spec>('ImageLoader');
2 changes: 1 addition & 1 deletion RNTester/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -377,4 +377,4 @@ SPEC CHECKSUMS:

PODFILE CHECKSUM: 060903e270072f1e192b064848e6c34528af1c87

COCOAPODS: 1.6.1
COCOAPODS: 1.7.1
10 changes: 7 additions & 3 deletions React/CoreModules/BUCK
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,13 @@ rn_apple_library(
["-D PIC_MODIFIER=@PLT"],
)],
plugins = react_module_plugin_providers(
name = "PlatformConstants",
native_class_func = "RCTPlatformCls",
),
name = "ImageLoader",
native_class_func = "RCTImageLoaderCls",
) +
react_module_plugin_providers(
name = "PlatformConstants",
native_class_func = "RCTPlatformCls",
),
preprocessor_flags = OBJC_ARC_PREPROCESSOR_FLAGS + get_debug_preprocessor_flags() + rn_debug_flags() + [
"-DRN_DISABLE_OSS_PLUGIN_HEADER",
],
Expand Down
1 change: 1 addition & 0 deletions React/CoreModules/CoreModulesPlugins.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ extern "C" {
Class RCTCoreModulesClassProvider(const char *name);

// Lookup functions
Class RCTImageLoaderCls(void);
Class RCTPlatformCls(void);

#ifdef __cplusplus
Expand Down
3 changes: 2 additions & 1 deletion React/CoreModules/CoreModulesPlugins.mm
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
#import <unordered_map>

static std::unordered_map<std::string, Class (*)(void)> sCoreModuleClassMap = {
{"PlatformConstants", RCTPlatformCls},
{"ImageLoader", RCTImageLoaderCls},
{"PlatformConstants", RCTPlatformCls},
};

Class RCTCoreModulesClassProvider(const char *name) {
Expand Down
5 changes: 2 additions & 3 deletions React/CoreModules/RCTImageEditingManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,12 @@
#import <UIKit/UIKit.h>

#import <React/RCTConvert.h>
#import <React/RCTLog.h>
#import <React/RCTUtils.h>

#import <React/RCTImageLoader.h>
#import <React/RCTImageStoreManager.h>
#import <React/RCTImageUtils.h>
#import <React/RCTImageLoaderProtocol.h>
#import <React/RCTLog.h>
#import <React/RCTUtils.h>

@implementation RCTImageEditingManager

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,33 @@
* LICENSE file in the root directory of this source tree.
*/

#import <stdatomic.h>
#import <objc/runtime.h>
#import <atomic>

#import <ImageIO/ImageIO.h>

#import <FBReactNativeSpec/FBReactNativeSpec.h>
#import <React/RCTConvert.h>
#import <React/RCTDefines.h>
#import <React/RCTImageCache.h>
#import <React/RCTImageLoader.h>
#import <React/RCTImageUtils.h>
#import <React/RCTLog.h>
#import <React/RCTNetworking.h>
#import <React/RCTUtils.h>

#import <React/RCTImageCache.h>
#import <React/RCTImageUtils.h>
#import "CoreModulesPlugins.h"

static NSInteger RCTImageBytesForImage(UIImage *image)
{
NSInteger singleImageBytes = image.size.width * image.size.height * image.scale * image.scale * 4;
return image.images ? image.images.count * singleImageBytes : singleImageBytes;
}

@interface RCTImageLoader() <NativeImageLoaderSpec>

@end

@implementation UIImage (React)

- (NSInteger)reactDecodedImageBytes
Expand Down Expand Up @@ -385,7 +391,7 @@ - (RCTImageLoaderCancellationBlock)_loadImageOrDataWithURLRequest:(NSURLRequest
BOOL cacheResult = [loadHandler respondsToSelector:@selector(shouldCacheLoadedImages)] ?
[loadHandler shouldCacheLoadedImages] : YES;

__block atomic_bool cancelled = ATOMIC_VAR_INIT(NO);
auto cancelled = std::make_shared<std::atomic<int>>(0);
__block dispatch_block_t cancelLoad = nil;
__block NSLock *cancelLoadLock = [NSLock new];
void (^completionHandler)(NSError *, id, NSURLResponse *) = ^(NSError *error, id imageOrData, NSURLResponse *response) {
Expand All @@ -399,11 +405,11 @@ - (RCTImageLoaderCancellationBlock)_loadImageOrDataWithURLRequest:(NSURLRequest
// Most loaders do not return on the main thread, so caller is probably not
// expecting it, and may do expensive post-processing in the callback
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
if (!atomic_load(&cancelled)) {
if (!std::atomic_load(cancelled.get())) {
completionBlock(error, imageOrData, cacheResult, response);
}
});
} else if (!atomic_load(&cancelled)) {
} else if (!std::atomic_load(cancelled.get())) {
completionBlock(error, imageOrData, cacheResult, response);
}
};
Expand All @@ -430,8 +436,8 @@ - (RCTImageLoaderCancellationBlock)_loadImageOrDataWithURLRequest:(NSURLRequest
__weak RCTImageLoader *weakSelf = self;
dispatch_async(_URLRequestQueue, ^{
__typeof(self) strongSelf = weakSelf;
if (atomic_load(&cancelled) || !strongSelf) {
return;
if (atomic_load(cancelled.get()) || !strongSelf) {
return;
}

if (loadHandler) {
Expand Down Expand Up @@ -471,7 +477,7 @@ - (RCTImageLoaderCancellationBlock)_loadImageOrDataWithURLRequest:(NSURLRequest
});

return ^{
BOOL alreadyCancelled = atomic_fetch_or(&cancelled, 1);
BOOL alreadyCancelled = atomic_fetch_or(cancelled.get(), 1);
if (alreadyCancelled) {
return;
}
Expand Down Expand Up @@ -605,11 +611,11 @@ - (RCTImageLoaderCancellationBlock)loadImageWithURLRequest:(NSURLRequest *)image
partialLoadBlock:(RCTImageLoaderPartialLoadBlock)partialLoadBlock
completionBlock:(RCTImageLoaderCompletionBlock)completionBlock
{
__block atomic_bool cancelled = ATOMIC_VAR_INIT(NO);
auto cancelled = std::make_shared<std::atomic<int>>(0);
__block dispatch_block_t cancelLoad = nil;
__block NSLock *cancelLoadLock = [NSLock new];
dispatch_block_t cancellationBlock = ^{
BOOL alreadyCancelled = atomic_fetch_or(&cancelled, 1);
BOOL alreadyCancelled = atomic_fetch_or(cancelled.get(), 1);
if (alreadyCancelled) {
return;
}
Expand All @@ -625,7 +631,7 @@ - (RCTImageLoaderCancellationBlock)loadImageWithURLRequest:(NSURLRequest *)image
__weak RCTImageLoader *weakSelf = self;
void (^completionHandler)(NSError *, id, BOOL, NSURLResponse *) = ^(NSError *error, id imageOrData, BOOL cacheResult, NSURLResponse *response) {
__typeof(self) strongSelf = weakSelf;
if (atomic_load(&cancelled) || !strongSelf) {
if (std::atomic_load(cancelled.get()) || !strongSelf) {
return;
}

Expand Down Expand Up @@ -685,17 +691,17 @@ - (RCTImageLoaderCancellationBlock)decodeImageData:(NSData *)data
return ^{};
}

__block atomic_bool cancelled = ATOMIC_VAR_INIT(NO);
auto cancelled = std::make_shared<std::atomic<int>>(0);
void (^completionHandler)(NSError *, UIImage *) = ^(NSError *error, UIImage *image) {
if (RCTIsMainQueue()) {
// Most loaders do not return on the main thread, so caller is probably not
// expecting it, and may do expensive post-processing in the callback
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
if (!atomic_load(&cancelled)) {
if (!std::atomic_load(cancelled.get())) {
completionBlock(error, clipped ? RCTResizeImageIfNeeded(image, size, scale, resizeMode) : image);
}
});
} else if (!atomic_load(&cancelled)) {
} else if (!std::atomic_load(cancelled.get())) {
completionBlock(error, clipped ? RCTResizeImageIfNeeded(image, size, scale, resizeMode) : image);
}
};
Expand All @@ -717,7 +723,7 @@ - (RCTImageLoaderCancellationBlock)decodeImageData:(NSData *)data

// Do actual decompression on a concurrent background queue
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
if (!atomic_load(&cancelled)) {
if (!std::atomic_load(cancelled.get())) {

// Decompress the image data (this may be CPU and memory intensive)
UIImage *image = RCTDecodeImageWithData(data, size, scale, resizeMode);
Expand Down Expand Up @@ -774,7 +780,7 @@ - (RCTImageLoaderCancellationBlock)decodeImageData:(NSData *)data
});

return ^{
atomic_store(&cancelled, YES);
std::atomic_store(cancelled.get(), 1);
};
}
}
Expand All @@ -795,8 +801,8 @@ - (RCTImageLoaderCancellationBlock)getImageSizeForURLRequest:(NSURLRequest *)ima
case kCGImagePropertyOrientationRightMirrored:
// swap width and height
size = (CGSize){
[meta[(id)kCGImagePropertyPixelHeight] doubleValue],
[meta[(id)kCGImagePropertyPixelWidth] doubleValue],
[meta[(id)kCGImagePropertyPixelHeight] floatValue],
[meta[(id)kCGImagePropertyPixelWidth] floatValue],
};
break;
case kCGImagePropertyOrientationUp:
Expand All @@ -805,8 +811,8 @@ - (RCTImageLoaderCancellationBlock)getImageSizeForURLRequest:(NSURLRequest *)ima
case kCGImagePropertyOrientationDownMirrored:
default:
size = (CGSize){
[meta[(id)kCGImagePropertyPixelWidth] doubleValue],
[meta[(id)kCGImagePropertyPixelHeight] doubleValue],
[meta[(id)kCGImagePropertyPixelWidth] floatValue],
[meta[(id)kCGImagePropertyPixelHeight] floatValue],
};
break;
}
Expand Down Expand Up @@ -937,6 +943,12 @@ - (void)cancelRequest:(id)requestToken
}
}

- (std::shared_ptr<facebook::react::TurboModule>)getTurboModuleWithJsInvoker:
(std::shared_ptr<facebook::react::JSCallInvoker>)jsInvoker
{
return std::make_shared<facebook::react::NativeImageLoaderSpecJSI>(self, jsInvoker);
}

@end

/**
Expand All @@ -953,3 +965,8 @@ - (RCTImageLoader *)imageLoader
}

@end

Class RCTImageLoaderCls(void)
{
return RCTImageLoader.class;
}

0 comments on commit 30c1196

Please sign in to comment.