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
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// Copyright © 2021-present 650 Industries, Inc. (aka Expo)
|
|
2
|
+
|
|
3
|
+
#pragma once
|
|
4
|
+
|
|
5
|
+
#include "JSIObjectWrapper.h"
|
|
6
|
+
|
|
7
|
+
#include <fbjni/fbjni.h>
|
|
8
|
+
#include <jsi/jsi.h>
|
|
9
|
+
|
|
10
|
+
#include <memory>
|
|
11
|
+
|
|
12
|
+
namespace jni = facebook::jni;
|
|
13
|
+
namespace jsi = facebook::jsi;
|
|
14
|
+
|
|
15
|
+
namespace expo {
|
|
16
|
+
class JavaScriptRuntime;
|
|
17
|
+
|
|
18
|
+
class JavaScriptObject;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Represents any JavaScript value. Its purpose is to expose the `jsi::Value` API back to Kotlin.
|
|
22
|
+
*/
|
|
23
|
+
class JavaScriptValue : public jni::HybridClass<JavaScriptValue>, JSIValueWrapper {
|
|
24
|
+
public:
|
|
25
|
+
static auto constexpr
|
|
26
|
+
kJavaDescriptor = "Lexpo/modules/kotlin/jni/JavaScriptValue;";
|
|
27
|
+
static auto constexpr TAG = "JavaScriptValue";
|
|
28
|
+
|
|
29
|
+
static void registerNatives();
|
|
30
|
+
|
|
31
|
+
JavaScriptValue(
|
|
32
|
+
std::weak_ptr<JavaScriptRuntime> runtime,
|
|
33
|
+
std::shared_ptr<jsi::Value> jsValue
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
std::shared_ptr<jsi::Value> get() override;
|
|
37
|
+
|
|
38
|
+
std::string kind();
|
|
39
|
+
|
|
40
|
+
bool isNull();
|
|
41
|
+
|
|
42
|
+
bool isUndefined();
|
|
43
|
+
|
|
44
|
+
bool isBool();
|
|
45
|
+
|
|
46
|
+
bool isNumber();
|
|
47
|
+
|
|
48
|
+
bool isString();
|
|
49
|
+
|
|
50
|
+
bool isSymbol();
|
|
51
|
+
|
|
52
|
+
bool isFunction();
|
|
53
|
+
|
|
54
|
+
bool isArray();
|
|
55
|
+
|
|
56
|
+
bool isObject();
|
|
57
|
+
|
|
58
|
+
bool getBool();
|
|
59
|
+
|
|
60
|
+
double getDouble();
|
|
61
|
+
|
|
62
|
+
std::string getString();
|
|
63
|
+
|
|
64
|
+
jni::local_ref<jni::HybridClass<JavaScriptObject>::javaobject> getObject();
|
|
65
|
+
|
|
66
|
+
jni::local_ref<jni::JArrayClass<JavaScriptValue::javaobject>> getArray();
|
|
67
|
+
|
|
68
|
+
private:
|
|
69
|
+
friend HybridBase;
|
|
70
|
+
|
|
71
|
+
std::weak_ptr<JavaScriptRuntime> runtimeHolder;
|
|
72
|
+
std::shared_ptr<jsi::Value> jsValue;
|
|
73
|
+
|
|
74
|
+
jni::local_ref<jstring> jniKind();
|
|
75
|
+
|
|
76
|
+
jni::local_ref<jstring> jniGetString();
|
|
77
|
+
};
|
|
78
|
+
} // namespace expo
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
#include "MethodMetadata.h"
|
|
2
|
+
|
|
3
|
+
#include "JSIInteropModuleRegistry.h"
|
|
4
|
+
|
|
5
|
+
namespace jni = facebook::jni;
|
|
6
|
+
namespace jsi = facebook::jsi;
|
|
7
|
+
namespace react = facebook::react;
|
|
8
|
+
|
|
9
|
+
namespace expo {
|
|
10
|
+
|
|
11
|
+
// Modified version of the RN implementation
|
|
12
|
+
// https://github.com/facebook/react-native/blob/7dceb9b63c0bfd5b13bf6d26f9530729506e9097/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaTurboModule.cpp#L57
|
|
13
|
+
jni::local_ref<react::JCxxCallbackImpl::JavaPart> createJavaCallbackFromJSIFunction(
|
|
14
|
+
jsi::Function &&function,
|
|
15
|
+
jsi::Runtime &rt,
|
|
16
|
+
std::shared_ptr<react::CallInvoker> jsInvoker
|
|
17
|
+
) {
|
|
18
|
+
auto weakWrapper = react::CallbackWrapper::createWeak(std::move(function), rt,
|
|
19
|
+
std::move(jsInvoker));
|
|
20
|
+
|
|
21
|
+
// This needs to be a shared_ptr because:
|
|
22
|
+
// 1. It cannot be unique_ptr. std::function is copyable but unique_ptr is
|
|
23
|
+
// not.
|
|
24
|
+
// 2. It cannot be weak_ptr since we need this object to live on.
|
|
25
|
+
// 3. It cannot be a value, because that would be deleted as soon as this
|
|
26
|
+
// function returns.
|
|
27
|
+
auto callbackWrapperOwner =
|
|
28
|
+
std::make_shared<react::RAIICallbackWrapperDestroyer>(weakWrapper);
|
|
29
|
+
|
|
30
|
+
std::function<void(folly::dynamic)> fn =
|
|
31
|
+
[weakWrapper, callbackWrapperOwner, wrapperWasCalled = false](
|
|
32
|
+
folly::dynamic responses) mutable {
|
|
33
|
+
if (wrapperWasCalled) {
|
|
34
|
+
throw std::runtime_error(
|
|
35
|
+
"callback 2 arg cannot be called more than once");
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
auto strongWrapper = weakWrapper.lock();
|
|
39
|
+
if (!strongWrapper) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
strongWrapper->jsInvoker().invokeAsync(
|
|
44
|
+
[weakWrapper, callbackWrapperOwner, responses]() mutable {
|
|
45
|
+
auto strongWrapper2 = weakWrapper.lock();
|
|
46
|
+
if (!strongWrapper2) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
jsi::Value args =
|
|
51
|
+
jsi::valueFromDynamic(strongWrapper2->runtime(), responses);
|
|
52
|
+
auto argsArray = args.getObject(strongWrapper2->runtime())
|
|
53
|
+
.asArray(strongWrapper2->runtime());
|
|
54
|
+
jsi::Value arg = argsArray.getValueAtIndex(strongWrapper2->runtime(), 0);
|
|
55
|
+
|
|
56
|
+
strongWrapper2->callback().call(
|
|
57
|
+
strongWrapper2->runtime(),
|
|
58
|
+
(const jsi::Value *) &arg,
|
|
59
|
+
(size_t) 1
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
callbackWrapperOwner.reset();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
wrapperWasCalled = true;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
return react::JCxxCallbackImpl::newObjectCxxArgs(fn);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
MethodMetadata::MethodMetadata(
|
|
72
|
+
std::string name,
|
|
73
|
+
int args,
|
|
74
|
+
bool isAsync,
|
|
75
|
+
jni::global_ref<jobject> &&jBodyReference
|
|
76
|
+
) : name(name),
|
|
77
|
+
args(args),
|
|
78
|
+
isAsync(isAsync),
|
|
79
|
+
jBodyReference(jBodyReference) {}
|
|
80
|
+
|
|
81
|
+
std::shared_ptr<jsi::Function> MethodMetadata::toJSFunction(
|
|
82
|
+
jsi::Runtime &runtime,
|
|
83
|
+
JSIInteropModuleRegistry *moduleRegistry
|
|
84
|
+
) {
|
|
85
|
+
if (body == nullptr) {
|
|
86
|
+
if (isAsync) {
|
|
87
|
+
body = std::make_shared<jsi::Function>(toAsyncFunction(runtime, moduleRegistry));
|
|
88
|
+
} else {
|
|
89
|
+
body = std::make_shared<jsi::Function>(toSyncFunction(runtime));
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return body;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
jsi::Function MethodMetadata::toSyncFunction(jsi::Runtime &runtime) {
|
|
97
|
+
return jsi::Function::createFromHostFunction(
|
|
98
|
+
runtime,
|
|
99
|
+
jsi::PropNameID::forAscii(runtime, name),
|
|
100
|
+
args,
|
|
101
|
+
[this](
|
|
102
|
+
jsi::Runtime &rt,
|
|
103
|
+
const jsi::Value &thisValue,
|
|
104
|
+
const jsi::Value *args,
|
|
105
|
+
size_t count
|
|
106
|
+
) -> jsi::Value {
|
|
107
|
+
auto dynamicArray = folly::dynamic::array();
|
|
108
|
+
for (int i = 0; i < count; i++) {
|
|
109
|
+
auto &arg = args[i];
|
|
110
|
+
dynamicArray.push_back(jsi::dynamicFromValue(rt, arg));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Cast in this place is safe, cause we know that this function is promise-less.
|
|
114
|
+
auto syncFunction = jni::static_ref_cast<JNIFunctionBody>(this->jBodyReference);
|
|
115
|
+
auto result = syncFunction->invoke(
|
|
116
|
+
react::ReadableNativeArray::newObjectCxxArgs(std::move(dynamicArray)).get()
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
if (result == nullptr) {
|
|
120
|
+
return jsi::Value::undefined();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return jsi::valueFromDynamic(rt, result->cthis()->consume())
|
|
124
|
+
.asObject(rt)
|
|
125
|
+
.asArray(rt)
|
|
126
|
+
.getValueAtIndex(rt, 0);
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
jsi::Function MethodMetadata::toAsyncFunction(
|
|
131
|
+
jsi::Runtime &runtime,
|
|
132
|
+
JSIInteropModuleRegistry *moduleRegistry
|
|
133
|
+
) {
|
|
134
|
+
return jsi::Function::createFromHostFunction(
|
|
135
|
+
runtime,
|
|
136
|
+
jsi::PropNameID::forAscii(runtime, name),
|
|
137
|
+
args,
|
|
138
|
+
[this, moduleRegistry](
|
|
139
|
+
jsi::Runtime &rt,
|
|
140
|
+
const jsi::Value &thisValue,
|
|
141
|
+
const jsi::Value *args,
|
|
142
|
+
size_t count
|
|
143
|
+
) -> jsi::Value {
|
|
144
|
+
auto dynamicArray = folly::dynamic::array();
|
|
145
|
+
for (int i = 0; i < count; i++) {
|
|
146
|
+
auto &arg = args[i];
|
|
147
|
+
dynamicArray.push_back(jsi::dynamicFromValue(rt, arg));
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
auto Promise = rt.global().getPropertyAsFunction(rt, "Promise");
|
|
151
|
+
// Creates a JSI promise
|
|
152
|
+
jsi::Value promise = Promise.callAsConstructor(
|
|
153
|
+
rt,
|
|
154
|
+
createPromiseBody(rt, moduleRegistry, std::move(dynamicArray))
|
|
155
|
+
);
|
|
156
|
+
return promise;
|
|
157
|
+
}
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
jsi::Function MethodMetadata::createPromiseBody(
|
|
162
|
+
jsi::Runtime &runtime,
|
|
163
|
+
JSIInteropModuleRegistry *moduleRegistry,
|
|
164
|
+
folly::dynamic &&args
|
|
165
|
+
) {
|
|
166
|
+
return jsi::Function::createFromHostFunction(
|
|
167
|
+
runtime,
|
|
168
|
+
jsi::PropNameID::forAscii(runtime, "promiseFn"),
|
|
169
|
+
2,
|
|
170
|
+
[this, args = std::move(args), moduleRegistry](
|
|
171
|
+
jsi::Runtime &rt,
|
|
172
|
+
const jsi::Value &thisVal,
|
|
173
|
+
const jsi::Value *promiseConstructorArgs,
|
|
174
|
+
size_t promiseConstructorArgCount
|
|
175
|
+
) {
|
|
176
|
+
if (promiseConstructorArgCount != 2) {
|
|
177
|
+
throw std::invalid_argument("Promise fn arg count must be 2");
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
jsi::Function resolveJSIFn = promiseConstructorArgs[0].getObject(rt).getFunction(rt);
|
|
181
|
+
jsi::Function rejectJSIFn = promiseConstructorArgs[1].getObject(rt).getFunction(rt);
|
|
182
|
+
|
|
183
|
+
auto &runtimeHolder = moduleRegistry->runtimeHolder;
|
|
184
|
+
jobject resolve = createJavaCallbackFromJSIFunction(
|
|
185
|
+
std::move(resolveJSIFn),
|
|
186
|
+
rt,
|
|
187
|
+
runtimeHolder->jsInvoker
|
|
188
|
+
).release();
|
|
189
|
+
|
|
190
|
+
jobject reject = createJavaCallbackFromJSIFunction(
|
|
191
|
+
std::move(rejectJSIFn),
|
|
192
|
+
rt,
|
|
193
|
+
runtimeHolder->jsInvoker
|
|
194
|
+
).release();
|
|
195
|
+
|
|
196
|
+
JNIEnv *env = jni::Environment::current();
|
|
197
|
+
|
|
198
|
+
jclass jPromiseImpl =
|
|
199
|
+
env->FindClass("com/facebook/react/bridge/PromiseImpl");
|
|
200
|
+
jmethodID jPromiseImplConstructor = env->GetMethodID(
|
|
201
|
+
jPromiseImpl,
|
|
202
|
+
"<init>",
|
|
203
|
+
"(Lcom/facebook/react/bridge/Callback;Lcom/facebook/react/bridge/Callback;)V");
|
|
204
|
+
|
|
205
|
+
// Creates a promise object
|
|
206
|
+
jobject promise = env->NewObject(
|
|
207
|
+
jPromiseImpl,
|
|
208
|
+
jPromiseImplConstructor,
|
|
209
|
+
resolve,
|
|
210
|
+
reject
|
|
211
|
+
);
|
|
212
|
+
|
|
213
|
+
// Cast in this place is safe, cause we know that this function expects promise.
|
|
214
|
+
auto asyncFunction = jni::static_ref_cast<JNIAsyncFunctionBody>(this->jBodyReference);
|
|
215
|
+
asyncFunction->invoke(
|
|
216
|
+
react::ReadableNativeArray::newObjectCxxArgs(args).get(),
|
|
217
|
+
promise
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
// We have to remove the local reference to the promise object.
|
|
221
|
+
// It doesn't mean that the promise will be deallocated, but rather that we move
|
|
222
|
+
// the ownership to the `JNIAsyncFunctionBody`.
|
|
223
|
+
env->DeleteLocalRef(promise);
|
|
224
|
+
|
|
225
|
+
return jsi::Value::undefined();
|
|
226
|
+
}
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
} // namespace expo
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// Copyright © 2021-present 650 Industries, Inc. (aka Expo)
|
|
2
|
+
|
|
3
|
+
#pragma once
|
|
4
|
+
|
|
5
|
+
#include <jsi/jsi.h>
|
|
6
|
+
#include <fbjni/fbjni.h>
|
|
7
|
+
#include <ReactCommon/TurboModuleUtils.h>
|
|
8
|
+
#include <react/jni/ReadableNativeArray.h>
|
|
9
|
+
#include <memory>
|
|
10
|
+
#include <folly/dynamic.h>
|
|
11
|
+
#include <jsi/JSIDynamic.h>
|
|
12
|
+
|
|
13
|
+
namespace jni = facebook::jni;
|
|
14
|
+
namespace jsi = facebook::jsi;
|
|
15
|
+
namespace react = facebook::react;
|
|
16
|
+
|
|
17
|
+
namespace expo {
|
|
18
|
+
class JSIInteropModuleRegistry;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* A class that holds information about the exported function.
|
|
22
|
+
*/
|
|
23
|
+
class MethodMetadata {
|
|
24
|
+
public:
|
|
25
|
+
/**
|
|
26
|
+
* Function name
|
|
27
|
+
*/
|
|
28
|
+
std::string name;
|
|
29
|
+
/**
|
|
30
|
+
* Number of arguments
|
|
31
|
+
*/
|
|
32
|
+
int args;
|
|
33
|
+
/*
|
|
34
|
+
* Whether this function is async
|
|
35
|
+
*/
|
|
36
|
+
bool isAsync;
|
|
37
|
+
|
|
38
|
+
MethodMetadata(
|
|
39
|
+
std::string name,
|
|
40
|
+
int args,
|
|
41
|
+
bool isAsync,
|
|
42
|
+
jni::global_ref<jobject> &&jBodyReference
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
// We deleted the copy contractor to not deal with transforming the ownership of the `jBodyReference`.
|
|
46
|
+
MethodMetadata(const MethodMetadata &) = delete;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* MethodMetadata owns the only reference to the Kotlin function.
|
|
50
|
+
* We have to clean that, cause it's a `global_ref`.
|
|
51
|
+
*/
|
|
52
|
+
~MethodMetadata() {
|
|
53
|
+
jBodyReference.release();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Transforms metadata to a jsi::Function.
|
|
58
|
+
*
|
|
59
|
+
* @param runtime
|
|
60
|
+
* @param moduleRegistry
|
|
61
|
+
* @return shared ptr to the jsi::Function that wrapped the underlying Kotlin's function.
|
|
62
|
+
*/
|
|
63
|
+
std::shared_ptr<jsi::Function> toJSFunction(
|
|
64
|
+
jsi::Runtime &runtime,
|
|
65
|
+
JSIInteropModuleRegistry *moduleRegistry
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
private:
|
|
69
|
+
/**
|
|
70
|
+
* Reference to one of two java objects - `JNIFunctionBody` or `JNIAsyncFunctionBody`.
|
|
71
|
+
*
|
|
72
|
+
* In case when `isAsync` is `true`, this variable will point to `JNIAsyncFunctionBody`.
|
|
73
|
+
* Otherwise to `JNIFunctionBody`
|
|
74
|
+
*/
|
|
75
|
+
jni::global_ref<jobject> jBodyReference;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* To not create a jsi::Function always when we need it, we cached that value.
|
|
79
|
+
*/
|
|
80
|
+
std::shared_ptr<jsi::Function> body = nullptr;
|
|
81
|
+
|
|
82
|
+
jsi::Function toSyncFunction(jsi::Runtime &runtime);
|
|
83
|
+
|
|
84
|
+
jsi::Function toAsyncFunction(jsi::Runtime &runtime, JSIInteropModuleRegistry *moduleRegistry);
|
|
85
|
+
|
|
86
|
+
jsi::Function createPromiseBody(
|
|
87
|
+
jsi::Runtime &runtime,
|
|
88
|
+
JSIInteropModuleRegistry *moduleRegistry,
|
|
89
|
+
folly::dynamic &&args
|
|
90
|
+
);
|
|
91
|
+
};
|
|
92
|
+
} // namespace expo
|
|
@@ -92,6 +92,8 @@ public class NativeModulesProxy extends ReactContextBaseJavaModule {
|
|
|
92
92
|
@Override
|
|
93
93
|
public Map<String, Object> getConstants() {
|
|
94
94
|
mModuleRegistry.ensureIsInitialized();
|
|
95
|
+
getKotlinInteropModuleRegistry().installJSIInterop();
|
|
96
|
+
|
|
95
97
|
Collection<ExportedModule> exportedModules = mModuleRegistry.getAllExportedModules();
|
|
96
98
|
Collection<ViewManager> viewManagers = mModuleRegistry.getAllViewManagers();
|
|
97
99
|
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
package expo.modules.core.errors
|
|
2
|
+
|
|
3
|
+
import kotlinx.coroutines.CancellationException
|
|
4
|
+
|
|
5
|
+
private const val DEFAULT_MESSAGE = "App context destroyed. All coroutines are cancelled."
|
|
6
|
+
|
|
7
|
+
class ContextDestroyedException(message: String = DEFAULT_MESSAGE) : CancellationException(message)
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
package expo.modules.interfaces.permissions;
|
|
2
2
|
|
|
3
|
+
import androidx.annotation.NonNull;
|
|
4
|
+
import androidx.annotation.Nullable;
|
|
3
5
|
import expo.modules.core.Promise;
|
|
4
6
|
|
|
5
7
|
public interface Permissions {
|
|
@@ -12,6 +14,20 @@ public interface Permissions {
|
|
|
12
14
|
permissionsManager.getPermissionsWithPromise(promise, permissions);
|
|
13
15
|
}
|
|
14
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Compatibility method that accepts expo.modules.kotlin.Promise, but forward the logic to the other method
|
|
19
|
+
*/
|
|
20
|
+
static void getPermissionsWithPermissionsManager(
|
|
21
|
+
@Nullable Permissions permissionsManager,
|
|
22
|
+
@NonNull final expo.modules.kotlin.Promise promise,
|
|
23
|
+
@NonNull String... permissions
|
|
24
|
+
) {
|
|
25
|
+
getPermissionsWithPermissionsManager(permissionsManager, new Promise() {
|
|
26
|
+
@Override public void resolve(Object value) { promise.resolve(value); }
|
|
27
|
+
@Override public void reject(String c, String m, Throwable e) { promise.reject(c, m, e); }
|
|
28
|
+
}, permissions);
|
|
29
|
+
}
|
|
30
|
+
|
|
15
31
|
static void askForPermissionsWithPermissionsManager(Permissions permissionsManager, final Promise promise, String... permissions) {
|
|
16
32
|
if (permissionsManager == null) {
|
|
17
33
|
promise.reject("E_NO_PERMISSIONS", "Permissions module is null. Are you sure all the installed Expo modules are properly linked?");
|
|
@@ -20,6 +36,20 @@ public interface Permissions {
|
|
|
20
36
|
permissionsManager.askForPermissionsWithPromise(promise, permissions);
|
|
21
37
|
}
|
|
22
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Compatibility method that accepts expo.modules.kotlin.Promise, but forward the logic to the other method
|
|
41
|
+
*/
|
|
42
|
+
static void askForPermissionsWithPermissionsManager(
|
|
43
|
+
@Nullable Permissions permissionsManager,
|
|
44
|
+
@NonNull final expo.modules.kotlin.Promise promise,
|
|
45
|
+
@NonNull String... permissions
|
|
46
|
+
) {
|
|
47
|
+
askForPermissionsWithPermissionsManager(permissionsManager, new Promise() {
|
|
48
|
+
@Override public void resolve(Object value) { promise.resolve(value); }
|
|
49
|
+
@Override public void reject(String c, String m, Throwable e) { promise.reject(c, m, e); }
|
|
50
|
+
}, permissions);
|
|
51
|
+
}
|
|
52
|
+
|
|
23
53
|
void getPermissionsWithPromise(final Promise promise, String... permissions);
|
|
24
54
|
|
|
25
55
|
void getPermissions(final PermissionsResponseListener response, String... permissions);
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
+
@file:OptIn(DelicateCoroutinesApi::class)
|
|
2
|
+
|
|
1
3
|
package expo.modules.kotlin
|
|
2
4
|
|
|
3
5
|
import android.app.Activity
|
|
4
6
|
import android.content.Context
|
|
5
7
|
import android.content.Intent
|
|
8
|
+
import androidx.appcompat.app.AppCompatActivity
|
|
6
9
|
import com.facebook.react.bridge.ReactApplicationContext
|
|
10
|
+
import com.facebook.react.turbomodule.core.CallInvokerHolderImpl
|
|
11
|
+
import expo.modules.core.errors.ContextDestroyedException
|
|
7
12
|
import expo.modules.core.interfaces.ActivityProvider
|
|
8
13
|
import expo.modules.interfaces.barcodescanner.BarCodeScannerInterface
|
|
9
14
|
import expo.modules.interfaces.camera.CameraViewInterface
|
|
@@ -20,19 +25,34 @@ import expo.modules.kotlin.events.EventName
|
|
|
20
25
|
import expo.modules.kotlin.events.KEventEmitterWrapper
|
|
21
26
|
import expo.modules.kotlin.events.KModuleEventEmitterWrapper
|
|
22
27
|
import expo.modules.kotlin.events.OnActivityResultPayload
|
|
28
|
+
import expo.modules.kotlin.jni.JSIInteropModuleRegistry
|
|
23
29
|
import expo.modules.kotlin.modules.Module
|
|
30
|
+
import expo.modules.kotlin.providers.CurrentActivityProvider
|
|
31
|
+
import kotlinx.coroutines.CoroutineName
|
|
32
|
+
import kotlinx.coroutines.CoroutineScope
|
|
33
|
+
import kotlinx.coroutines.DelicateCoroutinesApi
|
|
34
|
+
import kotlinx.coroutines.SupervisorJob
|
|
35
|
+
import kotlinx.coroutines.cancel
|
|
36
|
+
import kotlinx.coroutines.newSingleThreadContext
|
|
24
37
|
import java.lang.ref.WeakReference
|
|
25
38
|
|
|
26
39
|
class AppContext(
|
|
27
40
|
modulesProvider: ModulesProvider,
|
|
28
41
|
val legacyModuleRegistry: expo.modules.core.ModuleRegistry,
|
|
29
42
|
private val reactContextHolder: WeakReference<ReactApplicationContext>
|
|
30
|
-
) {
|
|
43
|
+
) : CurrentActivityProvider {
|
|
31
44
|
val registry = ModuleRegistry(WeakReference(this)).apply {
|
|
32
45
|
register(ErrorManagerModule())
|
|
33
46
|
register(modulesProvider)
|
|
34
47
|
}
|
|
35
48
|
private val reactLifecycleDelegate = ReactLifecycleDelegate(this)
|
|
49
|
+
// We postpone creating the `JSIInteropModuleRegistry` to not load so files in unit tests.
|
|
50
|
+
private lateinit var jsiInterop: JSIInteropModuleRegistry
|
|
51
|
+
internal val modulesQueue = CoroutineScope(
|
|
52
|
+
newSingleThreadContext("ExpoModulesCoreQueue") +
|
|
53
|
+
SupervisorJob() +
|
|
54
|
+
CoroutineName("ExpoModulesCoreCoroutineQueue")
|
|
55
|
+
)
|
|
36
56
|
|
|
37
57
|
init {
|
|
38
58
|
requireNotNull(reactContextHolder.get()) {
|
|
@@ -43,6 +63,18 @@ class AppContext(
|
|
|
43
63
|
}
|
|
44
64
|
}
|
|
45
65
|
|
|
66
|
+
fun installJSIInterop() {
|
|
67
|
+
jsiInterop = JSIInteropModuleRegistry(this)
|
|
68
|
+
val reactContext = reactContextHolder.get() ?: return
|
|
69
|
+
reactContext.javaScriptContextHolder?.get()?.let {
|
|
70
|
+
jsiInterop.installJSI(
|
|
71
|
+
it,
|
|
72
|
+
reactContext.catalystInstance.jsCallInvokerHolder as CallInvokerHolderImpl,
|
|
73
|
+
reactContext.catalystInstance.nativeCallInvokerHolder as CallInvokerHolderImpl
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
46
78
|
/**
|
|
47
79
|
* Returns a legacy module implementing given interface.
|
|
48
80
|
*/
|
|
@@ -149,6 +181,7 @@ class AppContext(
|
|
|
149
181
|
reactContextHolder.get()?.removeLifecycleEventListener(reactLifecycleDelegate)
|
|
150
182
|
registry.post(EventName.MODULE_DESTROY)
|
|
151
183
|
registry.cleanUp()
|
|
184
|
+
modulesQueue.cancel(ContextDestroyedException())
|
|
152
185
|
}
|
|
153
186
|
|
|
154
187
|
fun onHostResume() {
|
|
@@ -181,4 +214,19 @@ class AppContext(
|
|
|
181
214
|
intent
|
|
182
215
|
)
|
|
183
216
|
}
|
|
217
|
+
|
|
218
|
+
// region CurrentActivityProvider
|
|
219
|
+
|
|
220
|
+
override val currentActivity: AppCompatActivity?
|
|
221
|
+
get() {
|
|
222
|
+
val currentActivity = this.activityProvider?.currentActivity ?: return null
|
|
223
|
+
|
|
224
|
+
check(currentActivity is AppCompatActivity) {
|
|
225
|
+
"Current Activity is of incorrect class, expected AppCompatActivity, received ${currentActivity.localClassName}"
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return currentActivity
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// endregion
|
|
184
232
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
package expo.modules.kotlin
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Simple iterator that will merge two other iterators.
|
|
5
|
+
*/
|
|
6
|
+
class ConcatIterator<T>(
|
|
7
|
+
private val first: Iterator<T>,
|
|
8
|
+
private val second: Iterator<T>
|
|
9
|
+
) : Iterator<T> {
|
|
10
|
+
override fun hasNext(): Boolean = first.hasNext() || second.hasNext()
|
|
11
|
+
|
|
12
|
+
override fun next(): T =
|
|
13
|
+
if (first.hasNext()) {
|
|
14
|
+
first.next()
|
|
15
|
+
} else {
|
|
16
|
+
second.next()
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -41,26 +41,25 @@ class KotlinInteropModuleRegistry(
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
fun exportedModulesConstants(): Map<ModuleName, ModuleConstants> {
|
|
44
|
-
return registry
|
|
45
|
-
.
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
.toMap()
|
|
44
|
+
return registry.associate { holder ->
|
|
45
|
+
holder.name to holder.definition.constantsProvider()
|
|
46
|
+
}
|
|
49
47
|
}
|
|
50
48
|
|
|
51
49
|
fun exportMethods(exportKey: (String, List<ModuleMethodInfo>) -> Unit = { _, _ -> }): Map<ModuleName, List<ModuleMethodInfo>> {
|
|
52
|
-
return registry
|
|
53
|
-
|
|
54
|
-
|
|
50
|
+
return registry.associate { holder ->
|
|
51
|
+
val methodsInfo = holder
|
|
52
|
+
.definition
|
|
53
|
+
.asyncFunctions
|
|
54
|
+
.map { (name, method) ->
|
|
55
55
|
mapOf(
|
|
56
56
|
"name" to name,
|
|
57
57
|
"argumentsCount" to method.argsCount
|
|
58
58
|
)
|
|
59
59
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
.toMap()
|
|
60
|
+
exportKey(holder.name, methodsInfo)
|
|
61
|
+
holder.name to methodsInfo
|
|
62
|
+
}
|
|
64
63
|
}
|
|
65
64
|
|
|
66
65
|
fun exportViewManagers(): List<ViewManager<*, *>> {
|
|
@@ -110,4 +109,8 @@ class KotlinInteropModuleRegistry(
|
|
|
110
109
|
fun onDestroy() {
|
|
111
110
|
appContext.onDestroy()
|
|
112
111
|
}
|
|
112
|
+
|
|
113
|
+
fun installJSIInterop() {
|
|
114
|
+
appContext.installJSIInterop()
|
|
115
|
+
}
|
|
113
116
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
package expo.modules.kotlin
|
|
2
2
|
|
|
3
|
+
import com.facebook.react.bridge.Arguments
|
|
3
4
|
import com.facebook.react.bridge.ReadableArray
|
|
4
5
|
import expo.modules.kotlin.events.BasicEventListener
|
|
5
6
|
import expo.modules.kotlin.events.EventListenerWithPayload
|
|
@@ -8,19 +9,54 @@ import expo.modules.kotlin.events.EventName
|
|
|
8
9
|
import expo.modules.kotlin.exception.FunctionCallException
|
|
9
10
|
import expo.modules.kotlin.exception.MethodNotFoundException
|
|
10
11
|
import expo.modules.kotlin.exception.exceptionDecorator
|
|
12
|
+
import expo.modules.kotlin.jni.JavaScriptModuleObject
|
|
11
13
|
import expo.modules.kotlin.modules.Module
|
|
14
|
+
import expo.modules.kotlin.modules.ProcessedModuleDefinition
|
|
12
15
|
|
|
13
16
|
class ModuleHolder(val module: Module) {
|
|
14
|
-
val definition = module.definition()
|
|
17
|
+
val definition = ProcessedModuleDefinition(module.definition(), this)
|
|
18
|
+
|
|
15
19
|
val name get() = definition.name
|
|
16
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Cached instance of HybridObject used by CPP to interact with underlying [expo.modules.kotlin.modules.Module] object.
|
|
23
|
+
*/
|
|
24
|
+
val jsObject by lazy {
|
|
25
|
+
JavaScriptModuleObject()
|
|
26
|
+
.apply {
|
|
27
|
+
val constants = definition.constantsProvider()
|
|
28
|
+
val convertedConstants = Arguments.makeNativeMap(constants)
|
|
29
|
+
exportConstants(convertedConstants)
|
|
30
|
+
|
|
31
|
+
definition
|
|
32
|
+
.functions
|
|
33
|
+
.forEach { function ->
|
|
34
|
+
function.attachToJSObject(module.appContext, this)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Invokes a function with promise. Is used in the bridge implementation of the Sweet API.
|
|
41
|
+
*/
|
|
17
42
|
fun call(methodName: String, args: ReadableArray, promise: Promise) = exceptionDecorator({
|
|
18
43
|
FunctionCallException(methodName, definition.name, it)
|
|
19
44
|
}) {
|
|
20
|
-
val method = definition.
|
|
45
|
+
val method = definition.asyncFunctions[methodName]
|
|
46
|
+
?: throw MethodNotFoundException()
|
|
47
|
+
|
|
48
|
+
method.call(args, promise)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Invokes a function without promise.
|
|
53
|
+
* `callSync` was added only for test purpose and shouldn't be used anywhere else.
|
|
54
|
+
*/
|
|
55
|
+
fun callSync(methodName: String, args: ReadableArray): Any? {
|
|
56
|
+
val method = definition.syncFunctions[methodName]
|
|
21
57
|
?: throw MethodNotFoundException()
|
|
22
58
|
|
|
23
|
-
method.call(
|
|
59
|
+
return method.call(args)
|
|
24
60
|
}
|
|
25
61
|
|
|
26
62
|
fun post(eventName: EventName) {
|