mirror of
https://github.com/status-im/react-native.git
synced 2025-02-04 05:34:15 +00:00
Implement RCTJSCWrapper
Reviewed By: tadeuzagallo Differential Revision: D3258713 fbshipit-source-id: 418eb9d350bf3541c976b631bd9799a1c578f5e5
This commit is contained in:
parent
0f57702cd8
commit
abe0b349bc
@ -24,6 +24,8 @@ typedef NS_ENUM(NSUInteger, RCTPLTag) {
|
||||
RCTPLNativeModulePrepareConfig,
|
||||
RCTPLNativeModuleInjectConfig,
|
||||
RCTPLNativeModuleMainThreadUsesCount,
|
||||
RCTPLJSCWrapperOpenLibrary,
|
||||
RCTPLJSCWrapperLoadFunctions,
|
||||
RCTPLJSCExecutorSetup,
|
||||
RCTPLBridgeStartup,
|
||||
RCTPLTTI,
|
||||
|
@ -97,6 +97,8 @@ NSArray *RCTPerformanceLoggerLabels(void)
|
||||
@"NativeModulePrepareConfig",
|
||||
@"NativeModuleInjectConfig",
|
||||
@"NativeModuleMainThreadUsesCount",
|
||||
@"JSCWrapperOpenLibrary",
|
||||
@"JSCWrapperLoadFunctions",
|
||||
@"JSCExecutorSetup",
|
||||
@"BridgeStartup",
|
||||
@"RootViewTTI",
|
||||
|
@ -25,17 +25,31 @@ RCT_EXTERN NSString *const RCTJSCThreadName;
|
||||
*/
|
||||
RCT_EXTERN NSString *const RCTJavaScriptContextCreatedNotification;
|
||||
|
||||
/**
|
||||
* Uses a JavaScriptCore context as the execution engine.
|
||||
*/
|
||||
@interface RCTJSCExecutor : NSObject <RCTJavaScriptExecutor>
|
||||
|
||||
/**
|
||||
* Sets a type of JSC library (system or custom) that's used
|
||||
* to initialize RCTJSCWrapper.
|
||||
* @default is NO.
|
||||
*/
|
||||
+ (void)setUseCustomJSCLibrary:(BOOL)useCustomLibrary;
|
||||
|
||||
/**
|
||||
* Gets a type of JSC library (system or custom) that's used
|
||||
* to initialize RCTJSCWrapper.
|
||||
* @default is NO.
|
||||
*/
|
||||
+ (BOOL)useCustomJSCLibrary;
|
||||
|
||||
/**
|
||||
* Create a NSError from a JSError object.
|
||||
*
|
||||
* If available, the error's userInfo property will contain the JS stacktrace under
|
||||
* the RCTJSStackTraceKey key.
|
||||
*/
|
||||
RCT_EXTERN NSError *RCTNSErrorFromJSError(JSContextRef context, JSValueRef jsError);
|
||||
|
||||
/**
|
||||
* Uses a JavaScriptCore context as the execution engine.
|
||||
*/
|
||||
@interface RCTJSCExecutor : NSObject <RCTJavaScriptExecutor>
|
||||
- (NSError *)convertJSErrorToNSError:(JSValueRef)jsError context:(JSContextRef)context;
|
||||
|
||||
@end
|
||||
|
@ -12,13 +12,8 @@
|
||||
#import <cinttypes>
|
||||
#import <memory>
|
||||
#import <pthread.h>
|
||||
#import <string>
|
||||
|
||||
#ifdef WITH_FB_JSC_TUNING
|
||||
#include <string>
|
||||
#include <fbjsc/jsc_config_ios.h>
|
||||
#endif
|
||||
|
||||
#import <JavaScriptCore/JavaScriptCore.h>
|
||||
#import <UIKit/UIDevice.h>
|
||||
|
||||
#import "RCTAssert.h"
|
||||
@ -33,6 +28,7 @@
|
||||
#import "RCTJSCProfiler.h"
|
||||
#import "RCTRedBox.h"
|
||||
#import "RCTSourceCode.h"
|
||||
#import "RCTJSCWrapper.h"
|
||||
|
||||
NSString *const RCTJSCThreadName = @"com.facebook.react.JavaScript";
|
||||
|
||||
@ -137,6 +133,8 @@ RCT_NOT_IMPLEMENTED(-(instancetype)init)
|
||||
|
||||
JSStringRef _bundleURL;
|
||||
RandomAccessBundleData _randomAccessBundle;
|
||||
|
||||
RCTJSCWrapper *_jscWrapper;
|
||||
}
|
||||
|
||||
@synthesize valid = _valid;
|
||||
@ -144,36 +142,36 @@ RCT_NOT_IMPLEMENTED(-(instancetype)init)
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
static NSString *RCTJSValueToNSString(JSContextRef context, JSValueRef value, JSValueRef *exception)
|
||||
static NSString *RCTJSValueToNSString(RCTJSCWrapper *jscWrapper, JSContextRef context, JSValueRef value, JSValueRef *exception)
|
||||
{
|
||||
JSStringRef JSString = JSValueToStringCopy(context, value, exception);
|
||||
JSStringRef JSString = jscWrapper->JSValueToStringCopy(context, value, exception);
|
||||
if (!JSString) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
CFStringRef string = JSStringCopyCFString(kCFAllocatorDefault, JSString);
|
||||
JSStringRelease(JSString);
|
||||
CFStringRef string = jscWrapper->JSStringCopyCFString(kCFAllocatorDefault, JSString);
|
||||
jscWrapper->JSStringRelease(JSString);
|
||||
|
||||
return (__bridge_transfer NSString *)string;
|
||||
}
|
||||
|
||||
static NSString *RCTJSValueToJSONString(JSContextRef context, JSValueRef value, JSValueRef *exception, unsigned indent)
|
||||
static NSString *RCTJSValueToJSONString(RCTJSCWrapper *jscWrapper, JSContextRef context, JSValueRef value, JSValueRef *exception, unsigned indent)
|
||||
{
|
||||
JSStringRef JSString = JSValueCreateJSONString(context, value, indent, exception);
|
||||
CFStringRef string = JSStringCopyCFString(kCFAllocatorDefault, JSString);
|
||||
JSStringRelease(JSString);
|
||||
JSStringRef jsString = jscWrapper->JSValueCreateJSONString(context, value, indent, exception);
|
||||
CFStringRef string = jscWrapper->JSStringCopyCFString(kCFAllocatorDefault, jsString);
|
||||
jscWrapper->JSStringRelease(jsString);
|
||||
|
||||
return (__bridge_transfer NSString *)string;
|
||||
}
|
||||
|
||||
NSError *RCTNSErrorFromJSError(JSContextRef context, JSValueRef jsError)
|
||||
static NSError *RCTNSErrorFromJSError(RCTJSCWrapper *jscWrapper, JSContextRef context, JSValueRef jsError)
|
||||
{
|
||||
NSMutableDictionary *errorInfo = [NSMutableDictionary new];
|
||||
|
||||
NSString *description = jsError ? RCTJSValueToNSString(context, jsError, NULL) : @"Unknown JS error";
|
||||
NSString *description = jsError ? RCTJSValueToNSString(jscWrapper, context, jsError, NULL) : @"Unknown JS error";
|
||||
errorInfo[NSLocalizedDescriptionKey] = [@"Unhandled JS Exception: " stringByAppendingString:description];
|
||||
|
||||
NSString *details = jsError ? RCTJSValueToJSONString(context, jsError, NULL, 0) : nil;
|
||||
NSString *details = jsError ? RCTJSValueToJSONString(jscWrapper, context, jsError, NULL, 0) : nil;
|
||||
if (details) {
|
||||
errorInfo[NSLocalizedFailureReasonErrorKey] = details;
|
||||
|
||||
@ -219,6 +217,11 @@ NSError *RCTNSErrorFromJSError(JSContextRef context, JSValueRef jsError)
|
||||
return [NSError errorWithDomain:RCTErrorDomain code:1 userInfo:errorInfo];
|
||||
}
|
||||
|
||||
- (NSError *)convertJSErrorToNSError:(JSValueRef)jsError context:(JSContextRef)context
|
||||
{
|
||||
return RCTNSErrorFromJSError(_jscWrapper, context, jsError);
|
||||
}
|
||||
|
||||
#if RCT_DEV
|
||||
|
||||
static void RCTInstallJSCProfiler(RCTBridge *bridge, JSContextRef context)
|
||||
@ -259,6 +262,18 @@ static void RCTInstallJSCProfiler(RCTBridge *bridge, JSContextRef context)
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL useCustomJSCLibrary = NO;
|
||||
|
||||
+ (void)setUseCustomJSCLibrary:(BOOL)useCustomLibrary
|
||||
{
|
||||
useCustomJSCLibrary = useCustomLibrary;
|
||||
}
|
||||
|
||||
+ (BOOL)useCustomJSCLibrary
|
||||
{
|
||||
return useCustomJSCLibrary;
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
if (self = [super init]) {
|
||||
@ -290,7 +305,7 @@ static void RCTInstallJSCProfiler(RCTBridge *bridge, JSContextRef context)
|
||||
}
|
||||
|
||||
if (!_context) {
|
||||
JSContext *context = [JSContext new];
|
||||
JSContext *context = [_jscWrapper->JSContext new];
|
||||
_context = [[RCTJavaScriptContext alloc] initWithJSContext:context onThread:_javaScriptThread];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:RCTJavaScriptContextCreatedNotification
|
||||
@ -312,21 +327,33 @@ static void RCTInstallJSCProfiler(RCTBridge *bridge, JSContextRef context)
|
||||
{
|
||||
__weak RCTJSCExecutor *weakSelf = self;
|
||||
|
||||
#ifdef WITH_FB_JSC_TUNING
|
||||
[self executeBlockOnJavaScriptQueue:^{
|
||||
RCTJSCExecutor *strongSelf = weakSelf;
|
||||
if (!strongSelf.valid) {
|
||||
return;
|
||||
}
|
||||
|
||||
strongSelf->_jscWrapper = RCTJSCWrapperCreate(useCustomJSCLibrary);
|
||||
}];
|
||||
|
||||
|
||||
[self executeBlockOnJavaScriptQueue:^{
|
||||
RCTJSCExecutor *strongSelf = weakSelf;
|
||||
if (!strongSelf.valid) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (strongSelf->_jscWrapper->configureJSContextForIOS == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *cachesPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
|
||||
RCTAssert(cachesPath != nil, @"cachesPath should not be nil");
|
||||
if (cachesPath) {
|
||||
std::string path = std::string([cachesPath UTF8String]);
|
||||
configureJSContextForIOS(strongSelf.context.ctx, path);
|
||||
strongSelf->_jscWrapper->configureJSContextForIOS(strongSelf.context.ctx, path);
|
||||
}
|
||||
}];
|
||||
#endif
|
||||
|
||||
[self addSynchronousHookWithName:@"noop" usingBlock:^{}];
|
||||
|
||||
@ -454,11 +481,12 @@ static void RCTInstallJSCProfiler(RCTBridge *bridge, JSContextRef context)
|
||||
return;
|
||||
}
|
||||
|
||||
JSStringRef execJSString = JSStringCreateWithUTF8CString(sourceCode.UTF8String);
|
||||
JSStringRef jsURL = JSStringCreateWithUTF8CString(sourceCodeURL.UTF8String);
|
||||
JSEvaluateScript(strongSelf->_context.ctx, execJSString, NULL, jsURL, 0, NULL);
|
||||
JSStringRelease(jsURL);
|
||||
JSStringRelease(execJSString);
|
||||
RCTJSCWrapper *jscWrapper = strongSelf->_jscWrapper;
|
||||
JSStringRef execJSString = jscWrapper->JSStringCreateWithUTF8CString(sourceCode.UTF8String);
|
||||
JSStringRef jsURL = jscWrapper->JSStringCreateWithUTF8CString(sourceCodeURL.UTF8String);
|
||||
jscWrapper->JSEvaluateScript(strongSelf->_context.ctx, execJSString, NULL, jsURL, 0, NULL);
|
||||
jscWrapper->JSStringRelease(jsURL);
|
||||
jscWrapper->JSStringRelease(execJSString);
|
||||
}];
|
||||
#endif
|
||||
}
|
||||
@ -496,6 +524,12 @@ static void RCTInstallJSCProfiler(RCTBridge *bridge, JSContextRef context)
|
||||
|
||||
_randomAccessBundle.bundle.reset();
|
||||
_randomAccessBundle.table.reset();
|
||||
|
||||
if (_jscWrapper) {
|
||||
RCTJSCWrapperRelease(_jscWrapper);
|
||||
_jscWrapper = NULL;
|
||||
}
|
||||
|
||||
if (_cookieMap) {
|
||||
CFRelease(_cookieMap);
|
||||
}
|
||||
@ -539,41 +573,42 @@ static void RCTInstallJSCProfiler(RCTBridge *bridge, JSContextRef context)
|
||||
|
||||
JSValueRef errorJSRef = NULL;
|
||||
JSValueRef resultJSRef = NULL;
|
||||
JSGlobalContextRef contextJSRef = JSContextGetGlobalContext(strongSelf->_context.ctx);
|
||||
RCTJSCWrapper *jscWrapper = strongSelf->_jscWrapper;
|
||||
JSGlobalContextRef contextJSRef = jscWrapper->JSContextGetGlobalContext(strongSelf->_context.ctx);
|
||||
JSContext *context = strongSelf->_context.context;
|
||||
JSObjectRef globalObjectJSRef = JSContextGetGlobalObject(strongSelf->_context.ctx);
|
||||
JSObjectRef globalObjectJSRef = jscWrapper->JSContextGetGlobalObject(strongSelf->_context.ctx);
|
||||
|
||||
// get the BatchedBridge object
|
||||
JSStringRef moduleNameJSStringRef = JSStringCreateWithUTF8CString("__fbBatchedBridge");
|
||||
JSValueRef moduleJSRef = JSObjectGetProperty(contextJSRef, globalObjectJSRef, moduleNameJSStringRef, &errorJSRef);
|
||||
JSStringRelease(moduleNameJSStringRef);
|
||||
JSStringRef moduleNameJSStringRef = jscWrapper->JSStringCreateWithUTF8CString("__fbBatchedBridge");
|
||||
JSValueRef moduleJSRef = jscWrapper->JSObjectGetProperty(contextJSRef, globalObjectJSRef, moduleNameJSStringRef, &errorJSRef);
|
||||
jscWrapper->JSStringRelease(moduleNameJSStringRef);
|
||||
|
||||
if (moduleJSRef != NULL && errorJSRef == NULL && !JSValueIsUndefined(contextJSRef, moduleJSRef)) {
|
||||
if (moduleJSRef != NULL && errorJSRef == NULL && !jscWrapper->JSValueIsUndefined(contextJSRef, moduleJSRef)) {
|
||||
// get method
|
||||
JSStringRef methodNameJSStringRef = JSStringCreateWithCFString((__bridge CFStringRef)method);
|
||||
JSValueRef methodJSRef = JSObjectGetProperty(contextJSRef, (JSObjectRef)moduleJSRef, methodNameJSStringRef, &errorJSRef);
|
||||
JSStringRelease(methodNameJSStringRef);
|
||||
JSStringRef methodNameJSStringRef = jscWrapper->JSStringCreateWithCFString((__bridge CFStringRef)method);
|
||||
JSValueRef methodJSRef = jscWrapper->JSObjectGetProperty(contextJSRef, (JSObjectRef)moduleJSRef, methodNameJSStringRef, &errorJSRef);
|
||||
jscWrapper->JSStringRelease(methodNameJSStringRef);
|
||||
|
||||
if (methodJSRef != NULL && errorJSRef == NULL && !JSValueIsUndefined(contextJSRef, methodJSRef)) {
|
||||
if (methodJSRef != NULL && errorJSRef == NULL && !jscWrapper->JSValueIsUndefined(contextJSRef, methodJSRef)) {
|
||||
JSValueRef jsArgs[arguments.count];
|
||||
for (NSUInteger i = 0; i < arguments.count; i++) {
|
||||
jsArgs[i] = [JSValue valueWithObject:arguments[i] inContext:context].JSValueRef;
|
||||
jsArgs[i] = [jscWrapper->JSValue valueWithObject:arguments[i] inContext:context].JSValueRef;
|
||||
}
|
||||
resultJSRef = JSObjectCallAsFunction(contextJSRef, (JSObjectRef)methodJSRef, (JSObjectRef)moduleJSRef, arguments.count, jsArgs, &errorJSRef);
|
||||
resultJSRef = jscWrapper->JSObjectCallAsFunction(contextJSRef, (JSObjectRef)methodJSRef, (JSObjectRef)moduleJSRef, arguments.count, jsArgs, &errorJSRef);
|
||||
} else {
|
||||
if (!errorJSRef && JSValueIsUndefined(contextJSRef, methodJSRef)) {
|
||||
if (!errorJSRef && jscWrapper->JSValueIsUndefined(contextJSRef, methodJSRef)) {
|
||||
error = RCTErrorWithMessage([NSString stringWithFormat:@"Unable to execute JS call: method %@ is undefined", method]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!errorJSRef && JSValueIsUndefined(contextJSRef, moduleJSRef)) {
|
||||
if (!errorJSRef && jscWrapper->JSValueIsUndefined(contextJSRef, moduleJSRef)) {
|
||||
error = RCTErrorWithMessage(@"Unable to execute JS call: __fbBatchedBridge is undefined");
|
||||
}
|
||||
}
|
||||
|
||||
if (errorJSRef || error) {
|
||||
if (!error) {
|
||||
error = RCTNSErrorFromJSError(contextJSRef, errorJSRef);
|
||||
error = RCTNSErrorFromJSError(jscWrapper, contextJSRef, errorJSRef);
|
||||
}
|
||||
onComplete(nil, error);
|
||||
return;
|
||||
@ -585,8 +620,8 @@ static void RCTInstallJSCProfiler(RCTBridge *bridge, JSContextRef context)
|
||||
id objcValue;
|
||||
// We often return `null` from JS when there is nothing for native side. JSONKit takes an extra hundred microseconds
|
||||
// to handle this simple case, so we are adding a shortcut to make executeJSCall method even faster
|
||||
if (!JSValueIsNull(contextJSRef, resultJSRef)) {
|
||||
objcValue = [[JSValue valueWithJSValueRef:resultJSRef inContext:context] toObject];
|
||||
if (!jscWrapper->JSValueIsNull(contextJSRef, resultJSRef)) {
|
||||
objcValue = [[jscWrapper->JSValue valueWithJSValueRef:resultJSRef inContext:context] toObject];
|
||||
}
|
||||
|
||||
onComplete(objcValue, nil);
|
||||
@ -624,8 +659,6 @@ static void RCTInstallJSCProfiler(RCTBridge *bridge, JSContextRef context)
|
||||
script = nullTerminatedScript;
|
||||
}
|
||||
|
||||
_bundleURL = JSStringCreateWithUTF8CString(sourceURL.absoluteString.UTF8String);
|
||||
|
||||
__weak RCTJSCExecutor *weakSelf = self;
|
||||
|
||||
[self executeBlockOnJavaScriptQueue:RCTProfileBlock((^{
|
||||
@ -637,15 +670,17 @@ static void RCTInstallJSCProfiler(RCTBridge *bridge, JSContextRef context)
|
||||
RCTPerformanceLoggerStart(RCTPLScriptExecution);
|
||||
|
||||
JSValueRef jsError = NULL;
|
||||
JSStringRef execJSString = JSStringCreateWithUTF8CString((const char *)script.bytes);
|
||||
JSValueRef result = JSEvaluateScript(strongSelf->_context.ctx, execJSString, NULL, _bundleURL, 0, &jsError);
|
||||
JSStringRelease(execJSString);
|
||||
RCTJSCWrapper *jscWrapper = strongSelf->_jscWrapper;
|
||||
JSStringRef execJSString = jscWrapper->JSStringCreateWithUTF8CString((const char *)script.bytes);
|
||||
JSStringRef bundleURL = jscWrapper->JSStringCreateWithUTF8CString(sourceURL.absoluteString.UTF8String);
|
||||
JSValueRef result = jscWrapper->JSEvaluateScript(strongSelf->_context.ctx, execJSString, NULL, bundleURL, 0, &jsError);
|
||||
jscWrapper->JSStringRelease(execJSString);
|
||||
RCTPerformanceLoggerEnd(RCTPLScriptExecution);
|
||||
|
||||
if (onComplete) {
|
||||
NSError *error;
|
||||
if (!result) {
|
||||
error = RCTNSErrorFromJSError(strongSelf->_context.ctx, jsError);
|
||||
error = RCTNSErrorFromJSError(jscWrapper, strongSelf->_context.ctx, jsError);
|
||||
}
|
||||
onComplete(error);
|
||||
}
|
||||
@ -684,9 +719,11 @@ static void RCTInstallJSCProfiler(RCTBridge *bridge, JSContextRef context)
|
||||
if (!strongSelf || !strongSelf.isValid) {
|
||||
return;
|
||||
}
|
||||
JSStringRef execJSString = JSStringCreateWithCFString((__bridge CFStringRef)script);
|
||||
JSValueRef valueToInject = JSValueMakeFromJSONString(strongSelf->_context.ctx, execJSString);
|
||||
JSStringRelease(execJSString);
|
||||
|
||||
RCTJSCWrapper *jscWrapper = strongSelf->_jscWrapper;
|
||||
JSStringRef execJSString = jscWrapper->JSStringCreateWithCFString((__bridge CFStringRef)script);
|
||||
JSValueRef valueToInject = jscWrapper->JSValueMakeFromJSONString(strongSelf->_context.ctx, execJSString);
|
||||
jscWrapper->JSStringRelease(execJSString);
|
||||
|
||||
if (!valueToInject) {
|
||||
NSString *errorDesc = [NSString stringWithFormat:@"Can't make JSON value from script '%@'", script];
|
||||
@ -699,17 +736,17 @@ static void RCTInstallJSCProfiler(RCTBridge *bridge, JSContextRef context)
|
||||
return;
|
||||
}
|
||||
|
||||
JSObjectRef globalObject = JSContextGetGlobalObject(strongSelf->_context.ctx);
|
||||
JSStringRef JSName = JSStringCreateWithCFString((__bridge CFStringRef)objectName);
|
||||
JSObjectSetProperty(strongSelf->_context.ctx, globalObject, JSName, valueToInject, kJSPropertyAttributeNone, NULL);
|
||||
JSStringRelease(JSName);
|
||||
JSObjectRef globalObject = jscWrapper->JSContextGetGlobalObject(strongSelf->_context.ctx);
|
||||
JSStringRef JSName = jscWrapper->JSStringCreateWithCFString((__bridge CFStringRef)objectName);
|
||||
jscWrapper->JSObjectSetProperty(strongSelf->_context.ctx, globalObject, JSName, valueToInject, kJSPropertyAttributeNone, NULL);
|
||||
jscWrapper->JSStringRelease(JSName);
|
||||
if (onComplete) {
|
||||
onComplete(nil);
|
||||
}
|
||||
}), 0, @"js_call,json_call", (@{@"objectName": objectName}))];
|
||||
}
|
||||
|
||||
static bool readRandomAccessModule(const RandomAccessBundleData& bundleData, size_t offset, size_t size, char *data)
|
||||
static bool readRandomAccessModule(const RandomAccessBundleData &bundleData, size_t offset, size_t size, char *data)
|
||||
{
|
||||
return fseek(bundleData.bundle.get(), offset + bundleData.baseOffset, SEEK_SET) == 0 &&
|
||||
fread(data, 1, size, bundleData.bundle.get()) == size;
|
||||
@ -726,17 +763,18 @@ static void executeRandomAccessModule(RCTJSCExecutor *executor, uint32_t moduleI
|
||||
char url[14]; // 10 = maximum decimal digits in a 32bit unsigned int + ".js" + null byte
|
||||
sprintf(url, "%" PRIu32 ".js", moduleID);
|
||||
|
||||
JSStringRef code = JSStringCreateWithUTF8CString(data.get());
|
||||
RCTJSCWrapper *jscWrapper = executor->_jscWrapper;
|
||||
JSStringRef code = jscWrapper->JSStringCreateWithUTF8CString(data.get());
|
||||
JSValueRef jsError = NULL;
|
||||
JSStringRef sourceURL = JSStringCreateWithUTF8CString(url);
|
||||
JSValueRef result = JSEvaluateScript(executor->_context.ctx, code, NULL, sourceURL, 0, &jsError);
|
||||
JSStringRef sourceURL = jscWrapper->JSStringCreateWithUTF8CString(url);
|
||||
JSValueRef result = jscWrapper->JSEvaluateScript(executor->_context.ctx, code, NULL, sourceURL, 0, &jsError);
|
||||
|
||||
JSStringRelease(code);
|
||||
JSStringRelease(sourceURL);
|
||||
jscWrapper->JSStringRelease(code);
|
||||
jscWrapper->JSStringRelease(sourceURL);
|
||||
|
||||
if (!result) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
RCTFatal(RCTNSErrorFromJSError(executor->_context.ctx, jsError));
|
||||
RCTFatal(RCTNSErrorFromJSError(jscWrapper, executor->_context.ctx, jsError));
|
||||
[executor invalidate];
|
||||
});
|
||||
}
|
||||
@ -780,7 +818,7 @@ static void executeRandomAccessModule(RCTJSCExecutor *executor, uint32_t moduleI
|
||||
}];
|
||||
}
|
||||
|
||||
static RandomAccessBundleStartupCode readRAMBundle(file_ptr bundle, RandomAccessBundleData& randomAccessBundle)
|
||||
static RandomAccessBundleStartupCode readRAMBundle(file_ptr bundle, RandomAccessBundleData &randomAccessBundle)
|
||||
{
|
||||
// read in magic header, number of entries, and length of the startup section
|
||||
uint32_t header[3];
|
||||
@ -846,13 +884,10 @@ static RandomAccessBundleStartupCode readRAMBundle(file_ptr bundle, RandomAccess
|
||||
|
||||
RCT_EXPORT_METHOD(setContextName:(nonnull NSString *)name)
|
||||
{
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
|
||||
if (JSGlobalContextSetName != NULL) {
|
||||
#pragma clang diagnostic pop
|
||||
JSStringRef JSName = JSStringCreateWithCFString((__bridge CFStringRef)name);
|
||||
JSGlobalContextSetName(_context.ctx, JSName);
|
||||
JSStringRelease(JSName);
|
||||
if (_jscWrapper->JSGlobalContextSetName != NULL) {
|
||||
JSStringRef JSName = _jscWrapper->JSStringCreateWithCFString((__bridge CFStringRef)name);
|
||||
_jscWrapper->JSGlobalContextSetName(_context.ctx, JSName);
|
||||
_jscWrapper->JSStringRelease(JSName);
|
||||
}
|
||||
}
|
||||
|
||||
|
58
React/Executors/RCTJSCWrapper.h
Normal file
58
React/Executors/RCTJSCWrapper.h
Normal file
@ -0,0 +1,58 @@
|
||||
/**
|
||||
* Copyright (c) 2016-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import <JavaScriptCore/JavaScriptCore.h>
|
||||
|
||||
#import "RCTDefines.h"
|
||||
#import <string>
|
||||
|
||||
typedef JSStringRef (*JSValueToStringCopyFuncType)(JSContextRef, JSValueRef, JSValueRef *);
|
||||
typedef JSStringRef (*JSStringCreateWithCFStringFuncType)(CFStringRef);
|
||||
typedef CFStringRef (*JSStringCopyCFStringFuncType)(CFAllocatorRef, JSStringRef);
|
||||
typedef JSStringRef (*JSStringCreateWithUTF8CStringFuncType)(const char *);
|
||||
typedef void (*JSStringReleaseFuncType)(JSStringRef);
|
||||
typedef void (*JSGlobalContextSetNameFuncType)(JSGlobalContextRef, JSStringRef);
|
||||
typedef JSGlobalContextRef (*JSContextGetGlobalContextFuncType)(JSContextRef);
|
||||
typedef void (*JSObjectSetPropertyFuncType)(JSContextRef, JSObjectRef, JSStringRef, JSValueRef, JSPropertyAttributes, JSValueRef *);
|
||||
typedef JSObjectRef (*JSContextGetGlobalObjectFuncType)(JSContextRef);
|
||||
typedef JSValueRef (*JSObjectGetPropertyFuncType)(JSContextRef, JSObjectRef, JSStringRef, JSValueRef *);
|
||||
typedef JSValueRef (*JSValueMakeFromJSONStringFuncType)(JSContextRef, JSStringRef);
|
||||
typedef JSValueRef (*JSObjectCallAsFunctionFuncType)(JSContextRef, JSObjectRef, JSObjectRef, size_t, const JSValueRef *, JSValueRef *);
|
||||
typedef JSValueRef (*JSValueMakeNullFuncType)(JSContextRef);
|
||||
typedef JSStringRef (*JSValueCreateJSONStringFuncType)(JSContextRef, JSValueRef, unsigned, JSValueRef *);
|
||||
typedef bool (*JSValueIsUndefinedFuncType)(JSContextRef, JSValueRef);
|
||||
typedef bool (*JSValueIsNullFuncType)(JSContextRef, JSValueRef);
|
||||
typedef JSValueRef (*JSEvaluateScriptFuncType)(JSContextRef, JSStringRef, JSObjectRef, JSStringRef, int, JSValueRef *);
|
||||
typedef void (*configureJSContextForIOSFuncType)(JSContextRef ctx, const std::string &cacheDir);
|
||||
|
||||
typedef struct RCTJSCWrapper {
|
||||
JSValueToStringCopyFuncType JSValueToStringCopy;
|
||||
JSStringCreateWithCFStringFuncType JSStringCreateWithCFString;
|
||||
JSStringCopyCFStringFuncType JSStringCopyCFString;
|
||||
JSStringCreateWithUTF8CStringFuncType JSStringCreateWithUTF8CString;
|
||||
JSStringReleaseFuncType JSStringRelease;
|
||||
JSGlobalContextSetNameFuncType JSGlobalContextSetName;
|
||||
JSContextGetGlobalContextFuncType JSContextGetGlobalContext;
|
||||
JSObjectSetPropertyFuncType JSObjectSetProperty;
|
||||
JSContextGetGlobalObjectFuncType JSContextGetGlobalObject;
|
||||
JSObjectGetPropertyFuncType JSObjectGetProperty;
|
||||
JSValueMakeFromJSONStringFuncType JSValueMakeFromJSONString;
|
||||
JSObjectCallAsFunctionFuncType JSObjectCallAsFunction;
|
||||
JSValueMakeNullFuncType JSValueMakeNull;
|
||||
JSValueCreateJSONStringFuncType JSValueCreateJSONString;
|
||||
JSValueIsUndefinedFuncType JSValueIsUndefined;
|
||||
JSValueIsNullFuncType JSValueIsNull;
|
||||
JSEvaluateScriptFuncType JSEvaluateScript;
|
||||
Class JSContext;
|
||||
Class JSValue;
|
||||
configureJSContextForIOSFuncType configureJSContextForIOS;
|
||||
} RCTJSCWrapper;
|
||||
|
||||
RCT_EXTERN RCTJSCWrapper *RCTJSCWrapperCreate(BOOL useCustomJSC);
|
||||
RCT_EXTERN void RCTJSCWrapperRelease(RCTJSCWrapper *wrapper);
|
112
React/Executors/RCTJSCWrapper.mm
Normal file
112
React/Executors/RCTJSCWrapper.mm
Normal file
@ -0,0 +1,112 @@
|
||||
/**
|
||||
* Copyright (c) 2016-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import "RCTJSCWrapper.h"
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <JavaScriptCore/JavaScriptCore.h>
|
||||
|
||||
#import "RCTLog.h"
|
||||
#import "RCTPerformanceLogger.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
static void *RCTCustomLibraryHandler(void)
|
||||
{
|
||||
static dispatch_once_t token;
|
||||
static void *handler;
|
||||
dispatch_once(&token, ^{
|
||||
const char *path = [[[NSBundle mainBundle] pathForResource:@"JavaScriptCore"
|
||||
ofType:nil
|
||||
inDirectory:@"JavaScriptCore.framework"] UTF8String];
|
||||
if (path) {
|
||||
RCTPerformanceLoggerStart(RCTPLJSCWrapperOpenLibrary);
|
||||
handler = dlopen(path, RTLD_LAZY);
|
||||
RCTPerformanceLoggerEnd(RCTPLJSCWrapperOpenLibrary);
|
||||
if (!handler) {
|
||||
RCTLogWarn(@"Can't load custome JSC library: %s", dlerror());
|
||||
}
|
||||
}
|
||||
});
|
||||
return handler;
|
||||
}
|
||||
|
||||
static void RCTSetUpSystemLibraryPointers(RCTJSCWrapper *wrapper)
|
||||
{
|
||||
wrapper->JSValueToStringCopy = JSValueToStringCopy;
|
||||
wrapper->JSStringCreateWithCFString = JSStringCreateWithCFString;
|
||||
wrapper->JSStringCopyCFString = JSStringCopyCFString;
|
||||
wrapper->JSStringCreateWithUTF8CString = JSStringCreateWithUTF8CString;
|
||||
wrapper->JSStringRelease = JSStringRelease;
|
||||
wrapper->JSGlobalContextSetName = JSGlobalContextSetName;
|
||||
wrapper->JSContextGetGlobalContext = JSContextGetGlobalContext;
|
||||
wrapper->JSObjectSetProperty = JSObjectSetProperty;
|
||||
wrapper->JSContextGetGlobalObject = JSContextGetGlobalObject;
|
||||
wrapper->JSObjectGetProperty = JSObjectGetProperty;
|
||||
wrapper->JSValueMakeFromJSONString = JSValueMakeFromJSONString;
|
||||
wrapper->JSObjectCallAsFunction = JSObjectCallAsFunction;
|
||||
wrapper->JSValueMakeNull = JSValueMakeNull;
|
||||
wrapper->JSValueCreateJSONString = JSValueCreateJSONString;
|
||||
wrapper->JSValueIsUndefined = JSValueIsUndefined;
|
||||
wrapper->JSValueIsNull = JSValueIsNull;
|
||||
wrapper->JSEvaluateScript = JSEvaluateScript;
|
||||
wrapper->JSContext = [JSContext class];
|
||||
wrapper->JSValue = [JSValue class];
|
||||
wrapper->configureJSContextForIOS = NULL;
|
||||
}
|
||||
|
||||
static void RCTSetUpCustomLibraryPointers(RCTJSCWrapper *wrapper)
|
||||
{
|
||||
void *libraryHandle = RCTCustomLibraryHandler();
|
||||
if (!libraryHandle) {
|
||||
RCTSetUpSystemLibraryPointers(wrapper);
|
||||
return;
|
||||
}
|
||||
|
||||
RCTPerformanceLoggerStart(RCTPLJSCWrapperLoadFunctions);
|
||||
wrapper->JSValueToStringCopy = (JSValueToStringCopyFuncType)dlsym(libraryHandle, "JSValueToStringCopy");
|
||||
wrapper->JSStringCreateWithCFString = (JSStringCreateWithCFStringFuncType)dlsym(libraryHandle, "JSStringCreateWithCFString");
|
||||
wrapper->JSStringCopyCFString = (JSStringCopyCFStringFuncType)dlsym(libraryHandle, "JSStringCopyCFString");
|
||||
wrapper->JSStringCreateWithUTF8CString = (JSStringCreateWithUTF8CStringFuncType)dlsym(libraryHandle, "JSStringCreateWithUTF8CString");
|
||||
wrapper->JSStringRelease = (JSStringReleaseFuncType)dlsym(libraryHandle, "JSStringRelease");
|
||||
wrapper->JSGlobalContextSetName = (JSGlobalContextSetNameFuncType)dlsym(libraryHandle, "JSGlobalContextSetName");
|
||||
wrapper->JSContextGetGlobalContext = (JSContextGetGlobalContextFuncType)dlsym(libraryHandle, "JSContextGetGlobalContext");
|
||||
wrapper->JSObjectSetProperty = (JSObjectSetPropertyFuncType)dlsym(libraryHandle, "JSObjectSetProperty");
|
||||
wrapper->JSContextGetGlobalObject = (JSContextGetGlobalObjectFuncType)dlsym(libraryHandle, "JSContextGetGlobalObject");
|
||||
wrapper->JSObjectGetProperty = (JSObjectGetPropertyFuncType)dlsym(libraryHandle, "JSObjectGetProperty");
|
||||
wrapper->JSValueMakeFromJSONString = (JSValueMakeFromJSONStringFuncType)dlsym(libraryHandle, "JSValueMakeFromJSONString");
|
||||
wrapper->JSObjectCallAsFunction = (JSObjectCallAsFunctionFuncType)dlsym(libraryHandle, "JSObjectCallAsFunction");
|
||||
wrapper->JSValueMakeNull = (JSValueMakeNullFuncType)dlsym(libraryHandle, "JSValueMakeNull");
|
||||
wrapper->JSValueCreateJSONString = (JSValueCreateJSONStringFuncType)dlsym(libraryHandle, "JSValueCreateJSONString");
|
||||
wrapper->JSValueIsUndefined = (JSValueIsUndefinedFuncType)dlsym(libraryHandle, "JSValueIsUndefined");
|
||||
wrapper->JSValueIsNull = (JSValueIsNullFuncType)dlsym(libraryHandle, "JSValueIsNull");
|
||||
wrapper->JSEvaluateScript = (JSEvaluateScriptFuncType)dlsym(libraryHandle, "JSEvaluateScript");
|
||||
wrapper->JSContext = (__bridge Class)dlsym(libraryHandle, "OBJC_CLASS_$_JSContext");
|
||||
wrapper->JSValue = (__bridge Class)dlsym(libraryHandle, "OBJC_CLASS_$_JSValue");
|
||||
wrapper->configureJSContextForIOS = (configureJSContextForIOSFuncType)dlsym(libraryHandle, "configureJSContextForIOS");
|
||||
RCTPerformanceLoggerEnd(RCTPLJSCWrapperLoadFunctions);
|
||||
}
|
||||
|
||||
RCTJSCWrapper *RCTJSCWrapperCreate(BOOL useCustomJSC)
|
||||
{
|
||||
RCTJSCWrapper *wrapper = (RCTJSCWrapper *)malloc(sizeof(RCTJSCWrapper));
|
||||
if (useCustomJSC && [UIDevice currentDevice].systemVersion.floatValue >= 8) {
|
||||
RCTSetUpCustomLibraryPointers(wrapper);
|
||||
} else {
|
||||
RCTSetUpSystemLibraryPointers(wrapper);
|
||||
}
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
void RCTJSCWrapperRelease(RCTJSCWrapper *wrapper)
|
||||
{
|
||||
if (wrapper) {
|
||||
free(wrapper);
|
||||
}
|
||||
}
|
@ -94,6 +94,7 @@
|
||||
83CBBA691A601EF300E9B192 /* RCTEventDispatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 83CBBA661A601EF300E9B192 /* RCTEventDispatcher.m */; };
|
||||
83CBBA981A6020BB00E9B192 /* RCTTouchHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 83CBBA971A6020BB00E9B192 /* RCTTouchHandler.m */; };
|
||||
83CBBACC1A6023D300E9B192 /* RCTConvert.m in Sources */ = {isa = PBXBuildFile; fileRef = 83CBBACB1A6023D300E9B192 /* RCTConvert.m */; };
|
||||
85C199EE1CD2407900DAD810 /* RCTJSCWrapper.mm in Sources */ = {isa = PBXBuildFile; fileRef = 85C199ED1CD2407900DAD810 /* RCTJSCWrapper.mm */; };
|
||||
E9B20B7B1B500126007A2DA7 /* RCTAccessibilityManager.m in Sources */ = {isa = PBXBuildFile; fileRef = E9B20B7A1B500126007A2DA7 /* RCTAccessibilityManager.m */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
@ -302,6 +303,8 @@
|
||||
83CBBACA1A6023D300E9B192 /* RCTConvert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTConvert.h; sourceTree = "<group>"; };
|
||||
83CBBACB1A6023D300E9B192 /* RCTConvert.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTConvert.m; sourceTree = "<group>"; };
|
||||
83F15A171B7CC46900F10295 /* UIView+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIView+Private.h"; sourceTree = "<group>"; };
|
||||
85C199EC1CD2407900DAD810 /* RCTJSCWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTJSCWrapper.h; sourceTree = "<group>"; };
|
||||
85C199ED1CD2407900DAD810 /* RCTJSCWrapper.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTJSCWrapper.mm; sourceTree = "<group>"; };
|
||||
ACDD3FDA1BC7430D00E7DE33 /* RCTBorderStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTBorderStyle.h; sourceTree = "<group>"; };
|
||||
E3BBC8EB1ADE6F47001BBD81 /* RCTTextDecorationLineType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RCTTextDecorationLineType.h; sourceTree = "<group>"; };
|
||||
E9B20B791B500126007A2DA7 /* RCTAccessibilityManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTAccessibilityManager.h; sourceTree = "<group>"; };
|
||||
@ -324,6 +327,8 @@
|
||||
children = (
|
||||
134FCB391A6E7F0800051CC8 /* RCTJSCExecutor.h */,
|
||||
134FCB3A1A6E7F0800051CC8 /* RCTJSCExecutor.mm */,
|
||||
85C199EC1CD2407900DAD810 /* RCTJSCWrapper.h */,
|
||||
85C199ED1CD2407900DAD810 /* RCTJSCWrapper.mm */,
|
||||
);
|
||||
path = Executors;
|
||||
sourceTree = "<group>";
|
||||
@ -723,6 +728,7 @@
|
||||
13E067591A70F44B002CDEE1 /* UIView+React.m in Sources */,
|
||||
14F484561AABFCE100FDF6B9 /* RCTSliderManager.m in Sources */,
|
||||
13D033631C1837FE0021DC29 /* RCTClipboard.m in Sources */,
|
||||
85C199EE1CD2407900DAD810 /* RCTJSCWrapper.mm in Sources */,
|
||||
14C2CA741B3AC64300E6CBB2 /* RCTModuleData.m in Sources */,
|
||||
142014191B32094000CC17BA /* RCTPerformanceLogger.m in Sources */,
|
||||
83CBBA981A6020BB00E9B192 /* RCTTouchHandler.m in Sources */,
|
||||
|
Loading…
x
Reference in New Issue
Block a user