expo-modules-core 55.0.2 → 55.0.4
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 +12 -0
- package/android/build.gradle +2 -2
- package/android/src/main/cpp/JSIContext.cpp +14 -2
- package/android/src/main/cpp/JSIContext.h +5 -14
- package/android/src/main/cpp/JavaScriptArrayBuffer.cpp +11 -12
- package/android/src/main/cpp/JavaScriptArrayBuffer.h +2 -7
- package/android/src/main/cpp/JavaScriptFunction.cpp +9 -13
- package/android/src/main/cpp/JavaScriptFunction.h +1 -7
- package/android/src/main/cpp/JavaScriptObject.cpp +78 -44
- package/android/src/main/cpp/JavaScriptObject.h +12 -17
- package/android/src/main/cpp/JavaScriptRuntime.cpp +1 -5
- package/android/src/main/cpp/JavaScriptRuntime.h +7 -1
- package/android/src/main/cpp/JavaScriptTypedArray.cpp +16 -18
- package/android/src/main/cpp/JavaScriptTypedArray.h +0 -6
- package/android/src/main/cpp/JavaScriptValue.cpp +48 -32
- package/android/src/main/cpp/JavaScriptValue.h +1 -7
- package/android/src/main/cpp/JavaScriptWeakObject.cpp +21 -15
- package/android/src/main/cpp/JavaScriptWeakObject.h +13 -10
- package/android/src/main/java/expo/modules/kotlin/AppContext.kt +13 -4
- package/android/src/main/java/expo/modules/kotlin/jni/JNIDeallocator.kt +10 -9
- package/android/src/main/java/expo/modules/kotlin/jni/JSIContext.kt +4 -4
- package/android/src/main/java/expo/modules/kotlin/jni/JavaCallback.kt +3 -3
- package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptArrayBuffer.kt +3 -3
- package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptFunction.kt +3 -3
- package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptModuleObject.kt +4 -4
- package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptObject.kt +3 -3
- package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptValue.kt +3 -3
- package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptWeakObject.kt +4 -3
- package/android/src/main/java/expo/modules/kotlin/jni/NativeArrayBuffer.kt +3 -3
- package/android/src/main/java/expo/modules/kotlin/jni/PromiseImpl.kt +5 -5
- package/android/src/main/java/expo/modules/kotlin/jni/decorators/JSDecoratorsBridgingObject.kt +4 -4
- package/android/src/main/java/expo/modules/kotlin/jni/worklets/Serializable.kt +3 -3
- package/ios/Core/Objects/ConstantDefinition.swift +9 -0
- package/ios/DevTools/ModuleDefinitionEncoder.swift +11 -14
- package/package.json +3 -3
- package/android/src/main/cpp/WeakRuntimeHolder.cpp +0 -24
- package/android/src/main/cpp/WeakRuntimeHolder.h +0 -40
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,18 @@
|
|
|
10
10
|
|
|
11
11
|
### 💡 Others
|
|
12
12
|
|
|
13
|
+
## 55.0.4 — 2026-01-26
|
|
14
|
+
|
|
15
|
+
### 🐛 Bug fixes
|
|
16
|
+
|
|
17
|
+
- [Android] Added missing checks in the promise implementation. ([#42467](https://github.com/expo/expo/pull/42467) by [@lukmccall](https://github.com/lukmccall))
|
|
18
|
+
|
|
19
|
+
## 55.0.3 — 2026-01-22
|
|
20
|
+
|
|
21
|
+
### 🐛 Bug fixes
|
|
22
|
+
|
|
23
|
+
- [Android] Fixed crashes in JavaScriptValue/JavaScriptObject destructor caused by freeing memory after the runtime is destroyed. ([#42440](https://github.com/expo/expo/pull/42440) by [@lukmccall](https://github.com/lukmccall))
|
|
24
|
+
|
|
13
25
|
## 55.0.2 — 2026-01-22
|
|
14
26
|
|
|
15
27
|
### 💡 Others
|
package/android/build.gradle
CHANGED
|
@@ -29,7 +29,7 @@ if (shouldIncludeCompose) {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
group = 'host.exp.exponent'
|
|
32
|
-
version = '55.0.
|
|
32
|
+
version = '55.0.4'
|
|
33
33
|
|
|
34
34
|
def isExpoModulesCoreTests = {
|
|
35
35
|
Gradle gradle = getGradle()
|
|
@@ -96,7 +96,7 @@ android {
|
|
|
96
96
|
defaultConfig {
|
|
97
97
|
consumerProguardFiles 'proguard-rules.pro'
|
|
98
98
|
versionCode 1
|
|
99
|
-
versionName "55.0.
|
|
99
|
+
versionName "55.0.4"
|
|
100
100
|
buildConfigField "String", "EXPO_MODULES_CORE_VERSION", "\"${versionName}\""
|
|
101
101
|
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", "true"
|
|
102
102
|
|
|
@@ -13,13 +13,13 @@
|
|
|
13
13
|
#include <fbjni/fbjni.h>
|
|
14
14
|
|
|
15
15
|
#include <memory>
|
|
16
|
+
#include <shared_mutex>
|
|
16
17
|
|
|
17
18
|
namespace jni = facebook::jni;
|
|
18
19
|
namespace jsi = facebook::jsi;
|
|
19
20
|
|
|
20
21
|
namespace expo {
|
|
21
22
|
|
|
22
|
-
|
|
23
23
|
void JSIContext::registerNatives() {
|
|
24
24
|
registerHybrid({
|
|
25
25
|
makeNativeMethod("evaluateScript", JSIContext::evaluateScript),
|
|
@@ -263,14 +263,26 @@ bool JSIContext::wasDeallocated() const noexcept {
|
|
|
263
263
|
return wasDeallocated_;
|
|
264
264
|
}
|
|
265
265
|
|
|
266
|
-
std::unordered_map<uintptr_t, JSIContext *> jsiContexts;
|
|
266
|
+
static std::unordered_map<uintptr_t, JSIContext *> jsiContexts;
|
|
267
|
+
static std::shared_mutex jsiContextsMutex;
|
|
267
268
|
|
|
268
269
|
void bindJSIContext(const jsi::Runtime &runtime, JSIContext *jsiContext) {
|
|
270
|
+
std::unique_lock lock(jsiContextsMutex);
|
|
269
271
|
jsiContexts[reinterpret_cast<uintptr_t>(&runtime)] = jsiContext;
|
|
270
272
|
}
|
|
271
273
|
|
|
272
274
|
void unbindJSIContext(const jsi::Runtime &runtime) {
|
|
275
|
+
std::unique_lock lock(jsiContextsMutex);
|
|
273
276
|
jsiContexts.erase(reinterpret_cast<uintptr_t>(&runtime));
|
|
274
277
|
}
|
|
275
278
|
|
|
279
|
+
JSIContext *getJSIContext(const jsi::Runtime &runtime) {
|
|
280
|
+
std::shared_lock lock(jsiContextsMutex);
|
|
281
|
+
const auto iterator = jsiContexts.find(reinterpret_cast<uintptr_t>(&runtime));
|
|
282
|
+
if (iterator == jsiContexts.end()) {
|
|
283
|
+
throw std::invalid_argument("JSIContext for the given runtime doesn't exist");
|
|
284
|
+
}
|
|
285
|
+
return iterator->second;
|
|
286
|
+
}
|
|
287
|
+
|
|
276
288
|
} // namespace expo
|
|
@@ -167,14 +167,9 @@ private:
|
|
|
167
167
|
) noexcept;
|
|
168
168
|
};
|
|
169
169
|
|
|
170
|
-
/**
|
|
171
|
-
* We are binding the JSIContext to the runtime using a thread-local map.
|
|
172
|
-
* This is a simplification of how we're accessing the JSIContext from different places.
|
|
173
|
-
*/
|
|
174
|
-
extern std::unordered_map<uintptr_t, JSIContext *> jsiContexts;
|
|
175
|
-
|
|
176
170
|
/**
|
|
177
171
|
* Binds the JSIContext to the runtime.
|
|
172
|
+
* Thread-safe: uses exclusive lock.
|
|
178
173
|
* @param runtime
|
|
179
174
|
* @param jsiContext
|
|
180
175
|
*/
|
|
@@ -182,22 +177,18 @@ void bindJSIContext(const jsi::Runtime &runtime, JSIContext *jsiContext);
|
|
|
182
177
|
|
|
183
178
|
/**
|
|
184
179
|
* Unbinds the JSIContext from the runtime.
|
|
180
|
+
* Thread-safe: uses exclusive lock.
|
|
185
181
|
* @param runtime
|
|
186
182
|
*/
|
|
187
183
|
void unbindJSIContext(const jsi::Runtime &runtime);
|
|
188
184
|
|
|
189
185
|
/**
|
|
190
186
|
* Gets the JSIContext for the given runtime.
|
|
187
|
+
* Thread-safe: uses exclusive lock.
|
|
191
188
|
* @param runtime
|
|
192
189
|
* @return JSIContext * - it should never be stored when received from this function.
|
|
193
|
-
*
|
|
190
|
+
* @throws std::invalid_argument if the JSIContext for the given runtime doesn't exist.
|
|
194
191
|
*/
|
|
195
|
-
|
|
196
|
-
const auto iterator = jsiContexts.find(reinterpret_cast<uintptr_t>(&runtime));
|
|
197
|
-
if (iterator == jsiContexts.end()) {
|
|
198
|
-
throw std::invalid_argument("JSIContext for the given runtime doesn't exist");
|
|
199
|
-
}
|
|
200
|
-
return iterator->second;
|
|
201
|
-
}
|
|
192
|
+
JSIContext *getJSIContext(const jsi::Runtime &runtime);
|
|
202
193
|
|
|
203
194
|
} // namespace expo
|
|
@@ -22,14 +22,7 @@ JavaScriptArrayBuffer::JavaScriptArrayBuffer(
|
|
|
22
22
|
std::weak_ptr<JavaScriptRuntime> runtime,
|
|
23
23
|
std::shared_ptr<jsi::ArrayBuffer> jsObject
|
|
24
24
|
) : runtimeHolder(std::move(runtime)), arrayBuffer(std::move(jsObject)) {
|
|
25
|
-
runtimeHolder.
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
JavaScriptArrayBuffer::JavaScriptArrayBuffer(
|
|
29
|
-
WeakRuntimeHolder runtime,
|
|
30
|
-
std::shared_ptr<jsi::ArrayBuffer> jsObject
|
|
31
|
-
) : runtimeHolder(std::move(runtime)), arrayBuffer(std::move(jsObject)) {
|
|
32
|
-
runtimeHolder.ensureRuntimeIsValid();
|
|
25
|
+
assert((!runtimeHolder.expired()) && "JS Runtime was used after deallocation");
|
|
33
26
|
}
|
|
34
27
|
|
|
35
28
|
jni::local_ref<JavaScriptArrayBuffer::javaobject> JavaScriptArrayBuffer::newInstance(
|
|
@@ -46,13 +39,19 @@ jni::local_ref<JavaScriptArrayBuffer::javaobject> JavaScriptArrayBuffer::newInst
|
|
|
46
39
|
}
|
|
47
40
|
|
|
48
41
|
int JavaScriptArrayBuffer::size() {
|
|
49
|
-
|
|
50
|
-
|
|
42
|
+
auto runtime = runtimeHolder.lock();
|
|
43
|
+
assert((runtime != nullptr) && "JS Runtime was used after deallocation");
|
|
44
|
+
auto &rawRuntime = runtime->get();
|
|
45
|
+
|
|
46
|
+
return (int) arrayBuffer->size(rawRuntime);
|
|
51
47
|
}
|
|
52
48
|
|
|
53
49
|
uint8_t *JavaScriptArrayBuffer::data() {
|
|
54
|
-
|
|
55
|
-
|
|
50
|
+
auto runtime = runtimeHolder.lock();
|
|
51
|
+
assert((runtime != nullptr) && "JS Runtime was used after deallocation");
|
|
52
|
+
auto &rawRuntime = runtime->get();
|
|
53
|
+
|
|
54
|
+
return arrayBuffer->data(rawRuntime);
|
|
56
55
|
}
|
|
57
56
|
|
|
58
57
|
jni::local_ref<jni::JByteBuffer> JavaScriptArrayBuffer::toDirectBuffer() {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
|
-
#include "WeakRuntimeHolder.h"
|
|
4
3
|
#include "JNIDeallocator.h"
|
|
4
|
+
#include "JavaScriptRuntime.h"
|
|
5
5
|
|
|
6
6
|
#include <fbjni/ByteBuffer.h>
|
|
7
7
|
#include <fbjni/fbjni.h>
|
|
@@ -35,11 +35,6 @@ public:
|
|
|
35
35
|
std::shared_ptr<jsi::ArrayBuffer> arrayBuffer
|
|
36
36
|
);
|
|
37
37
|
|
|
38
|
-
JavaScriptArrayBuffer(
|
|
39
|
-
WeakRuntimeHolder runtime,
|
|
40
|
-
std::shared_ptr<jsi::ArrayBuffer> arrayBuffer
|
|
41
|
-
);
|
|
42
|
-
|
|
43
38
|
[[nodiscard]] int size();
|
|
44
39
|
|
|
45
40
|
[[nodiscard]] uint8_t* data();
|
|
@@ -54,7 +49,7 @@ public:
|
|
|
54
49
|
}
|
|
55
50
|
|
|
56
51
|
private:
|
|
57
|
-
|
|
52
|
+
std::weak_ptr<JavaScriptRuntime> runtimeHolder;
|
|
58
53
|
std::shared_ptr<jsi::ArrayBuffer> arrayBuffer;
|
|
59
54
|
};
|
|
60
55
|
} // namespace expo
|
|
@@ -18,14 +18,7 @@ JavaScriptFunction::JavaScriptFunction(
|
|
|
18
18
|
std::weak_ptr<JavaScriptRuntime> runtime,
|
|
19
19
|
std::shared_ptr<jsi::Function> jsFunction
|
|
20
20
|
) : runtimeHolder(std::move(runtime)), jsFunction(std::move(jsFunction)) {
|
|
21
|
-
runtimeHolder.
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
JavaScriptFunction::JavaScriptFunction(
|
|
25
|
-
WeakRuntimeHolder runtime,
|
|
26
|
-
std::shared_ptr<jsi::Function> jsFunction
|
|
27
|
-
) : runtimeHolder(std::move(runtime)), jsFunction(std::move(jsFunction)) {
|
|
28
|
-
runtimeHolder.ensureRuntimeIsValid();
|
|
21
|
+
assert((!runtimeHolder.expired()) && "JS Runtime was used after deallocation");
|
|
29
22
|
}
|
|
30
23
|
|
|
31
24
|
std::shared_ptr<jsi::Function> JavaScriptFunction::get() {
|
|
@@ -37,7 +30,10 @@ jobject JavaScriptFunction::invoke(
|
|
|
37
30
|
jni::alias_ref<jni::JArrayClass<jni::JObject>> args,
|
|
38
31
|
jni::alias_ref<ExpectedType::javaobject> expectedReturnType
|
|
39
32
|
) {
|
|
40
|
-
auto
|
|
33
|
+
auto runtime = runtimeHolder.lock();
|
|
34
|
+
assert((runtime != nullptr) && "JS Runtime was used after deallocation");
|
|
35
|
+
auto &rawRuntime = runtime->get();
|
|
36
|
+
|
|
41
37
|
JNIEnv *env = jni::Environment::current();
|
|
42
38
|
|
|
43
39
|
size_t size = args->size();
|
|
@@ -46,25 +42,25 @@ jobject JavaScriptFunction::invoke(
|
|
|
46
42
|
|
|
47
43
|
for (size_t i = 0; i < size; i++) {
|
|
48
44
|
jni::local_ref<jobject> arg = args->getElement(i);
|
|
49
|
-
convertedArgs.push_back(convert(env,
|
|
45
|
+
convertedArgs.push_back(convert(env, rawRuntime, arg));
|
|
50
46
|
}
|
|
51
47
|
|
|
52
48
|
// TODO(@lukmccall): add better error handling
|
|
53
49
|
jsi::Value result = jsThis == nullptr ?
|
|
54
50
|
jsFunction->call(
|
|
55
|
-
|
|
51
|
+
rawRuntime,
|
|
56
52
|
(const jsi::Value *) convertedArgs.data(),
|
|
57
53
|
size
|
|
58
54
|
) :
|
|
59
55
|
jsFunction->callWithThis(
|
|
60
|
-
|
|
56
|
+
rawRuntime,
|
|
61
57
|
*(jsThis->cthis()->get()),
|
|
62
58
|
(const jsi::Value *) convertedArgs.data(),
|
|
63
59
|
size
|
|
64
60
|
);
|
|
65
61
|
|
|
66
62
|
auto converter = AnyType(jni::make_local(expectedReturnType)).converter;
|
|
67
|
-
auto convertedResult = converter->convert(
|
|
63
|
+
auto convertedResult = converter->convert(rawRuntime, env, result);
|
|
68
64
|
return convertedResult;
|
|
69
65
|
}
|
|
70
66
|
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
#include "JSIObjectWrapper.h"
|
|
6
6
|
#include "JavaScriptRuntime.h"
|
|
7
|
-
#include "WeakRuntimeHolder.h"
|
|
8
7
|
#include "types/ExpectedType.h"
|
|
9
8
|
|
|
10
9
|
#include <fbjni/fbjni.h>
|
|
@@ -39,18 +38,13 @@ public:
|
|
|
39
38
|
std::shared_ptr<jsi::Function> jsFunction
|
|
40
39
|
);
|
|
41
40
|
|
|
42
|
-
JavaScriptFunction(
|
|
43
|
-
WeakRuntimeHolder runtime,
|
|
44
|
-
std::shared_ptr<jsi::Function> jsFunction
|
|
45
|
-
);
|
|
46
|
-
|
|
47
41
|
std::shared_ptr<jsi::Function> get() override;
|
|
48
42
|
|
|
49
43
|
|
|
50
44
|
private:
|
|
51
45
|
friend HybridBase;
|
|
52
46
|
|
|
53
|
-
|
|
47
|
+
std::weak_ptr<JavaScriptRuntime> runtimeHolder;
|
|
54
48
|
std::shared_ptr<jsi::Function> jsFunction;
|
|
55
49
|
|
|
56
50
|
jobject invoke(
|
|
@@ -51,14 +51,7 @@ JavaScriptObject::JavaScriptObject(
|
|
|
51
51
|
std::weak_ptr<JavaScriptRuntime> runtime,
|
|
52
52
|
std::shared_ptr<jsi::Object> jsObject
|
|
53
53
|
) : runtimeHolder(std::move(runtime)), jsObject(std::move(jsObject)) {
|
|
54
|
-
runtimeHolder.
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
JavaScriptObject::JavaScriptObject(
|
|
58
|
-
WeakRuntimeHolder runtime,
|
|
59
|
-
std::shared_ptr<jsi::Object> jsObject
|
|
60
|
-
) : runtimeHolder(std::move(runtime)), jsObject(std::move(jsObject)) {
|
|
61
|
-
runtimeHolder.ensureRuntimeIsValid();
|
|
54
|
+
assert((!runtimeHolder.expired()) && "JS Runtime was used after deallocation");
|
|
62
55
|
}
|
|
63
56
|
|
|
64
57
|
std::shared_ptr<jsi::Object> JavaScriptObject::get() {
|
|
@@ -66,13 +59,19 @@ std::shared_ptr<jsi::Object> JavaScriptObject::get() {
|
|
|
66
59
|
}
|
|
67
60
|
|
|
68
61
|
bool JavaScriptObject::hasProperty(const std::string &name) {
|
|
69
|
-
auto
|
|
70
|
-
|
|
62
|
+
auto runtime = runtimeHolder.lock();
|
|
63
|
+
assert((runtime != nullptr) && "JS Runtime was used after deallocation");
|
|
64
|
+
auto &rawRuntime = runtime->get();
|
|
65
|
+
|
|
66
|
+
return jsObject->hasProperty(rawRuntime, name.c_str());
|
|
71
67
|
}
|
|
72
68
|
|
|
73
69
|
jsi::Value JavaScriptObject::getProperty(const std::string &name) {
|
|
74
|
-
auto
|
|
75
|
-
|
|
70
|
+
auto runtime = runtimeHolder.lock();
|
|
71
|
+
assert((runtime != nullptr) && "JS Runtime was used after deallocation");
|
|
72
|
+
auto &rawRuntime = runtime->get();
|
|
73
|
+
|
|
74
|
+
return jsObject->getProperty(rawRuntime, name.c_str());
|
|
76
75
|
}
|
|
77
76
|
|
|
78
77
|
bool JavaScriptObject::jniHasProperty(jni::alias_ref<jstring> name) {
|
|
@@ -82,26 +81,32 @@ bool JavaScriptObject::jniHasProperty(jni::alias_ref<jstring> name) {
|
|
|
82
81
|
jni::local_ref<JavaScriptValue::javaobject> JavaScriptObject::jniGetProperty(
|
|
83
82
|
jni::alias_ref<jstring> name
|
|
84
83
|
) {
|
|
84
|
+
auto runtime = runtimeHolder.lock();
|
|
85
|
+
assert((runtime != nullptr) && "JS Runtime was used after deallocation");
|
|
86
|
+
auto &rawRuntime = runtime->get();
|
|
87
|
+
|
|
85
88
|
auto result = std::make_shared<jsi::Value>(getProperty(name->toStdString()));
|
|
86
89
|
return JavaScriptValue::newInstance(
|
|
87
|
-
|
|
90
|
+
expo::getJSIContext(rawRuntime),
|
|
88
91
|
runtimeHolder,
|
|
89
92
|
result
|
|
90
93
|
);
|
|
91
94
|
}
|
|
92
95
|
|
|
93
96
|
std::vector<std::string> JavaScriptObject::getPropertyNames() {
|
|
94
|
-
auto
|
|
97
|
+
auto runtime = runtimeHolder.lock();
|
|
98
|
+
assert((runtime != nullptr) && "JS Runtime was used after deallocation");
|
|
99
|
+
auto &rawRuntime = runtime->get();
|
|
95
100
|
|
|
96
|
-
jsi::Array properties = jsObject->getPropertyNames(
|
|
97
|
-
auto size = properties.size(
|
|
101
|
+
jsi::Array properties = jsObject->getPropertyNames(rawRuntime);
|
|
102
|
+
auto size = properties.size(rawRuntime);
|
|
98
103
|
|
|
99
104
|
std::vector<std::string> names(size);
|
|
100
105
|
for (size_t i = 0; i < size; i++) {
|
|
101
106
|
auto propertyName = properties
|
|
102
|
-
.getValueAtIndex(
|
|
103
|
-
.asString(
|
|
104
|
-
.utf8(
|
|
107
|
+
.getValueAtIndex(rawRuntime, i)
|
|
108
|
+
.asString(rawRuntime)
|
|
109
|
+
.utf8(rawRuntime);
|
|
105
110
|
names[i] = propertyName;
|
|
106
111
|
}
|
|
107
112
|
|
|
@@ -120,33 +125,46 @@ jni::local_ref<jni::JArrayClass<jstring>> JavaScriptObject::jniGetPropertyNames(
|
|
|
120
125
|
|
|
121
126
|
jni::local_ref<jni::HybridClass<JavaScriptWeakObject, Destructible>::javaobject>
|
|
122
127
|
JavaScriptObject::createWeak() {
|
|
128
|
+
auto runtime = runtimeHolder.lock();
|
|
129
|
+
assert((runtime != nullptr) && "JS Runtime was used after deallocation");
|
|
130
|
+
auto &rawRuntime = runtime->get();
|
|
131
|
+
|
|
123
132
|
return JavaScriptWeakObject::newInstance(
|
|
124
|
-
|
|
133
|
+
expo::getJSIContext(rawRuntime),
|
|
125
134
|
runtimeHolder,
|
|
126
135
|
get()
|
|
127
136
|
);
|
|
128
137
|
}
|
|
129
138
|
|
|
130
139
|
jni::local_ref<JavaScriptFunction::javaobject> JavaScriptObject::jniAsFunction() {
|
|
131
|
-
auto
|
|
132
|
-
|
|
140
|
+
auto runtime = runtimeHolder.lock();
|
|
141
|
+
assert((runtime != nullptr) && "JS Runtime was used after deallocation");
|
|
142
|
+
auto &rawRuntime = runtime->get();
|
|
143
|
+
|
|
144
|
+
auto jsFuncion = std::make_shared<jsi::Function>(jsObject->asFunction(rawRuntime));
|
|
133
145
|
return JavaScriptFunction::newInstance(
|
|
134
|
-
|
|
146
|
+
expo::getJSIContext(rawRuntime),
|
|
135
147
|
runtimeHolder,
|
|
136
148
|
jsFuncion
|
|
137
149
|
);
|
|
138
150
|
}
|
|
139
151
|
|
|
140
152
|
void JavaScriptObject::setProperty(const std::string &name, jsi::Value value) {
|
|
141
|
-
auto
|
|
142
|
-
|
|
153
|
+
auto runtime = runtimeHolder.lock();
|
|
154
|
+
assert((runtime != nullptr) && "JS Runtime was used after deallocation");
|
|
155
|
+
auto &rawRuntime = runtime->get();
|
|
156
|
+
|
|
157
|
+
jsObject->setProperty(rawRuntime, name.c_str(), value);
|
|
143
158
|
}
|
|
144
159
|
|
|
145
160
|
void JavaScriptObject::unsetProperty(jni::alias_ref<jstring> name) {
|
|
146
|
-
auto
|
|
161
|
+
auto runtime = runtimeHolder.lock();
|
|
162
|
+
assert((runtime != nullptr) && "JS Runtime was used after deallocation");
|
|
163
|
+
auto &rawRuntime = runtime->get();
|
|
164
|
+
|
|
147
165
|
auto cName = name->toStdString();
|
|
148
166
|
jsObject->setProperty(
|
|
149
|
-
|
|
167
|
+
rawRuntime,
|
|
150
168
|
cName.c_str(),
|
|
151
169
|
jsi::Value::undefined()
|
|
152
170
|
);
|
|
@@ -178,11 +196,14 @@ jni::local_ref<JavaScriptObject::javaobject> JavaScriptObject::newInstance(
|
|
|
178
196
|
void JavaScriptObject::defineNativeDeallocator(
|
|
179
197
|
jni::alias_ref<JNIFunctionBody::javaobject> deallocator
|
|
180
198
|
) {
|
|
181
|
-
auto
|
|
199
|
+
auto runtime = runtimeHolder.lock();
|
|
200
|
+
assert((runtime != nullptr) && "JS Runtime was used after deallocation");
|
|
201
|
+
auto &rawRuntime = runtime->get();
|
|
202
|
+
|
|
182
203
|
jni::global_ref<JNIFunctionBody::javaobject> globalRef = jni::make_global(deallocator);
|
|
183
204
|
|
|
184
205
|
common::setDeallocator(
|
|
185
|
-
|
|
206
|
+
rawRuntime,
|
|
186
207
|
jsObject,
|
|
187
208
|
[globalRef = std::move(globalRef)]() mutable {
|
|
188
209
|
auto args = jni::Environment::ensureCurrentThreadIsAttached()->NewObjectArray(
|
|
@@ -197,28 +218,36 @@ void JavaScriptObject::defineNativeDeallocator(
|
|
|
197
218
|
}
|
|
198
219
|
|
|
199
220
|
void JavaScriptObject::setExternalMemoryPressure(int size) {
|
|
200
|
-
auto
|
|
201
|
-
|
|
221
|
+
auto runtime = runtimeHolder.lock();
|
|
222
|
+
assert((runtime != nullptr) && "JS Runtime was used after deallocation");
|
|
223
|
+
auto &rawRuntime = runtime->get();
|
|
224
|
+
|
|
225
|
+
jsObject->setExternalMemoryPressure(rawRuntime, size);
|
|
202
226
|
}
|
|
203
227
|
|
|
204
228
|
bool JavaScriptObject::isArray() {
|
|
205
|
-
auto
|
|
206
|
-
|
|
229
|
+
auto runtime = runtimeHolder.lock();
|
|
230
|
+
assert((runtime != nullptr) && "JS Runtime was used after deallocation");
|
|
231
|
+
auto &rawRuntime = runtime->get();
|
|
232
|
+
|
|
233
|
+
return jsObject->isArray(rawRuntime);
|
|
207
234
|
}
|
|
208
235
|
|
|
209
236
|
jni::local_ref<jni::JArrayClass<JavaScriptValue::javaobject>> JavaScriptObject::getArray() {
|
|
210
|
-
auto
|
|
211
|
-
|
|
237
|
+
auto runtime = runtimeHolder.lock();
|
|
238
|
+
assert((runtime != nullptr) && "JS Runtime was used after deallocation");
|
|
239
|
+
auto &rawRuntime = runtime->get();
|
|
240
|
+
auto jsiContext = expo::getJSIContext(rawRuntime);
|
|
212
241
|
|
|
213
|
-
auto jsArray = jsObject->getArray(
|
|
214
|
-
size_t size = jsArray.size(
|
|
242
|
+
auto jsArray = jsObject->getArray(rawRuntime);
|
|
243
|
+
size_t size = jsArray.size(rawRuntime);
|
|
215
244
|
|
|
216
245
|
auto result = jni::JArrayClass<JavaScriptValue::javaobject>::newArray(size);
|
|
217
246
|
for (size_t i = 0; i < size; i++) {
|
|
218
247
|
auto element = JavaScriptValue::newInstance(
|
|
219
|
-
|
|
248
|
+
jsiContext,
|
|
220
249
|
runtimeHolder,
|
|
221
|
-
std::make_shared<jsi::Value>(jsArray.getValueAtIndex(
|
|
250
|
+
std::make_shared<jsi::Value>(jsArray.getValueAtIndex(rawRuntime, i))
|
|
222
251
|
);
|
|
223
252
|
|
|
224
253
|
result->setElement(i, element.release());
|
|
@@ -227,18 +256,23 @@ jni::local_ref<jni::JArrayClass<JavaScriptValue::javaobject>> JavaScriptObject::
|
|
|
227
256
|
}
|
|
228
257
|
|
|
229
258
|
bool JavaScriptObject::isArrayBuffer() {
|
|
230
|
-
auto
|
|
231
|
-
|
|
259
|
+
auto runtime = runtimeHolder.lock();
|
|
260
|
+
assert((runtime != nullptr) && "JS Runtime was used after deallocation");
|
|
261
|
+
auto &rawRuntime = runtime->get();
|
|
262
|
+
|
|
263
|
+
return jsObject->isArrayBuffer(rawRuntime);
|
|
232
264
|
}
|
|
233
265
|
|
|
234
266
|
jni::local_ref<JavaScriptArrayBuffer::javaobject> JavaScriptObject::getArrayBuffer() {
|
|
235
|
-
auto
|
|
236
|
-
|
|
267
|
+
auto runtime = runtimeHolder.lock();
|
|
268
|
+
assert((runtime != nullptr) && "JS Runtime was used after deallocation");
|
|
269
|
+
auto &rawRuntime = runtime->get();
|
|
270
|
+
auto jsiContext = expo::getJSIContext(rawRuntime);
|
|
237
271
|
|
|
238
272
|
return JavaScriptArrayBuffer::newInstance(
|
|
239
273
|
jsiContext,
|
|
240
274
|
runtimeHolder,
|
|
241
|
-
std::make_shared<jsi::ArrayBuffer>(jsObject->getArrayBuffer(
|
|
275
|
+
std::make_shared<jsi::ArrayBuffer>(jsObject->getArrayBuffer(rawRuntime))
|
|
242
276
|
);
|
|
243
277
|
}
|
|
244
278
|
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
#include "JSIObjectWrapper.h"
|
|
6
6
|
#include "JSITypeConverter.h"
|
|
7
7
|
#include "JavaScriptRuntime.h"
|
|
8
|
-
#include "WeakRuntimeHolder.h"
|
|
9
8
|
#include "JNIFunctionBody.h"
|
|
10
9
|
#include "JNIDeallocator.h"
|
|
11
10
|
#include "JSIUtils.h"
|
|
@@ -47,13 +46,6 @@ public:
|
|
|
47
46
|
std::shared_ptr<jsi::Object> jsObject
|
|
48
47
|
);
|
|
49
48
|
|
|
50
|
-
JavaScriptObject(
|
|
51
|
-
WeakRuntimeHolder runtime,
|
|
52
|
-
std::shared_ptr<jsi::Object> jsObject
|
|
53
|
-
);
|
|
54
|
-
|
|
55
|
-
virtual ~JavaScriptObject() = default;
|
|
56
|
-
|
|
57
49
|
std::shared_ptr<jsi::Object> get() override;
|
|
58
50
|
|
|
59
51
|
/**
|
|
@@ -92,9 +84,8 @@ public:
|
|
|
92
84
|
[[nodiscard]] jni::local_ref<jni::HybridClass<JavaScriptArrayBuffer, Destructible>::javaobject> getArrayBuffer();
|
|
93
85
|
|
|
94
86
|
protected:
|
|
95
|
-
|
|
87
|
+
std::weak_ptr<JavaScriptRuntime> runtimeHolder;
|
|
96
88
|
std::shared_ptr<jsi::Object> jsObject;
|
|
97
|
-
|
|
98
89
|
private:
|
|
99
90
|
friend HybridBase;
|
|
100
91
|
|
|
@@ -130,13 +121,15 @@ private:
|
|
|
130
121
|
typename = std::enable_if_t<is_jsi_type_converter_defined<T>>
|
|
131
122
|
>
|
|
132
123
|
void setProperty(jni::alias_ref<jstring> name, T value) {
|
|
133
|
-
|
|
124
|
+
auto runtime = runtimeHolder.lock();
|
|
125
|
+
assert((runtime != nullptr) && "JS Runtime was used after deallocation");
|
|
126
|
+
auto &rawRuntime = runtime->get();
|
|
134
127
|
|
|
135
128
|
auto cName = name->toStdString();
|
|
136
129
|
jsObject->setProperty(
|
|
137
|
-
|
|
130
|
+
rawRuntime,
|
|
138
131
|
cName.c_str(),
|
|
139
|
-
jsi_type_converter<T>::convert(
|
|
132
|
+
jsi_type_converter<T>::convert(rawRuntime, value)
|
|
140
133
|
);
|
|
141
134
|
}
|
|
142
135
|
|
|
@@ -145,12 +138,14 @@ private:
|
|
|
145
138
|
typename = std::enable_if_t<is_jsi_type_converter_defined<T>>
|
|
146
139
|
>
|
|
147
140
|
void defineProperty(jni::alias_ref<jstring> name, T value, int options) {
|
|
148
|
-
|
|
141
|
+
auto runtime = runtimeHolder.lock();
|
|
142
|
+
assert((runtime != nullptr) && "JS Runtime was used after deallocation");
|
|
143
|
+
auto &rawRuntime = runtime->get();
|
|
149
144
|
|
|
150
145
|
auto cName = name->toStdString();
|
|
151
|
-
jsi::Object descriptor = preparePropertyDescriptor(
|
|
152
|
-
descriptor.setProperty(
|
|
153
|
-
common::defineProperty(
|
|
146
|
+
jsi::Object descriptor = preparePropertyDescriptor(rawRuntime, options);
|
|
147
|
+
descriptor.setProperty(rawRuntime, "value", jsi_type_converter<T>::convert(rawRuntime, value));
|
|
148
|
+
common::defineProperty(rawRuntime, jsObject.get(), cName.c_str(), std::move(descriptor));
|
|
154
149
|
}
|
|
155
150
|
};
|
|
156
151
|
} // namespace expo
|
|
@@ -14,11 +14,7 @@ namespace expo {
|
|
|
14
14
|
JavaScriptRuntime::JavaScriptRuntime(
|
|
15
15
|
jsi::Runtime *runtime,
|
|
16
16
|
std::shared_ptr<react::CallInvoker> jsInvoker
|
|
17
|
-
) : jsInvoker(std::move(jsInvoker)) {
|
|
18
|
-
// Creating a shared pointer that points to the runtime but doesn't own it, thus doesn't release it.
|
|
19
|
-
// In this code flow, the runtime should be owned by something else like the CatalystInstance.
|
|
20
|
-
// See explanation for constructor (8): https://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr
|
|
21
|
-
this->runtime = std::shared_ptr<jsi::Runtime>(std::shared_ptr<jsi::Runtime>(), runtime);
|
|
17
|
+
) : runtime(runtime), jsInvoker(std::move(jsInvoker)) {
|
|
22
18
|
}
|
|
23
19
|
|
|
24
20
|
jsi::Runtime &JavaScriptRuntime::get() const noexcept {
|
|
@@ -76,6 +76,12 @@ public:
|
|
|
76
76
|
std::shared_ptr<react::CallInvoker> jsInvoker;
|
|
77
77
|
|
|
78
78
|
private:
|
|
79
|
-
|
|
79
|
+
/**
|
|
80
|
+
* Raw pointer to the runtime. We do not own this - it's managed by React Native.
|
|
81
|
+
* The runtime's lifetime is guaranteed to exceed JavaScriptRuntime's lifetime,
|
|
82
|
+
* as JSIContext::prepareForDeallocation() invalidates all weak references before
|
|
83
|
+
* the runtime is deallocated.
|
|
84
|
+
*/
|
|
85
|
+
jsi::Runtime *runtime;
|
|
80
86
|
};
|
|
81
87
|
} // namespace expo
|
|
@@ -5,24 +5,17 @@
|
|
|
5
5
|
|
|
6
6
|
namespace expo {
|
|
7
7
|
|
|
8
|
-
JavaScriptTypedArray::JavaScriptTypedArray(
|
|
9
|
-
WeakRuntimeHolder runtime,
|
|
10
|
-
std::shared_ptr<jsi::Object> jsObject
|
|
11
|
-
) : jni::HybridClass<JavaScriptTypedArray, JavaScriptObject>(std::move(runtime),
|
|
12
|
-
std::move(jsObject)) {
|
|
13
|
-
jsi::Runtime &jsRuntime = runtimeHolder.getJSRuntime();
|
|
14
|
-
typedArrayWrapper = std::make_shared<expo::TypedArray>(jsRuntime, *get());
|
|
15
|
-
rawPointer = static_cast<char *>(typedArrayWrapper->getRawPointer(jsRuntime));
|
|
16
|
-
}
|
|
17
|
-
|
|
18
8
|
JavaScriptTypedArray::JavaScriptTypedArray(
|
|
19
9
|
std::weak_ptr<JavaScriptRuntime> runtime,
|
|
20
10
|
std::shared_ptr<jsi::Object> jsObject
|
|
21
11
|
) : jni::HybridClass<JavaScriptTypedArray, JavaScriptObject>(std::move(runtime),
|
|
22
12
|
std::move(jsObject)) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
13
|
+
auto jsRuntime = runtimeHolder.lock();
|
|
14
|
+
assert((jsRuntime != nullptr) && "JS Runtime was used after deallocation");
|
|
15
|
+
auto &rawRuntime = jsRuntime->get();
|
|
16
|
+
|
|
17
|
+
typedArrayWrapper = std::make_shared<expo::TypedArray>(rawRuntime, *JavaScriptObject::get());
|
|
18
|
+
rawPointer = static_cast<char *>(typedArrayWrapper->getRawPointer(rawRuntime));
|
|
26
19
|
}
|
|
27
20
|
|
|
28
21
|
void JavaScriptTypedArray::registerNatives() {
|
|
@@ -49,17 +42,22 @@ void JavaScriptTypedArray::registerNatives() {
|
|
|
49
42
|
}
|
|
50
43
|
|
|
51
44
|
int JavaScriptTypedArray::getRawKind() {
|
|
52
|
-
|
|
53
|
-
|
|
45
|
+
auto runtime = runtimeHolder.lock();
|
|
46
|
+
assert((runtime != nullptr) && "JS Runtime was used after deallocation");
|
|
47
|
+
auto &rawRuntime = runtime->get();
|
|
48
|
+
|
|
49
|
+
return (int) typedArrayWrapper->getKind(rawRuntime);
|
|
54
50
|
}
|
|
55
51
|
|
|
56
52
|
jni::local_ref<jni::JByteBuffer> JavaScriptTypedArray::toDirectBuffer() {
|
|
57
|
-
|
|
53
|
+
auto runtime = runtimeHolder.lock();
|
|
54
|
+
assert((runtime != nullptr) && "JS Runtime was used after deallocation");
|
|
55
|
+
auto &rawRuntime = runtime->get();
|
|
58
56
|
|
|
59
|
-
auto byteLength = typedArrayWrapper->byteLength(
|
|
57
|
+
auto byteLength = typedArrayWrapper->byteLength(rawRuntime);
|
|
60
58
|
|
|
61
59
|
auto byteBuffer = jni::JByteBuffer::wrapBytes(
|
|
62
|
-
static_cast<uint8_t *>(typedArrayWrapper->getRawPointer(
|
|
60
|
+
static_cast<uint8_t *>(typedArrayWrapper->getRawPointer(rawRuntime)),
|
|
63
61
|
byteLength
|
|
64
62
|
);
|
|
65
63
|
|