@lucent-lang/lucent 0.0.4 → 0.1.1
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-eEez4jhQ.js} +10 -6
- package/dist/{build-CAIrRSYA.js → build-CpUjeHFz.js} +1 -1
- package/dist/{build-check-QozuNJm5.js → build-check-BA1ZEp9s.js} +28 -13
- package/dist/{check-1SCmYlqA.js → check-BZx3FgI6.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-CC-HXhcd.js} +2 -2
- package/dist/{dev-BYWMP7oC.js → dev-DI5yL8zx.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-BM_VM2X_.js +700 -0
- package/dist/project-BKNoTEEp.js +342 -0
- package/dist/sdk-coverage-iiv3JqMp.js +113 -0
- package/dist/sdk-diff-ByJ1Gw-F.js +109 -0
- package/dist/sdk-lock-BQn7IyRs.js +38 -0
- package/dist/{sdk-prefetch-mo04JDZV.js → sdk-prefetch-Bv2pNega.js} +2 -2
- package/dist/{sdk-search-Iv4K3-8a.js → sdk-search-CPGJm_Ne.js} +2 -2
- package/dist/{sdk-show-CkrdlqlP.js → sdk-show-BUkLqRnA.js} +5 -4
- package/dist/sdk-usage-0ZFMAYg1.js +95 -0
- package/dist/src-ChnmWLwn.js +40851 -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 +4 -3
- 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 +85 -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
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
#include "view.h"
|
|
2
|
+
|
|
3
|
+
#include <string>
|
|
4
|
+
#include <utility>
|
|
5
|
+
#include <vector>
|
|
6
|
+
|
|
7
|
+
#include "execution.h"
|
|
8
|
+
#include "report.h"
|
|
9
|
+
|
|
10
|
+
namespace lucent::ui {
|
|
11
|
+
|
|
12
|
+
std::shared_ptr<Graph> mainGraph() {
|
|
13
|
+
// Never destroyed, as the main context is not: nothing disposes at exit.
|
|
14
|
+
static auto* graph = new std::shared_ptr<Graph>(Graph::create(ExecutionContext::main()));
|
|
15
|
+
|
|
16
|
+
return *graph;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
void reportViewError(std::exception_ptr error, const char* component, const char* what, const char* source) {
|
|
20
|
+
std::string where = std::string(component) + " " + what + " (" + source + ")";
|
|
21
|
+
|
|
22
|
+
reportUncaught(error, where.c_str());
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
namespace {
|
|
26
|
+
|
|
27
|
+
/// Where the main thread is in its mounts' code. Main thread only.
|
|
28
|
+
struct Entries {
|
|
29
|
+
std::weak_ptr<Content> active;
|
|
30
|
+
int depth = 0;
|
|
31
|
+
std::vector<std::weak_ptr<Content>> marked;
|
|
32
|
+
bool flushPosted = false;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
Entries& entries() {
|
|
36
|
+
// Never destroyed: contents may outlive static destruction.
|
|
37
|
+
static auto* state = new Entries();
|
|
38
|
+
|
|
39
|
+
return *state;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/// Hosts call their mounts from the main thread, in the main context or not.
|
|
43
|
+
bool onMainExecutor() { return ExecutionContext::main().onExecutor(); }
|
|
44
|
+
|
|
45
|
+
} // namespace
|
|
46
|
+
|
|
47
|
+
std::shared_ptr<Content> Content::create(std::function<void()> changed) {
|
|
48
|
+
return std::make_shared<Content>(Token{}, std::move(changed));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
void Content::invalidate() {
|
|
52
|
+
if (marked_ || measuring_ || !onMainExecutor()) return;
|
|
53
|
+
|
|
54
|
+
auto& e = entries();
|
|
55
|
+
|
|
56
|
+
marked_ = true;
|
|
57
|
+
// Held weakly: a mount that goes before the flush is not measured.
|
|
58
|
+
e.marked.push_back(weak_from_this());
|
|
59
|
+
|
|
60
|
+
if (e.depth > 0 || e.flushPosted) return;
|
|
61
|
+
|
|
62
|
+
e.flushPosted = true;
|
|
63
|
+
ExecutionContext::main().post([] {
|
|
64
|
+
entries().flushPosted = false;
|
|
65
|
+
flush();
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
void Content::flush() {
|
|
70
|
+
auto& e = entries();
|
|
71
|
+
|
|
72
|
+
// Marks made while hosts measure wait for the next flush.
|
|
73
|
+
auto marked = std::move(e.marked);
|
|
74
|
+
|
|
75
|
+
e.marked.clear();
|
|
76
|
+
|
|
77
|
+
for (auto& weak : marked) {
|
|
78
|
+
auto content = weak.lock();
|
|
79
|
+
|
|
80
|
+
if (!content) continue;
|
|
81
|
+
|
|
82
|
+
content->marked_ = false;
|
|
83
|
+
content->measuring_ = true;
|
|
84
|
+
|
|
85
|
+
try {
|
|
86
|
+
content->changed_();
|
|
87
|
+
} catch (...) {
|
|
88
|
+
reportUncaught(std::current_exception(), "a component's measurement");
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
content->measuring_ = false;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
std::weak_ptr<Content> activeContent() { return onMainExecutor() ? entries().active : std::weak_ptr<Content>(); }
|
|
96
|
+
|
|
97
|
+
ContentEntry::ContentEntry(const std::weak_ptr<Content>& content) {
|
|
98
|
+
if (!onMainExecutor()) return;
|
|
99
|
+
|
|
100
|
+
auto& e = entries();
|
|
101
|
+
|
|
102
|
+
entered_ = true;
|
|
103
|
+
outer_ = std::exchange(e.active, content);
|
|
104
|
+
++e.depth;
|
|
105
|
+
|
|
106
|
+
if (auto entered = content.lock()) entered->invalidate();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
ContentEntry::~ContentEntry() {
|
|
110
|
+
if (!entered_) return;
|
|
111
|
+
|
|
112
|
+
auto& e = entries();
|
|
113
|
+
|
|
114
|
+
e.active = std::move(outer_);
|
|
115
|
+
|
|
116
|
+
if (--e.depth == 0) Content::flush();
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
void invalidateSize(const std::weak_ptr<Content>& content) {
|
|
120
|
+
if (auto target = content.lock()) target->invalidate();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
} // namespace lucent::ui
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
// Lucent runtime — what compiled views share: the main context's reactive
|
|
2
|
+
// graph, their events' routes, where their errors go, and how a mount's
|
|
3
|
+
// host hears that the mount's code ran.
|
|
4
|
+
//
|
|
5
|
+
// A component's setup runs once per mount, on the main context, inside the
|
|
6
|
+
// mount's scope (reactive.h). Its props are signals of that graph; its
|
|
7
|
+
// events are routes its host points at the mount's current event emitter.
|
|
8
|
+
// Nothing here knows React Native: the generated mount glue does.
|
|
9
|
+
//
|
|
10
|
+
// A host sizing a component by its content must measure it again after
|
|
11
|
+
// the mount's code changed its views. It cannot see those changes, so it
|
|
12
|
+
// hears of every entry into the mount instead (Content): its own calls
|
|
13
|
+
// (setup, commits, commands) and every function the setup made (native
|
|
14
|
+
// callbacks, effects, handlers), which enter the mount whenever they run.
|
|
15
|
+
// The host hears once, when the outermost entry on the main thread ends.
|
|
16
|
+
#pragma once
|
|
17
|
+
|
|
18
|
+
#include <exception>
|
|
19
|
+
#include <functional>
|
|
20
|
+
#include <memory>
|
|
21
|
+
#include <type_traits>
|
|
22
|
+
#include <utility>
|
|
23
|
+
#include <vector>
|
|
24
|
+
|
|
25
|
+
#include "json.h"
|
|
26
|
+
#include "reactive.h"
|
|
27
|
+
|
|
28
|
+
namespace lucent::ui {
|
|
29
|
+
|
|
30
|
+
/// The main context's graph, which every view's props, signals and effects
|
|
31
|
+
/// share. Made on first use; used only on the main context.
|
|
32
|
+
std::shared_ptr<Graph> mainGraph();
|
|
33
|
+
|
|
34
|
+
/// A component's event, as its setup sees it: calling it sends the
|
|
35
|
+
/// arguments along the route its host installed, or nowhere without one.
|
|
36
|
+
/// Copies share the route, so the host redirects events (a new emitter,
|
|
37
|
+
/// JavaScript no longer listening) without the setup, or the native
|
|
38
|
+
/// subscriptions it made, running again. Used on the main context.
|
|
39
|
+
template <class... Args>
|
|
40
|
+
class Event {
|
|
41
|
+
public:
|
|
42
|
+
using Route = std::function<void(Args...)>;
|
|
43
|
+
|
|
44
|
+
Event() : route_(std::make_shared<Route>()) {}
|
|
45
|
+
|
|
46
|
+
void route(Route route) const { *route_ = std::move(route); }
|
|
47
|
+
|
|
48
|
+
void operator()(Args... args) const {
|
|
49
|
+
// A copy: the route may replace itself while it runs.
|
|
50
|
+
if (Route r = *route_) r(std::move(args)...);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
private:
|
|
54
|
+
std::shared_ptr<Route> route_;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
} // namespace lucent::ui
|
|
58
|
+
|
|
59
|
+
namespace lucent {
|
|
60
|
+
|
|
61
|
+
// A signal as a JavaScript value: an object compared by identity, whose
|
|
62
|
+
// JSON is an object with no own properties.
|
|
63
|
+
template <class T>
|
|
64
|
+
bool strictEquals(const ui::Signal<T>& a, const ui::Signal<T>& b) {
|
|
65
|
+
return a.identity() == b.identity();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
template <class T>
|
|
69
|
+
String toJsString(const ui::Signal<T>&) {
|
|
70
|
+
return String::fromLatin1("[object Object]");
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
template <class T>
|
|
74
|
+
void jsonWrite(JsonWriter& w, const ui::Signal<T>&) {
|
|
75
|
+
w.raw("{}");
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
} // namespace lucent
|
|
79
|
+
|
|
80
|
+
namespace lucent::ui {
|
|
81
|
+
|
|
82
|
+
/// Reports a view's error nobody can catch (its setup's, a command's) with
|
|
83
|
+
/// the component's identity, what failed and the source line it maps to.
|
|
84
|
+
void reportViewError(std::exception_ptr error, const char* component, const char* what, const char* source);
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* A mount's native content, as its host sizes it. Marked whenever the
|
|
88
|
+
* mount's code runs, or by invalidateSize(); the host's `changed` runs
|
|
89
|
+
* once for any number of marks: when the outermost entry into a mount
|
|
90
|
+
* ends, or in a later turn of the main context for a mark made outside
|
|
91
|
+
* any. Marks made while `changed` runs (measuring may run the mount's
|
|
92
|
+
* code) are not changes. Main thread only.
|
|
93
|
+
*/
|
|
94
|
+
class Content : public std::enable_shared_from_this<Content> {
|
|
95
|
+
struct Token {};
|
|
96
|
+
|
|
97
|
+
public:
|
|
98
|
+
static std::shared_ptr<Content> create(std::function<void()> changed);
|
|
99
|
+
|
|
100
|
+
Content(Token, std::function<void()> changed) : changed_(std::move(changed)) {}
|
|
101
|
+
|
|
102
|
+
Content(const Content&) = delete;
|
|
103
|
+
Content& operator=(const Content&) = delete;
|
|
104
|
+
|
|
105
|
+
/// Marks the content changed.
|
|
106
|
+
void invalidate();
|
|
107
|
+
|
|
108
|
+
private:
|
|
109
|
+
friend class ContentEntry;
|
|
110
|
+
|
|
111
|
+
/// Runs `changed` for what is marked.
|
|
112
|
+
static void flush();
|
|
113
|
+
|
|
114
|
+
std::function<void()> changed_;
|
|
115
|
+
bool marked_ = false;
|
|
116
|
+
bool measuring_ = false;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
/// The content of the mount whose code runs now on the main thread (empty
|
|
120
|
+
/// outside any, and off the main thread).
|
|
121
|
+
std::weak_ptr<Content> activeContent();
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* While one lives, `content`'s mount runs (on the main thread, in the main
|
|
125
|
+
* context or not, as hosts call their mounts; elsewhere, or for a mount
|
|
126
|
+
* that has gone, it does nothing): the content is marked, and ending the
|
|
127
|
+
* outermost entry reports every content marked meanwhile.
|
|
128
|
+
*/
|
|
129
|
+
class ContentEntry {
|
|
130
|
+
public:
|
|
131
|
+
explicit ContentEntry(const std::weak_ptr<Content>& content);
|
|
132
|
+
~ContentEntry();
|
|
133
|
+
|
|
134
|
+
ContentEntry(const ContentEntry&) = delete;
|
|
135
|
+
ContentEntry& operator=(const ContentEntry&) = delete;
|
|
136
|
+
|
|
137
|
+
private:
|
|
138
|
+
bool entered_ = false;
|
|
139
|
+
std::weak_ptr<Content> outer_;
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
/// `f`, entering `content`'s mount whenever it runs: a function a setup made.
|
|
143
|
+
template <class F>
|
|
144
|
+
auto inContent(std::weak_ptr<Content> content, F f) {
|
|
145
|
+
return [content = std::move(content), f = std::move(f)](auto&&... args) mutable
|
|
146
|
+
-> std::invoke_result_t<F&, decltype(args)...> {
|
|
147
|
+
ContentEntry entry(content);
|
|
148
|
+
|
|
149
|
+
return f(std::forward<decltype(args)>(args)...);
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/// lucent:ui's invalidateSize(): marks `content` (the mount of the setup
|
|
154
|
+
/// the call is written in) changed; nothing once the mount has gone.
|
|
155
|
+
void invalidateSize(const std::weak_ptr<Content>& content);
|
|
156
|
+
|
|
157
|
+
} // namespace lucent::ui
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
// Lucent runtime — the iOS host of Lucent components in React Native's
|
|
2
|
+
// Fabric renderer.
|
|
3
|
+
//
|
|
4
|
+
// Each component's generated `<registration>ComponentView` derives from
|
|
5
|
+
// LucentComponentView, which does what every component's host does: it
|
|
6
|
+
// mounts the component when a commit reaches the view on the main thread
|
|
7
|
+
// (never while React renders or the renderer builds shadow trees), gives the
|
|
8
|
+
// mount a token, hands later commits and commands to it, and ends it when
|
|
9
|
+
// the view is recycled. The setup's view fills the host's content box, and
|
|
10
|
+
// the host measures it for a component with no size of its own
|
|
11
|
+
// (LucentViewSizing.h). The React children React Native mounts in the view
|
|
12
|
+
// go in the slot the host makes for each mount of a component taking them,
|
|
13
|
+
// never beside the content (LucentViewChildren.h), and the host reports
|
|
14
|
+
// where that slot is, for Yoga to lay them out in it (LucentViewSlots.h). A
|
|
15
|
+
// view that comes with its controller (a SwiftUI component's) has the
|
|
16
|
+
// controller contained in the nearest view controller above the host, as
|
|
17
|
+
// soon as there is one, until the mount ends, and laid out in the host's
|
|
18
|
+
// direction. The generated subclass provides the renderer's descriptor and
|
|
19
|
+
// the component's Lucent side (a Mounted).
|
|
20
|
+
//
|
|
21
|
+
// Everything runs on the main thread, in Lucent's main context.
|
|
22
|
+
#pragma once
|
|
23
|
+
|
|
24
|
+
#import <React/RCTViewComponentView.h>
|
|
25
|
+
|
|
26
|
+
#include <folly/dynamic.h>
|
|
27
|
+
#include <react/renderer/core/EventEmitter.h>
|
|
28
|
+
#include <react/renderer/core/Props.h>
|
|
29
|
+
|
|
30
|
+
#include <lucent/native.h>
|
|
31
|
+
|
|
32
|
+
#include <memory>
|
|
33
|
+
#include <optional>
|
|
34
|
+
#include <string>
|
|
35
|
+
|
|
36
|
+
#include "LucentViewRequests.h"
|
|
37
|
+
#include "LucentViews.h"
|
|
38
|
+
|
|
39
|
+
@class LucentComponentView;
|
|
40
|
+
|
|
41
|
+
namespace lucent::views {
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* One mount of a component on its host view: the component's Mount (its
|
|
45
|
+
* compiled setup, run once), as generated code adapts it for each
|
|
46
|
+
* component. Destroying it disposes the mount.
|
|
47
|
+
*/
|
|
48
|
+
class Mounted {
|
|
49
|
+
public:
|
|
50
|
+
virtual ~Mounted() = default;
|
|
51
|
+
|
|
52
|
+
/// The view the component's setup returned.
|
|
53
|
+
virtual UIView* view() const = 0;
|
|
54
|
+
|
|
55
|
+
/// The controller whose view view() is, which the host contains in the
|
|
56
|
+
/// nearest view controller above it (a SwiftUI component's hosting
|
|
57
|
+
/// controller); nil for a plain view.
|
|
58
|
+
virtual UIViewController* controller() const { return nil; }
|
|
59
|
+
|
|
60
|
+
/// Applies a later commit's props (the component's own Props type): what
|
|
61
|
+
/// changed reaches setup's signals; setup does not run again.
|
|
62
|
+
virtual void update(const facebook::react::Props& props, const facebook::react::Props& previous) = 0;
|
|
63
|
+
|
|
64
|
+
/// Runs command `name`; a request answers through `requester`.
|
|
65
|
+
virtual void command(const std::string& name, const folly::dynamic& args, const Requester& requester) = 0;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/** What a mount knows of its host view. Main thread. */
|
|
69
|
+
class HostView {
|
|
70
|
+
public:
|
|
71
|
+
HostView() = default;
|
|
72
|
+
HostView(LucentComponentView* view, MountToken token) : view_(view), token_(token) {}
|
|
73
|
+
|
|
74
|
+
const MountToken& token() const { return token_; }
|
|
75
|
+
|
|
76
|
+
/// Whether the view still holds this mount (not recycled or remounted).
|
|
77
|
+
bool current() const;
|
|
78
|
+
|
|
79
|
+
/// The event emitter of the view's current commit while the view holds
|
|
80
|
+
/// this mount; else null, and events are dropped.
|
|
81
|
+
std::shared_ptr<const facebook::react::EventEmitter> emitter() const;
|
|
82
|
+
|
|
83
|
+
/// The view the host made for this mount's React children (a component
|
|
84
|
+
/// taking them), while the view holds this mount; else empty.
|
|
85
|
+
lucent::NativeRef slot() const;
|
|
86
|
+
|
|
87
|
+
private:
|
|
88
|
+
__weak LucentComponentView* view_;
|
|
89
|
+
MountToken token_;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
} // namespace lucent::views
|
|
93
|
+
|
|
94
|
+
@interface LucentComponentView : RCTViewComponentView
|
|
95
|
+
|
|
96
|
+
/// The token of the mount the view holds, or a zero generation.
|
|
97
|
+
@property (nonatomic, readonly) lucent::views::MountToken lucentToken;
|
|
98
|
+
|
|
99
|
+
/// The event emitter of the view's current commit.
|
|
100
|
+
@property (nonatomic, readonly) std::shared_ptr<const facebook::react::EventEmitter> lucentEventEmitter;
|
|
101
|
+
|
|
102
|
+
/// Registers a component's view class with React Native's component view
|
|
103
|
+
/// factory: generated classes call it as they load.
|
|
104
|
+
+ (void)lucentRegister:(Class)componentViewClass;
|
|
105
|
+
|
|
106
|
+
/// Whether the component takes React children: its host then makes a slot
|
|
107
|
+
/// for them with each mount (implemented by each component taking them).
|
|
108
|
+
+ (BOOL)lucentTakesChildren;
|
|
109
|
+
|
|
110
|
+
/// The slot of the mount the view holds, or nil.
|
|
111
|
+
@property (nonatomic, readonly) UIView *lucentSlot;
|
|
112
|
+
|
|
113
|
+
/// The request id a command carries, if it is a request (implemented by
|
|
114
|
+
/// each component with commands).
|
|
115
|
+
- (std::optional<double>)lucentRequestId:(const std::string &)name args:(const folly::dynamic &)args;
|
|
116
|
+
|
|
117
|
+
/// Implemented by each component: sets it up for `props` on this view.
|
|
118
|
+
- (std::unique_ptr<lucent::views::Mounted>)lucentMount:(const facebook::react::Props &)props
|
|
119
|
+
host:(lucent::views::HostView)host;
|
|
120
|
+
|
|
121
|
+
@end
|