@shopify/react-native-skia 2.12.0-next.1 → 2.12.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/Package.swift +117 -0
- package/android/CMakeLists.txt +1 -2
- package/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h +0 -10
- package/android/src/main/java/com/shopify/reactnative/skia/ViewScreenshotService.java +9 -12
- package/apple/RNSkApplePlatformContext.h +0 -3
- package/apple/RNSkApplePlatformContext.mm +0 -11
- package/cpp/api/JsiSkApi.h +0 -6
- package/cpp/api/JsiSkFont.h +5 -10
- package/cpp/api/JsiSkMatrix.h +4 -2
- package/cpp/api/JsiSkSVGFactory.h +4 -0
- package/cpp/api/recorder/Convertor.h +5 -2
- package/cpp/api/recorder/Drawings.h +13 -3
- package/cpp/api/recorder/ImageFilters.h +15 -1
- package/cpp/api/recorder/Paint.h +8 -1
- package/cpp/jsi/JSICache.cpp +99 -0
- package/cpp/jsi/JSICache.h +90 -0
- package/cpp/jsi/NativeObject.h +38 -87
- package/cpp/jsi/ViewProperty.h +0 -24
- package/cpp/rnskia/RNDawnContext.h +2 -1
- package/cpp/rnskia/RNDawnWindowContext.h +22 -0
- package/cpp/rnskia/RNSkManager.cpp +0 -6
- package/cpp/rnskia/RNSkPlatformContext.h +0 -3
- package/cpp/skia/include/core/RasterContext.h +25 -0
- package/cpp/skia/include/core/SkCanvas.h +0 -1
- package/cpp/skia/include/core/SkContext.h +62 -0
- package/cpp/skia/include/core/SkContextOptions.h +15 -0
- package/cpp/skia/include/core/SkMilestone.h +1 -1
- package/cpp/skia/include/core/SkPicture.h +36 -18
- package/cpp/skia/include/core/SkRecorder.h +8 -0
- package/cpp/skia/include/core/SkSerialProcs.h +2 -6
- package/cpp/skia/include/effects/SkImageFilters.h +15 -2
- package/cpp/skia/include/gpu/ganesh/GrDirectContext.h +73 -47
- package/cpp/skia/include/gpu/ganesh/SkSurfaceGanesh.h +7 -4
- package/cpp/skia/include/gpu/ganesh/d3d/GrD3DDirectContext.h +12 -0
- package/cpp/skia/include/gpu/ganesh/gl/GrGLDirectContext.h +11 -0
- package/cpp/skia/include/gpu/ganesh/mtl/GrMtlDirectContext.h +11 -0
- package/cpp/skia/include/gpu/ganesh/vk/GrVkDirectContext.h +13 -0
- package/cpp/skia/include/gpu/graphite/ContextOptions.h +6 -0
- package/cpp/skia/include/gpu/graphite/GraphiteTypes.h +5 -4
- package/cpp/skia/include/gpu/graphite/PrecompileContext.h +9 -1
- package/cpp/skia/include/gpu/graphite/Recorder.h +0 -2
- package/cpp/skia/include/gpu/graphite/Recording.h +3 -0
- package/cpp/skia/include/gpu/graphite/dawn/DawnBackendContext.h +8 -0
- package/cpp/skia/include/gpu/graphite/mtl/MtlBackendContext.h +11 -0
- package/cpp/skia/include/gpu/graphite/vk/VulkanGraphiteContext.h +11 -0
- package/cpp/skia/include/private/SkLog.h +1 -19
- package/cpp/skia/include/private/chromium/GrVkSecondaryCBDrawContext.h +2 -1
- package/cpp/skia/include/utils/SkLogHandler.h +53 -0
- package/cpp/skia/include/utils/SkNWayCanvas.h +1 -0
- package/cpp/skia/modules/skcms/src/Transform_inl.h +9 -10
- package/cpp/skia/modules/skcms/src/skcms_internals.h +8 -3
- package/cpp/skia/modules/skottie/include/SkottieProperty.h +2 -0
- package/cpp/skia/modules/skottie/include/TextShaper.h +1 -0
- package/cpp/skia/modules/skshaper/include/SkShaper.h +23 -1
- package/include/ReactNativeSkia.h +6 -0
- package/lib/commonjs/dom/nodes/datatypes/Rect.js +5 -1
- package/lib/commonjs/dom/nodes/datatypes/Rect.js.map +1 -1
- package/lib/commonjs/external/reanimated/useVideo.js +8 -2
- package/lib/commonjs/external/reanimated/useVideo.js.map +1 -1
- package/lib/commonjs/renderer/components/Mask.js +3 -9
- package/lib/commonjs/renderer/components/Mask.js.map +1 -1
- package/lib/commonjs/skia/types/JsiInstance.d.ts +1 -0
- package/lib/commonjs/skia/types/JsiInstance.js.map +1 -1
- package/lib/commonjs/skia/types/Matrix4.js +7 -2
- package/lib/commonjs/skia/types/Matrix4.js.map +1 -1
- package/lib/commonjs/skia/types/Skia.d.ts +1 -6
- package/lib/commonjs/skia/types/Skia.js.map +1 -1
- package/lib/commonjs/skia/web/JsiSkCanvas.js +4 -4
- package/lib/commonjs/skia/web/JsiSkCanvas.js.map +1 -1
- package/lib/commonjs/skia/web/JsiSkImage.js +6 -3
- package/lib/commonjs/skia/web/JsiSkImage.js.map +1 -1
- package/lib/commonjs/skia/web/JsiSkPathBuilder.d.ts +1 -1
- package/lib/commonjs/skia/web/JsiSkPathBuilder.js +2 -2
- package/lib/commonjs/skia/web/JsiSkPathBuilder.js.map +1 -1
- package/lib/commonjs/skia/web/JsiSkTextStyle.js +5 -5
- package/lib/commonjs/skia/web/JsiSkTextStyle.js.map +1 -1
- package/lib/commonjs/skia/web/JsiSkia.js +0 -3
- package/lib/commonjs/skia/web/JsiSkia.js.map +1 -1
- package/lib/commonjs/skia/web/JsiSkottieAnimation.js +8 -8
- package/lib/commonjs/skia/web/JsiSkottieAnimation.js.map +1 -1
- package/lib/commonjs/sksg/Recorder/DrawingContext.d.ts +1 -0
- package/lib/commonjs/sksg/Recorder/DrawingContext.js +15 -0
- package/lib/commonjs/sksg/Recorder/DrawingContext.js.map +1 -1
- package/lib/commonjs/sksg/Recorder/Player.js +1 -1
- package/lib/commonjs/sksg/Recorder/Player.js.map +1 -1
- package/lib/commonjs/sksg/Recorder/Visitor.js +6 -1
- package/lib/commonjs/sksg/Recorder/Visitor.js.map +1 -1
- package/lib/commonjs/sksg/Recorder/commands/Drawing.js +12 -9
- package/lib/commonjs/sksg/Recorder/commands/Drawing.js.map +1 -1
- package/lib/commonjs/sksg/Recorder/commands/ImageFilters.js +15 -1
- package/lib/commonjs/sksg/Recorder/commands/ImageFilters.js.map +1 -1
- package/lib/commonjs/sksg/Recorder/commands/Shaders.js +1 -1
- package/lib/commonjs/sksg/Recorder/commands/Shaders.js.map +1 -1
- package/lib/commonjs/views/SkiaPictureView.web.js +247 -57
- package/lib/commonjs/views/SkiaPictureView.web.js.map +1 -1
- package/lib/module/dom/nodes/datatypes/Rect.js +5 -1
- package/lib/module/dom/nodes/datatypes/Rect.js.map +1 -1
- package/lib/module/external/reanimated/useVideo.js +8 -2
- package/lib/module/external/reanimated/useVideo.js.map +1 -1
- package/lib/module/renderer/components/Mask.js +3 -9
- package/lib/module/renderer/components/Mask.js.map +1 -1
- package/lib/module/skia/types/JsiInstance.d.ts +1 -0
- package/lib/module/skia/types/JsiInstance.js.map +1 -1
- package/lib/module/skia/types/Matrix4.js +7 -2
- package/lib/module/skia/types/Matrix4.js.map +1 -1
- package/lib/module/skia/types/Skia.d.ts +1 -6
- package/lib/module/skia/types/Skia.js.map +1 -1
- package/lib/module/skia/web/JsiSkCanvas.js +4 -4
- package/lib/module/skia/web/JsiSkCanvas.js.map +1 -1
- package/lib/module/skia/web/JsiSkImage.js +6 -3
- package/lib/module/skia/web/JsiSkImage.js.map +1 -1
- package/lib/module/skia/web/JsiSkPathBuilder.d.ts +1 -1
- package/lib/module/skia/web/JsiSkPathBuilder.js +2 -2
- package/lib/module/skia/web/JsiSkPathBuilder.js.map +1 -1
- package/lib/module/skia/web/JsiSkTextStyle.js +5 -5
- package/lib/module/skia/web/JsiSkTextStyle.js.map +1 -1
- package/lib/module/skia/web/JsiSkia.js +0 -3
- package/lib/module/skia/web/JsiSkia.js.map +1 -1
- package/lib/module/skia/web/JsiSkottieAnimation.js +8 -8
- package/lib/module/skia/web/JsiSkottieAnimation.js.map +1 -1
- package/lib/module/sksg/Recorder/DrawingContext.d.ts +1 -0
- package/lib/module/sksg/Recorder/DrawingContext.js +15 -0
- package/lib/module/sksg/Recorder/DrawingContext.js.map +1 -1
- package/lib/module/sksg/Recorder/Player.js +1 -1
- package/lib/module/sksg/Recorder/Player.js.map +1 -1
- package/lib/module/sksg/Recorder/Visitor.js +6 -1
- package/lib/module/sksg/Recorder/Visitor.js.map +1 -1
- package/lib/module/sksg/Recorder/commands/Drawing.js +12 -9
- package/lib/module/sksg/Recorder/commands/Drawing.js.map +1 -1
- package/lib/module/sksg/Recorder/commands/ImageFilters.js +15 -1
- package/lib/module/sksg/Recorder/commands/ImageFilters.js.map +1 -1
- package/lib/module/sksg/Recorder/commands/Shaders.js +1 -1
- package/lib/module/sksg/Recorder/commands/Shaders.js.map +1 -1
- package/lib/module/views/SkiaPictureView.web.js +247 -57
- package/lib/module/views/SkiaPictureView.web.js.map +1 -1
- package/lib/typescript/lib/commonjs/skia/web/JsiSkPathBuilder.d.ts +1 -1
- package/lib/typescript/lib/commonjs/skia/web/JsiSkia.d.ts +0 -1
- package/lib/typescript/lib/commonjs/sksg/Recorder/DrawingContext.d.ts +1 -0
- package/lib/typescript/lib/module/skia/Skia.web.d.ts +0 -1
- package/lib/typescript/lib/module/skia/web/JsiSkPathBuilder.d.ts +1 -1
- package/lib/typescript/lib/module/skia/web/JsiSkia.d.ts +0 -1
- package/lib/typescript/lib/module/sksg/Recorder/DrawingContext.d.ts +1 -0
- package/lib/typescript/react-native.config.d.ts +3 -0
- package/lib/typescript/src/skia/types/JsiInstance.d.ts +1 -0
- package/lib/typescript/src/skia/types/Skia.d.ts +1 -6
- package/lib/typescript/src/skia/web/JsiSkPathBuilder.d.ts +1 -1
- package/lib/typescript/src/sksg/Recorder/DrawingContext.d.ts +1 -0
- package/package.json +13 -10
- package/react-native.config.js +5 -0
- package/src/dom/nodes/datatypes/Rect.ts +6 -1
- package/src/external/reanimated/useVideo.ts +7 -2
- package/src/renderer/components/Mask.tsx +10 -3
- package/src/skia/types/JsiInstance.ts +2 -0
- package/src/skia/types/Matrix4.ts +6 -2
- package/src/skia/types/Skia.ts +1 -7
- package/src/skia/web/JsiSkCanvas.ts +11 -6
- package/src/skia/web/JsiSkImage.ts +6 -3
- package/src/skia/web/JsiSkPathBuilder.ts +2 -2
- package/src/skia/web/JsiSkTextStyle.ts +20 -15
- package/src/skia/web/JsiSkia.ts +0 -4
- package/src/skia/web/JsiSkottieAnimation.ts +8 -8
- package/src/sksg/Recorder/DrawingContext.ts +15 -0
- package/src/sksg/Recorder/Player.ts +1 -1
- package/src/sksg/Recorder/Visitor.ts +9 -6
- package/src/sksg/Recorder/commands/Drawing.ts +12 -9
- package/src/sksg/Recorder/commands/ImageFilters.ts +20 -1
- package/src/sksg/Recorder/commands/Shaders.ts +1 -1
- package/src/views/SkiaPictureView.web.tsx +245 -57
- package/cpp/api/JsiSkiaContext.h +0 -94
- package/cpp/dawn/include/dawn/dawn_proc.h +0 -53
- package/cpp/dawn/include/dawn/dawn_proc_table.h +0 -330
- package/cpp/dawn/include/dawn/dawn_thread_dispatch_proc.h +0 -47
- package/cpp/dawn/include/dawn/dawn_version.h +0 -41
- package/cpp/dawn/include/dawn/native/D3D11Backend.h +0 -65
- package/cpp/dawn/include/dawn/native/D3D12Backend.h +0 -103
- package/cpp/dawn/include/dawn/native/D3DBackend.h +0 -56
- package/cpp/dawn/include/dawn/native/DawnNative.h +0 -368
- package/cpp/dawn/include/dawn/native/MetalBackend.h +0 -56
- package/cpp/dawn/include/dawn/native/NullBackend.h +0 -39
- package/cpp/dawn/include/dawn/native/OpenGLBackend.h +0 -89
- package/cpp/dawn/include/dawn/native/VulkanBackend.h +0 -183
- package/cpp/dawn/include/dawn/native/WebGPUBackend.h +0 -49
- package/cpp/dawn/include/dawn/native/dawn_native_export.h +0 -49
- package/cpp/dawn/include/dawn/platform/DawnPlatform.h +0 -207
- package/cpp/dawn/include/dawn/platform/dawn_platform_export.h +0 -49
- package/cpp/dawn/include/dawn/replay/Replay.h +0 -99
- package/cpp/dawn/include/dawn/replay/dawn_replay_export.h +0 -49
- package/cpp/dawn/include/dawn/webgpu_cpp_print.h +0 -2856
- package/cpp/dawn/include/tint/tint.h +0 -91
- package/cpp/dawn/include/webgpu/webgpu.h +0 -5029
- package/cpp/dawn/include/webgpu/webgpu_cpp.h +0 -10353
- package/cpp/dawn/include/webgpu/webgpu_cpp_chained_struct.h +0 -57
- package/cpp/dawn/include/webgpu/webgpu_enum_class_bitmasks.h +0 -162
- package/cpp/dawn/include/webgpu/webgpu_glfw.h +0 -88
- package/cpp/jsi/RuntimeAwareCache.cpp +0 -7
- package/cpp/jsi/RuntimeAwareCache.h +0 -117
- package/cpp/jsi/RuntimeLifecycleMonitor.cpp +0 -72
- package/cpp/jsi/RuntimeLifecycleMonitor.h +0 -32
- package/cpp/skia/src/gpu/graphite/ContextOptionsPriv.h +0 -45
- package/cpp/skia/src/gpu/graphite/ResourceTypes.h +0 -360
- package/cpp/skia/src/gpu/graphite/TextureProxyView.h +0 -105
- package/libs/.graphite +0 -1
package/Package.swift
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
// swift-tools-version: 6.0
|
|
2
|
+
//
|
|
3
|
+
// SwiftPM manifest for @shopify/react-native-skia. iOS, Ganesh.
|
|
4
|
+
// Additive: the CocoaPods podspec remains the supported default.
|
|
5
|
+
//
|
|
6
|
+
// React Native 0.87+ references a library that ships its own Package.swift
|
|
7
|
+
// through a symlink at <app>/ios/build/generated/autolinking/libs/<name>, and
|
|
8
|
+
// resolves the relative paths below against that symlink. They are the same
|
|
9
|
+
// for every standard app, because the symlink location is.
|
|
10
|
+
|
|
11
|
+
import Foundation
|
|
12
|
+
import PackageDescription
|
|
13
|
+
|
|
14
|
+
// Skia's xcframeworks are ~200MB and are not carried in this package. They come
|
|
15
|
+
// from the react-native-skia-apple-ios npm package, which @shopify/react-native-skia
|
|
16
|
+
// depends on, so a checkout that has installed its dependencies builds offline.
|
|
17
|
+
// Xcode passes the symlink as the package directory, hence resolvingSymlinks.
|
|
18
|
+
let packageRoot = URL(fileURLWithPath: Context.packageDirectory)
|
|
19
|
+
.resolvingSymlinksInPath().path
|
|
20
|
+
|
|
21
|
+
let binariesPath = [
|
|
22
|
+
"../../react-native-skia-apple-ios", // consumer: sibling in node_modules
|
|
23
|
+
"../../node_modules/react-native-skia-apple-ios", // this monorepo
|
|
24
|
+
]
|
|
25
|
+
.map { "\(packageRoot)/\($0)" }
|
|
26
|
+
.first { FileManager.default.fileExists(atPath: "\($0)/Package.swift") }
|
|
27
|
+
|
|
28
|
+
guard let binariesPath else {
|
|
29
|
+
// Reached when the package was skipped at install time (`--omit=optional`,
|
|
30
|
+
// or a non-Apple `os` filter), which SwiftPM would otherwise report as an
|
|
31
|
+
// unresolvable dependency path.
|
|
32
|
+
fatalError(
|
|
33
|
+
"""
|
|
34
|
+
react-native-skia-apple-ios was not found next to @shopify/react-native-skia. \
|
|
35
|
+
It ships the prebuilt Skia binaries this package links against. Reinstall \
|
|
36
|
+
dependencies without --omit=optional, on macOS.
|
|
37
|
+
""")
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
let package = Package(
|
|
41
|
+
name: "ReactNativeSkia",
|
|
42
|
+
platforms: [.iOS(.v15)],
|
|
43
|
+
products: [
|
|
44
|
+
// Autolinking looks this name up verbatim; react-native.config.js pins it.
|
|
45
|
+
.library(name: "ReactNativeSkia", targets: ["ReactNativeSkia"])
|
|
46
|
+
],
|
|
47
|
+
dependencies: [
|
|
48
|
+
.package(name: "React-GeneratedCode", path: "../../../ios"),
|
|
49
|
+
.package(name: "ReactNative", path: "../../../../xcframeworks"),
|
|
50
|
+
.package(path: binariesPath),
|
|
51
|
+
],
|
|
52
|
+
targets: [
|
|
53
|
+
.target(
|
|
54
|
+
name: "ReactNativeSkia",
|
|
55
|
+
dependencies: [
|
|
56
|
+
.product(name: "ReactHeaders", package: "ReactNative"),
|
|
57
|
+
.product(name: "ReactNativeHeaders", package: "ReactNative"),
|
|
58
|
+
.product(name: "ReactNativeDependenciesHeaders", package: "ReactNative"),
|
|
59
|
+
.product(name: "ReactAppHeaders", package: "React-GeneratedCode"),
|
|
60
|
+
.product(name: "react-native-skia-apple-ios", package: "react-native-skia-apple-ios"),
|
|
61
|
+
],
|
|
62
|
+
// apple/ and cpp/ have no common ancestor below the package root, and
|
|
63
|
+
// .headerSearchPath cannot escape the target path.
|
|
64
|
+
path: ".",
|
|
65
|
+
exclude: [
|
|
66
|
+
"cpp/rnskia/RNDawnWindowContext.cpp", // Graphite only
|
|
67
|
+
"cpp/rnskia/RNDawnInterop.cpp", // Graphite only
|
|
68
|
+
],
|
|
69
|
+
// Explicit, so SwiftPM never walks node_modules, lib, android, or the
|
|
70
|
+
// headers-only cpp/skia — which carries x86 AVX skcms sources that
|
|
71
|
+
// cannot build for arm64.
|
|
72
|
+
sources: [
|
|
73
|
+
"apple",
|
|
74
|
+
"cpp/api",
|
|
75
|
+
"cpp/jsi",
|
|
76
|
+
"cpp/rnskia",
|
|
77
|
+
"cpp/utils",
|
|
78
|
+
// libskottie.a needs skjson and Apple builds no libskjson archive.
|
|
79
|
+
// CocoaPods compiles this via its cpp/**/*.cpp glob.
|
|
80
|
+
"cpp/skia/modules/jsonreader/SkJSONReader.cpp",
|
|
81
|
+
],
|
|
82
|
+
cxxSettings: [
|
|
83
|
+
// Replaces the podspec's recursive cpp/** glob, which expands to 90.
|
|
84
|
+
.headerSearchPath("cpp"), // "api/…", "jsi/…", "utils/…"
|
|
85
|
+
.headerSearchPath("cpp/skia"), // "include/core/…", "modules/…", "src/…"
|
|
86
|
+
.headerSearchPath("cpp/rnskia"), // apple/ uses bare "RNSkView.h"
|
|
87
|
+
.headerSearchPath("cpp/utils"), // apple/ uses bare "RNSkLog.h"
|
|
88
|
+
|
|
89
|
+
// CocoaPods forces both project-wide; the SwiftPM path defines neither.
|
|
90
|
+
// Skia's Apple sources still gate on them: without them RNSkiaModule's
|
|
91
|
+
// legacy branch fails to compile and -getTurboModule: is dropped, so
|
|
92
|
+
// the JSI bindings never install.
|
|
93
|
+
.define("RCT_NEW_ARCH_ENABLED", to: "1"),
|
|
94
|
+
.define("RCT_REMOVE_LEGACY_ARCH", to: "1"),
|
|
95
|
+
|
|
96
|
+
.define("SK_METAL", to: "1"),
|
|
97
|
+
.define("SK_GANESH", to: "1"),
|
|
98
|
+
.define("SK_IMAGE_READ_PIXELS_DISABLE_LEGACY_API", to: "1"),
|
|
99
|
+
.define("SK_DISABLE_LEGACY_SHAPER_FACTORY", to: "1"),
|
|
100
|
+
|
|
101
|
+
// React's prebuilt C++ ABI is NDEBUG-gated, and Skia derives
|
|
102
|
+
// SK_RELEASE from it. Omitting either breaks the Release link.
|
|
103
|
+
.define("DEBUG", .when(configuration: .debug)),
|
|
104
|
+
.define("NDEBUG", .when(configuration: .release)),
|
|
105
|
+
],
|
|
106
|
+
linkerSettings: [
|
|
107
|
+
.linkedFramework("MetalKit"),
|
|
108
|
+
.linkedFramework("AVFoundation"),
|
|
109
|
+
.linkedFramework("AVKit"),
|
|
110
|
+
.linkedFramework("CoreMedia"),
|
|
111
|
+
]
|
|
112
|
+
)
|
|
113
|
+
],
|
|
114
|
+
// React Native's headers need C++20, and so does Skia m152: SkMathPriv.h
|
|
115
|
+
// calls std::countl_zero, std::countr_zero and std::popcount.
|
|
116
|
+
cxxLanguageStandard: .cxx20
|
|
117
|
+
)
|
package/android/CMakeLists.txt
CHANGED
|
@@ -100,8 +100,7 @@ add_library(
|
|
|
100
100
|
"${PROJECT_SOURCE_DIR}/cpp/rnskia-android/AHardwareBufferUtils.cpp"
|
|
101
101
|
"${PROJECT_SOURCE_DIR}/cpp/rnskia-android/RNSkAndroidVideo.cpp"
|
|
102
102
|
|
|
103
|
-
"${PROJECT_SOURCE_DIR}/../cpp/jsi/
|
|
104
|
-
"${PROJECT_SOURCE_DIR}/../cpp/jsi/RuntimeAwareCache.cpp"
|
|
103
|
+
"${PROJECT_SOURCE_DIR}/../cpp/jsi/JSICache.cpp"
|
|
105
104
|
"${PROJECT_SOURCE_DIR}/../cpp/jsi/JsiPromises.cpp"
|
|
106
105
|
"${PROJECT_SOURCE_DIR}/../cpp/jsi/Promise.cpp"
|
|
107
106
|
|
|
@@ -63,16 +63,6 @@ public:
|
|
|
63
63
|
#endif
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
std::shared_ptr<WindowContext>
|
|
67
|
-
makeContextFromNativeSurface(void *surface, int width, int height) override {
|
|
68
|
-
#if defined(SK_GRAPHITE)
|
|
69
|
-
return DawnContext::getInstance().MakeWindow(surface, width, height);
|
|
70
|
-
#else
|
|
71
|
-
auto aWindow = reinterpret_cast<ANativeWindow *>(surface);
|
|
72
|
-
return OpenGLContext::getInstance().MakeWindow(aWindow);
|
|
73
|
-
#endif
|
|
74
|
-
}
|
|
75
|
-
|
|
76
66
|
sk_sp<SkImage> makeImageFromNativeBuffer(void *buffer) override {
|
|
77
67
|
#if defined(SK_GRAPHITE)
|
|
78
68
|
return DawnContext::getInstance().MakeImageFromBuffer(buffer);
|
|
@@ -19,10 +19,11 @@ import android.widget.ScrollView;
|
|
|
19
19
|
import androidx.annotation.NonNull;
|
|
20
20
|
import com.facebook.react.bridge.ReactContext;
|
|
21
21
|
import com.facebook.react.bridge.UIManager;
|
|
22
|
+
import com.facebook.react.uimanager.BackgroundStyleApplicator;
|
|
22
23
|
import com.facebook.react.uimanager.UIManagerHelper;
|
|
24
|
+
import com.facebook.react.uimanager.ViewProps;
|
|
23
25
|
import com.facebook.react.views.view.ReactViewGroup;
|
|
24
26
|
|
|
25
|
-
import java.lang.reflect.Method;
|
|
26
27
|
import java.util.concurrent.CountDownLatch;
|
|
27
28
|
import java.util.concurrent.TimeUnit;
|
|
28
29
|
|
|
@@ -118,17 +119,13 @@ public class ViewScreenshotService {
|
|
|
118
119
|
}
|
|
119
120
|
|
|
120
121
|
private static void drawChildren(Canvas canvas, ViewGroup group, Paint paint, float parentOpacity) {
|
|
121
|
-
//
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
method.invoke(group, canvas);
|
|
129
|
-
} catch (Exception e) {
|
|
130
|
-
Log.e(TAG, "couldn't invoke dispatchOverflowDraw() on ReactViewGroup", e);
|
|
131
|
-
}
|
|
122
|
+
// ReactViewGroup applies `overflow: hidden` / `overflow: scroll` clipping from its
|
|
123
|
+
// dispatchDraw() override. We never call dispatchDraw() here because children are
|
|
124
|
+
// walked manually (TextureView / SurfaceView need special handling), so the clip has
|
|
125
|
+
// to be replicated explicitly, exactly as ReactViewGroup.dispatchDraw() does it.
|
|
126
|
+
if (group instanceof ReactViewGroup
|
|
127
|
+
&& !ViewProps.VISIBLE.equals(((ReactViewGroup) group).getOverflow())) {
|
|
128
|
+
BackgroundStyleApplicator.clipToPaddingBox(group, canvas);
|
|
132
129
|
}
|
|
133
130
|
for (int i = 0; i < group.getChildCount(); i++) {
|
|
134
131
|
View child = group.getChildAt(i);
|
|
@@ -63,9 +63,6 @@ public:
|
|
|
63
63
|
|
|
64
64
|
std::shared_ptr<RNSkVideo> createVideo(const std::string &url) override;
|
|
65
65
|
|
|
66
|
-
std::shared_ptr<WindowContext>
|
|
67
|
-
makeContextFromNativeSurface(void *surface, int width, int height) override;
|
|
68
|
-
|
|
69
66
|
virtual void performStreamOperation(
|
|
70
67
|
const std::string &sourceUri,
|
|
71
68
|
const std::function<void(std::unique_ptr<SkStreamAsset>)> &op) override;
|
|
@@ -307,17 +307,6 @@ RNSkApplePlatformContext::createVideo(const std::string &url) {
|
|
|
307
307
|
return std::make_shared<RNSkAppleVideo>(url, this);
|
|
308
308
|
}
|
|
309
309
|
|
|
310
|
-
std::shared_ptr<WindowContext>
|
|
311
|
-
RNSkApplePlatformContext::makeContextFromNativeSurface(void *surface, int width,
|
|
312
|
-
int height) {
|
|
313
|
-
#if defined(SK_GRAPHITE)
|
|
314
|
-
return DawnContext::getInstance().MakeWindow(surface, width, height);
|
|
315
|
-
#else
|
|
316
|
-
return MetalContext::getInstance().MakeWindow((__bridge CALayer *)surface,
|
|
317
|
-
width, height);
|
|
318
|
-
#endif
|
|
319
|
-
}
|
|
320
|
-
|
|
321
310
|
void RNSkApplePlatformContext::raiseError(const std::exception &err) {
|
|
322
311
|
RCTFatal(RCTErrorWithMessage([NSString stringWithUTF8String:err.what()]));
|
|
323
312
|
}
|
package/cpp/api/JsiSkApi.h
CHANGED
|
@@ -56,7 +56,6 @@
|
|
|
56
56
|
#include "JsiSkTypefaceFactory.h"
|
|
57
57
|
#include "JsiSkTypefaceFontProviderFactory.h"
|
|
58
58
|
#include "JsiSkVertices.h"
|
|
59
|
-
#include "JsiSkiaContext.h"
|
|
60
59
|
#include "JsiSkottieFactory.h"
|
|
61
60
|
#include "JsiVideo.h"
|
|
62
61
|
#include "api/recorder/JsiRecorder.h"
|
|
@@ -116,10 +115,6 @@ public:
|
|
|
116
115
|
return JsiVideo::createCtor(getContext())(runtime, thisValue, arguments,
|
|
117
116
|
count);
|
|
118
117
|
}
|
|
119
|
-
JSI_HOST_FUNCTION(Context) {
|
|
120
|
-
return JsiSkiaContext::createCtor(getContext())(runtime, thisValue,
|
|
121
|
-
arguments, count);
|
|
122
|
-
}
|
|
123
118
|
JSI_HOST_FUNCTION(Font) {
|
|
124
119
|
return JsiSkFont::createCtor(getContext())(runtime, thisValue, arguments,
|
|
125
120
|
count);
|
|
@@ -256,7 +251,6 @@ public:
|
|
|
256
251
|
|
|
257
252
|
static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) {
|
|
258
253
|
installHostMethod(runtime, prototype, "Video", &JsiSkApi::Video);
|
|
259
|
-
installHostMethod(runtime, prototype, "Context", &JsiSkApi::Context);
|
|
260
254
|
installHostMethod(runtime, prototype, "getNativeDevice",
|
|
261
255
|
&JsiSkApi::getNativeDevice);
|
|
262
256
|
installHostMethod(runtime, prototype, "Font", &JsiSkApi::Font);
|
package/cpp/api/JsiSkFont.h
CHANGED
|
@@ -135,8 +135,9 @@ public:
|
|
|
135
135
|
bool isEmbolden() { return getObject()->isEmbolden(); }
|
|
136
136
|
|
|
137
137
|
std::shared_ptr<JsiSkTypeface> getTypeface() {
|
|
138
|
-
|
|
139
|
-
|
|
138
|
+
// refTypeface(), not getTypeface(): the wrapper owns what it is handed.
|
|
139
|
+
return std::make_shared<JsiSkTypeface>(getContext(),
|
|
140
|
+
getObject()->refTypeface());
|
|
140
141
|
}
|
|
141
142
|
|
|
142
143
|
void setEdging(double edging) {
|
|
@@ -161,15 +162,9 @@ public:
|
|
|
161
162
|
|
|
162
163
|
void setSize(double size) { getObject()->setSize(size); }
|
|
163
164
|
|
|
164
|
-
|
|
165
|
-
// the arguments with asNumber() — keep accepting numbers.
|
|
166
|
-
void setEmbolden(double embolden) {
|
|
167
|
-
getObject()->setEmbolden(static_cast<bool>(embolden));
|
|
168
|
-
}
|
|
165
|
+
void setEmbolden(bool embolden) { getObject()->setEmbolden(embolden); }
|
|
169
166
|
|
|
170
|
-
void setSubpixel(
|
|
171
|
-
getObject()->setSubpixel(static_cast<bool>(subpixel));
|
|
172
|
-
}
|
|
167
|
+
void setSubpixel(bool subpixel) { getObject()->setSubpixel(subpixel); }
|
|
173
168
|
|
|
174
169
|
void setTypeface(std::variant<std::nullptr_t, sk_sp<SkTypeface>> typeface) {
|
|
175
170
|
getObject()->setTypeface(
|
package/cpp/api/JsiSkMatrix.h
CHANGED
|
@@ -69,12 +69,14 @@ public:
|
|
|
69
69
|
|
|
70
70
|
void postTranslate(double x, double y) { getObject()->postTranslate(x, y); }
|
|
71
71
|
|
|
72
|
+
// A missing y means a uniform scale, matching the CanvasKit backend and the
|
|
73
|
+
// SkMatrix type, where y is optional rather than defaulted to 1.
|
|
72
74
|
void scale(double x, JsiOptional<double> y) {
|
|
73
|
-
getObject()->preScale(x, y.has_value() ? *y :
|
|
75
|
+
getObject()->preScale(x, y.has_value() ? *y : x);
|
|
74
76
|
}
|
|
75
77
|
|
|
76
78
|
void postScale(double x, JsiOptional<double> y) {
|
|
77
|
-
getObject()->postScale(x, y.has_value() ? *y :
|
|
79
|
+
getObject()->postScale(x, y.has_value() ? *y : x);
|
|
78
80
|
}
|
|
79
81
|
|
|
80
82
|
void skew(double x, double y) { getObject()->preSkew(x, y); }
|
|
@@ -116,6 +116,10 @@ private:
|
|
|
116
116
|
builder.setResourceProvider(provider);
|
|
117
117
|
|
|
118
118
|
auto svg_dom = builder.make(*stream);
|
|
119
|
+
if (!svg_dom) {
|
|
120
|
+
return jsi::Value::null();
|
|
121
|
+
}
|
|
122
|
+
|
|
119
123
|
return makeJsiObject(
|
|
120
124
|
runtime, std::make_shared<JsiSkSVG>(getContext(), std::move(svg_dom)));
|
|
121
125
|
}
|
|
@@ -361,13 +361,16 @@ SkM44 getPropertyValue(jsi::Runtime &runtime, const jsi::Value &value) {
|
|
|
361
361
|
m4.preScale(1, s);
|
|
362
362
|
} else if (key == "skewX") {
|
|
363
363
|
auto angle = value.getProperty(runtime, key.c_str()).asNumber();
|
|
364
|
-
|
|
364
|
+
// The SkM44 constructor takes its arguments in row-major reading
|
|
365
|
+
// order, so the shear factor of a horizontal skew belongs in row 0,
|
|
366
|
+
// where it scales y into x.
|
|
367
|
+
SkM44 skewX(1, std::tan(angle), 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0,
|
|
365
368
|
1);
|
|
366
369
|
m4.preConcat(skewX);
|
|
367
370
|
|
|
368
371
|
} else if (key == "skewY") {
|
|
369
372
|
auto angle = value.getProperty(runtime, key.c_str()).asNumber();
|
|
370
|
-
SkM44 skewY(1,
|
|
373
|
+
SkM44 skewY(1, 0, 0, 0, std::tan(angle), 1, 0, 0, 0, 0, 1, 0, 0, 0, 0,
|
|
371
374
|
1);
|
|
372
375
|
m4.preConcat(skewY);
|
|
373
376
|
} else if (key == "rotate" || key == "rotateZ") {
|
|
@@ -149,6 +149,9 @@ public:
|
|
|
149
149
|
if (hasStrokeOptions) {
|
|
150
150
|
const auto &stroke = props.stroke.value();
|
|
151
151
|
SkPaint strokePaint;
|
|
152
|
+
// A default SkPaint is fill-style, and FillPathWithPaint only
|
|
153
|
+
// outlines a paint that strokes.
|
|
154
|
+
strokePaint.setStyle(SkPaint::kStroke_Style);
|
|
152
155
|
|
|
153
156
|
if (stroke.cap.has_value()) {
|
|
154
157
|
strokePaint.setStrokeCap(stroke.cap.value());
|
|
@@ -166,11 +169,18 @@ public:
|
|
|
166
169
|
strokePaint.setStrokeMiter(stroke.miter_limit.value());
|
|
167
170
|
}
|
|
168
171
|
|
|
172
|
+
float precision = stroke.precision.value_or(1.0f);
|
|
173
|
+
|
|
169
174
|
SkPathBuilder resultBuilder;
|
|
170
|
-
|
|
171
|
-
|
|
175
|
+
auto ctm = SkMatrix::Scale(precision, precision);
|
|
176
|
+
if (skpathutils::FillPathWithPaint(*p, strokePaint, &resultBuilder,
|
|
177
|
+
nullptr, ctm)) {
|
|
178
|
+
pathToUse = std::make_shared<const SkPath>(resultBuilder.snapshot());
|
|
179
|
+
} else {
|
|
180
|
+
// The JS player keeps the unstroked path when Path.Stroke returns
|
|
181
|
+
// null (e.g. a hairline width of 0).
|
|
182
|
+
pathToUse = std::const_pointer_cast<const SkPath>(p);
|
|
172
183
|
}
|
|
173
|
-
pathToUse = std::make_shared<const SkPath>(resultBuilder.snapshot());
|
|
174
184
|
} else {
|
|
175
185
|
pathToUse = std::const_pointer_cast<const SkPath>(p);
|
|
176
186
|
}
|
|
@@ -135,8 +135,22 @@ private:
|
|
|
135
135
|
auto sourceAlpha = SkImageFilters::ColorFilter(
|
|
136
136
|
SkColorFilters::Blend(SK_ColorBLACK, SkBlendMode::kSrcIn), nullptr);
|
|
137
137
|
|
|
138
|
+
// The shadow is generated outside the shape and then clipped back into it,
|
|
139
|
+
// so "outside" has to be the complement of the shape's silhouette. Taking
|
|
140
|
+
// SrcOut against the source graphic itself makes it the complement of the
|
|
141
|
+
// source's *alpha*: inside a translucent shape 1 - alpha is non-zero, so
|
|
142
|
+
// the shadow is generated across the whole interior and tints it, no matter
|
|
143
|
+
// how small the blur and the offset are (issue #2990). Saturating alpha
|
|
144
|
+
// first keeps the shadow tied to the shape's outline instead of to its
|
|
145
|
+
// opacity. 255 is the saturation point of an 8-bit alpha channel, so one
|
|
146
|
+
// unit of coverage is enough to reach 1.
|
|
147
|
+
static constexpr float kAlphaSaturate[20] = {
|
|
148
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0};
|
|
149
|
+
auto coverage = SkImageFilters::ColorFilter(
|
|
150
|
+
SkColorFilters::Matrix(kAlphaSaturate), nullptr);
|
|
151
|
+
|
|
138
152
|
auto f1 = SkImageFilters::ColorFilter(
|
|
139
|
-
SkColorFilters::Blend(color, SkBlendMode::kSrcOut),
|
|
153
|
+
SkColorFilters::Blend(color, SkBlendMode::kSrcOut), coverage);
|
|
140
154
|
|
|
141
155
|
auto f2 = SkImageFilters::Offset(dx, dy, f1);
|
|
142
156
|
auto f3 = SkImageFilters::Blur(sigmaX, sigmaY, SkTileMode::kDecal, f2);
|
package/cpp/api/recorder/Paint.h
CHANGED
|
@@ -154,8 +154,15 @@ public:
|
|
|
154
154
|
}
|
|
155
155
|
ctx->savePaint();
|
|
156
156
|
if (standalone) {
|
|
157
|
+
// Reset the paint that savePaint() just pushed instead of pushing a
|
|
158
|
+
// second one: the matching RestorePaintDeclaration pops a single frame,
|
|
159
|
+
// so an extra push would leave the enclosing group's opacity on the
|
|
160
|
+
// stack and leak it onto every sibling drawn afterwards. The fresh
|
|
161
|
+
// paint is anti-aliased to match the TS player, which resets with
|
|
162
|
+
// Skia.Paint().
|
|
157
163
|
SkPaint freshPaint;
|
|
158
|
-
|
|
164
|
+
freshPaint.setAntiAlias(true);
|
|
165
|
+
ctx->getPaint() = freshPaint;
|
|
159
166
|
}
|
|
160
167
|
auto &paint = ctx->getPaint();
|
|
161
168
|
if (props.opacity.has_value()) {
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
#include "JSICache.h"
|
|
2
|
+
|
|
3
|
+
#include <iterator>
|
|
4
|
+
#include <memory>
|
|
5
|
+
#include <stdexcept>
|
|
6
|
+
#include <string>
|
|
7
|
+
#include <unordered_map>
|
|
8
|
+
#include <utility>
|
|
9
|
+
|
|
10
|
+
namespace RNJsi {
|
|
11
|
+
|
|
12
|
+
namespace {
|
|
13
|
+
// Hidden global holding the per-runtime cache object. Named so it is
|
|
14
|
+
// obviously ours if it ever shows up in a debugger or heap snapshot.
|
|
15
|
+
constexpr const char *kGlobalName = "__rnskiaJsiCache";
|
|
16
|
+
} // namespace
|
|
17
|
+
|
|
18
|
+
std::mutex JSICache::_registryMutex;
|
|
19
|
+
std::unordered_map<jsi::Runtime *, std::weak_ptr<JSICache>> JSICache::_registry;
|
|
20
|
+
|
|
21
|
+
JSICache &JSICache::get(jsi::Runtime &runtime) {
|
|
22
|
+
{
|
|
23
|
+
std::lock_guard<std::mutex> lock(_registryMutex);
|
|
24
|
+
auto it = _registry.find(&runtime);
|
|
25
|
+
if (it != _registry.end()) {
|
|
26
|
+
if (auto cache = it->second.lock()) {
|
|
27
|
+
// The cache is kept alive by `runtime`'s global, so the raw
|
|
28
|
+
// reference stays valid for as long as the caller may legally use
|
|
29
|
+
// `runtime` on this thread.
|
|
30
|
+
return *cache;
|
|
31
|
+
}
|
|
32
|
+
// Expired: the runtime that owned this entry is gone and `&runtime` is
|
|
33
|
+
// a new runtime reusing the address. Fall through and recreate.
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
auto cache = getOrCreateOnGlobal(runtime);
|
|
37
|
+
{
|
|
38
|
+
std::lock_guard<std::mutex> lock(_registryMutex);
|
|
39
|
+
// Drop entries of runtimes that are gone so the map does not grow by one
|
|
40
|
+
// stale pointer per reload / worklet runtime.
|
|
41
|
+
for (auto it = _registry.begin(); it != _registry.end();) {
|
|
42
|
+
it = it->second.expired() ? _registry.erase(it) : std::next(it);
|
|
43
|
+
}
|
|
44
|
+
_registry[&runtime] = cache;
|
|
45
|
+
}
|
|
46
|
+
return *cache;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
std::shared_ptr<JSICache> JSICache::getOrCreateOnGlobal(jsi::Runtime &runtime) {
|
|
50
|
+
auto global = runtime.global();
|
|
51
|
+
auto existing = global.getProperty(runtime, kGlobalName);
|
|
52
|
+
if (existing.isObject()) {
|
|
53
|
+
auto obj = existing.getObject(runtime);
|
|
54
|
+
if (obj.hasNativeState<JSICache>(runtime)) {
|
|
55
|
+
return obj.getNativeState<JSICache>(runtime);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (!existing.isUndefined()) {
|
|
59
|
+
// Something else already claimed our global. The most likely cause is two
|
|
60
|
+
// copies of react-native-skia loaded in one process (each has its own
|
|
61
|
+
// JSICache type, so the NativeState check above fails). Say so instead of
|
|
62
|
+
// letting Object.defineProperty throw a bare TypeError on the
|
|
63
|
+
// non-configurable property.
|
|
64
|
+
throw std::runtime_error(
|
|
65
|
+
std::string("react-native-skia: global.") + kGlobalName +
|
|
66
|
+
" already exists but is not our JSICache. Is react-native-skia "
|
|
67
|
+
"linked twice, or is another module using this global?");
|
|
68
|
+
}
|
|
69
|
+
auto cache = std::make_shared<JSICache>();
|
|
70
|
+
jsi::Object holder(runtime);
|
|
71
|
+
holder.setNativeState(runtime, cache);
|
|
72
|
+
// Non-enumerable, non-writable, non-configurable: JS code must not be able
|
|
73
|
+
// to drop the holder (which would finalize the cache under our feet).
|
|
74
|
+
auto objectCtor = global.getPropertyAsObject(runtime, "Object");
|
|
75
|
+
auto defineProperty =
|
|
76
|
+
objectCtor.getPropertyAsFunction(runtime, "defineProperty");
|
|
77
|
+
jsi::Object descriptor(runtime);
|
|
78
|
+
descriptor.setProperty(runtime, "value", std::move(holder));
|
|
79
|
+
descriptor.setProperty(runtime, "writable", false);
|
|
80
|
+
descriptor.setProperty(runtime, "enumerable", false);
|
|
81
|
+
descriptor.setProperty(runtime, "configurable", false);
|
|
82
|
+
defineProperty.call(runtime, global,
|
|
83
|
+
jsi::String::createFromAscii(runtime, kGlobalName),
|
|
84
|
+
descriptor);
|
|
85
|
+
return cache;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
jsi::Object *JSICache::getPrototype(PrototypeKey key) {
|
|
89
|
+
auto it = _prototypes.find(key);
|
|
90
|
+
return it == _prototypes.end() ? nullptr : &it->second;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
jsi::Object &JSICache::setPrototype(PrototypeKey key, jsi::Object prototype) {
|
|
94
|
+
auto [it, inserted] = _prototypes.insert_or_assign(key, std::move(prototype));
|
|
95
|
+
(void)inserted;
|
|
96
|
+
return it->second;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
} // namespace RNJsi
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <jsi/jsi.h>
|
|
4
|
+
|
|
5
|
+
#include <memory>
|
|
6
|
+
#include <mutex>
|
|
7
|
+
#include <typeindex>
|
|
8
|
+
#include <unordered_map>
|
|
9
|
+
|
|
10
|
+
namespace RNJsi {
|
|
11
|
+
|
|
12
|
+
namespace jsi = facebook::jsi;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Per-runtime store for JSI values that native code wants to keep across
|
|
16
|
+
* calls (currently: the prototype object of every NativeObject class).
|
|
17
|
+
*
|
|
18
|
+
* Ownership model (borrowed from react-native-nitro-modules' JSICache):
|
|
19
|
+
*
|
|
20
|
+
* - One JSICache exists per jsi::Runtime. It is attached as the NativeState
|
|
21
|
+
* of a hidden object stored on that runtime's `global`, so the RUNTIME owns
|
|
22
|
+
* the cache. When the runtime is destroyed the engine finalizes the object,
|
|
23
|
+
* ~JSICache runs while the runtime is still alive, and every cached
|
|
24
|
+
* jsi::Object is released correctly. Nothing outlives its runtime and
|
|
25
|
+
* nothing has to be leaked.
|
|
26
|
+
*
|
|
27
|
+
* - Native code reaches the cache through JSICache::get(runtime). A static
|
|
28
|
+
* map of std::weak_ptr, keyed by jsi::Runtime*, makes the lookup cheap; the
|
|
29
|
+
* pointer is only a map key, never proof that a runtime is alive. If the
|
|
30
|
+
* weak_ptr is expired (the runtime that owned it is gone) the entry is
|
|
31
|
+
* recreated on the runtime asking for it. This is what makes an in-process
|
|
32
|
+
* runtime recreate (expo-updates OTA apply, DevSettings.reload) safe even
|
|
33
|
+
* when the new runtime is allocated at the address of the freed one: the
|
|
34
|
+
* old cache was destroyed with the old runtime, so the reused address can
|
|
35
|
+
* only ever resolve to a fresh cache.
|
|
36
|
+
*
|
|
37
|
+
* - The cache itself is not locked: a jsi::Runtime is single-threaded, and
|
|
38
|
+
* the cache is only ever touched from its runtime's thread. Only the static
|
|
39
|
+
* runtime -> cache map is guarded.
|
|
40
|
+
*
|
|
41
|
+
* The same mechanism works for worklet runtimes (Reanimated UI runtime,
|
|
42
|
+
* createWorkletRuntime, ...); each gets its own JSICache.
|
|
43
|
+
*/
|
|
44
|
+
class JSICache final : public jsi::NativeState {
|
|
45
|
+
public:
|
|
46
|
+
/**
|
|
47
|
+
* Key identifying one cached prototype: the C++ type of the NativeObject
|
|
48
|
+
* subclass (std::type_index(typeid(Derived))), as in Nitro. It prints as
|
|
49
|
+
* the class name in a debugger.
|
|
50
|
+
*/
|
|
51
|
+
using PrototypeKey = std::type_index;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Returns the cache owned by `runtime`, creating it on first use. Must be
|
|
55
|
+
* called on the runtime's thread.
|
|
56
|
+
*/
|
|
57
|
+
static JSICache &get(jsi::Runtime &runtime);
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Returns the cached prototype for `key` or nullptr if none was stored.
|
|
61
|
+
*
|
|
62
|
+
* The pointer points into `_prototypes`. std::unordered_map never
|
|
63
|
+
* invalidates pointers/references to elements on insert or rehash (only on
|
|
64
|
+
* erase of that element, which we never do), so it stays valid for as long
|
|
65
|
+
* as the runtime does. Do not swap the container for one without that
|
|
66
|
+
* guarantee (std::vector, absl::flat_hash_map, ...).
|
|
67
|
+
*/
|
|
68
|
+
jsi::Object *getPrototype(PrototypeKey key);
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Stores (or replaces) the prototype for `key` and returns it.
|
|
72
|
+
*/
|
|
73
|
+
jsi::Object &setPrototype(PrototypeKey key, jsi::Object prototype);
|
|
74
|
+
|
|
75
|
+
JSICache() = default;
|
|
76
|
+
~JSICache() override = default;
|
|
77
|
+
JSICache(const JSICache &) = delete;
|
|
78
|
+
JSICache &operator=(const JSICache &) = delete;
|
|
79
|
+
|
|
80
|
+
private:
|
|
81
|
+
static std::shared_ptr<JSICache> getOrCreateOnGlobal(jsi::Runtime &runtime);
|
|
82
|
+
|
|
83
|
+
std::unordered_map<PrototypeKey, jsi::Object> _prototypes;
|
|
84
|
+
|
|
85
|
+
// Runtime -> cache. Weak on purpose: the runtime's global owns the cache.
|
|
86
|
+
static std::mutex _registryMutex;
|
|
87
|
+
static std::unordered_map<jsi::Runtime *, std::weak_ptr<JSICache>> _registry;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
} // namespace RNJsi
|