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