1a2ddfabcSTomasz Sapeta// Copyright 2023-present 650 Industries. All rights reserved.
2a2ddfabcSTomasz Sapeta
3a2ddfabcSTomasz Sapeta#import <ExpoModulesCore/EXJSIConversions.h>
4a2ddfabcSTomasz Sapeta#import <ExpoModulesCore/EXRawJavaScriptFunction.h>
5a2ddfabcSTomasz Sapeta
6a2ddfabcSTomasz Sapeta@implementation EXRawJavaScriptFunction {
7a2ddfabcSTomasz Sapeta  /**
8a2ddfabcSTomasz Sapeta   Pointer to the `EXJavaScriptRuntime` wrapper.
9a2ddfabcSTomasz Sapeta
10a2ddfabcSTomasz Sapeta   \note It must be weak because only then the original runtime can be safely deallocated
11a2ddfabcSTomasz Sapeta   when the JS engine wants to without unsetting it on each created object.
12a2ddfabcSTomasz Sapeta   */
13a2ddfabcSTomasz Sapeta  __weak EXJavaScriptRuntime *_runtime;
14a2ddfabcSTomasz Sapeta
15a2ddfabcSTomasz Sapeta  /**
16*6b3436a7STomasz Sapeta   Shared pointer to the underlying JSI function.
17a2ddfabcSTomasz Sapeta   */
18a2ddfabcSTomasz Sapeta  std::shared_ptr<jsi::Function> _function;
19a2ddfabcSTomasz Sapeta}
20a2ddfabcSTomasz Sapeta
21a2ddfabcSTomasz Sapeta- (nonnull instancetype)initWith:(std::shared_ptr<jsi::Function>)function
22a2ddfabcSTomasz Sapeta                         runtime:(nonnull EXJavaScriptRuntime *)runtime
23a2ddfabcSTomasz Sapeta{
24a2ddfabcSTomasz Sapeta  if (self = [super init]) {
25a2ddfabcSTomasz Sapeta    _runtime = runtime;
26a2ddfabcSTomasz Sapeta    _function = function;
27a2ddfabcSTomasz Sapeta  }
28a2ddfabcSTomasz Sapeta  return self;
29a2ddfabcSTomasz Sapeta}
30a2ddfabcSTomasz Sapeta
31a2ddfabcSTomasz Sapeta- (nonnull EXJavaScriptValue *)callWithArguments:(nonnull NSArray<id> *)arguments
32a2ddfabcSTomasz Sapeta                                      thisObject:(nullable EXJavaScriptObject *)thisObject
33a2ddfabcSTomasz Sapeta                                   asConstructor:(BOOL)asConstructor
34a2ddfabcSTomasz Sapeta{
35a2ddfabcSTomasz Sapeta  jsi::Runtime *runtime = [_runtime get];
36a2ddfabcSTomasz Sapeta  std::vector<jsi::Value> vector = expo::convertNSArrayToStdVector(*runtime, arguments);
37a2ddfabcSTomasz Sapeta  const jsi::Value *data = vector.data();
38a2ddfabcSTomasz Sapeta  jsi::Value result;
39a2ddfabcSTomasz Sapeta
40a2ddfabcSTomasz Sapeta  if (asConstructor) {
41a2ddfabcSTomasz Sapeta    result = _function->callAsConstructor(*runtime, data, arguments.count);
42a2ddfabcSTomasz Sapeta  } else if (thisObject) {
43a2ddfabcSTomasz Sapeta    result = _function->callWithThis(*runtime, *[thisObject get], data, arguments.count);
44a2ddfabcSTomasz Sapeta  } else {
45a2ddfabcSTomasz Sapeta    result = _function->call(*runtime, data, arguments.count);
46a2ddfabcSTomasz Sapeta  }
47a2ddfabcSTomasz Sapeta
48a2ddfabcSTomasz Sapeta  std::shared_ptr<jsi::Value> resultPtr = std::make_shared<jsi::Value>(*runtime, result);
49a2ddfabcSTomasz Sapeta  return [[EXJavaScriptValue alloc] initWithRuntime:_runtime value:resultPtr];
50a2ddfabcSTomasz Sapeta}
51a2ddfabcSTomasz Sapeta
52a2ddfabcSTomasz Sapeta@end
53