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