1ec62a260STomasz Sapeta// Copyright 2022-present 650 Industries. All rights reserved.
2ec62a260STomasz Sapeta
3ec62a260STomasz Sapeta#import <ExpoModulesCore/EXJSIConversions.h>
4ec62a260STomasz Sapeta#import <ExpoModulesCore/EXJavaScriptValue.h>
5ec62a260STomasz Sapeta#import <ExpoModulesCore/EXJavaScriptRuntime.h>
6*a2ddfabcSTomasz Sapeta#import <ExpoModulesCore/EXRawJavaScriptFunction.h>
7002d516eSTomasz Sapeta#import <ExpoModulesCore/EXJavaScriptTypedArray.h>
8002d516eSTomasz Sapeta#import <ExpoModulesCore/TypedArray.h>
9ec62a260STomasz Sapeta
10ec62a260STomasz Sapeta@implementation EXJavaScriptValue {
11ec62a260STomasz Sapeta  __weak EXJavaScriptRuntime *_runtime;
12ec62a260STomasz Sapeta  std::shared_ptr<jsi::Value> _value;
13ec62a260STomasz Sapeta}
14ec62a260STomasz Sapeta
15ec62a260STomasz Sapeta- (nonnull instancetype)initWithRuntime:(nonnull EXJavaScriptRuntime *)runtime
16ec62a260STomasz Sapeta                                  value:(std::shared_ptr<jsi::Value>)value
17ec62a260STomasz Sapeta{
18ec62a260STomasz Sapeta  if (self = [super init]) {
19ec62a260STomasz Sapeta    _runtime = runtime;
20ec62a260STomasz Sapeta    _value = value;
21ec62a260STomasz Sapeta  }
22ec62a260STomasz Sapeta  return self;
23ec62a260STomasz Sapeta}
24ec62a260STomasz Sapeta
259bc9ec42STomasz Sapeta- (nonnull jsi::Value *)get
269bc9ec42STomasz Sapeta{
279bc9ec42STomasz Sapeta  return _value.get();
289bc9ec42STomasz Sapeta}
299bc9ec42STomasz Sapeta
30ec62a260STomasz Sapeta#pragma mark - Type checking
31ec62a260STomasz Sapeta
32ec62a260STomasz Sapeta- (BOOL)isUndefined
33ec62a260STomasz Sapeta{
34ec62a260STomasz Sapeta  return _value->isUndefined();
35ec62a260STomasz Sapeta}
36ec62a260STomasz Sapeta
37ec62a260STomasz Sapeta- (BOOL)isNull
38ec62a260STomasz Sapeta{
39ec62a260STomasz Sapeta  return _value->isNull();
40ec62a260STomasz Sapeta}
41ec62a260STomasz Sapeta
42ec62a260STomasz Sapeta- (BOOL)isBool
43ec62a260STomasz Sapeta{
44ec62a260STomasz Sapeta  return _value->isBool();
45ec62a260STomasz Sapeta}
46ec62a260STomasz Sapeta
47ec62a260STomasz Sapeta- (BOOL)isNumber
48ec62a260STomasz Sapeta{
49ec62a260STomasz Sapeta  return _value->isNumber();
50ec62a260STomasz Sapeta}
51ec62a260STomasz Sapeta
52ec62a260STomasz Sapeta- (BOOL)isString
53ec62a260STomasz Sapeta{
54ec62a260STomasz Sapeta  return _value->isString();
55ec62a260STomasz Sapeta}
56ec62a260STomasz Sapeta
57ec62a260STomasz Sapeta- (BOOL)isSymbol
58ec62a260STomasz Sapeta{
59ec62a260STomasz Sapeta  return _value->isSymbol();
60ec62a260STomasz Sapeta}
61ec62a260STomasz Sapeta
62ec62a260STomasz Sapeta- (BOOL)isObject
63ec62a260STomasz Sapeta{
64ec62a260STomasz Sapeta  return _value->isObject();
65ec62a260STomasz Sapeta}
66ec62a260STomasz Sapeta
67ec62a260STomasz Sapeta- (BOOL)isFunction
68ec62a260STomasz Sapeta{
69ec62a260STomasz Sapeta  if (_value->isObject()) {
70ec62a260STomasz Sapeta    jsi::Runtime *runtime = [_runtime get];
71ec62a260STomasz Sapeta    return _value->getObject(*runtime).isFunction(*runtime);
72ec62a260STomasz Sapeta  }
73ec62a260STomasz Sapeta  return false;
74ec62a260STomasz Sapeta}
75ec62a260STomasz Sapeta
76002d516eSTomasz Sapeta- (BOOL)isTypedArray
77002d516eSTomasz Sapeta{
78002d516eSTomasz Sapeta  if (_value->isObject()) {
79002d516eSTomasz Sapeta    jsi::Runtime *runtime = [_runtime get];
80002d516eSTomasz Sapeta    return expo::isTypedArray(*runtime, _value->getObject(*runtime));
81002d516eSTomasz Sapeta  }
82002d516eSTomasz Sapeta  return false;
83002d516eSTomasz Sapeta}
84002d516eSTomasz Sapeta
85ec62a260STomasz Sapeta#pragma mark - Type casting
86ec62a260STomasz Sapeta
87ec62a260STomasz Sapeta- (nullable id)getRaw
88ec62a260STomasz Sapeta{
89ec62a260STomasz Sapeta  return expo::convertJSIValueToObjCObject(*[_runtime get], *_value, [_runtime callInvoker]);
90ec62a260STomasz Sapeta}
91ec62a260STomasz Sapeta
92ec62a260STomasz Sapeta- (BOOL)getBool
93ec62a260STomasz Sapeta{
94ec62a260STomasz Sapeta  return _value->getBool();
95ec62a260STomasz Sapeta}
96ec62a260STomasz Sapeta
97ec62a260STomasz Sapeta- (NSInteger)getInt
98ec62a260STomasz Sapeta{
99ec62a260STomasz Sapeta  return _value->getNumber();
100ec62a260STomasz Sapeta}
101ec62a260STomasz Sapeta
102ec62a260STomasz Sapeta- (double)getDouble
103ec62a260STomasz Sapeta{
104ec62a260STomasz Sapeta  return _value->getNumber();
105ec62a260STomasz Sapeta}
106ec62a260STomasz Sapeta
107ec62a260STomasz Sapeta- (nonnull NSString *)getString
108ec62a260STomasz Sapeta{
109ec62a260STomasz Sapeta  jsi::Runtime *runtime = [_runtime get];
110ec62a260STomasz Sapeta  return expo::convertJSIStringToNSString(*runtime, _value->getString(*runtime));
111ec62a260STomasz Sapeta}
112ec62a260STomasz Sapeta
113ec62a260STomasz Sapeta- (nonnull NSArray<EXJavaScriptValue *> *)getArray
114ec62a260STomasz Sapeta{
115ec62a260STomasz Sapeta  jsi::Runtime *runtime = [_runtime get];
116ec62a260STomasz Sapeta  jsi::Array jsiArray = _value->getObject(*runtime).getArray(*runtime);
117ec62a260STomasz Sapeta  size_t arraySize = jsiArray.size(*runtime);
118ec62a260STomasz Sapeta  NSMutableArray *result = [NSMutableArray arrayWithCapacity:arraySize];
119ec62a260STomasz Sapeta
120ec62a260STomasz Sapeta  for (size_t i = 0; i < arraySize; i++) {
121ec62a260STomasz Sapeta    jsi::Value item = jsiArray.getValueAtIndex(*runtime, i);
122ec62a260STomasz Sapeta
123ec62a260STomasz Sapeta    if (item.isUndefined() || item.isNull()) {
124ec62a260STomasz Sapeta      [result addObject:(id)kCFNull];
125ec62a260STomasz Sapeta    } else {
126ec62a260STomasz Sapeta      std::shared_ptr<jsi::Value> valuePtr = std::make_shared<jsi::Value>(*runtime, item);
127ec62a260STomasz Sapeta      [result addObject:[[EXJavaScriptValue alloc] initWithRuntime:_runtime value:valuePtr]];
128ec62a260STomasz Sapeta    }
129ec62a260STomasz Sapeta  }
130ec62a260STomasz Sapeta  return result;
131ec62a260STomasz Sapeta}
132ec62a260STomasz Sapeta
133ec62a260STomasz Sapeta- (nonnull NSDictionary<NSString *, id> *)getDictionary
134ec62a260STomasz Sapeta{
135ec62a260STomasz Sapeta  jsi::Runtime *runtime = [_runtime get];
136ec62a260STomasz Sapeta  return expo::convertJSIObjectToNSDictionary(*runtime, _value->getObject(*runtime), [_runtime callInvoker]);
137ec62a260STomasz Sapeta}
138ec62a260STomasz Sapeta
139ec62a260STomasz Sapeta- (nonnull EXJavaScriptObject *)getObject
140ec62a260STomasz Sapeta{
141ec62a260STomasz Sapeta  jsi::Runtime *runtime = [_runtime get];
142ec62a260STomasz Sapeta  std::shared_ptr<jsi::Object> objectPtr = std::make_shared<jsi::Object>(_value->asObject(*runtime));
143ec62a260STomasz Sapeta  return [[EXJavaScriptObject alloc] initWith:objectPtr runtime:_runtime];
144ec62a260STomasz Sapeta}
145ec62a260STomasz Sapeta
146*a2ddfabcSTomasz Sapeta- (nonnull EXRawJavaScriptFunction *)getFunction
147*a2ddfabcSTomasz Sapeta{
148*a2ddfabcSTomasz Sapeta  jsi::Runtime *runtime = [_runtime get];
149*a2ddfabcSTomasz Sapeta  std::shared_ptr<jsi::Function> functionPtr = std::make_shared<jsi::Function>(_value->asObject(*runtime).asFunction(*runtime));
150*a2ddfabcSTomasz Sapeta  return [[EXRawJavaScriptFunction alloc] initWith:functionPtr runtime:_runtime];
151*a2ddfabcSTomasz Sapeta}
152*a2ddfabcSTomasz Sapeta
153002d516eSTomasz Sapeta- (nullable EXJavaScriptTypedArray *)getTypedArray
154002d516eSTomasz Sapeta{
155002d516eSTomasz Sapeta  if (![self isTypedArray]) {
156002d516eSTomasz Sapeta    return nil;
157002d516eSTomasz Sapeta  }
158002d516eSTomasz Sapeta  jsi::Runtime *runtime = [_runtime get];
159002d516eSTomasz Sapeta  std::shared_ptr<jsi::Object> objectPtr = std::make_shared<jsi::Object>(_value->asObject(*runtime));
160002d516eSTomasz Sapeta  return [[EXJavaScriptTypedArray alloc] initWith:objectPtr runtime:_runtime];
161002d516eSTomasz Sapeta}
162002d516eSTomasz Sapeta
163ec62a260STomasz Sapeta#pragma mark - Helpers
164ec62a260STomasz Sapeta
165ec62a260STomasz Sapeta- (nonnull NSString *)toString
166ec62a260STomasz Sapeta{
167ec62a260STomasz Sapeta  jsi::Runtime *runtime = [_runtime get];
168ec62a260STomasz Sapeta  return expo::convertJSIStringToNSString(*runtime, _value->toString(*runtime));
169ec62a260STomasz Sapeta}
170ec62a260STomasz Sapeta
171ec62a260STomasz Sapeta@end
172