1// Copyright 2022-present 650 Industries. All rights reserved. 2 3#import <ExpoModulesCore/EXJSIConversions.h> 4#import <ExpoModulesCore/EXJavaScriptValue.h> 5#import <ExpoModulesCore/EXJavaScriptRuntime.h> 6 7@implementation EXJavaScriptValue { 8 __weak EXJavaScriptRuntime *_runtime; 9 std::shared_ptr<jsi::Value> _value; 10} 11 12- (nonnull instancetype)initWithRuntime:(nonnull EXJavaScriptRuntime *)runtime 13 value:(std::shared_ptr<jsi::Value>)value 14{ 15 if (self = [super init]) { 16 _runtime = runtime; 17 _value = value; 18 } 19 return self; 20} 21 22#pragma mark - Type checking 23 24- (BOOL)isUndefined 25{ 26 return _value->isUndefined(); 27} 28 29- (BOOL)isNull 30{ 31 return _value->isNull(); 32} 33 34- (BOOL)isBool 35{ 36 return _value->isBool(); 37} 38 39- (BOOL)isNumber 40{ 41 return _value->isNumber(); 42} 43 44- (BOOL)isString 45{ 46 return _value->isString(); 47} 48 49- (BOOL)isSymbol 50{ 51 return _value->isSymbol(); 52} 53 54- (BOOL)isObject 55{ 56 return _value->isObject(); 57} 58 59- (BOOL)isFunction 60{ 61 if (_value->isObject()) { 62 jsi::Runtime *runtime = [_runtime get]; 63 return _value->getObject(*runtime).isFunction(*runtime); 64 } 65 return false; 66} 67 68+ (nonnull NSString *)kindOf:(nonnull EXJavaScriptValue *)value 69{ 70 if ([value isUndefined]) { 71 return @"undefined"; 72 } 73 if ([value isNull]) { 74 return @"null"; 75 } 76 if ([value isBool]) { 77 return @"boolean"; 78 } 79 if ([value isNumber]) { 80 return @"number"; 81 } 82 if ([value isString]) { 83 return @"string"; 84 } 85 if ([value isFunction]) { 86 return @"function"; 87 } 88 assert([value isObject] && "Expecting object."); 89 return @"object"; 90} 91 92#pragma mark - Type casting 93 94- (nullable id)getRaw 95{ 96 return expo::convertJSIValueToObjCObject(*[_runtime get], *_value, [_runtime callInvoker]); 97} 98 99- (BOOL)getBool 100{ 101 return _value->getBool(); 102} 103 104- (NSInteger)getInt 105{ 106 return _value->getNumber(); 107} 108 109- (double)getDouble 110{ 111 return _value->getNumber(); 112} 113 114- (nonnull NSString *)getString 115{ 116 jsi::Runtime *runtime = [_runtime get]; 117 return expo::convertJSIStringToNSString(*runtime, _value->getString(*runtime)); 118} 119 120- (nonnull NSArray<EXJavaScriptValue *> *)getArray 121{ 122 jsi::Runtime *runtime = [_runtime get]; 123 jsi::Array jsiArray = _value->getObject(*runtime).getArray(*runtime); 124 size_t arraySize = jsiArray.size(*runtime); 125 NSMutableArray *result = [NSMutableArray arrayWithCapacity:arraySize]; 126 127 for (size_t i = 0; i < arraySize; i++) { 128 jsi::Value item = jsiArray.getValueAtIndex(*runtime, i); 129 130 if (item.isUndefined() || item.isNull()) { 131 [result addObject:(id)kCFNull]; 132 } else { 133 std::shared_ptr<jsi::Value> valuePtr = std::make_shared<jsi::Value>(*runtime, item); 134 [result addObject:[[EXJavaScriptValue alloc] initWithRuntime:_runtime value:valuePtr]]; 135 } 136 } 137 return result; 138} 139 140- (nonnull NSDictionary<NSString *, id> *)getDictionary 141{ 142 jsi::Runtime *runtime = [_runtime get]; 143 return expo::convertJSIObjectToNSDictionary(*runtime, _value->getObject(*runtime), [_runtime callInvoker]); 144} 145 146- (nonnull EXJavaScriptObject *)getObject 147{ 148 jsi::Runtime *runtime = [_runtime get]; 149 std::shared_ptr<jsi::Object> objectPtr = std::make_shared<jsi::Object>(_value->asObject(*runtime)); 150 return [[EXJavaScriptObject alloc] initWith:objectPtr runtime:_runtime]; 151} 152 153#pragma mark - Helpers 154 155- (nonnull NSString *)toString 156{ 157 jsi::Runtime *runtime = [_runtime get]; 158 return expo::convertJSIStringToNSString(*runtime, _value->toString(*runtime)); 159} 160 161@end 162