expo-modules-core 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/android/CMakeLists.txt +154 -0
- package/android/build.gradle +293 -5
- package/android/src/main/cpp/Exceptions.cpp +22 -0
- package/android/src/main/cpp/Exceptions.h +38 -0
- package/android/src/main/cpp/ExpoModulesHostObject.cpp +47 -0
- package/android/src/main/cpp/ExpoModulesHostObject.h +32 -0
- package/android/src/main/cpp/JNIFunctionBody.cpp +29 -0
- package/android/src/main/cpp/JNIFunctionBody.h +50 -0
- package/android/src/main/cpp/JNIInjector.cpp +19 -0
- package/android/src/main/cpp/JSIInteropModuleRegistry.cpp +122 -0
- package/android/src/main/cpp/JSIInteropModuleRegistry.h +96 -0
- package/android/src/main/cpp/JSIObjectWrapper.h +33 -0
- package/android/src/main/cpp/JSITypeConverter.h +84 -0
- package/android/src/main/cpp/JavaScriptModuleObject.cpp +138 -0
- package/android/src/main/cpp/JavaScriptModuleObject.h +122 -0
- package/android/src/main/cpp/JavaScriptObject.cpp +125 -0
- package/android/src/main/cpp/JavaScriptObject.h +131 -0
- package/android/src/main/cpp/JavaScriptRuntime.cpp +127 -0
- package/android/src/main/cpp/JavaScriptRuntime.h +87 -0
- package/android/src/main/cpp/JavaScriptValue.cpp +172 -0
- package/android/src/main/cpp/JavaScriptValue.h +78 -0
- package/android/src/main/cpp/MethodMetadata.cpp +230 -0
- package/android/src/main/cpp/MethodMetadata.h +92 -0
- package/android/src/main/java/expo/modules/adapters/react/NativeModulesProxy.java +2 -0
- package/android/src/main/java/expo/modules/core/errors/ContextDestroyedException.kt +7 -0
- package/android/src/main/java/expo/modules/interfaces/permissions/Permissions.java +30 -0
- package/android/src/main/java/expo/modules/kotlin/AppContext.kt +49 -1
- package/android/src/main/java/expo/modules/kotlin/ConcatIterator.kt +18 -0
- package/android/src/main/java/expo/modules/kotlin/KotlinInteropModuleRegistry.kt +15 -12
- package/android/src/main/java/expo/modules/kotlin/ModuleHolder.kt +39 -3
- package/android/src/main/java/expo/modules/kotlin/defaultmodules/ErrorManagerModule.kt +2 -2
- package/android/src/main/java/expo/modules/kotlin/exception/CodedException.kt +13 -0
- package/android/src/main/java/expo/modules/kotlin/exception/ExceptionDecorator.kt +2 -0
- package/android/src/main/java/expo/modules/kotlin/functions/AnyFunction.kt +19 -14
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunction.kt +29 -7
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionBuilder.kt +13 -13
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionComponent.kt +18 -0
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionWithPromiseComponent.kt +18 -0
- package/android/src/main/java/expo/modules/kotlin/functions/SuspendFunctionComponent.kt +56 -0
- package/android/src/main/java/expo/modules/kotlin/functions/SyncFunctionComponent.kt +28 -0
- package/android/src/main/java/expo/modules/kotlin/jni/CppType.kt +18 -0
- package/android/src/main/java/expo/modules/kotlin/jni/JNIFunctionBody.kt +39 -0
- package/android/src/main/java/expo/modules/kotlin/jni/JSIInteropModuleRegistry.kt +89 -0
- package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptModuleObject.kt +44 -0
- package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptObject.kt +113 -0
- package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptValue.kt +35 -0
- package/android/src/main/java/expo/modules/kotlin/modules/Module.kt +15 -5
- package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionBuilder.kt +65 -111
- package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionData.kt +35 -2
- package/android/src/main/java/expo/modules/kotlin/providers/AppContextProvider.kt +14 -0
- package/android/src/main/java/expo/modules/kotlin/providers/CurrentActivityProvider.kt +22 -0
- package/android/src/main/java/expo/modules/kotlin/records/RecordTypeConverter.kt +19 -2
- package/android/src/main/java/expo/modules/kotlin/types/AnyType.kt +3 -2
- package/android/src/main/java/expo/modules/kotlin/types/ArrayTypeConverter.kt +7 -2
- package/android/src/main/java/expo/modules/kotlin/types/BasicTypeConverters.kt +68 -20
- package/android/src/main/java/expo/modules/kotlin/types/EnumTypeConverter.kt +50 -22
- package/android/src/main/java/expo/modules/kotlin/types/ListTypeConverter.kt +18 -2
- package/android/src/main/java/expo/modules/kotlin/types/MapTypeConverter.kt +18 -2
- package/android/src/main/java/expo/modules/kotlin/types/PairTypeConverter.kt +17 -2
- package/android/src/main/java/expo/modules/kotlin/types/TypeConverter.kt +43 -3
- package/android/src/main/java/expo/modules/kotlin/types/TypeConverterProvider.kt +5 -0
- package/build/NativeModulesProxy.native.d.ts.map +1 -1
- package/build/NativeModulesProxy.native.js +9 -3
- package/build/NativeModulesProxy.native.js.map +1 -1
- package/ios/AppDelegates/EXAppDelegatesLoader.m +1 -2
- package/ios/ExpoModulesCore.podspec +1 -1
- package/ios/JSI/EXJSIConversions.mm +6 -0
- package/ios/JSI/EXJSIInstaller.h +15 -21
- package/ios/JSI/EXJSIInstaller.mm +39 -3
- package/ios/JSI/EXJSIUtils.h +47 -3
- package/ios/JSI/EXJSIUtils.mm +88 -4
- package/ios/JSI/EXJavaScriptObject.h +11 -18
- package/ios/JSI/EXJavaScriptObject.mm +37 -18
- package/ios/JSI/EXJavaScriptRuntime.h +43 -9
- package/ios/JSI/EXJavaScriptRuntime.mm +70 -27
- package/ios/JSI/EXJavaScriptTypedArray.h +30 -0
- package/ios/JSI/EXJavaScriptTypedArray.mm +29 -0
- package/ios/JSI/EXJavaScriptValue.h +3 -2
- package/ios/JSI/EXJavaScriptValue.mm +17 -20
- package/ios/JSI/EXJavaScriptWeakObject.h +23 -0
- package/ios/JSI/EXJavaScriptWeakObject.mm +53 -0
- package/ios/JSI/EXObjectDeallocator.h +27 -0
- package/ios/JSI/ExpoModulesHostObject.h +3 -3
- package/ios/JSI/ExpoModulesHostObject.mm +4 -4
- package/ios/JSI/JavaScriptRuntime.swift +38 -1
- package/ios/JSI/JavaScriptValue.swift +7 -0
- package/ios/JSI/TypedArray.cpp +67 -0
- package/ios/JSI/TypedArray.h +46 -0
- package/ios/ModuleRegistryAdapter/EXModuleRegistryAdapter.m +0 -11
- package/ios/NativeModulesProxy/EXNativeModulesProxy.h +17 -10
- package/ios/NativeModulesProxy/EXNativeModulesProxy.mm +88 -77
- package/ios/NativeModulesProxy/NativeModulesProxyModule.swift +17 -0
- package/ios/Services/EXReactNativeEventEmitter.h +2 -2
- package/ios/Services/EXReactNativeEventEmitter.m +11 -6
- package/ios/Swift/AppContext.swift +208 -28
- package/ios/Swift/Arguments/AnyArgument.swift +18 -0
- package/ios/Swift/Arguments/{Types/EnumArgumentType.swift → EnumArgument.swift} +2 -17
- package/ios/Swift/Classes/ClassComponent.swift +95 -0
- package/ios/Swift/Classes/ClassComponentElement.swift +33 -0
- package/ios/Swift/Classes/ClassComponentElementsBuilder.swift +34 -0
- package/ios/Swift/Classes/ClassComponentFactories.swift +96 -0
- package/ios/Swift/DynamicTypes/AnyDynamicType.swift +44 -0
- package/ios/Swift/DynamicTypes/DynamicArrayType.swift +56 -0
- package/ios/Swift/DynamicTypes/DynamicConvertibleType.swift +27 -0
- package/ios/Swift/DynamicTypes/DynamicEnumType.swift +27 -0
- package/ios/Swift/DynamicTypes/DynamicOptionalType.swift +63 -0
- package/ios/Swift/DynamicTypes/DynamicRawType.swift +33 -0
- package/ios/Swift/DynamicTypes/DynamicSharedObjectType.swift +37 -0
- package/ios/Swift/DynamicTypes/DynamicType.swift +39 -0
- package/ios/Swift/DynamicTypes/DynamicTypedArrayType.swift +46 -0
- package/ios/Swift/Exceptions/CodedError.swift +1 -1
- package/ios/Swift/Exceptions/Exception.swift +8 -6
- package/ios/Swift/Exceptions/UnexpectedException.swift +2 -1
- package/ios/Swift/ExpoBridgeModule.m +5 -0
- package/ios/Swift/ExpoBridgeModule.swift +65 -0
- package/ios/Swift/Functions/AnyFunction.swift +33 -31
- package/ios/Swift/Functions/AsyncFunctionComponent.swift +196 -59
- package/ios/Swift/Functions/SyncFunctionComponent.swift +142 -58
- package/ios/Swift/JavaScriptUtils.swift +32 -57
- package/ios/Swift/Logging/LogHandlers.swift +39 -0
- package/ios/Swift/Logging/LogType.swift +62 -0
- package/ios/Swift/Logging/Logger.swift +198 -0
- package/ios/Swift/ModuleHolder.swift +19 -54
- package/ios/Swift/ModuleRegistry.swift +7 -1
- package/ios/Swift/Modules/AnyModule.swift +3 -3
- package/ios/Swift/ModulesProvider.swift +2 -0
- package/ios/Swift/Objects/JavaScriptObjectBuilder.swift +37 -0
- package/ios/Swift/Objects/ObjectDefinition.swift +74 -1
- package/ios/Swift/Objects/ObjectDefinitionComponents.swift +77 -68
- package/ios/Swift/Objects/PropertyComponent.swift +147 -0
- package/ios/Swift/Promise.swift +12 -3
- package/ios/Swift/Records/Field.swift +2 -2
- package/ios/Swift/SharedObjects/SharedObject.swift +20 -0
- package/ios/Swift/SharedObjects/SharedObjectRegistry.swift +129 -0
- package/ios/Swift/TypedArrays/AnyTypedArray.swift +11 -0
- package/ios/Swift/TypedArrays/ConcreteTypedArrays.swift +56 -0
- package/ios/Swift/TypedArrays/GenericTypedArray.swift +49 -0
- package/ios/Swift/TypedArrays/TypedArray.swift +80 -0
- package/ios/Swift/Utilities.swift +28 -0
- package/ios/Swift/Views/ConcreteViewProp.swift +3 -3
- package/ios/Swift/Views/ViewManagerDefinitionComponents.swift +2 -2
- package/ios/Tests/ClassComponentSpec.swift +210 -0
- package/ios/Tests/DynamicTypeSpec.swift +336 -0
- package/ios/Tests/EnumArgumentSpec.swift +48 -0
- package/ios/Tests/ExpoModulesSpec.swift +17 -3
- package/ios/Tests/FunctionSpec.swift +167 -118
- package/ios/Tests/Mocks/ModuleMocks.swift +1 -1
- package/ios/Tests/PropertyComponentSpec.swift +95 -0
- package/ios/Tests/SharedObjectRegistrySpec.swift +109 -0
- package/ios/Tests/TypedArraysSpec.swift +136 -0
- package/package.json +2 -2
- package/src/NativeModulesProxy.native.ts +13 -3
- package/src/ts-declarations/ExpoModules.d.ts +7 -0
- package/tsconfig.json +1 -1
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionWithPromise.kt +0 -15
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncSuspendFunction.kt +0 -36
- package/ios/Swift/Arguments/AnyArgumentType.swift +0 -13
- package/ios/Swift/Arguments/ArgumentType.swift +0 -28
- package/ios/Swift/Arguments/Types/ArrayArgumentType.swift +0 -42
- package/ios/Swift/Arguments/Types/ConvertibleArgumentType.swift +0 -16
- package/ios/Swift/Arguments/Types/OptionalArgumentType.swift +0 -49
- package/ios/Swift/Arguments/Types/PromiseArgumentType.swift +0 -15
- package/ios/Swift/Arguments/Types/RawArgumentType.swift +0 -25
- package/ios/Swift/Functions/ConcreteFunction.swift +0 -103
- package/ios/Swift/SwiftInteropBridge.swift +0 -155
- package/ios/Tests/ArgumentTypeSpec.swift +0 -143
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
// Copyright 2018-present 650 Industries. All rights reserved.
|
|
2
2
|
|
|
3
3
|
#import <ReactCommon/TurboModuleUtils.h>
|
|
4
|
+
#import <ExpoModulesCore/EXJavaScriptValue.h>
|
|
5
|
+
#import <ExpoModulesCore/EXJavaScriptObject.h>
|
|
6
|
+
#import <ExpoModulesCore/EXJavaScriptWeakObject.h>
|
|
4
7
|
#import <ExpoModulesCore/EXJSIConversions.h>
|
|
5
8
|
#import <ExpoModulesCore/EXJavaScriptValue.h>
|
|
6
9
|
#import <ExpoModulesCore/EXJavaScriptRuntime.h>
|
|
@@ -60,6 +63,9 @@ jsi::Value convertObjCObjectToJSIValue(jsi::Runtime &runtime, id value)
|
|
|
60
63
|
if ([value isKindOfClass:[EXJavaScriptObject class]]) {
|
|
61
64
|
return jsi::Value(runtime, *[(EXJavaScriptObject *)value get]);
|
|
62
65
|
}
|
|
66
|
+
if ([value isKindOfClass:[EXJavaScriptWeakObject class]]) {
|
|
67
|
+
return jsi::Value(runtime, *[[(EXJavaScriptWeakObject *)value lock] get]);
|
|
68
|
+
}
|
|
63
69
|
if ([value isKindOfClass:[NSString class]]) {
|
|
64
70
|
return convertNSStringToJSIString(runtime, (NSString *)value);
|
|
65
71
|
} else if ([value isKindOfClass:[NSNumber class]]) {
|
package/ios/JSI/EXJSIInstaller.h
CHANGED
|
@@ -1,29 +1,23 @@
|
|
|
1
1
|
// Copyright 2018-present 650 Industries. All rights reserved.
|
|
2
2
|
|
|
3
|
-
#
|
|
3
|
+
#import <React/RCTBridge.h>
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
#import <ExpoModulesCore/EXNativeModulesProxy.h>
|
|
9
|
-
|
|
10
|
-
using namespace facebook;
|
|
11
|
-
using namespace react;
|
|
12
|
-
|
|
13
|
-
namespace expo {
|
|
14
|
-
|
|
15
|
-
void installRuntimeObjects(jsi::Runtime &runtime, std::shared_ptr<CallInvoker> callInvoker, EXNativeModulesProxy *nativeModulesProxy);
|
|
16
|
-
|
|
17
|
-
} // namespace expo
|
|
18
|
-
|
|
19
|
-
#endif
|
|
20
|
-
|
|
21
|
-
#import <ExpoModulesCore/EXJavaScriptRuntime.h>
|
|
22
|
-
|
|
23
|
-
@class SwiftInteropBridge;
|
|
5
|
+
// Swift classes need forward-declaration in the headers.
|
|
6
|
+
@class EXAppContext;
|
|
7
|
+
@class EXJavaScriptRuntime;
|
|
24
8
|
|
|
25
9
|
@interface EXJavaScriptRuntimeManager : NSObject
|
|
26
10
|
|
|
27
|
-
|
|
11
|
+
/**
|
|
12
|
+
Gets the JS runtime from the given bridge. May return `nil` when
|
|
13
|
+
the runtime is not available yet or the remote debugging is enabled.
|
|
14
|
+
*/
|
|
15
|
+
+ (nullable EXJavaScriptRuntime *)runtimeFromBridge:(nonnull RCTBridge *)bridge NS_SWIFT_NAME(runtime(fromBridge:));
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
Installs ExpoModules host object in the runtime of the given app context.
|
|
19
|
+
Returns a bool value whether the installation succeeded.
|
|
20
|
+
*/
|
|
21
|
+
+ (BOOL)installExpoModulesHostObject:(nonnull EXAppContext *)appContext;
|
|
28
22
|
|
|
29
23
|
@end
|
|
@@ -4,14 +4,50 @@
|
|
|
4
4
|
#import <ExpoModulesCore/ExpoModulesHostObject.h>
|
|
5
5
|
#import <ExpoModulesCore/Swift.h>
|
|
6
6
|
|
|
7
|
+
namespace jsi = facebook::jsi;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
This name will be used as a property of the JS global object to which the host object is added.
|
|
11
|
+
*/
|
|
12
|
+
static NSString *expoModulesHostObjectPropertyName = @"ExpoModules";
|
|
13
|
+
|
|
14
|
+
@interface RCTBridge (ExpoBridgeWithRuntime)
|
|
15
|
+
|
|
16
|
+
- (void *)runtime;
|
|
17
|
+
|
|
18
|
+
@end
|
|
19
|
+
|
|
7
20
|
@implementation EXJavaScriptRuntimeManager
|
|
8
21
|
|
|
9
|
-
+ (
|
|
22
|
+
+ (nullable EXJavaScriptRuntime *)runtimeFromBridge:(nonnull RCTBridge *)bridge
|
|
10
23
|
{
|
|
11
|
-
|
|
24
|
+
jsi::Runtime *jsiRuntime = [bridge respondsToSelector:@selector(runtime)] ? reinterpret_cast<jsi::Runtime *>(bridge.runtime) : nullptr;
|
|
25
|
+
return jsiRuntime ? [[EXJavaScriptRuntime alloc] initWithRuntime:jsiRuntime callInvoker:bridge.jsCallInvoker] : nil;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
+ (BOOL)installExpoModulesHostObject:(nonnull EXAppContext *)appContext
|
|
29
|
+
{
|
|
30
|
+
EXJavaScriptRuntime *runtime = [appContext runtime];
|
|
31
|
+
|
|
32
|
+
// The runtime may be unavailable, e.g. remote debugger is enabled or it hasn't been set yet.
|
|
33
|
+
if (!runtime) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
|
|
12
37
|
EXJavaScriptObject *global = [runtime global];
|
|
13
38
|
|
|
14
|
-
[global
|
|
39
|
+
if ([global hasProperty:expoModulesHostObjectPropertyName]) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
std::shared_ptr<expo::ExpoModulesHostObject> hostObjectPtr = std::make_shared<expo::ExpoModulesHostObject>(appContext);
|
|
44
|
+
EXJavaScriptObject *hostObject = [runtime createHostObject:hostObjectPtr];
|
|
45
|
+
|
|
46
|
+
// Define the ExpoModules object as a non-configurable, read-only and enumerable property.
|
|
47
|
+
[global defineProperty:expoModulesHostObjectPropertyName
|
|
48
|
+
value:hostObject
|
|
49
|
+
options:EXJavaScriptObjectPropertyDescriptorEnumerable];
|
|
50
|
+
return true;
|
|
15
51
|
}
|
|
16
52
|
|
|
17
53
|
@end
|
package/ios/JSI/EXJSIUtils.h
CHANGED
|
@@ -2,17 +2,61 @@
|
|
|
2
2
|
|
|
3
3
|
#ifdef __cplusplus
|
|
4
4
|
|
|
5
|
+
#import <functional>
|
|
6
|
+
|
|
5
7
|
#import <jsi/jsi.h>
|
|
6
8
|
#import <ReactCommon/RCTTurboModule.h>
|
|
9
|
+
#import <ExpoModulesCore/EXObjectDeallocator.h>
|
|
7
10
|
|
|
8
|
-
|
|
9
|
-
|
|
11
|
+
namespace jsi = facebook::jsi;
|
|
12
|
+
namespace react = facebook::react;
|
|
10
13
|
|
|
11
14
|
namespace expo {
|
|
12
15
|
|
|
16
|
+
#pragma mark - Promises
|
|
17
|
+
|
|
13
18
|
using PromiseInvocationBlock = void (^)(RCTPromiseResolveBlock resolveWrapper, RCTPromiseRejectBlock rejectWrapper);
|
|
14
19
|
|
|
15
|
-
void callPromiseSetupWithBlock(jsi::Runtime &runtime, std::shared_ptr<CallInvoker> jsInvoker, std::shared_ptr<Promise> promise, PromiseInvocationBlock setupBlock);
|
|
20
|
+
void callPromiseSetupWithBlock(jsi::Runtime &runtime, std::shared_ptr<react::CallInvoker> jsInvoker, std::shared_ptr<react::Promise> promise, PromiseInvocationBlock setupBlock);
|
|
21
|
+
|
|
22
|
+
#pragma mark - Classes
|
|
23
|
+
|
|
24
|
+
using ClassConstructor = std::function<void(jsi::Runtime &runtime, const jsi::Value &thisValue, const jsi::Value *args, size_t count)>;
|
|
25
|
+
|
|
26
|
+
std::shared_ptr<jsi::Function> createClass(jsi::Runtime &runtime, const char *name, ClassConstructor constructor);
|
|
27
|
+
|
|
28
|
+
#pragma mark - Weak objects
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
Checks whether the `WeakRef` class is available in the given runtime.
|
|
32
|
+
According to the docs, it is unimplemented in JSC prior to iOS 14.5.
|
|
33
|
+
As of the time of writing this comment it's also unimplemented in Hermes
|
|
34
|
+
where you should use `jsi::WeakObject` instead.
|
|
35
|
+
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakRef
|
|
36
|
+
*/
|
|
37
|
+
bool isWeakRefSupported(jsi::Runtime &runtime);
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
Creates the `WeakRef` with given JSI object. You should first use `isWeakRefSupported`
|
|
41
|
+
to check whether this feature is supported by the runtime.
|
|
42
|
+
*/
|
|
43
|
+
std::shared_ptr<jsi::Object> createWeakRef(jsi::Runtime &runtime, std::shared_ptr<jsi::Object> object);
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
Returns the `WeakRef` object's target object, or an empty pointer if the target object has been reclaimed.
|
|
47
|
+
*/
|
|
48
|
+
std::shared_ptr<jsi::Object> derefWeakRef(jsi::Runtime &runtime, std::shared_ptr<jsi::Object> object);
|
|
49
|
+
|
|
50
|
+
#pragma mark - Define property
|
|
51
|
+
|
|
52
|
+
void defineProperty(jsi::Runtime &runtime, const jsi::Object *object, const char *name, jsi::Value value);
|
|
53
|
+
|
|
54
|
+
#pragma mark - Deallocator
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
Sets the deallocator block on a given object, which is called when the object is being deallocated.
|
|
58
|
+
*/
|
|
59
|
+
void setDeallocator(jsi::Runtime &runtime, std::shared_ptr<jsi::Object> object, ObjectDeallocatorBlock deallocatorBlock);
|
|
16
60
|
|
|
17
61
|
} // namespace expo
|
|
18
62
|
|
package/ios/JSI/EXJSIUtils.mm
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
// Copyright 2022-present 650 Industries. All rights reserved.
|
|
2
2
|
|
|
3
|
+
#import <sstream>
|
|
4
|
+
|
|
3
5
|
#import <React/RCTUtils.h>
|
|
4
6
|
#import <ExpoModulesCore/EXJSIConversions.h>
|
|
5
7
|
#import <ExpoModulesCore/EXJSIUtils.h>
|
|
6
8
|
|
|
7
|
-
using namespace facebook;
|
|
8
|
-
|
|
9
9
|
namespace expo {
|
|
10
10
|
|
|
11
11
|
void callPromiseSetupWithBlock(jsi::Runtime &runtime, std::shared_ptr<CallInvoker> jsInvoker, std::shared_ptr<Promise> promise, PromiseInvocationBlock setupBlock)
|
|
12
12
|
{
|
|
13
|
-
auto weakResolveWrapper = CallbackWrapper::createWeak(promise->resolve_.getFunction(runtime), runtime, jsInvoker);
|
|
14
|
-
auto weakRejectWrapper = CallbackWrapper::createWeak(promise->reject_.getFunction(runtime), runtime, jsInvoker);
|
|
13
|
+
auto weakResolveWrapper = react::CallbackWrapper::createWeak(promise->resolve_.getFunction(runtime), runtime, jsInvoker);
|
|
14
|
+
auto weakRejectWrapper = react::CallbackWrapper::createWeak(promise->reject_.getFunction(runtime), runtime, jsInvoker);
|
|
15
15
|
|
|
16
16
|
__block BOOL resolveWasCalled = NO;
|
|
17
17
|
__block BOOL rejectWasCalled = NO;
|
|
@@ -86,4 +86,88 @@ void callPromiseSetupWithBlock(jsi::Runtime &runtime, std::shared_ptr<CallInvoke
|
|
|
86
86
|
setupBlock(resolveBlock, rejectBlock);
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
+
std::shared_ptr<jsi::Function> createClass(jsi::Runtime &runtime, const char *name, ClassConstructor constructor) {
|
|
90
|
+
std::string nativeConstructorKey("__native_constructor__");
|
|
91
|
+
|
|
92
|
+
// Create a string buffer of the source code to evaluate.
|
|
93
|
+
std::stringstream source;
|
|
94
|
+
source << "(function " << name << "(...args) { this." << nativeConstructorKey << "(...args); return this; })";
|
|
95
|
+
std::shared_ptr<jsi::StringBuffer> sourceBuffer = std::make_shared<jsi::StringBuffer>(source.str());
|
|
96
|
+
|
|
97
|
+
// Evaluate the code and obtain returned value (the constructor function).
|
|
98
|
+
jsi::Object klass = runtime.evaluateJavaScript(sourceBuffer, "").asObject(runtime);
|
|
99
|
+
|
|
100
|
+
// Set the native constructor in the prototype.
|
|
101
|
+
jsi::Object prototype = klass.getPropertyAsObject(runtime, "prototype");
|
|
102
|
+
jsi::PropNameID nativeConstructorPropId = jsi::PropNameID::forAscii(runtime, nativeConstructorKey);
|
|
103
|
+
jsi::Function nativeConstructor = jsi::Function::createFromHostFunction(
|
|
104
|
+
runtime,
|
|
105
|
+
nativeConstructorPropId,
|
|
106
|
+
// The paramCount is not obligatory to match, it only affects the `length` property of the function.
|
|
107
|
+
0,
|
|
108
|
+
[constructor](jsi::Runtime &runtime, const jsi::Value &thisValue, const jsi::Value *args, size_t count) -> jsi::Value {
|
|
109
|
+
constructor(runtime, thisValue, args, count);
|
|
110
|
+
return jsi::Value::undefined();
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
defineProperty(runtime, &prototype, nativeConstructorKey.c_str(), jsi::Value(runtime, nativeConstructor));
|
|
114
|
+
|
|
115
|
+
return std::make_shared<jsi::Function>(klass.asFunction(runtime));
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
#pragma mark - Weak objects
|
|
119
|
+
|
|
120
|
+
bool isWeakRefSupported(jsi::Runtime &runtime) {
|
|
121
|
+
return runtime.global().hasProperty(runtime, "WeakRef");
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
std::shared_ptr<jsi::Object> createWeakRef(jsi::Runtime &runtime, std::shared_ptr<jsi::Object> object) {
|
|
125
|
+
jsi::Object weakRef = runtime
|
|
126
|
+
.global()
|
|
127
|
+
.getProperty(runtime, "WeakRef")
|
|
128
|
+
.asObject(runtime)
|
|
129
|
+
.asFunction(runtime)
|
|
130
|
+
.callAsConstructor(runtime, jsi::Value(runtime, *object))
|
|
131
|
+
.asObject(runtime);
|
|
132
|
+
return std::make_shared<jsi::Object>(std::move(weakRef));
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
std::shared_ptr<jsi::Object> derefWeakRef(jsi::Runtime &runtime, std::shared_ptr<jsi::Object> object) {
|
|
136
|
+
jsi::Value ref = object->getProperty(runtime, "deref")
|
|
137
|
+
.asObject(runtime)
|
|
138
|
+
.asFunction(runtime)
|
|
139
|
+
.callWithThis(runtime, *object);
|
|
140
|
+
|
|
141
|
+
if (ref.isUndefined()) {
|
|
142
|
+
return nullptr;
|
|
143
|
+
}
|
|
144
|
+
return std::make_shared<jsi::Object>(ref.asObject(runtime));
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
#pragma mark - Define property
|
|
148
|
+
|
|
149
|
+
void defineProperty(jsi::Runtime &runtime, const jsi::Object *object, const char *name, jsi::Value value) {
|
|
150
|
+
jsi::Object global = runtime.global();
|
|
151
|
+
jsi::Object objectClass = global.getPropertyAsObject(runtime, "Object");
|
|
152
|
+
jsi::Function definePropertyFunction = objectClass.getPropertyAsFunction(runtime, "defineProperty");
|
|
153
|
+
|
|
154
|
+
jsi::Object descriptor(runtime);
|
|
155
|
+
descriptor.setProperty(runtime, "value", value);
|
|
156
|
+
|
|
157
|
+
definePropertyFunction.callWithThis(runtime, objectClass, {
|
|
158
|
+
jsi::Value(runtime, *object),
|
|
159
|
+
jsi::String::createFromUtf8(runtime, name),
|
|
160
|
+
std::move(descriptor),
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
#pragma mark - Deallocator
|
|
165
|
+
|
|
166
|
+
void setDeallocator(jsi::Runtime &runtime, std::shared_ptr<jsi::Object> object, ObjectDeallocatorBlock deallocatorBlock) {
|
|
167
|
+
std::shared_ptr<expo::ObjectDeallocator> hostObjectPtr = std::make_shared<ObjectDeallocator>(deallocatorBlock);
|
|
168
|
+
jsi::Object jsObject = jsi::Object::createFromHostObject(runtime, hostObjectPtr);
|
|
169
|
+
|
|
170
|
+
object->setProperty(runtime, "__expo_object_deallocator__", jsi::Value(runtime, jsObject));
|
|
171
|
+
}
|
|
172
|
+
|
|
89
173
|
} // namespace expo
|
|
@@ -1,20 +1,16 @@
|
|
|
1
1
|
// Copyright 2022-present 650 Industries. All rights reserved.
|
|
2
2
|
|
|
3
3
|
#import <Foundation/Foundation.h>
|
|
4
|
-
#import <React/RCTBridgeModule.h>
|
|
5
4
|
|
|
6
5
|
#ifdef __cplusplus
|
|
7
6
|
#import <jsi/jsi.h>
|
|
8
|
-
#import <ReactCommon/CallInvoker.h>
|
|
9
7
|
|
|
10
8
|
namespace jsi = facebook::jsi;
|
|
11
9
|
#endif // __cplusplus
|
|
12
10
|
|
|
13
|
-
typedef void (^JSAsyncFunctionBlock)(NSArray * _Nonnull, RCTPromiseResolveBlock _Nonnull, RCTPromiseRejectBlock _Nonnull);
|
|
14
|
-
typedef id _Nullable (^JSSyncFunctionBlock)(NSArray * _Nonnull);
|
|
15
|
-
|
|
16
11
|
@class EXJavaScriptRuntime;
|
|
17
12
|
@class EXJavaScriptValue;
|
|
13
|
+
@class EXJavaScriptWeakObject;
|
|
18
14
|
|
|
19
15
|
/**
|
|
20
16
|
The property descriptor options for the property being defined or modified.
|
|
@@ -73,25 +69,22 @@ NS_SWIFT_NAME(JavaScriptObject)
|
|
|
73
69
|
*/
|
|
74
70
|
- (void)setProperty:(nonnull NSString *)name value:(nullable id)value;
|
|
75
71
|
|
|
72
|
+
/**
|
|
73
|
+
Defines a new property or modifies an existing property on the object using the property descriptor.
|
|
74
|
+
*/
|
|
75
|
+
- (void)defineProperty:(nonnull NSString *)name descriptor:(nonnull EXJavaScriptObject *)descriptor;
|
|
76
|
+
|
|
76
77
|
/**
|
|
77
78
|
Defines a new property or modifies an existing property on the object. Calls `Object.defineProperty` under the hood.
|
|
78
79
|
*/
|
|
79
80
|
- (void)defineProperty:(nonnull NSString *)name value:(nullable id)value options:(EXJavaScriptObjectPropertyDescriptor)options;
|
|
80
81
|
|
|
81
|
-
#pragma mark -
|
|
82
|
+
#pragma mark - WeakObject
|
|
82
83
|
|
|
83
|
-
|
|
84
|
-
Sets given function block on the object as a host function returning a promise.
|
|
85
|
-
*/
|
|
86
|
-
- (void)setAsyncFunction:(nonnull NSString *)key
|
|
87
|
-
argsCount:(NSInteger)argsCount
|
|
88
|
-
block:(nonnull JSAsyncFunctionBlock)block;
|
|
84
|
+
- (nonnull EXJavaScriptWeakObject *)createWeak;
|
|
89
85
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
- (void)setSyncFunction:(nonnull NSString *)name
|
|
94
|
-
argsCount:(NSInteger)argsCount
|
|
95
|
-
block:(nonnull JSSyncFunctionBlock)block;
|
|
86
|
+
#pragma mark - Deallocator
|
|
87
|
+
|
|
88
|
+
- (void)setObjectDeallocator:(void (^ _Nonnull)(void))deallocatorBlock;
|
|
96
89
|
|
|
97
90
|
@end
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
// Copyright 2022-present 650 Industries. All rights reserved.
|
|
2
2
|
|
|
3
3
|
#import <ExpoModulesCore/EXJSIConversions.h>
|
|
4
|
+
#import <ExpoModulesCore/EXJavaScriptValue.h>
|
|
4
5
|
#import <ExpoModulesCore/EXJavaScriptObject.h>
|
|
5
6
|
#import <ExpoModulesCore/EXJavaScriptRuntime.h>
|
|
7
|
+
#import <ExpoModulesCore/EXJavaScriptWeakObject.h>
|
|
8
|
+
#import <ExpoModulesCore/EXJSIUtils.h>
|
|
6
9
|
|
|
7
10
|
@implementation EXJavaScriptObject {
|
|
8
11
|
/**
|
|
@@ -62,6 +65,21 @@
|
|
|
62
65
|
_jsObjectPtr->setProperty(*[_runtime get], [name UTF8String], jsiValue);
|
|
63
66
|
}
|
|
64
67
|
|
|
68
|
+
- (void)defineProperty:(nonnull NSString *)name descriptor:(nonnull EXJavaScriptObject *)descriptor
|
|
69
|
+
{
|
|
70
|
+
jsi::Runtime *runtime = [_runtime get];
|
|
71
|
+
jsi::Object global = runtime->global();
|
|
72
|
+
jsi::Object objectClass = global.getPropertyAsObject(*runtime, "Object");
|
|
73
|
+
jsi::Function definePropertyFunction = objectClass.getPropertyAsFunction(*runtime, "defineProperty");
|
|
74
|
+
|
|
75
|
+
// This call is basically the same as `Object.defineProperty(object, name, descriptor)` in JS
|
|
76
|
+
definePropertyFunction.callWithThis(*runtime, objectClass, {
|
|
77
|
+
jsi::Value(*runtime, *_jsObjectPtr.get()),
|
|
78
|
+
jsi::String::createFromUtf8(*runtime, [name UTF8String]),
|
|
79
|
+
std::move(*[descriptor get]),
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
65
83
|
- (void)defineProperty:(nonnull NSString *)name value:(nullable id)value options:(EXJavaScriptObjectPropertyDescriptor)options
|
|
66
84
|
{
|
|
67
85
|
jsi::Runtime *runtime = [_runtime get];
|
|
@@ -80,30 +98,31 @@
|
|
|
80
98
|
});
|
|
81
99
|
}
|
|
82
100
|
|
|
83
|
-
#pragma mark -
|
|
101
|
+
#pragma mark - WeakObject
|
|
84
102
|
|
|
85
|
-
- (
|
|
86
|
-
argsCount:(NSInteger)argsCount
|
|
87
|
-
block:(nonnull JSAsyncFunctionBlock)block
|
|
103
|
+
- (nonnull EXJavaScriptWeakObject *)createWeak
|
|
88
104
|
{
|
|
89
|
-
|
|
90
|
-
NSLog(@"Cannot set '%@' async function when the EXJavaScript runtime is no longer available.", name);
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
jsi::Function function = [_runtime createAsyncFunction:name argsCount:argsCount block:block];
|
|
94
|
-
_jsObjectPtr->setProperty(*[_runtime get], [name UTF8String], function);
|
|
105
|
+
return [[EXJavaScriptWeakObject alloc] initWith:_jsObjectPtr runtime:_runtime];
|
|
95
106
|
}
|
|
96
107
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
108
|
+
#pragma mark - Deallocator
|
|
109
|
+
|
|
110
|
+
- (void)setObjectDeallocator:(void (^)(void))deallocatorBlock
|
|
111
|
+
{
|
|
112
|
+
expo::setDeallocator(*[_runtime get], _jsObjectPtr, deallocatorBlock);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
#pragma mark - Equality
|
|
116
|
+
|
|
117
|
+
- (BOOL)isEqual:(id)object
|
|
100
118
|
{
|
|
101
|
-
if (
|
|
102
|
-
|
|
103
|
-
|
|
119
|
+
if ([object isKindOfClass:EXJavaScriptObject.class]) {
|
|
120
|
+
jsi::Runtime *runtime = [_runtime get];
|
|
121
|
+
jsi::Object *a = _jsObjectPtr.get();
|
|
122
|
+
jsi::Object *b = [object get];
|
|
123
|
+
return jsi::Object::strictEquals(*runtime, *a, *b);
|
|
104
124
|
}
|
|
105
|
-
|
|
106
|
-
_jsObjectPtr->setProperty(*[_runtime get], [name UTF8String], function);
|
|
125
|
+
return false;
|
|
107
126
|
}
|
|
108
127
|
|
|
109
128
|
#pragma mark - Private helpers
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
// Copyright 2018-present 650 Industries. All rights reserved.
|
|
2
2
|
|
|
3
|
+
#import <Foundation/Foundation.h>
|
|
3
4
|
#import <ExpoModulesCore/EXJavaScriptValue.h>
|
|
4
5
|
#import <ExpoModulesCore/EXJavaScriptObject.h>
|
|
6
|
+
#import <React/RCTBridgeModule.h>
|
|
5
7
|
|
|
6
8
|
#ifdef __cplusplus
|
|
7
9
|
#import <ReactCommon/CallInvoker.h>
|
|
@@ -13,8 +15,20 @@ namespace react = facebook::react;
|
|
|
13
15
|
@class EXJavaScriptValue;
|
|
14
16
|
@class EXJavaScriptObject;
|
|
15
17
|
|
|
18
|
+
typedef void (^JSAsyncFunctionBlock)(EXJavaScriptValue * _Nonnull thisValue,
|
|
19
|
+
NSArray<EXJavaScriptValue *> * _Nonnull arguments,
|
|
20
|
+
RCTPromiseResolveBlock _Nonnull resolve,
|
|
21
|
+
RCTPromiseRejectBlock _Nonnull reject);
|
|
22
|
+
|
|
23
|
+
typedef id _Nullable (^JSSyncFunctionBlock)(EXJavaScriptValue * _Nonnull thisValue,
|
|
24
|
+
NSArray<EXJavaScriptValue *> * _Nonnull arguments,
|
|
25
|
+
NSError * _Nullable __autoreleasing * _Nullable error);
|
|
26
|
+
|
|
16
27
|
#ifdef __cplusplus
|
|
17
|
-
typedef jsi::Value (^JSHostFunctionBlock)(jsi::Runtime &runtime,
|
|
28
|
+
typedef jsi::Value (^JSHostFunctionBlock)(jsi::Runtime &runtime,
|
|
29
|
+
std::shared_ptr<react::CallInvoker> callInvoker,
|
|
30
|
+
EXJavaScriptValue * _Nonnull thisValue,
|
|
31
|
+
NSArray<EXJavaScriptValue *> * _Nonnull arguments);
|
|
18
32
|
#endif // __cplusplus
|
|
19
33
|
|
|
20
34
|
NS_SWIFT_NAME(JavaScriptRuntime)
|
|
@@ -26,6 +40,7 @@ NS_SWIFT_NAME(JavaScriptRuntime)
|
|
|
26
40
|
- (nonnull instancetype)init;
|
|
27
41
|
|
|
28
42
|
#ifdef __cplusplus
|
|
43
|
+
|
|
29
44
|
- (nonnull instancetype)initWithRuntime:(nonnull jsi::Runtime *)runtime
|
|
30
45
|
callInvoker:(std::shared_ptr<react::CallInvoker>)callInvoker;
|
|
31
46
|
|
|
@@ -44,13 +59,6 @@ NS_SWIFT_NAME(JavaScriptRuntime)
|
|
|
44
59
|
*/
|
|
45
60
|
- (nonnull EXJavaScriptObject *)createHostObject:(std::shared_ptr<jsi::HostObject>)jsiHostObjectPtr;
|
|
46
61
|
|
|
47
|
-
- (jsi::Function)createSyncFunction:(nonnull NSString *)name
|
|
48
|
-
argsCount:(NSInteger)argsCount
|
|
49
|
-
block:(nonnull JSSyncFunctionBlock)block;
|
|
50
|
-
|
|
51
|
-
- (jsi::Function)createAsyncFunction:(nonnull NSString *)name
|
|
52
|
-
argsCount:(NSInteger)argsCount
|
|
53
|
-
block:(nonnull JSAsyncFunctionBlock)block;
|
|
54
62
|
#endif // __cplusplus
|
|
55
63
|
|
|
56
64
|
/**
|
|
@@ -63,11 +71,37 @@ NS_SWIFT_NAME(JavaScriptRuntime)
|
|
|
63
71
|
*/
|
|
64
72
|
- (nonnull EXJavaScriptObject *)createObject;
|
|
65
73
|
|
|
74
|
+
/**
|
|
75
|
+
Creates a synchronous host function that runs given block when it's called.
|
|
76
|
+
The value returned by the block is synchronously returned to JS.
|
|
77
|
+
\return A JavaScript function represented as a `JavaScriptObject`.
|
|
78
|
+
*/
|
|
79
|
+
- (nonnull EXJavaScriptObject *)createSyncFunction:(nonnull NSString *)name
|
|
80
|
+
argsCount:(NSInteger)argsCount
|
|
81
|
+
block:(nonnull JSSyncFunctionBlock)block NS_REFINED_FOR_SWIFT;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
Creates an asynchronous host function that runs given block when it's called.
|
|
85
|
+
The block receives a resolver that you should call when the asynchronous operation
|
|
86
|
+
succeeds and a rejecter to call whenever it fails.
|
|
87
|
+
\return A JavaScript function represented as a `JavaScriptObject`.
|
|
88
|
+
*/
|
|
89
|
+
- (nonnull EXJavaScriptObject *)createAsyncFunction:(nonnull NSString *)name
|
|
90
|
+
argsCount:(NSInteger)argsCount
|
|
91
|
+
block:(nonnull JSAsyncFunctionBlock)block;
|
|
92
|
+
|
|
93
|
+
#pragma mark - Classes
|
|
94
|
+
|
|
95
|
+
typedef void (^ClassConstructorBlock)(EXJavaScriptObject * _Nonnull thisValue, NSArray<EXJavaScriptValue *> * _Nonnull arguments);
|
|
96
|
+
|
|
97
|
+
- (nonnull EXJavaScriptObject *)createClass:(nonnull NSString *)name
|
|
98
|
+
constructor:(nonnull ClassConstructorBlock)constructor;
|
|
99
|
+
|
|
66
100
|
#pragma mark - Script evaluation
|
|
67
101
|
|
|
68
102
|
/**
|
|
69
103
|
Evaluates given JavaScript source code.
|
|
70
104
|
*/
|
|
71
|
-
- (nonnull EXJavaScriptValue *)evaluateScript:(nonnull NSString *)scriptSource;
|
|
105
|
+
- (nonnull EXJavaScriptValue *)evaluateScript:(nonnull NSString *)scriptSource NS_REFINED_FOR_SWIFT;
|
|
72
106
|
|
|
73
107
|
@end
|
|
@@ -82,33 +82,66 @@ using namespace facebook;
|
|
|
82
82
|
return [[EXJavaScriptObject alloc] initWith:jsGlobalPtr runtime:self];
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
- (
|
|
86
|
-
|
|
87
|
-
|
|
85
|
+
- (nonnull EXJavaScriptObject *)createSyncFunction:(nonnull NSString *)name
|
|
86
|
+
argsCount:(NSInteger)argsCount
|
|
87
|
+
block:(nonnull JSSyncFunctionBlock)block
|
|
88
88
|
{
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
89
|
+
JSHostFunctionBlock hostFunctionBlock = ^jsi::Value(
|
|
90
|
+
jsi::Runtime &runtime,
|
|
91
|
+
std::shared_ptr<react::CallInvoker> callInvoker,
|
|
92
|
+
EXJavaScriptValue * _Nonnull thisValue,
|
|
93
|
+
NSArray<EXJavaScriptValue *> * _Nonnull arguments) {
|
|
94
|
+
NSError *error;
|
|
95
|
+
id result = block(thisValue, arguments, &error);
|
|
96
|
+
|
|
97
|
+
if (error == nil) {
|
|
98
|
+
return expo::convertObjCObjectToJSIValue(runtime, result);
|
|
99
|
+
} else {
|
|
100
|
+
throw jsi::JSError(runtime, [error.userInfo[@"message"] UTF8String]);
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
return [self createHostFunction:name argsCount:argsCount block:hostFunctionBlock];
|
|
92
104
|
}
|
|
93
105
|
|
|
94
|
-
- (
|
|
95
|
-
|
|
96
|
-
|
|
106
|
+
- (nonnull EXJavaScriptObject *)createAsyncFunction:(nonnull NSString *)name
|
|
107
|
+
argsCount:(NSInteger)argsCount
|
|
108
|
+
block:(nonnull JSAsyncFunctionBlock)block
|
|
97
109
|
{
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
110
|
+
JSHostFunctionBlock hostFunctionBlock = ^jsi::Value(
|
|
111
|
+
jsi::Runtime &runtime,
|
|
112
|
+
std::shared_ptr<react::CallInvoker> callInvoker,
|
|
113
|
+
EXJavaScriptValue * _Nonnull thisValue,
|
|
114
|
+
NSArray<EXJavaScriptValue *> * _Nonnull arguments) {
|
|
115
|
+
if (!callInvoker) {
|
|
116
|
+
// In mocked environment the call invoker may be null so it's not supported to call async functions.
|
|
117
|
+
// Testing async functions is a bit more complicated anyway. See `init` description for more.
|
|
118
|
+
throw jsi::JSError(runtime, "Calling async functions is not supported when the call invoker is unavailable");
|
|
119
|
+
}
|
|
120
|
+
// The function that is invoked as a setup of the EXJavaScript `Promise`.
|
|
121
|
+
auto promiseSetup = [callInvoker, block, thisValue, arguments](jsi::Runtime &runtime, std::shared_ptr<Promise> promise) {
|
|
122
|
+
expo::callPromiseSetupWithBlock(runtime, callInvoker, promise, ^(RCTPromiseResolveBlock resolver, RCTPromiseRejectBlock rejecter) {
|
|
123
|
+
block(thisValue, arguments, resolver, rejecter);
|
|
124
|
+
});
|
|
125
|
+
};
|
|
126
|
+
return createPromiseAsJSIValue(runtime, promiseSetup);
|
|
109
127
|
};
|
|
110
|
-
|
|
111
|
-
|
|
128
|
+
return [self createHostFunction:name argsCount:argsCount block:hostFunctionBlock];
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
#pragma mark - Classes
|
|
132
|
+
|
|
133
|
+
- (nonnull EXJavaScriptObject *)createClass:(nonnull NSString *)name
|
|
134
|
+
constructor:(nonnull ClassConstructorBlock)constructor
|
|
135
|
+
{
|
|
136
|
+
expo::ClassConstructor jsConstructor = [self, constructor](jsi::Runtime &runtime, const jsi::Value &thisValue, const jsi::Value *args, size_t count) {
|
|
137
|
+
std::shared_ptr<jsi::Object> thisPtr = std::make_shared<jsi::Object>(thisValue.asObject(runtime));
|
|
138
|
+
EXJavaScriptObject *caller = [[EXJavaScriptObject alloc] initWith:thisPtr runtime:self];
|
|
139
|
+
NSArray<EXJavaScriptValue *> *arguments = expo::convertJSIValuesToNSArray(self, args, count);
|
|
140
|
+
|
|
141
|
+
constructor(caller, arguments);
|
|
142
|
+
};
|
|
143
|
+
std::shared_ptr<jsi::Function> klass = expo::createClass(*_runtime, [name UTF8String], jsConstructor);
|
|
144
|
+
return [[EXJavaScriptObject alloc] initWith:klass runtime:self];
|
|
112
145
|
}
|
|
113
146
|
|
|
114
147
|
#pragma mark - Script evaluation
|
|
@@ -128,15 +161,21 @@ using namespace facebook;
|
|
|
128
161
|
@"message": reason,
|
|
129
162
|
@"stack": stack,
|
|
130
163
|
}];
|
|
164
|
+
} catch (jsi::JSIException &error) {
|
|
165
|
+
NSString *reason = [NSString stringWithUTF8String:error.what()];
|
|
166
|
+
|
|
167
|
+
@throw [NSException exceptionWithName:@"ScriptEvaluationException" reason:reason userInfo:@{
|
|
168
|
+
@"message": reason
|
|
169
|
+
}];
|
|
131
170
|
}
|
|
132
171
|
return [[EXJavaScriptValue alloc] initWithRuntime:self value:result];
|
|
133
172
|
}
|
|
134
173
|
|
|
135
174
|
#pragma mark - Private
|
|
136
175
|
|
|
137
|
-
- (
|
|
138
|
-
|
|
139
|
-
|
|
176
|
+
- (nonnull EXJavaScriptObject *)createHostFunction:(nonnull NSString *)name
|
|
177
|
+
argsCount:(NSInteger)argsCount
|
|
178
|
+
block:(nonnull JSHostFunctionBlock)block
|
|
140
179
|
{
|
|
141
180
|
jsi::PropNameID propNameId = jsi::PropNameID::forAscii(*_runtime, [name UTF8String], [name length]);
|
|
142
181
|
std::weak_ptr<react::CallInvoker> weakCallInvoker = _jsCallInvoker;
|
|
@@ -145,9 +184,13 @@ using namespace facebook;
|
|
|
145
184
|
// there is no need to care about that for synchronous calls, so it's ensured in `createAsyncFunction` instead.
|
|
146
185
|
auto callInvoker = weakCallInvoker.lock();
|
|
147
186
|
NSArray<EXJavaScriptValue *> *arguments = expo::convertJSIValuesToNSArray(self, args, count);
|
|
148
|
-
|
|
187
|
+
std::shared_ptr<jsi::Value> thisValPtr = std::make_shared<jsi::Value>(runtime, std::move(thisVal));
|
|
188
|
+
EXJavaScriptValue *thisValue = [[EXJavaScriptValue alloc] initWithRuntime:self value:thisValPtr];
|
|
189
|
+
|
|
190
|
+
return block(runtime, callInvoker, thisValue, arguments);
|
|
149
191
|
};
|
|
150
|
-
|
|
192
|
+
std::shared_ptr<jsi::Object> fnPtr = std::make_shared<jsi::Object>(jsi::Function::createFromHostFunction(*_runtime, propNameId, (unsigned int)argsCount, function));
|
|
193
|
+
return [[EXJavaScriptObject alloc] initWith:fnPtr runtime:self];
|
|
151
194
|
}
|
|
152
195
|
|
|
153
196
|
@end
|