react-native-unistyles 3.4.0 → 3.5.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 +23 -7
- package/android/build.gradle +12 -1
- package/android/src/main/cxx/NativeUnistylesModule.cpp +8 -4
- package/android/src/main/cxx/NativeUnistylesModule.h +5 -1
- package/components/native/ActivityIndicator/package.json +1 -1
- package/cxx/common/UnistylesConstants.h +1 -0
- package/cxx/converters/TransformOriginConverter.cpp +106 -0
- package/cxx/core/StyleSheetRegistry.cpp +9 -9
- package/cxx/core/StyleSheetRegistry.h +3 -3
- package/cxx/core/UnistyleWrapper.h +13 -1
- package/cxx/core/UnistylesRegistry.cpp +102 -18
- package/cxx/core/UnistylesRegistry.h +42 -5
- package/cxx/hybridObjects/HybridShadowRegistry.cpp +124 -4
- package/cxx/hybridObjects/HybridShadowRegistry.h +20 -0
- package/cxx/hybridObjects/HybridStyleSheet.cpp +20 -12
- package/cxx/hybridObjects/HybridUnistylesRuntime.cpp +11 -1
- package/cxx/hybridObjects/HybridUnistylesRuntime.h +4 -2
- package/cxx/parser/Parser.cpp +29 -1
- package/cxx/parser/Parser.h +1 -0
- package/cxx/shadowTree/NativeProps.h +46 -2
- package/cxx/shadowTree/ShadowTrafficController.h +4 -0
- package/cxx/shadowTree/ShadowTreeDiagnostics.cpp +339 -0
- package/cxx/shadowTree/ShadowTreeDiagnostics.h +18 -0
- package/cxx/shadowTree/ShadowTreeManager.cpp +7 -1
- package/cxx/shadowTree/ShadowTreeManager.h +1 -1
- package/diagnostics/package.json +6 -0
- package/ios/UnistylesModuleOnLoad.mm +9 -3
- package/lib/commonjs/components/native/ActivityIndicator.native.js +10 -0
- package/lib/commonjs/components/native/ActivityIndicator.native.js.map +1 -0
- package/lib/commonjs/components/native/NativeText.js +6 -0
- package/lib/commonjs/components/native/NativeText.js.map +1 -1
- package/lib/commonjs/components/native/NativeText.native.js +17 -1
- package/lib/commonjs/components/native/NativeText.native.js.map +1 -1
- package/lib/commonjs/components/native/NativeView.js +6 -0
- package/lib/commonjs/components/native/NativeView.js.map +1 -1
- package/lib/commonjs/components/native/NativeView.native.js +22 -3
- package/lib/commonjs/components/native/NativeView.native.js.map +1 -1
- package/lib/commonjs/components/native/Pressable.js +7 -3
- package/lib/commonjs/components/native/Pressable.js.map +1 -1
- package/lib/commonjs/components/native/TouchableHighlight.native.js +10 -0
- package/lib/commonjs/components/native/TouchableHighlight.native.js.map +1 -0
- package/lib/commonjs/core/createUnistylesActivityIndicator.js +41 -0
- package/lib/commonjs/core/createUnistylesActivityIndicator.js.map +1 -0
- package/lib/commonjs/core/createUnistylesElement.js +59 -14
- package/lib/commonjs/core/createUnistylesElement.js.map +1 -1
- package/lib/commonjs/core/createUnistylesTouchableHighlight.js +58 -0
- package/lib/commonjs/core/createUnistylesTouchableHighlight.js.map +1 -0
- package/lib/commonjs/core/index.js +14 -0
- package/lib/commonjs/core/index.js.map +1 -1
- package/lib/commonjs/diagnostics/index.js +13 -0
- package/lib/commonjs/diagnostics/index.js.map +1 -0
- package/lib/commonjs/diagnostics/types.js +2 -0
- package/lib/commonjs/diagnostics/types.js.map +1 -0
- package/lib/commonjs/diagnostics/verify.js +19 -0
- package/lib/commonjs/diagnostics/verify.js.map +1 -0
- package/lib/commonjs/diagnostics/verify.native.js +12 -0
- package/lib/commonjs/diagnostics/verify.native.js.map +1 -0
- package/lib/commonjs/index.js +38 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/mocks.js +41 -0
- package/lib/commonjs/mocks.js.map +1 -1
- package/lib/commonjs/reanimated/variant/useUpdateVariantColor.native.js +8 -0
- package/lib/commonjs/reanimated/variant/useUpdateVariantColor.native.js.map +1 -1
- package/lib/commonjs/specs/ShadowRegistry/index.js +97 -1
- package/lib/commonjs/specs/ShadowRegistry/index.js.map +1 -1
- package/lib/commonjs/specs/StyleSheet/index.js +5 -1
- package/lib/commonjs/specs/StyleSheet/index.js.map +1 -1
- package/lib/commonjs/specs/UnistylesRuntime/index.js.map +1 -1
- package/lib/commonjs/web/registry.js +3 -0
- package/lib/commonjs/web/registry.js.map +1 -1
- package/lib/module/components/native/ActivityIndicator.native.js +6 -0
- package/lib/module/components/native/ActivityIndicator.native.js.map +1 -0
- package/lib/module/components/native/NativeText.js +1 -1
- package/lib/module/components/native/NativeText.js.map +1 -1
- package/lib/module/components/native/NativeText.native.js +15 -1
- package/lib/module/components/native/NativeText.native.js.map +1 -1
- package/lib/module/components/native/NativeView.js +1 -0
- package/lib/module/components/native/NativeView.js.map +1 -1
- package/lib/module/components/native/NativeView.native.js +19 -2
- package/lib/module/components/native/NativeView.native.js.map +1 -1
- package/lib/module/components/native/Pressable.js +7 -3
- package/lib/module/components/native/Pressable.js.map +1 -1
- package/lib/module/components/native/TouchableHighlight.native.js +6 -0
- package/lib/module/components/native/TouchableHighlight.native.js.map +1 -0
- package/lib/module/core/createUnistylesActivityIndicator.js +35 -0
- package/lib/module/core/createUnistylesActivityIndicator.js.map +1 -0
- package/lib/module/core/createUnistylesElement.js +58 -13
- package/lib/module/core/createUnistylesElement.js.map +1 -1
- package/lib/module/core/createUnistylesTouchableHighlight.js +52 -0
- package/lib/module/core/createUnistylesTouchableHighlight.js.map +1 -0
- package/lib/module/core/index.js +2 -0
- package/lib/module/core/index.js.map +1 -1
- package/lib/module/diagnostics/index.js +5 -0
- package/lib/module/diagnostics/index.js.map +1 -0
- package/lib/module/diagnostics/types.js +2 -0
- package/lib/module/diagnostics/types.js.map +1 -0
- package/lib/module/diagnostics/verify.js +14 -0
- package/lib/module/diagnostics/verify.js.map +1 -0
- package/lib/module/diagnostics/verify.native.js +8 -0
- package/lib/module/diagnostics/verify.native.js.map +1 -0
- package/lib/module/index.js +2 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/mocks.js +41 -0
- package/lib/module/mocks.js.map +1 -1
- package/lib/module/reanimated/variant/useUpdateVariantColor.native.js +9 -1
- package/lib/module/reanimated/variant/useUpdateVariantColor.native.js.map +1 -1
- package/lib/module/specs/ShadowRegistry/index.js +97 -1
- package/lib/module/specs/ShadowRegistry/index.js.map +1 -1
- package/lib/module/specs/StyleSheet/index.js +6 -1
- package/lib/module/specs/StyleSheet/index.js.map +1 -1
- package/lib/module/specs/UnistylesRuntime/index.js.map +1 -1
- package/lib/module/web/registry.js +3 -0
- package/lib/module/web/registry.js.map +1 -1
- package/lib/typescript/src/components/native/ActivityIndicator.native.d.ts +2 -0
- package/lib/typescript/src/components/native/ActivityIndicator.native.d.ts.map +1 -0
- package/lib/typescript/src/components/native/NativeText.d.ts +1 -1
- package/lib/typescript/src/components/native/NativeText.d.ts.map +1 -1
- package/lib/typescript/src/components/native/NativeText.native.d.ts.map +1 -1
- package/lib/typescript/src/components/native/NativeView.d.ts +1 -0
- package/lib/typescript/src/components/native/NativeView.d.ts.map +1 -1
- package/lib/typescript/src/components/native/NativeView.native.d.ts +2 -2
- package/lib/typescript/src/components/native/NativeView.native.d.ts.map +1 -1
- package/lib/typescript/src/components/native/Pressable.d.ts.map +1 -1
- package/lib/typescript/src/components/native/TouchableHighlight.native.d.ts +2 -0
- package/lib/typescript/src/components/native/TouchableHighlight.native.d.ts.map +1 -0
- package/lib/typescript/src/core/createUnistylesActivityIndicator.d.ts +3 -0
- package/lib/typescript/src/core/createUnistylesActivityIndicator.d.ts.map +1 -0
- package/lib/typescript/src/core/createUnistylesElement.d.ts.map +1 -1
- package/lib/typescript/src/core/createUnistylesTouchableHighlight.d.ts +3 -0
- package/lib/typescript/src/core/createUnistylesTouchableHighlight.d.ts.map +1 -0
- package/lib/typescript/src/core/index.d.ts +2 -0
- package/lib/typescript/src/core/index.d.ts.map +1 -1
- package/lib/typescript/src/core/useUnistyles.d.ts +1 -1
- package/lib/typescript/src/diagnostics/index.d.ts +3 -0
- package/lib/typescript/src/diagnostics/index.d.ts.map +1 -0
- package/lib/typescript/src/diagnostics/types.d.ts +19 -0
- package/lib/typescript/src/diagnostics/types.d.ts.map +1 -0
- package/lib/typescript/src/diagnostics/verify.d.ts +3 -0
- package/lib/typescript/src/diagnostics/verify.d.ts.map +1 -0
- package/lib/typescript/src/diagnostics/verify.native.d.ts +3 -0
- package/lib/typescript/src/diagnostics/verify.native.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +4 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/reanimated/variant/useUpdateVariantColor.native.d.ts.map +1 -1
- package/lib/typescript/src/specs/ShadowRegistry/index.d.ts +5 -1
- package/lib/typescript/src/specs/ShadowRegistry/index.d.ts.map +1 -1
- package/lib/typescript/src/specs/ShadowRegistry/types.d.ts +3 -0
- package/lib/typescript/src/specs/ShadowRegistry/types.d.ts.map +1 -1
- package/lib/typescript/src/specs/StyleSheet/index.d.ts +4 -1
- package/lib/typescript/src/specs/StyleSheet/index.d.ts.map +1 -1
- package/lib/typescript/src/specs/UnistylesRuntime/index.d.ts +2 -2
- package/lib/typescript/src/specs/UnistylesRuntime/index.d.ts.map +1 -1
- package/lib/typescript/src/types/breakpoints.d.ts +1 -1
- package/lib/typescript/src/types/breakpoints.d.ts.map +1 -1
- package/lib/typescript/src/types/stylesheet.d.ts +3 -3
- package/lib/typescript/src/types/stylesheet.d.ts.map +1 -1
- package/lib/typescript/src/web/registry.d.ts.map +1 -1
- package/package.json +9 -1
- package/plugin/index.d.ts +4 -4
- package/plugin/index.js +21 -5
- package/src/components/native/ActivityIndicator.native.tsx +5 -0
- package/src/components/native/NativeText.native.tsx +18 -1
- package/src/components/native/NativeText.tsx +1 -1
- package/src/components/native/NativeView.native.tsx +22 -2
- package/src/components/native/NativeView.tsx +2 -0
- package/src/components/native/Pressable.tsx +8 -3
- package/src/components/native/TouchableHighlight.native.tsx +5 -0
- package/src/core/createUnistylesActivityIndicator.tsx +47 -0
- package/src/core/createUnistylesElement.tsx +45 -14
- package/src/core/createUnistylesTouchableHighlight.tsx +69 -0
- package/src/core/index.ts +2 -0
- package/src/diagnostics/index.ts +3 -0
- package/src/diagnostics/types.ts +25 -0
- package/src/diagnostics/verify.native.ts +7 -0
- package/src/diagnostics/verify.ts +13 -0
- package/src/index.ts +4 -1
- package/src/mocks.ts +41 -0
- package/src/reanimated/variant/useUpdateVariantColor.native.ts +7 -1
- package/src/specs/ShadowRegistry/index.ts +128 -1
- package/src/specs/ShadowRegistry/types.ts +3 -0
- package/src/specs/StyleSheet/index.ts +10 -2
- package/src/specs/UnistylesRuntime/index.ts +7 -2
- package/src/types/breakpoints.ts +5 -3
- package/src/types/stylesheet.ts +3 -3
- package/src/web/registry.ts +3 -0
package/README.md
CHANGED
|
@@ -12,16 +12,18 @@
|
|
|
12
12
|
[](https://nextjs.org/)
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
##
|
|
15
|
+
## Requirements
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
- React Native 0.81+ with the New Architecture
|
|
18
|
+
- React 19+
|
|
19
|
+
- Expo SDK 54+ (if you use Expo, development builds only, Expo Go is not supported)
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
Need support for older React Native versions or the Old Architecture? Use [Unistyles 2.0](https://v2.unistyl.es).
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
22
24
|
|
|
23
25
|
```shell
|
|
24
|
-
yarn add react-native-nitro-modules
|
|
26
|
+
yarn add react-native-unistyles react-native-nitro-modules
|
|
25
27
|
```
|
|
26
28
|
|
|
27
29
|
| react-native-unistyles | Minimum react-native-nitro-modules |
|
|
@@ -29,6 +31,8 @@ yarn add react-native-nitro-modules
|
|
|
29
31
|
| >= 3.0.0 | >= 0.33.9 |
|
|
30
32
|
| >= 3.1.0 | >= 0.35.0 |
|
|
31
33
|
| >= 3.2.0 | >= 0.35.2 |
|
|
34
|
+
| >= 3.3.0 | >= 0.36.1 |
|
|
35
|
+
| >= 3.4.0 | >= 0.37.1 |
|
|
32
36
|
|
|
33
37
|
> **Note:** Since v3.1.0, `react-native-edge-to-edge` is an **optional** dependency. We strongly recommend setting `edgeToEdgeEnabled=true` in your `android/gradle.properties` — it enforces translucent system bars on modals, disables legacy StatusBar hacks, and enables additional React Native core fixes. **Expo SDK 54+** enables this automatically. You can still install `react-native-edge-to-edge` for ecosystem compatibility with libraries like `react-native-bootsplash` or `react-native-permissions`.
|
|
34
38
|
|
|
@@ -39,7 +43,19 @@ Then follow [installation guides](https://unistyl.es/v3/start/getting-started) f
|
|
|
39
43
|
- [Migration from Unistyles 2.0](https://unistyl.es/v3/start/migration-guide)
|
|
40
44
|
- [Learn how Unistyles 3.0 works](https://unistyl.es/v3/start/how-unistyles-works)
|
|
41
45
|
- [API](https://unistyl.es/v3/references/stylesheet)
|
|
42
|
-
- [
|
|
46
|
+
- [Tutorial](https://unistyl.es/v3/tutorial/intro)
|
|
47
|
+
- [LLMs](https://unistyl.es/v3/llms/info)
|
|
48
|
+
|
|
49
|
+
## AI agent skills
|
|
50
|
+
|
|
51
|
+
This repository ships skills for AI coding agents (Claude Code, Codex, Cursor and others):
|
|
52
|
+
|
|
53
|
+
- `react-native-unistyles-v3` - setup, theming, responsive styles, variants, web and 3rd party integrations
|
|
54
|
+
- `unistyles-v2-to-v3-migration` - step by step migration from Unistyles 2.0
|
|
55
|
+
|
|
56
|
+
```shell
|
|
57
|
+
npx skills add jpudysz/react-native-unistyles
|
|
58
|
+
```
|
|
43
59
|
|
|
44
60
|
## Features
|
|
45
61
|
- 🚀 Shared core with C++ and JSI bindings
|
package/android/build.gradle
CHANGED
|
@@ -18,9 +18,20 @@ def reactNativeArchitectures() {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
apply plugin: 'com.android.library'
|
|
21
|
-
|
|
21
|
+
// AGP 9 ships built-in Kotlin support and registers the `kotlin` extension
|
|
22
|
+
// itself. Applying the Kotlin plugin on top of it fails configuration with
|
|
23
|
+
// "Cannot add extension with name 'kotlin'". Only apply it when nothing has
|
|
24
|
+
// registered that extension yet.
|
|
25
|
+
if (project.extensions.findByName('kotlin') == null) {
|
|
26
|
+
apply plugin: 'org.jetbrains.kotlin.android'
|
|
27
|
+
}
|
|
28
|
+
|
|
22
29
|
apply from: '../nitrogen/generated/android/unistyles+autolinking.gradle'
|
|
23
30
|
|
|
31
|
+
// Nitrogen adds its generated Kotlin files to java.srcDirs, which AGP 9 built-in Kotlin
|
|
32
|
+
// doesn't compile. It only compiles Kotlin directories from the kotlin source set.
|
|
33
|
+
android.sourceSets.main.kotlin.srcDirs += ["${project.projectDir}/../nitrogen/generated/android/kotlin"]
|
|
34
|
+
|
|
24
35
|
def resolveBuildType() {
|
|
25
36
|
Gradle gradle = getGradle()
|
|
26
37
|
String tskReqStr = gradle.getStartParameter().getTaskRequests()['args'].toString()
|
|
@@ -31,11 +31,15 @@ void UnistylesModule::registerNatives() {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
jni::local_ref<BindingsInstallerHolder::javaobject> UnistylesModule::getBindingsInstaller(jni::alias_ref<UnistylesModule::javaobject> jobj) {
|
|
34
|
-
auto
|
|
35
|
-
auto&
|
|
34
|
+
auto* self = jobj->cthis();
|
|
35
|
+
auto& runtimeExecutor = self->_runtimeExecutor;
|
|
36
|
+
auto& nativePlatform = self->_nativePlatform;
|
|
36
37
|
|
|
37
|
-
return BindingsInstallerHolder::newObjectCxxArgs([&runtimeExecutor, &nativePlatform](jsi::Runtime& rt) {
|
|
38
|
+
return BindingsInstallerHolder::newObjectCxxArgs([self, &runtimeExecutor, &nativePlatform](jsi::Runtime& rt) {
|
|
38
39
|
// function is called on: first init and every live reload
|
|
40
|
+
// newest runtime owns the registry, previous runtime's state is kept until it releases ownership
|
|
41
|
+
self->_generation = core::UnistylesRegistry::get().takeOwnership();
|
|
42
|
+
|
|
39
43
|
// check if this is live reload, if so let's replace UnistylesRuntime with new runtime
|
|
40
44
|
auto hasUnistylesRuntime = HybridObjectRegistry::hasHybridObject("UnistylesRuntime");
|
|
41
45
|
|
|
@@ -52,7 +56,7 @@ jni::local_ref<BindingsInstallerHolder::javaobject> UnistylesModule::getBindings
|
|
|
52
56
|
};
|
|
53
57
|
|
|
54
58
|
// init hybrids
|
|
55
|
-
auto unistylesRuntime = std::make_shared<HybridUnistylesRuntime>(nativePlatform, runOnJSThread);
|
|
59
|
+
auto unistylesRuntime = std::make_shared<HybridUnistylesRuntime>(nativePlatform, runOnJSThread, self->_generation);
|
|
56
60
|
auto styleSheet = std::make_shared<HybridStyleSheet>(unistylesRuntime);
|
|
57
61
|
|
|
58
62
|
HybridObjectRegistry::registerHybridObjectConstructor("UnistylesRuntime", [unistylesRuntime]() -> std::shared_ptr<HybridObject>{
|
|
@@ -29,7 +29,10 @@ struct UnistylesModule : public jni::HybridClass<UnistylesModule> {
|
|
|
29
29
|
jni::alias_ref<JHybridNativePlatformSpec::JavaPart> nativePlatform
|
|
30
30
|
);
|
|
31
31
|
static void invalidateNative(jni::alias_ref<jhybridobject> jThis) {
|
|
32
|
-
|
|
32
|
+
auto* self = jThis->cthis();
|
|
33
|
+
|
|
34
|
+
// releases this runtime's state, also when a newer runtime already replaced it
|
|
35
|
+
core::UnistylesRegistry::get().releaseOwnership(self->_generation);
|
|
33
36
|
}
|
|
34
37
|
|
|
35
38
|
static jni::local_ref<BindingsInstallerHolder::javaobject> getBindingsInstaller(jni::alias_ref<UnistylesModule::javaobject> jThis);
|
|
@@ -37,6 +40,7 @@ struct UnistylesModule : public jni::HybridClass<UnistylesModule> {
|
|
|
37
40
|
private:
|
|
38
41
|
RuntimeExecutor _runtimeExecutor;
|
|
39
42
|
std::shared_ptr<HybridNativePlatformSpec> _nativePlatform;
|
|
43
|
+
uint64_t _generation = 0;
|
|
40
44
|
};
|
|
41
45
|
|
|
42
46
|
}
|
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
"main": "../../../lib/commonjs/components/native/ActivityIndicator.js",
|
|
3
3
|
"module": "../../../lib/module/components/native/ActivityIndicator.js",
|
|
4
4
|
"browser": "../../../lib/module/components/native/ActivityIndicator.js",
|
|
5
|
-
"react-native": "../../../src/components/native/ActivityIndicator.tsx"
|
|
5
|
+
"react-native": "../../../src/components/native/ActivityIndicator.native.tsx"
|
|
6
6
|
}
|
|
@@ -12,5 +12,6 @@ static const std::string EXOTIC_STYLE_KEY = "_exotic";
|
|
|
12
12
|
static const std::string ARGUMENTS = "__uni__args";
|
|
13
13
|
static const std::string GET_STYLES = "uni__getStyles";
|
|
14
14
|
static const std::string UNDEFINED_MARKER = "__unistyles_undefined__";
|
|
15
|
+
static const std::string RUNTIME_REPLACED_ERROR = "Unistyles: this runtime was replaced (reload in progress)";
|
|
15
16
|
|
|
16
17
|
}
|
|
@@ -1,13 +1,117 @@
|
|
|
1
1
|
#include "TransformOriginConverter.h"
|
|
2
2
|
|
|
3
|
+
#include <cxxreact/ReactNativeVersion.h>
|
|
4
|
+
|
|
5
|
+
// facebook::react::parseUnprocessedTransformOriginString was introduced in
|
|
6
|
+
// React Native 0.85, while conversions.h is available in every supported
|
|
7
|
+
// version, so the include alone is not enough to detect the parser.
|
|
3
8
|
#if defined(RN_SERIALIZABLE_STATE) && \
|
|
9
|
+
(REACT_NATIVE_VERSION_MAJOR > 0 || REACT_NATIVE_VERSION_MINOR >= 85) && \
|
|
4
10
|
__has_include(<react/renderer/components/view/conversions.h>)
|
|
5
11
|
#include <react/renderer/components/view/conversions.h>
|
|
6
12
|
#define UNISTYLES_HAS_RN_TRANSFORM_ORIGIN_PARSER 1
|
|
13
|
+
#elif defined(RN_SERIALIZABLE_STATE)
|
|
14
|
+
#include <algorithm>
|
|
15
|
+
#include <cctype>
|
|
16
|
+
#include <cstdlib>
|
|
17
|
+
#include <regex>
|
|
18
|
+
#define UNISTYLES_HAS_TRANSFORM_ORIGIN_FALLBACK 1
|
|
7
19
|
#endif
|
|
8
20
|
|
|
9
21
|
namespace margelo::nitro::unistyles::converters {
|
|
10
22
|
|
|
23
|
+
#ifdef UNISTYLES_HAS_TRANSFORM_ORIGIN_FALLBACK
|
|
24
|
+
namespace {
|
|
25
|
+
|
|
26
|
+
// Port of React Native's processTransformOrigin.js. Android forwards raw props
|
|
27
|
+
// to the view manager, which expects the processed [x, y, z] array, so a string
|
|
28
|
+
// must not reach it. Returns null (default origin) for an invalid value.
|
|
29
|
+
folly::dynamic processTransformOriginString(const std::string &value) {
|
|
30
|
+
static const std::regex tokenRegex(
|
|
31
|
+
"(top|bottom|left|right|center|\\d+(?:%|px)|0)", std::regex::icase);
|
|
32
|
+
constexpr size_t INDEX_X = 0;
|
|
33
|
+
constexpr size_t INDEX_Y = 1;
|
|
34
|
+
constexpr size_t INDEX_Z = 2;
|
|
35
|
+
|
|
36
|
+
auto toLower = [](std::string token) {
|
|
37
|
+
std::transform(token.begin(), token.end(), token.begin(),
|
|
38
|
+
[](unsigned char c) { return std::tolower(c); });
|
|
39
|
+
|
|
40
|
+
return token;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
folly::dynamic result = folly::dynamic::array("50%", "50%", 0);
|
|
44
|
+
size_t index = INDEX_X;
|
|
45
|
+
auto it = std::sregex_iterator(value.begin(), value.end(), tokenRegex);
|
|
46
|
+
const auto end = std::sregex_iterator();
|
|
47
|
+
|
|
48
|
+
for (; it != end; ++it) {
|
|
49
|
+
if (index > INDEX_Z) {
|
|
50
|
+
return nullptr;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
auto token = toLower(it->str());
|
|
54
|
+
auto nextIndex = index + 1;
|
|
55
|
+
|
|
56
|
+
if (token == "left" || token == "right") {
|
|
57
|
+
if (index != INDEX_X) {
|
|
58
|
+
return nullptr;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
result[INDEX_X] = token == "left" ? folly::dynamic(0) : folly::dynamic("100%");
|
|
62
|
+
} else if (token == "top" || token == "bottom") {
|
|
63
|
+
if (index == INDEX_Z) {
|
|
64
|
+
return nullptr;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
result[INDEX_Y] = token == "top" ? folly::dynamic(0) : folly::dynamic("100%");
|
|
68
|
+
|
|
69
|
+
// [ center | left | right ] after a vertical keyword in the first place
|
|
70
|
+
if (index == INDEX_X) {
|
|
71
|
+
if (++it == end) {
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
auto horizontal = toLower(it->str());
|
|
76
|
+
|
|
77
|
+
if (horizontal == "left") {
|
|
78
|
+
result[INDEX_X] = 0;
|
|
79
|
+
} else if (horizontal == "right") {
|
|
80
|
+
result[INDEX_X] = "100%";
|
|
81
|
+
} else if (horizontal == "center") {
|
|
82
|
+
result[INDEX_X] = "50%";
|
|
83
|
+
} else {
|
|
84
|
+
return nullptr;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
nextIndex = INDEX_Z;
|
|
88
|
+
}
|
|
89
|
+
} else if (token == "center") {
|
|
90
|
+
if (index == INDEX_Z) {
|
|
91
|
+
return nullptr;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
result[index] = "50%";
|
|
95
|
+
} else if (token.back() == '%') {
|
|
96
|
+
if (index == INDEX_Z) {
|
|
97
|
+
return nullptr;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
result[index] = token;
|
|
101
|
+
} else {
|
|
102
|
+
// 0 or <digits>px
|
|
103
|
+
result[index] = std::strtod(token.c_str(), nullptr);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
index = nextIndex;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return result;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
} // namespace
|
|
113
|
+
#endif
|
|
114
|
+
|
|
11
115
|
bool isTransformOriginPropName(const std::string &propertyName) {
|
|
12
116
|
return propertyName == "transformOrigin";
|
|
13
117
|
}
|
|
@@ -25,6 +129,8 @@ parseTransformOriginString(const std::string &transformOriginString) {
|
|
|
25
129
|
}
|
|
26
130
|
|
|
27
131
|
return static_cast<folly::dynamic>(transformOrigin);
|
|
132
|
+
#elif defined(UNISTYLES_HAS_TRANSFORM_ORIGIN_FALLBACK)
|
|
133
|
+
return processTransformOriginString(transformOriginString);
|
|
28
134
|
#else
|
|
29
135
|
return std::nullopt;
|
|
30
136
|
#endif
|
|
@@ -4,15 +4,15 @@
|
|
|
4
4
|
using namespace margelo::nitro::unistyles::core;
|
|
5
5
|
using namespace facebook;
|
|
6
6
|
|
|
7
|
-
std::shared_ptr<StyleSheet> StyleSheetRegistry::addStyleSheetFromValue(jsi::Runtime& rt, jsi::Object rawStyleSheet) {
|
|
7
|
+
std::shared_ptr<StyleSheet> StyleSheetRegistry::addStyleSheetFromValue(jsi::Runtime& rt, uint64_t generation, jsi::Object rawStyleSheet) {
|
|
8
8
|
if (rawStyleSheet.isFunction(rt)) {
|
|
9
|
-
return this->addFromFunction(rt, rawStyleSheet.asFunction(rt));
|
|
9
|
+
return this->addFromFunction(rt, generation, rawStyleSheet.asFunction(rt));
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
return this->addFromObject(rt, std::move(rawStyleSheet));
|
|
12
|
+
return this->addFromObject(rt, generation, std::move(rawStyleSheet));
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
std::shared_ptr<StyleSheet> StyleSheetRegistry::addFromFunction(jsi::Runtime& rt, jsi::Function styleSheetFn) {
|
|
15
|
+
std::shared_ptr<StyleSheet> StyleSheetRegistry::addFromFunction(jsi::Runtime& rt, uint64_t generation, jsi::Function styleSheetFn) {
|
|
16
16
|
auto numberOfArgs = styleSheetFn.getProperty(rt, "length").getNumber();
|
|
17
17
|
|
|
18
18
|
helpers::assertThat(rt, numberOfArgs <= 2, "StyleSheet.create expected up to 2 arguments.");
|
|
@@ -23,20 +23,20 @@ std::shared_ptr<StyleSheet> StyleSheetRegistry::addFromFunction(jsi::Runtime& rt
|
|
|
23
23
|
if (numberOfArgs == 0) {
|
|
24
24
|
auto staticStyleSheet = styleSheetFn.call(rt).asObject(rt);
|
|
25
25
|
|
|
26
|
-
return registry.addStyleSheet(rt, core::StyleSheetType::Static, std::move(staticStyleSheet));
|
|
26
|
+
return registry.addStyleSheet(rt, generation, core::StyleSheetType::Static, std::move(staticStyleSheet));
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
// stylesheet depends only on theme
|
|
30
30
|
if (numberOfArgs == 1) {
|
|
31
|
-
return registry.addStyleSheet(rt, core::StyleSheetType::Themable, std::move(styleSheetFn));
|
|
31
|
+
return registry.addStyleSheet(rt, generation, core::StyleSheetType::Themable, std::move(styleSheetFn));
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
// stylesheet depends on theme and mini runtime
|
|
35
|
-
return registry.addStyleSheet(rt, core::StyleSheetType::ThemableWithMiniRuntime, std::move(styleSheetFn));
|
|
35
|
+
return registry.addStyleSheet(rt, generation, core::StyleSheetType::ThemableWithMiniRuntime, std::move(styleSheetFn));
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
std::shared_ptr<StyleSheet> StyleSheetRegistry::addFromObject(jsi::Runtime& rt, jsi::Object rawStyleSheet) {
|
|
38
|
+
std::shared_ptr<StyleSheet> StyleSheetRegistry::addFromObject(jsi::Runtime& rt, uint64_t generation, jsi::Object rawStyleSheet) {
|
|
39
39
|
auto& registry = UnistylesRegistry::get();
|
|
40
40
|
|
|
41
|
-
return registry.addStyleSheet(rt, core::StyleSheetType::Static, std::move(rawStyleSheet));
|
|
41
|
+
return registry.addStyleSheet(rt, generation, core::StyleSheetType::Static, std::move(rawStyleSheet));
|
|
42
42
|
}
|
|
@@ -16,11 +16,11 @@ struct StyleSheetRegistry {
|
|
|
16
16
|
StyleSheetRegistry(const StyleSheetRegistry&) = delete;
|
|
17
17
|
StyleSheetRegistry(StyleSheetRegistry&&) = delete;
|
|
18
18
|
|
|
19
|
-
virtual std::shared_ptr<StyleSheet> addStyleSheetFromValue(jsi::Runtime& rt, jsi::Object rawStyleSheet);
|
|
19
|
+
virtual std::shared_ptr<StyleSheet> addStyleSheetFromValue(jsi::Runtime& rt, uint64_t generation, jsi::Object rawStyleSheet);
|
|
20
20
|
|
|
21
21
|
private:
|
|
22
|
-
virtual std::shared_ptr<StyleSheet> addFromFunction(jsi::Runtime& rt, jsi::Function styleSheetFn);
|
|
23
|
-
virtual std::shared_ptr<StyleSheet> addFromObject(jsi::Runtime& rt, jsi::Object rawStyleSheet);
|
|
22
|
+
virtual std::shared_ptr<StyleSheet> addFromFunction(jsi::Runtime& rt, uint64_t generation, jsi::Function styleSheetFn);
|
|
23
|
+
virtual std::shared_ptr<StyleSheet> addFromObject(jsi::Runtime& rt, uint64_t generation, jsi::Object rawStyleSheet);
|
|
24
24
|
};
|
|
25
25
|
|
|
26
26
|
}
|
|
@@ -157,7 +157,19 @@ inline static jsi::Value objectFromUnistyle(jsi::Runtime& rt, std::shared_ptr<Hy
|
|
|
157
157
|
[unistyleID = unistyle->unid, unistylesRuntime, variants, parsedArguments](jsi::Runtime &rt, const jsi::Value &thisValue, const jsi::Value *args, size_t count
|
|
158
158
|
) {
|
|
159
159
|
auto& registry = UnistylesRegistry::get();
|
|
160
|
-
|
|
160
|
+
// ids repeat across runtimes, so a replaced runtime can't look up its unistyle anymore
|
|
161
|
+
auto unistyle = unistylesRuntime->ownsRegistry()
|
|
162
|
+
? registry.getUnistyleById(unistyleID)
|
|
163
|
+
: nullptr;
|
|
164
|
+
|
|
165
|
+
// the unistyle may have been unregistered while this call was in flight,
|
|
166
|
+
// eg. during a reload while the outgoing runtime still executes queued work
|
|
167
|
+
if (unistyle == nullptr) {
|
|
168
|
+
throw jsi::JSError(rt, R"(Unistyles: Style is no longer registered!
|
|
169
|
+
|
|
170
|
+
You likely accessed a style while the runtime was being torn down (eg. during a reload).)");
|
|
171
|
+
}
|
|
172
|
+
|
|
161
173
|
auto scopedTheme = registry.getScopedTheme();
|
|
162
174
|
parser::Parser parser(unistylesRuntime);
|
|
163
175
|
|
|
@@ -9,7 +9,13 @@ using namespace facebook::react;
|
|
|
9
9
|
|
|
10
10
|
std::atomic<int> core::UnistylesRegistry::_nextStyleSheetTag{0};
|
|
11
11
|
|
|
12
|
-
void core::UnistylesRegistry::registerTheme(jsi::Runtime& rt, std::string name, jsi::Value& theme) {
|
|
12
|
+
void core::UnistylesRegistry::registerTheme(jsi::Runtime& rt, uint64_t generation, std::string name, jsi::Value& theme) {
|
|
13
|
+
std::lock_guard<std::mutex> lock(this->_ownershipMutex);
|
|
14
|
+
|
|
15
|
+
if (!this->isCurrent(generation)) {
|
|
16
|
+
throw std::runtime_error(helpers::RUNTIME_REPLACED_ERROR);
|
|
17
|
+
}
|
|
18
|
+
|
|
13
19
|
auto& state = this->getState();
|
|
14
20
|
|
|
15
21
|
state._jsThemes.emplace(name, std::move(theme));
|
|
@@ -46,7 +52,7 @@ void core::UnistylesRegistry::createState() {
|
|
|
46
52
|
this->_state = std::make_unique<UnistylesState>();
|
|
47
53
|
}
|
|
48
54
|
|
|
49
|
-
void core::UnistylesRegistry::updateTheme(jsi::Runtime& rt, std::string& themeName, jsi::Function&& callback) {
|
|
55
|
+
void core::UnistylesRegistry::updateTheme(jsi::Runtime& rt, uint64_t generation, std::string& themeName, jsi::Function&& callback) {
|
|
50
56
|
auto& state = this->getState();
|
|
51
57
|
auto it = state._jsThemes.find(themeName);
|
|
52
58
|
|
|
@@ -56,25 +62,38 @@ void core::UnistylesRegistry::updateTheme(jsi::Runtime& rt, std::string& themeNa
|
|
|
56
62
|
|
|
57
63
|
helpers::assertThat(rt, result.isObject(), "Unistyles: Returned theme is not an object. Please check your updateTheme function.");
|
|
58
64
|
|
|
59
|
-
|
|
65
|
+
auto theme = result.asObject(rt);
|
|
66
|
+
std::lock_guard<std::mutex> lock(this->_ownershipMutex);
|
|
67
|
+
|
|
68
|
+
if (!this->isCurrent(generation)) {
|
|
69
|
+
throw std::runtime_error(helpers::RUNTIME_REPLACED_ERROR);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
it->second = std::move(theme);
|
|
60
73
|
}
|
|
61
74
|
|
|
62
75
|
void core::UnistylesRegistry::linkShadowNodeWithUnistyle(
|
|
63
76
|
jsi::Runtime& rt,
|
|
77
|
+
uint64_t generation,
|
|
64
78
|
const std::shared_ptr<const ShadowNodeFamily>& shadowNodeFamily,
|
|
65
79
|
std::vector<std::shared_ptr<UnistyleData>>& unistylesData,
|
|
66
80
|
std::optional<folly::dynamic> initialScopedUpdate
|
|
67
81
|
) {
|
|
68
82
|
// released after unlocking, so a family destructor never runs within the lock
|
|
69
83
|
ReleasedFamilies releasedFamilies;
|
|
84
|
+
std::lock_guard<std::mutex> lock(this->_ownershipMutex);
|
|
85
|
+
|
|
86
|
+
if (!this->isCurrent(generation)) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
70
89
|
|
|
71
90
|
this->trafficController.withLock([this, &unistylesData, &shadowNodeFamily, &initialScopedUpdate, &releasedFamilies](){
|
|
72
91
|
auto family = shadowNodeFamily.get();
|
|
73
92
|
auto it = this->_shadowRegistry.find(family);
|
|
74
93
|
|
|
75
94
|
// Clear suspension state if this family was previously suspended
|
|
95
|
+
// native props stay, they hold values from theme changes that React doesn't know about
|
|
76
96
|
if (it != this->_shadowRegistry.end() && it->second.isSuspended) {
|
|
77
|
-
shadow::resetNativeProps(family);
|
|
78
97
|
// Clear old registry entries to prevent stale UnistyleData accumulation
|
|
79
98
|
// and any stale traffic controller entry (e.g. from a theme change during suspension)
|
|
80
99
|
this->forgetFamilyUnsafe(family, releasedFamilies);
|
|
@@ -183,7 +202,13 @@ bool core::UnistylesRegistry::isSuspended(const ShadowNodeFamily* family) const
|
|
|
183
202
|
return it != this->_shadowRegistry.end() && it->second.isSuspended;
|
|
184
203
|
}
|
|
185
204
|
|
|
186
|
-
std::shared_ptr<core::StyleSheet> core::UnistylesRegistry::addStyleSheet(jsi::Runtime& rt, core::StyleSheetType type, jsi::Object&& rawValue) {
|
|
205
|
+
std::shared_ptr<core::StyleSheet> core::UnistylesRegistry::addStyleSheet(jsi::Runtime& rt, uint64_t generation, core::StyleSheetType type, jsi::Object&& rawValue) {
|
|
206
|
+
std::lock_guard<std::mutex> lock(this->_ownershipMutex);
|
|
207
|
+
|
|
208
|
+
if (!this->isCurrent(generation)) {
|
|
209
|
+
throw std::runtime_error(helpers::RUNTIME_REPLACED_ERROR);
|
|
210
|
+
}
|
|
211
|
+
|
|
187
212
|
int tag = _nextStyleSheetTag.fetch_add(1);
|
|
188
213
|
|
|
189
214
|
auto sheet = std::make_shared<core::StyleSheet>(tag, type, std::move(rawValue));
|
|
@@ -335,26 +360,85 @@ void core::UnistylesRegistry::setScopedTheme(std::optional<std::string> themeNam
|
|
|
335
360
|
this->_scopedTheme = std::move(themeName);
|
|
336
361
|
}
|
|
337
362
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
ReleasedFamilies releasedFamilies;
|
|
363
|
+
uint64_t core::UnistylesRegistry::takeOwnership() {
|
|
364
|
+
std::lock_guard<std::mutex> lock(this->_ownershipMutex);
|
|
365
|
+
auto previousGeneration = this->_generation.load();
|
|
342
366
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
}
|
|
367
|
+
if (previousGeneration != 0) {
|
|
368
|
+
this->_replacedStates[previousGeneration] = this->takeOwnedState();
|
|
369
|
+
}
|
|
347
370
|
|
|
348
|
-
|
|
349
|
-
|
|
371
|
+
this->_generation.store(++this->_lastGeneration);
|
|
372
|
+
|
|
373
|
+
return this->_lastGeneration;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
void core::UnistylesRegistry::releaseOwnership(uint64_t generation) {
|
|
377
|
+
// called when module is invalidated, before React Native destroys the runtime
|
|
378
|
+
// declared before the lock, so jsi values and pins are released after unlocking
|
|
379
|
+
OwnedState releasedState;
|
|
380
|
+
|
|
381
|
+
{
|
|
382
|
+
std::lock_guard<std::mutex> lock(this->_ownershipMutex);
|
|
383
|
+
|
|
384
|
+
if (this->isCurrent(generation)) {
|
|
385
|
+
releasedState = this->takeOwnedState();
|
|
386
|
+
this->_generation.store(0);
|
|
387
|
+
} else if (auto it = this->_replacedStates.find(generation); it != this->_replacedStates.end()) {
|
|
388
|
+
releasedState = std::move(it->second);
|
|
389
|
+
this->_replacedStates.erase(it);
|
|
350
390
|
}
|
|
391
|
+
}
|
|
351
392
|
|
|
352
|
-
|
|
393
|
+
for (auto& [_, styleSheet] : releasedState.styleSheets) {
|
|
394
|
+
styleSheet->unistyles.clear();
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
core::UnistylesRegistry::OwnedState core::UnistylesRegistry::takeOwnedState() {
|
|
399
|
+
OwnedState ownedState;
|
|
400
|
+
|
|
401
|
+
this->trafficController.withLock([this, &ownedState](){
|
|
402
|
+
ownedState.shadowRegistry = std::exchange(this->_shadowRegistry, {});
|
|
403
|
+
ownedState.updates = this->trafficController.takeUpdates();
|
|
353
404
|
this->_sweepThreshold = MIN_SWEEP_THRESHOLD;
|
|
354
405
|
});
|
|
355
406
|
|
|
356
|
-
this->
|
|
357
|
-
this->
|
|
407
|
+
ownedState.styleSheets = std::exchange(this->_styleSheetRegistry, {});
|
|
408
|
+
ownedState.state = std::move(this->_state);
|
|
358
409
|
this->_scopedTheme = std::nullopt;
|
|
410
|
+
this->_committedTags.clear();
|
|
359
411
|
_nextStyleSheetTag.store(0);
|
|
412
|
+
|
|
413
|
+
return ownedState;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
std::vector<core::LinkedFamilySnapshot> core::UnistylesRegistry::getLinkedFamiliesSnapshot() {
|
|
417
|
+
std::vector<LinkedFamilySnapshot> snapshot;
|
|
418
|
+
|
|
419
|
+
this->trafficController.withLock([this, &snapshot](){
|
|
420
|
+
snapshot.reserve(this->_shadowRegistry.size());
|
|
421
|
+
|
|
422
|
+
for (const auto& [_, linkedFamily] : this->_shadowRegistry) {
|
|
423
|
+
const bool isOwnedOnlyByUnistyles = this->isOwnedOnlyByUnistyles(linkedFamily);
|
|
424
|
+
|
|
425
|
+
snapshot.push_back({linkedFamily.family, linkedFamily.unistyles, linkedFamily.isSuspended, isOwnedOnlyByUnistyles});
|
|
426
|
+
}
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
return snapshot;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
size_t core::UnistylesRegistry::getPendingUpdatesCount() {
|
|
433
|
+
return this->trafficController.withLock([this](){
|
|
434
|
+
return this->trafficController.getUpdatesCount();
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
void core::UnistylesRegistry::setCommittedTags(std::vector<Tag>&& tags) {
|
|
439
|
+
this->_committedTags = std::move(tags);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
std::vector<Tag> core::UnistylesRegistry::takeCommittedTags() {
|
|
443
|
+
return std::exchange(this->_committedTags, {});
|
|
360
444
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
#include "set"
|
|
4
4
|
#include <atomic>
|
|
5
|
+
#include <mutex>
|
|
5
6
|
#include <jsi/jsi.h>
|
|
6
7
|
#include <folly/dynamic.h>
|
|
7
8
|
#include <react/renderer/uimanager/UIManager.h>
|
|
@@ -29,6 +30,13 @@ struct LinkedFamily {
|
|
|
29
30
|
bool isSuspended = false;
|
|
30
31
|
};
|
|
31
32
|
|
|
33
|
+
struct LinkedFamilySnapshot {
|
|
34
|
+
std::shared_ptr<const ShadowNodeFamily> family;
|
|
35
|
+
std::vector<std::shared_ptr<UnistyleData>> unistyles;
|
|
36
|
+
bool isSuspended = false;
|
|
37
|
+
bool isOwnedOnlyByUnistyles = false;
|
|
38
|
+
};
|
|
39
|
+
|
|
32
40
|
struct UnistylesRegistry: public StyleSheetRegistry {
|
|
33
41
|
static UnistylesRegistry& get();
|
|
34
42
|
|
|
@@ -37,20 +45,20 @@ struct UnistylesRegistry: public StyleSheetRegistry {
|
|
|
37
45
|
|
|
38
46
|
bool shouldUsePointsForBreakpoints = false;
|
|
39
47
|
|
|
40
|
-
void registerTheme(jsi::Runtime& rt, std::string name, jsi::Value& theme);
|
|
48
|
+
void registerTheme(jsi::Runtime& rt, uint64_t generation, std::string name, jsi::Value& theme);
|
|
41
49
|
void registerBreakpoints(std::vector<std::pair<std::string, double>>& sortedBreakpoints);
|
|
42
50
|
void setPrefersAdaptiveThemes(bool prefersAdaptiveThemes);
|
|
43
51
|
void setInitialThemeName(std::string themeName);
|
|
44
|
-
void updateTheme(jsi::Runtime& rt, std::string& themeName, jsi::Function&& callback);
|
|
52
|
+
void updateTheme(jsi::Runtime& rt, uint64_t generation, std::string& themeName, jsi::Function&& callback);
|
|
45
53
|
|
|
46
54
|
UnistylesState& getState();
|
|
47
55
|
void createState();
|
|
48
56
|
std::vector<std::shared_ptr<core::StyleSheet>> getStyleSheetsToRefresh(std::vector<UnistyleDependency>& unistylesDependencies);
|
|
49
|
-
void linkShadowNodeWithUnistyle(jsi::Runtime& rt, const std::shared_ptr<const ShadowNodeFamily>& shadowNodeFamily, std::vector<std::shared_ptr<UnistyleData>>& unistylesData, std::optional<folly::dynamic> initialScopedUpdate = std::nullopt);
|
|
57
|
+
void linkShadowNodeWithUnistyle(jsi::Runtime& rt, uint64_t generation, const std::shared_ptr<const ShadowNodeFamily>& shadowNodeFamily, std::vector<std::shared_ptr<UnistyleData>>& unistylesData, std::optional<folly::dynamic> initialScopedUpdate = std::nullopt);
|
|
50
58
|
void unlinkShadowNodeWithUnistyles(const ShadowNodeFamily*);
|
|
51
59
|
void suspendShadowNode(const ShadowNodeFamily*);
|
|
52
60
|
bool isSuspended(const ShadowNodeFamily*) const noexcept;
|
|
53
|
-
std::shared_ptr<core::StyleSheet> addStyleSheet(jsi::Runtime& rt, core::StyleSheetType type, jsi::Object&& rawValue);
|
|
61
|
+
std::shared_ptr<core::StyleSheet> addStyleSheet(jsi::Runtime& rt, uint64_t generation, core::StyleSheetType type, jsi::Object&& rawValue);
|
|
54
62
|
DependencyMap buildDependencyMap(std::vector<UnistyleDependency>& deps);
|
|
55
63
|
void shadowLeafUpdateFromUnistyle(jsi::Runtime& rt, Unistyle::Shared unistyle, jsi::Value& maybePressableId);
|
|
56
64
|
// call it only within trafficController.withLock!
|
|
@@ -60,13 +68,36 @@ struct UnistylesRegistry: public StyleSheetRegistry {
|
|
|
60
68
|
void removeDuplicatedUnistyles(const ShadowNodeFamily* shadowNodeFamily, std::vector<core::Unistyle::Shared>& unistyles);
|
|
61
69
|
void setScopedTheme(std::optional<std::string> themeName);
|
|
62
70
|
core::Unistyle::Shared getUnistyleById(std::string unistyleID);
|
|
63
|
-
|
|
71
|
+
std::vector<LinkedFamilySnapshot> getLinkedFamiliesSnapshot();
|
|
72
|
+
size_t getPendingUpdatesCount();
|
|
73
|
+
void setCommittedTags(std::vector<Tag>&& tags);
|
|
74
|
+
std::vector<Tag> takeCommittedTags();
|
|
75
|
+
|
|
76
|
+
// newest installed runtime owns the registry, generation 0 means no owner
|
|
77
|
+
// previous runtime's state is kept aside until it releases ownership, as it may still run JS
|
|
78
|
+
uint64_t takeOwnership();
|
|
79
|
+
void releaseOwnership(uint64_t generation);
|
|
80
|
+
|
|
81
|
+
inline bool isCurrent(uint64_t generation) const noexcept {
|
|
82
|
+
return generation != 0 && generation == this->_generation.load();
|
|
83
|
+
}
|
|
64
84
|
|
|
65
85
|
private:
|
|
66
86
|
using ReleasedFamilies = std::vector<std::shared_ptr<const ShadowNodeFamily>>;
|
|
67
87
|
|
|
88
|
+
struct OwnedState {
|
|
89
|
+
std::unordered_map<const ShadowNodeFamily*, LinkedFamily> shadowRegistry;
|
|
90
|
+
shadow::PinnedShadowLeafUpdates updates;
|
|
91
|
+
std::unordered_map<int, std::shared_ptr<core::StyleSheet>> styleSheets;
|
|
92
|
+
std::unique_ptr<UnistylesState> state;
|
|
93
|
+
};
|
|
94
|
+
|
|
68
95
|
UnistylesRegistry() = default;
|
|
69
96
|
|
|
97
|
+
// call it only within _ownershipMutex!
|
|
98
|
+
// destructs nothing, so it can run on the next runtime's thread
|
|
99
|
+
OwnedState takeOwnedState();
|
|
100
|
+
|
|
70
101
|
// call it only within trafficController.withLock!
|
|
71
102
|
// pins are moved to releasedFamilies, so they can be released after unlocking
|
|
72
103
|
void forgetFamilyUnsafe(const ShadowNodeFamily* shadowNodeFamily, ReleasedFamilies& releasedFamilies);
|
|
@@ -77,12 +108,18 @@ private:
|
|
|
77
108
|
|
|
78
109
|
static constexpr size_t MIN_SWEEP_THRESHOLD = 64;
|
|
79
110
|
|
|
111
|
+
// lock order is _ownershipMutex -> trafficController, never call JS within
|
|
112
|
+
std::mutex _ownershipMutex;
|
|
113
|
+
std::atomic<uint64_t> _generation{0};
|
|
114
|
+
uint64_t _lastGeneration = 0;
|
|
115
|
+
std::unordered_map<uint64_t, OwnedState> _replacedStates{};
|
|
80
116
|
static std::atomic<int> _nextStyleSheetTag;
|
|
81
117
|
std::optional<std::string> _scopedTheme{};
|
|
82
118
|
std::unique_ptr<UnistylesState> _state{};
|
|
83
119
|
std::unordered_map<int, std::shared_ptr<core::StyleSheet>> _styleSheetRegistry{};
|
|
84
120
|
std::unordered_map<const ShadowNodeFamily*, LinkedFamily> _shadowRegistry{};
|
|
85
121
|
size_t _sweepThreshold = MIN_SWEEP_THRESHOLD;
|
|
122
|
+
std::vector<Tag> _committedTags{};
|
|
86
123
|
};
|
|
87
124
|
|
|
88
125
|
inline UnistylesRegistry& UnistylesRegistry::get() {
|