@lucent-lang/lucent 0.0.4 → 0.1.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/README.md +97 -0
- package/app.plugin.js +46 -10
- package/dist/{bench-CR3E7e2e.js → bench-B555m0wU.js} +10 -6
- package/dist/{build-CAIrRSYA.js → build-UZ5Zm5m6.js} +1 -1
- package/dist/{build-check-QozuNJm5.js → build-check-Dmf8_yiw.js} +28 -13
- package/dist/{check-1SCmYlqA.js → check-D-H9WLG4.js} +1 -1
- package/dist/cli.js +62 -13
- package/dist/{codes-CIuwXt1S.js → codes-D-6LxUqD.js} +163 -7
- package/dist/compiler.js +4 -4
- package/dist/{dashboard-B-NzjjaN.js → dashboard-C8iF5-6T.js} +2 -2
- package/dist/{dev-BYWMP7oC.js → dev-B3lSx5CF.js} +62 -23
- package/dist/{diagnostic-BM9sXmwl.js → diagnostic-BvwLZQS1.js} +3 -1
- package/dist/{doctor-C0PrfWT6.js → doctor-CTAX3euc.js} +1 -1
- package/dist/{doctor-DdR4JnVc.js → doctor-CrgOAV5L.js} +1 -1
- package/dist/{explain--vV1oaRl.js → explain-Byit07F-.js} +1 -1
- package/dist/{packages-HyskKIsY.js → packages-CSmKeaAh.js} +2 -33
- package/dist/pipeline-BBY0df_2.js +700 -0
- package/dist/project-BLhWwnns.js +342 -0
- package/dist/sdk-coverage-DFGiDOzR.js +113 -0
- package/dist/sdk-diff-DpPYWzrl.js +109 -0
- package/dist/sdk-lock-QOxEFD1o.js +38 -0
- package/dist/{sdk-prefetch-mo04JDZV.js → sdk-prefetch-DX6ztlPN.js} +2 -2
- package/dist/{sdk-search-Iv4K3-8a.js → sdk-search-BShBL1LL.js} +2 -2
- package/dist/{sdk-show-CkrdlqlP.js → sdk-show-B3bI-0M7.js} +5 -4
- package/dist/sdk-usage-ljX5bTuZ.js +95 -0
- package/dist/src-DlICbK91.js +39682 -0
- package/dist/trace-Bi4hkmPx.js +139 -0
- package/lib/core.cjs +368 -1
- package/lib/sdk/android.d.ts +54 -1
- package/lib/sdk/compose.d.ts +94 -0
- package/lib/sdk/compose.schemas.json.gz +0 -0
- package/lib/sdk/core.d.ts +201 -0
- package/lib/sdk/ios.d.ts +75 -2
- package/lib/sdk/ui.d.ts +129 -0
- package/metro/transformer.cjs +11 -2
- package/package.json +2 -1
- package/runtime/cpp/lucent/abort.cpp +59 -11
- package/runtime/cpp/lucent/abort.h +22 -6
- package/runtime/cpp/lucent/array.h +12 -2
- package/runtime/cpp/lucent/async.h +101 -21
- package/runtime/cpp/lucent/bigint.cpp +898 -0
- package/runtime/cpp/lucent/bigint.h +302 -0
- package/runtime/cpp/lucent/buffer.cpp +228 -0
- package/runtime/cpp/lucent/buffer.h +328 -0
- package/runtime/cpp/lucent/builtins.cpp +4 -1
- package/runtime/cpp/lucent/bytes.h +21 -2
- package/runtime/cpp/lucent/callback.cpp +29 -0
- package/runtime/cpp/lucent/callback.h +230 -0
- package/runtime/cpp/lucent/compute.cpp +370 -0
- package/runtime/cpp/lucent/compute.h +455 -0
- package/runtime/cpp/lucent/conversions.h +111 -0
- package/runtime/cpp/lucent/core.h +16 -5
- package/runtime/cpp/lucent/equality.h +107 -28
- package/runtime/cpp/lucent/execution.cpp +416 -0
- package/runtime/cpp/lucent/execution.h +270 -0
- package/runtime/cpp/lucent/extension.cpp +97 -0
- package/runtime/cpp/lucent/extension.h +210 -0
- package/runtime/cpp/lucent/helpers.h +12 -5
- package/runtime/cpp/lucent/items.h +52 -0
- package/runtime/cpp/lucent/jserror.cpp +9 -0
- package/runtime/cpp/lucent/jserror.h +11 -0
- package/runtime/cpp/lucent/jsi/convert.cpp +138 -0
- package/runtime/cpp/lucent/jsi/convert.h +128 -59
- package/runtime/cpp/lucent/jsi/host.cpp +213 -35
- package/runtime/cpp/lucent/jsi/host.h +116 -16
- package/runtime/cpp/lucent/json.h +19 -1
- package/runtime/cpp/lucent/lifecycle.cpp +260 -0
- package/runtime/cpp/lucent/lifecycle.h +124 -0
- package/runtime/cpp/lucent/lucent.h +7 -0
- package/runtime/cpp/lucent/map.h +41 -7
- package/runtime/cpp/lucent/native.cpp +35 -47
- package/runtime/cpp/lucent/native.h +116 -26
- package/runtime/cpp/lucent/number.cpp +38 -38
- package/runtime/cpp/lucent/number.h +33 -0
- package/runtime/cpp/lucent/operation.h +65 -0
- package/runtime/cpp/lucent/ops.h +14 -6
- package/runtime/cpp/lucent/platform/android.cpp +223 -10
- package/runtime/cpp/lucent/platform/android.h +227 -4
- package/runtime/cpp/lucent/platform/android_activity.cpp +258 -0
- package/runtime/cpp/lucent/platform/android_requests.h +140 -0
- package/runtime/cpp/lucent/platform/compose.h +256 -0
- package/runtime/cpp/lucent/platform/ios.h +325 -25
- package/runtime/cpp/lucent/platform/ios.mm +1 -14
- package/runtime/cpp/lucent/platform/ios_ui.h +192 -0
- package/runtime/cpp/lucent/platform/ios_ui.mm +454 -0
- package/runtime/cpp/lucent/platform/swiftui.h +190 -0
- package/runtime/cpp/lucent/presentation.cpp +11 -0
- package/runtime/cpp/lucent/presentation.h +109 -0
- package/runtime/cpp/lucent/reactive.cpp +406 -0
- package/runtime/cpp/lucent/reactive.h +566 -0
- package/runtime/cpp/lucent/report.cpp +40 -0
- package/runtime/cpp/lucent/report.h +16 -0
- package/runtime/cpp/lucent/resource.cpp +83 -0
- package/runtime/cpp/lucent/resource.h +75 -0
- package/runtime/cpp/lucent/scheduler.cpp +38 -124
- package/runtime/cpp/lucent/scheduler.h +102 -83
- package/runtime/cpp/lucent/scope.cpp +308 -0
- package/runtime/cpp/lucent/scope.h +452 -0
- package/runtime/cpp/lucent/sizing.h +263 -0
- package/runtime/cpp/lucent/slots.h +231 -0
- package/runtime/cpp/lucent/trace.cpp +539 -0
- package/runtime/cpp/lucent/trace.h +251 -0
- package/runtime/cpp/lucent/transport.cpp +9 -0
- package/runtime/cpp/lucent/transport.h +341 -0
- package/runtime/cpp/lucent/view.cpp +123 -0
- package/runtime/cpp/lucent/view.h +157 -0
- package/runtime/cpp/rn/LucentComponentView.h +121 -0
- package/runtime/cpp/rn/LucentComponentView.mm +479 -0
- package/runtime/cpp/rn/LucentModule.cpp +37 -7
- package/runtime/cpp/rn/LucentModule.h +3 -0
- package/runtime/cpp/rn/LucentViewChildren.h +80 -0
- package/runtime/cpp/rn/LucentViewChildren.mm +211 -0
- package/runtime/cpp/rn/LucentViewRegistry.h +62 -0
- package/runtime/cpp/rn/LucentViewRequests.cpp +91 -0
- package/runtime/cpp/rn/LucentViewRequests.h +104 -0
- package/runtime/cpp/rn/LucentViewSizing.h +345 -0
- package/runtime/cpp/rn/LucentViewSlots.h +242 -0
- package/runtime/cpp/rn/LucentViewValues.h +125 -0
- package/runtime/cpp/rn/LucentViews.h +440 -0
- package/runtime/cpp/rn/LucentViewsAndroid.cpp +439 -0
- package/runtime/cpp/rn/LucentViewsAndroid.h +138 -0
- package/runtime/cpp/third_party/dragonbox/LICENSE-Boost +23 -0
- package/runtime/cpp/third_party/dragonbox/README.md +16 -0
- package/runtime/cpp/third_party/dragonbox/dragonbox.h +4440 -0
- package/runtime/js/index.d.ts +11 -1
- package/runtime/js/index.js +84 -8
- package/runtime/js/views.d.ts +38 -0
- package/runtime/js/views.js +226 -0
- package/runtime/native/android/CMakeLists.txt +4 -1
- package/runtime/native/android/src/compose/java/dev/lucent/compose/CompositionRules.kt +44 -0
- package/runtime/native/android/src/compose/java/dev/lucent/compose/LucentComposition.kt +161 -0
- package/runtime/native/android/src/main/java/dev/lucent/LucentActivities.java +292 -0
- package/runtime/native/android/src/main/java/dev/lucent/LucentChildren.java +174 -0
- package/runtime/native/android/src/main/java/dev/lucent/LucentHostView.java +232 -0
- package/runtime/native/android/src/main/java/dev/lucent/LucentInitializer.java +46 -0
- package/runtime/native/android/src/main/java/dev/lucent/LucentPackage.java +4 -3
- package/runtime/native/android/src/main/java/dev/lucent/LucentRequestActivity.java +92 -0
- package/runtime/native/android/src/main/java/dev/lucent/LucentSlotView.java +102 -0
- package/runtime/native/android/src/main/java/dev/lucent/LucentViewManager.java +149 -0
- package/runtime/native/android/src/main/java/dev/lucent/LucentViewManagers.java +16 -0
- package/runtime/native/android/src/main/java/dev/lucent/LucentViews.java +44 -0
- package/runtime/test/jsi/harness.cpp +9 -0
- package/schemas/build.schema.json +96 -1
- package/schemas/check.schema.json +56 -1
- package/schemas/lucent.schema.json +495 -9
- package/schemas/sdk-diff.schema.json +70 -0
- package/schemas/sdk-lock.schema.json +67 -0
- package/ts-plugin/index.js +77 -4
- package/dist/pipeline-CH7-2cxu.js +0 -232
- package/dist/project-D8tEet0k.js +0 -150
- package/dist/sdk-coverage-BoW_3Efd.js +0 -64
- package/dist/src-BD7f1_aZ.js +0 -11493
|
@@ -8,10 +8,14 @@
|
|
|
8
8
|
#include <fbjni/fbjni.h>
|
|
9
9
|
#include <sys/system_properties.h>
|
|
10
10
|
|
|
11
|
+
#include <atomic>
|
|
12
|
+
#include <cstdint>
|
|
11
13
|
#include <cstdlib>
|
|
12
14
|
#include <mutex>
|
|
15
|
+
#include <optional>
|
|
13
16
|
#include <string>
|
|
14
17
|
#include <unordered_map>
|
|
18
|
+
#include <vector>
|
|
15
19
|
|
|
16
20
|
namespace lucent::jni {
|
|
17
21
|
|
|
@@ -84,9 +88,75 @@ jmethodID staticMethod(jclass cls, const char* name, const char* sig) { LUCENT_J
|
|
|
84
88
|
jfieldID field(jclass cls, const char* name, const char* sig) { LUCENT_JNI_ID(GetFieldID, "field") }
|
|
85
89
|
jfieldID staticField(jclass cls, const char* name, const char* sig) { LUCENT_JNI_ID(GetStaticFieldID, "field") }
|
|
86
90
|
|
|
91
|
+
namespace {
|
|
92
|
+
|
|
93
|
+
/// Lucent errors thrown to Java, by the Java exception carrying each (a weak
|
|
94
|
+
/// reference): errorOf gives back the error itself, not a copy.
|
|
95
|
+
struct Thrown {
|
|
96
|
+
jweak exception;
|
|
97
|
+
Error error;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
std::mutex thrownMutex;
|
|
101
|
+
std::vector<Thrown>& thrown() {
|
|
102
|
+
static auto* v = new std::vector<Thrown>();
|
|
103
|
+
return *v;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/// The Lucent error `t` carries, removed from the list; none for other exceptions.
|
|
107
|
+
std::optional<Error> takeThrown(JNIEnv* e, jobject t) {
|
|
108
|
+
std::lock_guard<std::mutex> g(thrownMutex);
|
|
109
|
+
auto& v = thrown();
|
|
110
|
+
for (auto it = v.begin(); it != v.end(); ++it) {
|
|
111
|
+
if (!e->IsSameObject(it->exception, t)) continue;
|
|
112
|
+
|
|
113
|
+
Error error = std::move(it->error);
|
|
114
|
+
e->DeleteWeakGlobalRef(it->exception);
|
|
115
|
+
v.erase(it);
|
|
116
|
+
return error;
|
|
117
|
+
}
|
|
118
|
+
return std::nullopt;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
} // namespace
|
|
122
|
+
|
|
123
|
+
void throwToJava(JNIEnv* e, Error error) {
|
|
124
|
+
static jclass cls = findClass("java/lang/RuntimeException");
|
|
125
|
+
static jmethodID init = method(cls, "<init>", "(Ljava/lang/String;)V");
|
|
126
|
+
jstring message = toJString(e, error->message);
|
|
127
|
+
auto exception = static_cast<jthrowable>(e->NewObject(cls, init, message));
|
|
128
|
+
e->DeleteLocalRef(message);
|
|
129
|
+
if (!exception) return; // A pending OutOfMemoryError ends the call instead.
|
|
130
|
+
|
|
131
|
+
{
|
|
132
|
+
std::lock_guard<std::mutex> g(thrownMutex);
|
|
133
|
+
auto& v = thrown();
|
|
134
|
+
// Exceptions Java dropped without Lucent reading them.
|
|
135
|
+
std::erase_if(v, [e](Thrown& x) {
|
|
136
|
+
if (!e->IsSameObject(x.exception, nullptr)) return false;
|
|
137
|
+
e->DeleteWeakGlobalRef(x.exception);
|
|
138
|
+
return true;
|
|
139
|
+
});
|
|
140
|
+
v.push_back({e->NewWeakGlobalRef(exception), std::move(error)});
|
|
141
|
+
}
|
|
142
|
+
e->Throw(exception);
|
|
143
|
+
e->DeleteLocalRef(exception);
|
|
144
|
+
}
|
|
145
|
+
|
|
87
146
|
void rethrowPending(JNIEnv* e) {
|
|
88
147
|
jthrowable t = e->ExceptionOccurred();
|
|
89
148
|
e->ExceptionClear();
|
|
149
|
+
throw Exception(errorOf(e, t));
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
Error errorOf(JNIEnv* e, jobject t) {
|
|
153
|
+
if (auto own = t ? takeThrown(e, t) : std::nullopt) return std::move(*own);
|
|
154
|
+
if (!t) {
|
|
155
|
+
// No exception to read: a cancelled task.
|
|
156
|
+
Error err = makeError(String::fromLatin1("Error"), String::fromLatin1("cancelled"));
|
|
157
|
+
err->code = String::fromLatin1("java.util.concurrent.CancellationException");
|
|
158
|
+
return err;
|
|
159
|
+
}
|
|
90
160
|
jclass objectCls = e->FindClass("java/lang/Object");
|
|
91
161
|
jobject cls = e->CallObjectMethod(t, e->GetMethodID(objectCls, "getClass", "()Ljava/lang/Class;"));
|
|
92
162
|
jclass classCls = e->FindClass("java/lang/Class");
|
|
@@ -97,7 +167,14 @@ void rethrowPending(JNIEnv* e) {
|
|
|
97
167
|
String className = name ? fromJString(e, name, "") : String::fromLatin1("java.lang.Throwable");
|
|
98
168
|
Error err = makeError(String::fromLatin1("Error"), message ? fromJString(e, message, "") : className);
|
|
99
169
|
err->code = className;
|
|
100
|
-
|
|
170
|
+
return err;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
void close(const NativeRef& closeable) {
|
|
174
|
+
JNIEnv* e = env();
|
|
175
|
+
static jmethodID m = method(findClass("java/lang/AutoCloseable"), "close", "()V");
|
|
176
|
+
e->CallVoidMethod(unwrap(closeable), m);
|
|
177
|
+
check(e);
|
|
101
178
|
}
|
|
102
179
|
|
|
103
180
|
NativeRef wrap(JNIEnv* e, jobject local, const char* what) {
|
|
@@ -161,13 +238,13 @@ jobjectArray toStringArray(JNIEnv* e, const Array<String>& a) {
|
|
|
161
238
|
return out;
|
|
162
239
|
}
|
|
163
240
|
|
|
164
|
-
Array<
|
|
241
|
+
Array<BigInt> fromLongArray(JNIEnv* e, jlongArray a, const char* what) {
|
|
165
242
|
if (!a) failWith("TypeError", std::string(what) + " returned null");
|
|
166
243
|
jsize n = e->GetArrayLength(a);
|
|
167
244
|
std::vector<jlong> buf(static_cast<size_t>(n));
|
|
168
245
|
e->GetLongArrayRegion(a, 0, n, buf.data());
|
|
169
|
-
Array<
|
|
170
|
-
for (jlong v : buf) out.push(
|
|
246
|
+
Array<BigInt> out;
|
|
247
|
+
for (jlong v : buf) out.push(BigInt(v));
|
|
171
248
|
return out;
|
|
172
249
|
}
|
|
173
250
|
|
|
@@ -202,11 +279,11 @@ Array<String> fromStringArray(JNIEnv* e, jobjectArray a, const char* what) {
|
|
|
202
279
|
return out;
|
|
203
280
|
}
|
|
204
281
|
|
|
205
|
-
jlongArray toLongArray(JNIEnv* e, const Array<
|
|
282
|
+
jlongArray toLongArray(JNIEnv* e, const Array<BigInt>& a, const char* what) {
|
|
206
283
|
auto n = static_cast<jsize>(a.size());
|
|
207
|
-
jlongArray out = e->NewLongArray(n);
|
|
208
284
|
std::vector<jlong> buf(static_cast<size_t>(n));
|
|
209
|
-
for (jsize i = 0; i < n; i++) buf[static_cast<size_t>(i)] =
|
|
285
|
+
for (jsize i = 0; i < n; i++) buf[static_cast<size_t>(i)] = toNativeInteger<jlong>(a.at(static_cast<size_t>(i)), what);
|
|
286
|
+
jlongArray out = e->NewLongArray(n);
|
|
210
287
|
e->SetLongArrayRegion(out, 0, n, buf.data());
|
|
211
288
|
return out;
|
|
212
289
|
}
|
|
@@ -220,6 +297,94 @@ jintArray toIntArray(JNIEnv* e, const Array<double>& a) {
|
|
|
220
297
|
return out;
|
|
221
298
|
}
|
|
222
299
|
|
|
300
|
+
void returnedNull(const char* what) { failWith("TypeError", std::string(what) + " returned null"); }
|
|
301
|
+
|
|
302
|
+
jobjectArray listElements(JNIEnv* e, jobject list, const char* what) {
|
|
303
|
+
if (!list) returnedNull(what);
|
|
304
|
+
|
|
305
|
+
static jmethodID toArray = method(findClass("java/util/Collection"), "toArray", "()[Ljava/lang/Object;");
|
|
306
|
+
auto a = static_cast<jobjectArray>(e->CallObjectMethod(list, toArray));
|
|
307
|
+
check(e);
|
|
308
|
+
return a;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
jobject newList(JNIEnv* e, jsize n) {
|
|
312
|
+
static jclass cls = findClass("java/util/ArrayList");
|
|
313
|
+
static jmethodID init = method(cls, "<init>", "(I)V");
|
|
314
|
+
jobject list = e->NewObject(cls, init, n);
|
|
315
|
+
check(e);
|
|
316
|
+
return list;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
void listAdd(JNIEnv* e, jobject list, jobject element) {
|
|
320
|
+
static jmethodID add = method(findClass("java/util/List"), "add", "(Ljava/lang/Object;)Z");
|
|
321
|
+
e->CallBooleanMethod(list, add, element);
|
|
322
|
+
check(e);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
namespace {
|
|
326
|
+
|
|
327
|
+
/// A Java array of primitives as numbers (or booleans), read in one copy.
|
|
328
|
+
template <class R, class A, class J>
|
|
329
|
+
Array<R> fromPrimitives(JNIEnv* e, A a, void (JNIEnv::*get)(A, jsize, jsize, J*), const char* what) {
|
|
330
|
+
if (!a) returnedNull(what);
|
|
331
|
+
|
|
332
|
+
jsize n = e->GetArrayLength(a);
|
|
333
|
+
std::vector<J> buf(static_cast<size_t>(n));
|
|
334
|
+
(e->*get)(a, 0, n, buf.data());
|
|
335
|
+
|
|
336
|
+
Array<R> out;
|
|
337
|
+
for (J v : buf) out.push(static_cast<R>(v));
|
|
338
|
+
return out;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/// Numbers (or booleans) as a Java array of primitives, each converted by `to`.
|
|
342
|
+
template <class A, class J, class T, class F>
|
|
343
|
+
A toPrimitives(JNIEnv* e, const Array<T>& a, A (JNIEnv::*make)(jsize), void (JNIEnv::*set)(A, jsize, jsize, const J*), F to) {
|
|
344
|
+
auto n = static_cast<jsize>(a.size());
|
|
345
|
+
A out = (e->*make)(n);
|
|
346
|
+
|
|
347
|
+
std::vector<J> buf(static_cast<size_t>(n));
|
|
348
|
+
for (jsize i = 0; i < n; i++) buf[static_cast<size_t>(i)] = to(a.at(static_cast<size_t>(i)));
|
|
349
|
+
(e->*set)(out, 0, n, buf.data());
|
|
350
|
+
return out;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
} // namespace
|
|
354
|
+
|
|
355
|
+
Array<double> fromShortArray(JNIEnv* e, jshortArray a, const char* what) { return fromPrimitives<double>(e, a, &JNIEnv::GetShortArrayRegion, what); }
|
|
356
|
+
Array<double> fromCharArray(JNIEnv* e, jcharArray a, const char* what) { return fromPrimitives<double>(e, a, &JNIEnv::GetCharArrayRegion, what); }
|
|
357
|
+
Array<double> fromFloatArray(JNIEnv* e, jfloatArray a, const char* what) { return fromPrimitives<double>(e, a, &JNIEnv::GetFloatArrayRegion, what); }
|
|
358
|
+
Array<double> fromDoubleArray(JNIEnv* e, jdoubleArray a, const char* what) { return fromPrimitives<double>(e, a, &JNIEnv::GetDoubleArrayRegion, what); }
|
|
359
|
+
|
|
360
|
+
Array<bool> fromBooleanArray(JNIEnv* e, jbooleanArray a, const char* what) {
|
|
361
|
+
if (!a) returnedNull(what);
|
|
362
|
+
|
|
363
|
+
jsize n = e->GetArrayLength(a);
|
|
364
|
+
std::vector<jboolean> buf(static_cast<size_t>(n));
|
|
365
|
+
e->GetBooleanArrayRegion(a, 0, n, buf.data());
|
|
366
|
+
|
|
367
|
+
Array<bool> out;
|
|
368
|
+
for (jboolean v : buf) out.push(v == JNI_TRUE);
|
|
369
|
+
return out;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
jshortArray toShortArray(JNIEnv* e, const Array<double>& a) {
|
|
373
|
+
return toPrimitives<jshortArray, jshort>(e, a, &JNIEnv::NewShortArray, &JNIEnv::SetShortArrayRegion, [](double v) { return static_cast<jshort>(toInt32(v)); });
|
|
374
|
+
}
|
|
375
|
+
jcharArray toCharArray(JNIEnv* e, const Array<double>& a) {
|
|
376
|
+
return toPrimitives<jcharArray, jchar>(e, a, &JNIEnv::NewCharArray, &JNIEnv::SetCharArrayRegion, [](double v) { return static_cast<jchar>(toInt32(v)); });
|
|
377
|
+
}
|
|
378
|
+
jfloatArray toFloatArray(JNIEnv* e, const Array<double>& a) {
|
|
379
|
+
return toPrimitives<jfloatArray, jfloat>(e, a, &JNIEnv::NewFloatArray, &JNIEnv::SetFloatArrayRegion, [](double v) { return static_cast<jfloat>(v); });
|
|
380
|
+
}
|
|
381
|
+
jdoubleArray toDoubleArray(JNIEnv* e, const Array<double>& a) {
|
|
382
|
+
return toPrimitives<jdoubleArray, jdouble>(e, a, &JNIEnv::NewDoubleArray, &JNIEnv::SetDoubleArrayRegion, [](double v) { return v; });
|
|
383
|
+
}
|
|
384
|
+
jbooleanArray toBooleanArray(JNIEnv* e, const Array<bool>& a) {
|
|
385
|
+
return toPrimitives<jbooleanArray, jboolean>(e, a, &JNIEnv::NewBooleanArray, &JNIEnv::SetBooleanArrayRegion, [](bool v) { return static_cast<jboolean>(v ? JNI_TRUE : JNI_FALSE); });
|
|
386
|
+
}
|
|
387
|
+
|
|
223
388
|
// --- proxies ---------------------------------------------------------------------------
|
|
224
389
|
|
|
225
390
|
namespace {
|
|
@@ -339,8 +504,10 @@ jobject cachedJavaObject(JNIEnv* e, std::pair<const void*, std::string> key, std
|
|
|
339
504
|
|
|
340
505
|
} // namespace
|
|
341
506
|
|
|
342
|
-
jobject proxyFor(JNIEnv* e, const char* iface, const void* identity, std::initializer_list<std::pair<const char*, ProxyMethod>> methods
|
|
343
|
-
|
|
507
|
+
jobject proxyFor(JNIEnv* e, const char* iface, const void* identity, std::initializer_list<std::pair<const char*, ProxyMethod>> methods,
|
|
508
|
+
const char* variant) {
|
|
509
|
+
std::string key = variant ? std::string(iface) + "#" + variant : std::string(iface);
|
|
510
|
+
return cachedJavaObject(e, {identity, key}, methods, [&](jlong handle) {
|
|
344
511
|
jclass cls = nativeProxyClass(e);
|
|
345
512
|
static jmethodID create = staticMethod(cls, "create", "(Ljava/lang/Class;J)Ljava/lang/Object;");
|
|
346
513
|
return e->CallStaticObjectMethod(cls, create, findClass(iface), handle);
|
|
@@ -356,6 +523,19 @@ jobject subclassFor(JNIEnv* e, const char* cls, const void* identity, std::initi
|
|
|
356
523
|
|
|
357
524
|
jobject arg(JNIEnv* e, jobjectArray args, int i) { return e->GetObjectArrayElement(args, i); }
|
|
358
525
|
|
|
526
|
+
jobject detail::completionFor(JNIEnv* e, std::function<void(JNIEnv*, jobject, jobject)> settle) {
|
|
527
|
+
// A fresh identity for each call: proxies are cached per identity while Java holds them.
|
|
528
|
+
static std::atomic<uintptr_t> next{1};
|
|
529
|
+
const void* identity = reinterpret_cast<const void*>(next.fetch_add(1));
|
|
530
|
+
|
|
531
|
+
ProxyMethod accept = [settle = std::move(settle)](JNIEnv* env, jobjectArray args) -> jobject {
|
|
532
|
+
settle(env, arg(env, args, 0), arg(env, args, 1));
|
|
533
|
+
return nullptr;
|
|
534
|
+
};
|
|
535
|
+
|
|
536
|
+
return proxyFor(e, "java/util/function/BiConsumer", identity, {{"accept(Ljava/lang/Object;Ljava/lang/Object;)", accept}});
|
|
537
|
+
}
|
|
538
|
+
|
|
359
539
|
double unboxNumber(JNIEnv* e, jobject boxed) {
|
|
360
540
|
static jmethodID doubleValue = method(findClass("java/lang/Number"), "doubleValue", "()D");
|
|
361
541
|
double v = e->CallDoubleMethod(boxed, doubleValue);
|
|
@@ -363,6 +543,13 @@ double unboxNumber(JNIEnv* e, jobject boxed) {
|
|
|
363
543
|
return v;
|
|
364
544
|
}
|
|
365
545
|
|
|
546
|
+
jlong unboxLong(JNIEnv* e, jobject boxed) {
|
|
547
|
+
static jmethodID longValue = method(findClass("java/lang/Number"), "longValue", "()J");
|
|
548
|
+
jlong v = e->CallLongMethod(boxed, longValue);
|
|
549
|
+
check(e);
|
|
550
|
+
return v;
|
|
551
|
+
}
|
|
552
|
+
|
|
366
553
|
bool unboxBoolean(JNIEnv* e, jobject boxed) {
|
|
367
554
|
static jmethodID booleanValue = method(findClass("java/lang/Boolean"), "booleanValue", "()Z");
|
|
368
555
|
bool v = e->CallBooleanMethod(boxed, booleanValue) == JNI_TRUE;
|
|
@@ -371,6 +558,9 @@ bool unboxBoolean(JNIEnv* e, jobject boxed) {
|
|
|
371
558
|
}
|
|
372
559
|
|
|
373
560
|
jobject boxInt(JNIEnv* e, jint v) { return boxWith(e, "java/lang/Integer", "(I)Ljava/lang/Integer;", jvalue{.i = v}); }
|
|
561
|
+
jobject boxShort(JNIEnv* e, jshort v) { return boxWith(e, "java/lang/Short", "(S)Ljava/lang/Short;", jvalue{.s = v}); }
|
|
562
|
+
jobject boxByte(JNIEnv* e, jbyte v) { return boxWith(e, "java/lang/Byte", "(B)Ljava/lang/Byte;", jvalue{.b = v}); }
|
|
563
|
+
jobject boxChar(JNIEnv* e, jchar v) { return boxWith(e, "java/lang/Character", "(C)Ljava/lang/Character;", jvalue{.c = v}); }
|
|
374
564
|
jobject boxLong(JNIEnv* e, jlong v) { return boxWith(e, "java/lang/Long", "(J)Ljava/lang/Long;", jvalue{.j = v}); }
|
|
375
565
|
jobject boxDouble(JNIEnv* e, jdouble v) { return boxWith(e, "java/lang/Double", "(D)Ljava/lang/Double;", jvalue{.d = v}); }
|
|
376
566
|
jobject boxFloat(JNIEnv* e, jfloat v) { return boxWith(e, "java/lang/Float", "(F)Ljava/lang/Float;", jvalue{.f = v}); }
|
|
@@ -383,11 +573,34 @@ NativeRef appContext() {
|
|
|
383
573
|
check(e);
|
|
384
574
|
jmethodID current = e->GetStaticMethodID(cls, "currentApplication", "()Landroid/app/Application;");
|
|
385
575
|
check(e);
|
|
386
|
-
|
|
576
|
+
auto* kept = new NativeRef(wrap(e, e->CallStaticObjectMethod(cls, current), "ActivityThread.currentApplication()"));
|
|
577
|
+
|
|
578
|
+
// Never released: not what a JavaScript runtime's teardown leaves behind.
|
|
579
|
+
kept->keepForProcess();
|
|
580
|
+
return kept;
|
|
387
581
|
}();
|
|
388
582
|
return *app;
|
|
389
583
|
}
|
|
390
584
|
|
|
585
|
+
namespace {
|
|
586
|
+
thread_local jobject hostingView = nullptr;
|
|
587
|
+
} // namespace
|
|
588
|
+
|
|
589
|
+
HostViewEntry::HostViewEntry(jobject view) : outer_(hostingView) { hostingView = view; }
|
|
590
|
+
|
|
591
|
+
HostViewEntry::~HostViewEntry() { hostingView = outer_; }
|
|
592
|
+
|
|
593
|
+
Opt<NativeRef> hostContext() {
|
|
594
|
+
if (!hostingView) return Opt<NativeRef>(null);
|
|
595
|
+
|
|
596
|
+
JNIEnv* e = env();
|
|
597
|
+
static jmethodID getContext = method(findClass("android/view/View"), "getContext", "()Landroid/content/Context;");
|
|
598
|
+
jobject context = e->CallObjectMethod(hostingView, getContext);
|
|
599
|
+
|
|
600
|
+
check(e);
|
|
601
|
+
return wrapOpt(e, context);
|
|
602
|
+
}
|
|
603
|
+
|
|
391
604
|
bool available(double api) {
|
|
392
605
|
static int level = [] {
|
|
393
606
|
char value[PROP_VALUE_MAX] = {0};
|
|
@@ -7,10 +7,15 @@
|
|
|
7
7
|
#include <initializer_list>
|
|
8
8
|
#include <utility>
|
|
9
9
|
|
|
10
|
+
#include "../abort.h"
|
|
10
11
|
#include "../array.h"
|
|
12
|
+
#include "../async.h"
|
|
13
|
+
#include "../bigint.h"
|
|
11
14
|
#include "../bytes.h"
|
|
15
|
+
#include "../function.h"
|
|
12
16
|
#include "../jsstring.h"
|
|
13
17
|
#include "../native.h"
|
|
18
|
+
#include "../operation.h"
|
|
14
19
|
|
|
15
20
|
namespace lucent::jni {
|
|
16
21
|
|
|
@@ -30,6 +35,12 @@ void rethrowPending(JNIEnv* env);
|
|
|
30
35
|
inline void check(JNIEnv* env) {
|
|
31
36
|
if (env->ExceptionCheck()) rethrowPending(env);
|
|
32
37
|
}
|
|
38
|
+
/// A Java exception (a Throwable) as a Lucent error, coded as rethrowPending does.
|
|
39
|
+
Error errorOf(JNIEnv* env, jobject throwable);
|
|
40
|
+
|
|
41
|
+
/// Closes an AutoCloseable (a Closeable, a Cursor…): how a `using`
|
|
42
|
+
/// declaration disposes one. Throws what close() throws.
|
|
43
|
+
void close(const NativeRef& closeable);
|
|
33
44
|
|
|
34
45
|
/// A Lucent reference to `local` (a global ref; the local ref is deleted).
|
|
35
46
|
/// Throws TypeError for null.
|
|
@@ -46,16 +57,29 @@ String charSequenceToString(JNIEnv* env, jobject s, const char* what);
|
|
|
46
57
|
Opt<String> charSequenceToStringOpt(JNIEnv* env, jobject s);
|
|
47
58
|
|
|
48
59
|
// Arrays are copied in both directions; a null reference is an absent value.
|
|
49
|
-
|
|
60
|
+
// Numbers go to Java's integral types as ToInt32 would, then narrowed (short,
|
|
61
|
+
// char), as JavaScript's typed arrays store them.
|
|
62
|
+
/// Each element exactly, or RangeError naming `what`.
|
|
63
|
+
jlongArray toLongArray(JNIEnv* env, const Array<BigInt>& a, const char* what);
|
|
50
64
|
jintArray toIntArray(JNIEnv* env, const Array<double>& a);
|
|
65
|
+
jshortArray toShortArray(JNIEnv* env, const Array<double>& a);
|
|
66
|
+
jcharArray toCharArray(JNIEnv* env, const Array<double>& a);
|
|
67
|
+
jfloatArray toFloatArray(JNIEnv* env, const Array<double>& a);
|
|
68
|
+
jdoubleArray toDoubleArray(JNIEnv* env, const Array<double>& a);
|
|
69
|
+
jbooleanArray toBooleanArray(JNIEnv* env, const Array<bool>& a);
|
|
51
70
|
jbyteArray toByteArray(JNIEnv* env, const Bytes& b);
|
|
52
71
|
jobjectArray toStringArray(JNIEnv* env, const Array<String>& a);
|
|
53
72
|
template <class T, class F>
|
|
54
73
|
auto toArrayOpt(JNIEnv* env, const Opt<T>& v, F convert) -> decltype(convert(env, v.get())) {
|
|
55
74
|
return v.has() ? convert(env, v.get()) : nullptr;
|
|
56
75
|
}
|
|
57
|
-
Array<
|
|
76
|
+
Array<BigInt> fromLongArray(JNIEnv* env, jlongArray a, const char* what);
|
|
58
77
|
Array<double> fromIntArray(JNIEnv* env, jintArray a, const char* what);
|
|
78
|
+
Array<double> fromShortArray(JNIEnv* env, jshortArray a, const char* what);
|
|
79
|
+
Array<double> fromCharArray(JNIEnv* env, jcharArray a, const char* what);
|
|
80
|
+
Array<double> fromFloatArray(JNIEnv* env, jfloatArray a, const char* what);
|
|
81
|
+
Array<double> fromDoubleArray(JNIEnv* env, jdoubleArray a, const char* what);
|
|
82
|
+
Array<bool> fromBooleanArray(JNIEnv* env, jbooleanArray a, const char* what);
|
|
59
83
|
Bytes fromByteArray(JNIEnv* env, jbyteArray a, const char* what);
|
|
60
84
|
Array<String> fromStringArray(JNIEnv* env, jobjectArray a, const char* what);
|
|
61
85
|
template <class T, class A, class F>
|
|
@@ -76,6 +100,69 @@ class LocalFrame {
|
|
|
76
100
|
JNIEnv* env_;
|
|
77
101
|
};
|
|
78
102
|
|
|
103
|
+
[[noreturn]] void returnedNull(const char* what);
|
|
104
|
+
|
|
105
|
+
/// A Java array of objects (or of arrays) as a Lucent array: `each` gets
|
|
106
|
+
/// every element as a local reference, which is freed once it has run.
|
|
107
|
+
template <class T, class F>
|
|
108
|
+
Array<T> fromObjectArray(JNIEnv* env, jobjectArray a, F each, const char* what) {
|
|
109
|
+
if (!a) returnedNull(what);
|
|
110
|
+
|
|
111
|
+
jsize n = env->GetArrayLength(a);
|
|
112
|
+
Array<T> out;
|
|
113
|
+
for (jsize i = 0; i < n; i++) {
|
|
114
|
+
LocalFrame frame(env);
|
|
115
|
+
out.push(each(env->GetObjectArrayElement(a, i)));
|
|
116
|
+
}
|
|
117
|
+
return out;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/// A Lucent array as a Java array of `elementClass` (a class, or an array
|
|
121
|
+
/// type's descriptor): `each` gives every element's reference, a local one
|
|
122
|
+
/// freed once it is stored.
|
|
123
|
+
template <class T, class F>
|
|
124
|
+
jobjectArray toObjectArray(JNIEnv* env, const Array<T>& a, const char* elementClass, F each) {
|
|
125
|
+
auto n = static_cast<jsize>(a.size());
|
|
126
|
+
jobjectArray out = env->NewObjectArray(n, findClass(elementClass), nullptr);
|
|
127
|
+
for (jsize i = 0; i < n; i++) {
|
|
128
|
+
LocalFrame frame(env);
|
|
129
|
+
env->SetObjectArrayElement(out, i, each(a.at(static_cast<size_t>(i))));
|
|
130
|
+
}
|
|
131
|
+
return out;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// --- Kotlin's read-only lists, copied ------------------------------------------------
|
|
135
|
+
|
|
136
|
+
/// A list's elements, in one copy (Collection.toArray()): a local reference.
|
|
137
|
+
jobjectArray listElements(JNIEnv* env, jobject list, const char* what);
|
|
138
|
+
/// A new java.util.ArrayList with room for `n` elements: a local reference.
|
|
139
|
+
jobject newList(JNIEnv* env, jsize n);
|
|
140
|
+
/// Appends `element` (null allowed) to `list`.
|
|
141
|
+
void listAdd(JNIEnv* env, jobject list, jobject element);
|
|
142
|
+
|
|
143
|
+
/// A java.util.List as a Lucent array, copied: `each` gets every element (a
|
|
144
|
+
/// local reference, null where the list holds null), freed once it has run.
|
|
145
|
+
template <class T, class F>
|
|
146
|
+
Array<T> fromList(JNIEnv* env, jobject list, F each, const char* what) {
|
|
147
|
+
jobjectArray a = listElements(env, list, what);
|
|
148
|
+
Array<T> out = fromObjectArray<T>(env, a, each, what);
|
|
149
|
+
env->DeleteLocalRef(a);
|
|
150
|
+
return out;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/// A Lucent array as a new java.util.ArrayList, copied: `each` gives every
|
|
154
|
+
/// element's reference (null allowed), a local one freed once it is added.
|
|
155
|
+
template <class T, class F>
|
|
156
|
+
jobject toList(JNIEnv* env, const Array<T>& a, F each) {
|
|
157
|
+
auto n = static_cast<jsize>(a.size());
|
|
158
|
+
jobject out = newList(env, n);
|
|
159
|
+
for (jsize i = 0; i < n; i++) {
|
|
160
|
+
LocalFrame frame(env);
|
|
161
|
+
listAdd(env, out, each(a.at(static_cast<size_t>(i))));
|
|
162
|
+
}
|
|
163
|
+
return out;
|
|
164
|
+
}
|
|
165
|
+
|
|
79
166
|
// --- Java interfaces implemented by Lucent code --------------------------------------
|
|
80
167
|
|
|
81
168
|
/// Handles one method of a proxy: its arguments (boxed), its result (boxed,
|
|
@@ -87,9 +174,12 @@ using ProxyMethod = std::function<jobject(JNIEnv*, jobjectArray)>;
|
|
|
87
174
|
* methods are `methods`, keyed by name and parameter descriptor
|
|
88
175
|
* (`onLocationChanged(Landroid/location/Location;)`). One per `identity` (a Lucent function or
|
|
89
176
|
* object) while Java holds it, so passing the same function twice passes
|
|
90
|
-
* the same object
|
|
177
|
+
* the same object; one per `variant` too, when methods of the same
|
|
178
|
+
* interface differ by where the object is passed (a Kotlin function's
|
|
179
|
+
* arguments are read as each place types them). A local reference.
|
|
91
180
|
*/
|
|
92
|
-
jobject proxyFor(JNIEnv* env, const char* iface, const void* identity, std::initializer_list<std::pair<const char*, ProxyMethod>> methods
|
|
181
|
+
jobject proxyFor(JNIEnv* env, const char* iface, const void* identity, std::initializer_list<std::pair<const char*, ProxyMethod>> methods,
|
|
182
|
+
const char* variant = nullptr);
|
|
93
183
|
|
|
94
184
|
/**
|
|
95
185
|
* An instance of `cls` (a generated Java subclass of an SDK class, made with
|
|
@@ -102,16 +192,149 @@ jobject subclassFor(JNIEnv* env, const char* cls, const void* identity, std::ini
|
|
|
102
192
|
jobject arg(JNIEnv* env, jobjectArray args, int i);
|
|
103
193
|
/// Primitive values of boxed arguments, and boxed results.
|
|
104
194
|
double unboxNumber(JNIEnv* env, jobject boxed);
|
|
195
|
+
/// A boxed long, as it is (the glue makes it a bigint, or a group's number).
|
|
196
|
+
jlong unboxLong(JNIEnv* env, jobject boxed);
|
|
105
197
|
bool unboxBoolean(JNIEnv* env, jobject boxed);
|
|
106
198
|
jobject boxInt(JNIEnv* env, jint v);
|
|
199
|
+
jobject boxShort(JNIEnv* env, jshort v);
|
|
200
|
+
jobject boxByte(JNIEnv* env, jbyte v);
|
|
201
|
+
jobject boxChar(JNIEnv* env, jchar v);
|
|
107
202
|
jobject boxLong(JNIEnv* env, jlong v);
|
|
108
203
|
jobject boxDouble(JNIEnv* env, jdouble v);
|
|
109
204
|
jobject boxFloat(JNIEnv* env, jfloat v);
|
|
110
205
|
jobject boxBoolean(JNIEnv* env, bool v);
|
|
111
206
|
|
|
207
|
+
// --- Kotlin coroutines through generated shims ----------------------------------------
|
|
208
|
+
|
|
209
|
+
/// Throws `error` to Java as a java.lang.RuntimeException carrying its
|
|
210
|
+
/// message, which errorOf reads back as `error` itself.
|
|
211
|
+
void throwToJava(JNIEnv* env, Error error);
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* A Lucent function a generated shim runs as a Kotlin suspend function (a
|
|
215
|
+
* suspend function argument, a fun interface's suspending function), which
|
|
216
|
+
* Kotlin waits for: `f` runs on the calling thread holding the Lucent lock
|
|
217
|
+
* and gives the boxed result. What it throws is thrown to Kotlin (see
|
|
218
|
+
* throwToJava), so the Kotlin call ends with that error.
|
|
219
|
+
*/
|
|
220
|
+
template <class F>
|
|
221
|
+
jobject callSuspending(JNIEnv* env, F f) {
|
|
222
|
+
LucentScope scope;
|
|
223
|
+
try {
|
|
224
|
+
return f();
|
|
225
|
+
} catch (...) {
|
|
226
|
+
throwToJava(env, currentError(std::current_exception()));
|
|
227
|
+
return nullptr;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
namespace detail {
|
|
232
|
+
|
|
233
|
+
/// A java.util.function.BiConsumer whose accept(value, error) calls
|
|
234
|
+
/// `settle`, where Java calls it. A local reference, new for each call.
|
|
235
|
+
jobject completionFor(JNIEnv* env, std::function<void(JNIEnv*, jobject value, jobject error)> settle);
|
|
236
|
+
|
|
237
|
+
} // namespace detail
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* A suspend function called through a generated Kotlin shim, as a promise
|
|
241
|
+
* of the calling context. `start` calls the shim with a completion (a
|
|
242
|
+
* BiConsumer of the value, or of the Throwable it threw) and returns what
|
|
243
|
+
* cancels the coroutine (an AutoCloseable). `convert` reads the value,
|
|
244
|
+
* where the coroutine completes. The signal aborting, or the context's
|
|
245
|
+
* scope being disposed, rejects the promise and cancels the coroutine; a
|
|
246
|
+
* value that arrives after that is released (nativeOperation).
|
|
247
|
+
*/
|
|
248
|
+
template <class T>
|
|
249
|
+
Promise<T> launch(Opt<AbortSignal> signal, const char* what, const std::function<jobject(JNIEnv*, jobject)>& start,
|
|
250
|
+
std::function<::lucent::detail::Stored<T>(JNIEnv*, jobject)> convert) {
|
|
251
|
+
auto registration = [&start, convert = std::move(convert), what](const std::shared_ptr<Operation<T>>& op) -> std::function<void()> {
|
|
252
|
+
JNIEnv* e = env();
|
|
253
|
+
LocalFrame frame(e);
|
|
254
|
+
std::weak_ptr<Operation<T>> pending = op;
|
|
255
|
+
|
|
256
|
+
jobject done = detail::completionFor(e, [pending, convert](JNIEnv* e, jobject value, jobject error) {
|
|
257
|
+
auto o = pending.lock();
|
|
258
|
+
if (!o) return;
|
|
259
|
+
|
|
260
|
+
if (error) {
|
|
261
|
+
o->fail(errorOf(e, error));
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
try {
|
|
266
|
+
if constexpr (std::is_void_v<T>) {
|
|
267
|
+
o->succeed();
|
|
268
|
+
} else {
|
|
269
|
+
o->succeed(convert(e, value));
|
|
270
|
+
}
|
|
271
|
+
} catch (...) {
|
|
272
|
+
o->fail(currentError(std::current_exception()));
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
jobject cancel = start(e, done);
|
|
277
|
+
check(e);
|
|
278
|
+
|
|
279
|
+
NativeRef stop = wrap(e, cancel, what);
|
|
280
|
+
return [stop] { close(stop); };
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
return nativeOperation<T>(registration, std::move(signal));
|
|
284
|
+
}
|
|
285
|
+
|
|
112
286
|
/// `appContext()` from lucent:android: the Application.
|
|
113
287
|
NativeRef appContext();
|
|
288
|
+
|
|
289
|
+
/// The context of the view hosting the mount whose setup runs now on this
|
|
290
|
+
/// thread (the Activity's, as React Native themes its views), or null
|
|
291
|
+
/// outside any setup.
|
|
292
|
+
Opt<NativeRef> hostContext();
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* While one lives, `view` (a local reference) hosts the mount whose setup
|
|
296
|
+
* runs on this thread, and hostContext() is its context: the Android host
|
|
297
|
+
* of components holds one around each setup. Nests.
|
|
298
|
+
*/
|
|
299
|
+
class HostViewEntry {
|
|
300
|
+
public:
|
|
301
|
+
explicit HostViewEntry(jobject view);
|
|
302
|
+
~HostViewEntry();
|
|
303
|
+
|
|
304
|
+
HostViewEntry(const HostViewEntry&) = delete;
|
|
305
|
+
HostViewEntry& operator=(const HostViewEntry&) = delete;
|
|
306
|
+
|
|
307
|
+
private:
|
|
308
|
+
jobject outer_;
|
|
309
|
+
};
|
|
114
310
|
/// `available("android", api)`.
|
|
115
311
|
bool available(double api);
|
|
116
312
|
|
|
313
|
+
// --- the app's Activities (platform/android_activity.cpp) ------------------------------
|
|
314
|
+
|
|
315
|
+
/// `currentActivity()` from lucent:android: the Activity in front (created,
|
|
316
|
+
/// started or resumed, and not destroyed), or null. Lucent holds Activities
|
|
317
|
+
/// weakly; the reference returned is one, for the caller's use now.
|
|
318
|
+
Opt<NativeRef> currentActivity();
|
|
319
|
+
|
|
320
|
+
/// `startActivityForResult(intent, signal)`: starts `intent` from the
|
|
321
|
+
/// Activity in front, through Lucent's request Activity, and resolves with
|
|
322
|
+
/// an android.app.Instrumentation.ActivityResult. Rejects with
|
|
323
|
+
/// ERR_NO_ACTIVITY without one; an aborted signal or the calling context's
|
|
324
|
+
/// root disposed cancels it, and a later answer is dropped.
|
|
325
|
+
Promise<NativeRef> startActivityForResult(const NativeRef& intent, Opt<AbortSignal> signal = {});
|
|
326
|
+
|
|
327
|
+
/// `requestPermissions(permissions, signal)`: whether each was granted, in
|
|
328
|
+
/// order. Requests run one at a time, as Android requires.
|
|
329
|
+
Promise<Array<bool>> requestPermissions(const Array<String>& permissions, Opt<AbortSignal> signal = {});
|
|
330
|
+
|
|
331
|
+
/// A lifecycle event's handler: the Activity, and the intent of a new intent.
|
|
332
|
+
using ActivityHandler = Fn<void(NativeRef, Opt<NativeRef>)>;
|
|
333
|
+
|
|
334
|
+
/// `onActivityEvent(event, handler)`: runs `handler` on the subscribing
|
|
335
|
+
/// context after each such event of the app's Activities ("created",
|
|
336
|
+
/// "started", "resumed", "paused", "stopped", "destroyed", "newIntent").
|
|
337
|
+
/// Returns the function that unsubscribes.
|
|
338
|
+
Fn<void()> onActivityEvent(const String& event, ActivityHandler handler);
|
|
339
|
+
|
|
117
340
|
} // namespace lucent::jni
|