BC Soft Errors

Reviewed By: javache

Differential Revision: D4131340

fbshipit-source-id: b0827fc99d94985fbbb2a1b03ddc4d6feab10bff
This commit is contained in:
Ashok Menon 2016-11-11 05:21:37 -08:00 committed by Facebook Github Bot
parent 7a073d3b13
commit 8288bc2006
5 changed files with 63 additions and 21 deletions

View File

@ -24,25 +24,33 @@ typedef NS_ENUM(NSInteger) {
} RCTScriptTag; } RCTScriptTag;
/** /**
* RCTMagicNumber * RCTBundleHeader
* *
* RAM bundles and BC bundles begin with magic numbers. For RAM bundles this is * RAM bundles and BC bundles begin with headers. For RAM bundles this is
* 4 bytes, for BC bundles this is 8 bytes. This structure holds the first 8 * 4 bytes, for BC bundles this is 12 bytes. This structure holds the first 12
* bytes from a bundle in a way that gives access to that information. * bytes from a bundle in a way that gives access to that information.
*/ */
typedef union { typedef union {
uint64_t allBytes; // `allBytes` is the first field so that zero-initializing the union fills
uint32_t first4; // it completely with zeroes. Without it, only the first field of the union
uint64_t first8; // gets zero-initialized.
} RCTMagicNumber; uint32_t allBytes[3];
uint32_t RAMMagic;
struct {
uint64_t BCMagic;
uint32_t BCVersion;
};
} RCTBundleHeader;
/** /**
* RCTParseMagicNumber * RCTParseTypeFromHeader
* *
* Takes the first 8 bytes of a bundle, and returns a tag describing the * Takes the first 8 bytes of a bundle, and returns a tag describing the
* bundle's format. * bundle's format.
*/ */
RCT_EXTERN RCTScriptTag RCTParseMagicNumber(RCTMagicNumber magic); RCT_EXTERN RCTScriptTag RCTParseTypeFromHeader(RCTBundleHeader header);
extern NSString *const RCTJavaScriptLoaderErrorDomain; extern NSString *const RCTJavaScriptLoaderErrorDomain;
@ -52,6 +60,7 @@ NS_ENUM(NSInteger) {
RCTJavaScriptLoaderErrorFailedReadingFile = 3, RCTJavaScriptLoaderErrorFailedReadingFile = 3,
RCTJavaScriptLoaderErrorFailedStatingFile = 3, RCTJavaScriptLoaderErrorFailedStatingFile = 3,
RCTJavaScriptLoaderErrorURLLoadFailed = 3, RCTJavaScriptLoaderErrorURLLoadFailed = 3,
RCTJavaScriptLoaderErrorBCVersion = 4,
RCTJavaScriptLoaderErrorCannotBeLoadedSynchronously = 1000, RCTJavaScriptLoaderErrorCannotBeLoadedSynchronously = 1000,
}; };
@ -80,6 +89,7 @@ typedef void (^RCTSourceLoadBlock)(NSError *error, NSData *source, int64_t sourc
* RCTJavaScriptLoaderErrorDomain and the code RCTJavaScriptLoaderErrorCannotBeLoadedSynchronously. * RCTJavaScriptLoaderErrorDomain and the code RCTJavaScriptLoaderErrorCannotBeLoadedSynchronously.
*/ */
+ (NSData *)attemptSynchronousLoadOfBundleAtURL:(NSURL *)scriptURL + (NSData *)attemptSynchronousLoadOfBundleAtURL:(NSURL *)scriptURL
runtimeBCVersion:(int32_t)runtimeBCVersion
sourceLength:(int64_t *)sourceLength sourceLength:(int64_t *)sourceLength
error:(NSError **)error; error:(NSError **)error;

View File

@ -11,6 +11,7 @@
#import "RCTBridge.h" #import "RCTBridge.h"
#import "RCTConvert.h" #import "RCTConvert.h"
#import "RCTJSCWrapper.h"
#import "RCTSourceCode.h" #import "RCTSourceCode.h"
#import "RCTUtils.h" #import "RCTUtils.h"
#import "RCTPerformanceLogger.h" #import "RCTPerformanceLogger.h"
@ -23,13 +24,13 @@ static uint64_t const RCTBCBundleMagicNumber = 0xFF4865726D657300;
NSString *const RCTJavaScriptLoaderErrorDomain = @"RCTJavaScriptLoaderErrorDomain"; NSString *const RCTJavaScriptLoaderErrorDomain = @"RCTJavaScriptLoaderErrorDomain";
RCTScriptTag RCTParseMagicNumber(RCTMagicNumber magic) RCTScriptTag RCTParseTypeFromHeader(RCTBundleHeader header)
{ {
if (NSSwapLittleIntToHost(magic.first4) == RCTRAMBundleMagicNumber) { if (NSSwapLittleIntToHost(header.RAMMagic) == RCTRAMBundleMagicNumber) {
return RCTScriptRAMBundle; return RCTScriptRAMBundle;
} }
if (NSSwapLittleLongLongToHost(magic.first8) == RCTBCBundleMagicNumber) { if (NSSwapLittleLongLongToHost(header.BCMagic) == RCTBCBundleMagicNumber) {
return RCTScriptBCBundle; return RCTScriptBCBundle;
} }
@ -61,6 +62,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
int64_t sourceLength; int64_t sourceLength;
NSError *error; NSError *error;
NSData *data = [self attemptSynchronousLoadOfBundleAtURL:scriptURL NSData *data = [self attemptSynchronousLoadOfBundleAtURL:scriptURL
runtimeBCVersion:JSNoBytecodeFileFormatVersion
sourceLength:&sourceLength sourceLength:&sourceLength
error:&error]; error:&error];
if (data) { if (data) {
@ -80,6 +82,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
} }
+ (NSData *)attemptSynchronousLoadOfBundleAtURL:(NSURL *)scriptURL + (NSData *)attemptSynchronousLoadOfBundleAtURL:(NSURL *)scriptURL
runtimeBCVersion:(int32_t)runtimeBCVersion
sourceLength:(int64_t *)sourceLength sourceLength:(int64_t *)sourceLength
error:(NSError **)error error:(NSError **)error
{ {
@ -126,8 +129,8 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
return nil; return nil;
} }
RCTMagicNumber magicNumber = {.allBytes = 0}; RCTBundleHeader header = {};
size_t readResult = fread(&magicNumber, sizeof(magicNumber), 1, bundle); size_t readResult = fread(&header, sizeof(header), 1, bundle);
fclose(bundle); fclose(bundle);
if (readResult != 1) { if (readResult != 1) {
if (error) { if (error) {
@ -139,8 +142,12 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
return nil; return nil;
} }
RCTScriptTag tag = RCTParseMagicNumber(magicNumber); RCTScriptTag tag = RCTParseTypeFromHeader(header);
if (tag == RCTScriptString) { switch (tag) {
case RCTScriptRAMBundle:
break;
case RCTScriptString:
if (error) { if (error) {
*error = [NSError errorWithDomain:RCTJavaScriptLoaderErrorDomain *error = [NSError errorWithDomain:RCTJavaScriptLoaderErrorDomain
code:RCTJavaScriptLoaderErrorCannotBeLoadedSynchronously code:RCTJavaScriptLoaderErrorCannotBeLoadedSynchronously
@ -148,6 +155,21 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
@"Cannot load text/javascript files synchronously"}]; @"Cannot load text/javascript files synchronously"}];
} }
return nil; return nil;
case RCTScriptBCBundle:
if (header.BCVersion != runtimeBCVersion) {
if (error) {
NSString *errDesc =
[NSString stringWithFormat:@"BC Version Mismatch. Expect: %d, Actual: %d",
runtimeBCVersion, header.BCVersion];
*error = [NSError errorWithDomain:RCTJavaScriptLoaderErrorDomain
code:RCTJavaScriptLoaderErrorBCVersion
userInfo:@{NSLocalizedDescriptionKey: errDesc}];
}
return nil;
}
break;
} }
struct stat statInfo; struct stat statInfo;
@ -163,7 +185,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
if (sourceLength) { if (sourceLength) {
*sourceLength = statInfo.st_size; *sourceLength = statInfo.st_size;
} }
return [NSData dataWithBytes:&magicNumber length:sizeof(magicNumber)]; return [NSData dataWithBytes:&header length:sizeof(header)];
} }
static void attemptAsynchronousLoadOfBundleAtURL(NSURL *scriptURL, RCTSourceLoadProgressBlock onProgress, RCTSourceLoadBlock onComplete) static void attemptAsynchronousLoadOfBundleAtURL(NSURL *scriptURL, RCTSourceLoadProgressBlock onProgress, RCTSourceLoadBlock onComplete)

View File

@ -72,6 +72,11 @@ RCT_EXTERN NSString *const RCTFBJSValueClassKey;
*/ */
@property (nonatomic, readonly, assign) BOOL useCustomJSCLibrary; @property (nonatomic, readonly, assign) BOOL useCustomJSCLibrary;
/**
* Returns the bytecode file format that the underlying runtime supports.
*/
@property (nonatomic, readonly) int32_t bytecodeFileFormatVersion;
/** /**
* Specify a name for the JSContext used, which will be visible in debugging tools * Specify a name for the JSContext used, which will be visible in debugging tools
* @default is "RCTJSContext" * @default is "RCTJSContext"

View File

@ -500,6 +500,11 @@ static void installBasicSynchronousHooksOnContext(JSContext *context)
#endif #endif
} }
- (int32_t)bytecodeFileFormatVersion
{
return _jscWrapper->JSBytecodeFileFormatVersion;
}
- (NSString *)contextName - (NSString *)contextName
{ {
return [_context.context name]; return [_context.context name];
@ -688,9 +693,9 @@ static TaggedScript loadTaggedScript(NSData *script,
{ {
RCT_PROFILE_BEGIN_EVENT(0, @"executeApplicationScript / prepare bundle", nil); RCT_PROFILE_BEGIN_EVENT(0, @"executeApplicationScript / prepare bundle", nil);
RCTMagicNumber magicNumber = {.allBytes = 0}; RCTBundleHeader header = {};
[script getBytes:&magicNumber length:sizeof(magicNumber)]; [script getBytes:&header length:sizeof(header)];
RCTScriptTag tag = RCTParseMagicNumber(magicNumber); RCTScriptTag tag = RCTParseTypeFromHeader(header);
NSData *loadedScript = NULL; NSData *loadedScript = NULL;
switch (tag) { switch (tag) {

View File

@ -74,9 +74,9 @@ static RCTJSCWrapper *RCTSetUpSystemLibraryPointers()
.JSValueIsUndefined = JSValueIsUndefined, .JSValueIsUndefined = JSValueIsUndefined,
.JSValueIsNull = JSValueIsNull, .JSValueIsNull = JSValueIsNull,
.JSEvaluateScript = JSEvaluateScript, .JSEvaluateScript = JSEvaluateScript,
.JSBytecodeFileFormatVersion = JSNoBytecodeFileFormatVersion,
.JSEvaluateBytecodeBundle = (JSEvaluateBytecodeBundleFuncType)UnimplementedJSEvaluateBytecodeBundle, .JSEvaluateBytecodeBundle = (JSEvaluateBytecodeBundleFuncType)UnimplementedJSEvaluateBytecodeBundle,
.configureJSCForIOS = (voidWithNoParamsFuncType)noOpSystemJSCFunc, .configureJSCForIOS = (voidWithNoParamsFuncType)noOpSystemJSCFunc,
.JSBytecodeFileFormatVersion = JSNoBytecodeFileFormatVersion,
.JSContext = [JSContext class], .JSContext = [JSContext class],
.JSValue = [JSValue class], .JSValue = [JSValue class],
}; };