react-native-reanimated 3.15.1 → 3.15.3
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/Common/cpp/reanimated/Fabric/PropsRegistry.h +15 -12
- package/Common/cpp/reanimated/Fabric/ReanimatedCommitHook.cpp +7 -8
- package/Common/cpp/reanimated/Fabric/ReanimatedCommitShadowNode.h +16 -1
- package/Common/cpp/reanimated/Fabric/ReanimatedMountHook.cpp +82 -0
- package/Common/cpp/reanimated/Fabric/ReanimatedMountHook.h +33 -0
- package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy.cpp +76 -36
- package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsUtils.h +4 -0
- package/Common/cpp/reanimated/NativeModules/NativeReanimatedModule.cpp +16 -22
- package/Common/cpp/reanimated/NativeModules/NativeReanimatedModule.h +2 -0
- package/lib/module/initializers.js +37 -3
- package/lib/module/initializers.js.map +1 -1
- package/lib/module/platform-specific/jsVersion.js +1 -1
- package/lib/module/platform-specific/jsVersion.js.map +1 -1
- package/lib/typescript/platform-specific/jsVersion.d.ts +1 -1
- package/package.json +1 -1
- package/src/initializers.ts +40 -1
- package/src/platform-specific/jsVersion.ts +1 -1
|
@@ -25,22 +25,24 @@ class PropsRegistry {
|
|
|
25
25
|
|
|
26
26
|
void remove(const Tag tag);
|
|
27
27
|
|
|
28
|
-
void
|
|
29
|
-
|
|
28
|
+
void pauseReanimatedCommits() {
|
|
29
|
+
isPaused_ = true;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
bool shouldReanimatedSkipCommit() {
|
|
33
|
-
|
|
34
|
-
// In RN 0.73+ we have a mount hook that will properly unset this flag
|
|
35
|
-
// after a non-Reanimated commit.
|
|
36
|
-
return shouldReanimatedSkipCommit_;
|
|
37
|
-
#else
|
|
38
|
-
return shouldReanimatedSkipCommit_.exchange(false);
|
|
39
|
-
#endif
|
|
33
|
+
return isPaused_;
|
|
40
34
|
}
|
|
41
35
|
|
|
42
|
-
void
|
|
43
|
-
|
|
36
|
+
void unpauseReanimatedCommits() {
|
|
37
|
+
isPaused_ = false;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
void pleaseCommitAfterPause() {
|
|
41
|
+
shouldCommitAfterPause_ = true;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
bool shouldCommitAfterPause() {
|
|
45
|
+
return shouldCommitAfterPause_.exchange(false);
|
|
44
46
|
}
|
|
45
47
|
|
|
46
48
|
private:
|
|
@@ -48,7 +50,8 @@ class PropsRegistry {
|
|
|
48
50
|
|
|
49
51
|
mutable std::mutex mutex_; // Protects `map_`.
|
|
50
52
|
|
|
51
|
-
std::atomic<bool>
|
|
53
|
+
std::atomic<bool> isPaused_;
|
|
54
|
+
std::atomic<bool> shouldCommitAfterPause_;
|
|
52
55
|
};
|
|
53
56
|
|
|
54
57
|
} // namespace reanimated
|
|
@@ -26,12 +26,7 @@ ReanimatedCommitHook::~ReanimatedCommitHook() noexcept {
|
|
|
26
26
|
RootShadowNode::Unshared ReanimatedCommitHook::shadowTreeWillCommit(
|
|
27
27
|
ShadowTree const &,
|
|
28
28
|
RootShadowNode::Shared const &,
|
|
29
|
-
#if REACT_NATIVE_MINOR_VERSION >= 73
|
|
30
29
|
RootShadowNode::Unshared const &newRootShadowNode) noexcept {
|
|
31
|
-
#else
|
|
32
|
-
RootShadowNode::Unshared const &newRootShadowNode) const noexcept {
|
|
33
|
-
#endif
|
|
34
|
-
|
|
35
30
|
auto reaShadowNode =
|
|
36
31
|
std::reinterpret_pointer_cast<ReanimatedCommitShadowNode>(
|
|
37
32
|
newRootShadowNode);
|
|
@@ -40,11 +35,12 @@ RootShadowNode::Unshared ReanimatedCommitHook::shadowTreeWillCommit(
|
|
|
40
35
|
// ShadowTree commited by Reanimated, no need to apply updates from
|
|
41
36
|
// PropsRegistry
|
|
42
37
|
reaShadowNode->unsetReanimatedCommitTrait();
|
|
38
|
+
reaShadowNode->setReanimatedMountTrait();
|
|
43
39
|
return newRootShadowNode;
|
|
44
40
|
}
|
|
45
41
|
|
|
46
42
|
// ShadowTree not commited by Reanimated, apply updates from PropsRegistry
|
|
47
|
-
|
|
43
|
+
reaShadowNode->unsetReanimatedMountTrait();
|
|
48
44
|
RootShadowNode::Unshared rootNode = newRootShadowNode;
|
|
49
45
|
PropsMap propsMap;
|
|
50
46
|
|
|
@@ -58,12 +54,15 @@ RootShadowNode::Unshared ReanimatedCommitHook::shadowTreeWillCommit(
|
|
|
58
54
|
|
|
59
55
|
rootNode = cloneShadowTreeWithNewProps(*rootNode, propsMap);
|
|
60
56
|
|
|
61
|
-
// If the commit comes from React Native then
|
|
57
|
+
// If the commit comes from React Native then pause commits from
|
|
62
58
|
// Reanimated since the ShadowTree to be committed by Reanimated may not
|
|
63
59
|
// include the new changes from React Native yet and all changes of animated
|
|
64
60
|
// props will be applied in ReanimatedCommitHook by iterating over
|
|
65
61
|
// PropsRegistry.
|
|
66
|
-
|
|
62
|
+
// This is very important, since if we didn't pause Reanimated commits,
|
|
63
|
+
// it could lead to RN commits being delayed until the animation is finished
|
|
64
|
+
// (very bad).
|
|
65
|
+
propsRegistry_->pauseReanimatedCommits();
|
|
67
66
|
}
|
|
68
67
|
|
|
69
68
|
return rootNode;
|
|
@@ -9,8 +9,14 @@ namespace reanimated {
|
|
|
9
9
|
// We need this information to skip unnecessary updates in
|
|
10
10
|
// the commit hook.
|
|
11
11
|
// Currently RN traits go up to 10, so hopefully
|
|
12
|
-
// the arbitrarily chosen
|
|
12
|
+
// the arbitrarily chosen numbers 27 and 28 will be safe :)
|
|
13
|
+
|
|
14
|
+
// We have to use 2 traits, because we want to distinguish reanimated
|
|
15
|
+
// commits both in the commit hook and mount hook. If we only had one trait
|
|
16
|
+
// and didn't remove it in the commit hook, then any node that would clone
|
|
17
|
+
// this node would also have our commit trait, rendering this trait useless.
|
|
13
18
|
constexpr ShadowNodeTraits::Trait ReanimatedCommitTrait{1 << 27};
|
|
19
|
+
constexpr ShadowNodeTraits::Trait ReanimatedMountTrait{1 << 28};
|
|
14
20
|
|
|
15
21
|
class ReanimatedCommitShadowNode : public ShadowNode {
|
|
16
22
|
public:
|
|
@@ -23,6 +29,15 @@ class ReanimatedCommitShadowNode : public ShadowNode {
|
|
|
23
29
|
inline bool hasReanimatedCommitTrait() {
|
|
24
30
|
return traits_.check(ReanimatedCommitTrait);
|
|
25
31
|
}
|
|
32
|
+
inline void setReanimatedMountTrait() {
|
|
33
|
+
traits_.set(ReanimatedMountTrait);
|
|
34
|
+
}
|
|
35
|
+
inline void unsetReanimatedMountTrait() {
|
|
36
|
+
traits_.unset(ReanimatedMountTrait);
|
|
37
|
+
}
|
|
38
|
+
inline bool hasReanimatedMountTrait() {
|
|
39
|
+
return traits_.check(ReanimatedMountTrait);
|
|
40
|
+
}
|
|
26
41
|
};
|
|
27
42
|
|
|
28
43
|
} // namespace reanimated
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
2
|
+
|
|
3
|
+
#include "ReanimatedMountHook.h"
|
|
4
|
+
#include "ReanimatedCommitShadowNode.h"
|
|
5
|
+
|
|
6
|
+
namespace reanimated {
|
|
7
|
+
|
|
8
|
+
ReanimatedMountHook::ReanimatedMountHook(
|
|
9
|
+
const std::shared_ptr<PropsRegistry> &propsRegistry,
|
|
10
|
+
const std::shared_ptr<UIManager> &uiManager)
|
|
11
|
+
: propsRegistry_(propsRegistry), uiManager_(uiManager) {
|
|
12
|
+
uiManager_->registerMountHook(*this);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
ReanimatedMountHook::~ReanimatedMountHook() noexcept {
|
|
16
|
+
uiManager_->unregisterMountHook(*this);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
void ReanimatedMountHook::shadowTreeDidMount(
|
|
20
|
+
RootShadowNode::Shared const &rootShadowNode,
|
|
21
|
+
double) noexcept {
|
|
22
|
+
auto reaShadowNode =
|
|
23
|
+
std::reinterpret_pointer_cast<ReanimatedCommitShadowNode>(
|
|
24
|
+
std::const_pointer_cast<RootShadowNode>(rootShadowNode));
|
|
25
|
+
|
|
26
|
+
if (reaShadowNode->hasReanimatedMountTrait()) {
|
|
27
|
+
// We mark reanimated commits with ReanimatedMountTrait. We don't want other
|
|
28
|
+
// shadow nodes to use this trait, but since this rootShadowNode is Shared,
|
|
29
|
+
// we don't have that guarantee. That's why we also unset this trait in the
|
|
30
|
+
// commit hook. We remove it here mainly for the sake of cleanliness.
|
|
31
|
+
reaShadowNode->unsetReanimatedMountTrait();
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// When commit from React Native has finished, we reset the skip commit flag
|
|
36
|
+
// in order to allow Reanimated to commit its tree
|
|
37
|
+
propsRegistry_->unpauseReanimatedCommits();
|
|
38
|
+
if (!propsRegistry_->shouldCommitAfterPause()) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const auto &shadowTreeRegistry = uiManager_->getShadowTreeRegistry();
|
|
43
|
+
shadowTreeRegistry.visit(
|
|
44
|
+
rootShadowNode->getSurfaceId(), [&](ShadowTree const &shadowTree) {
|
|
45
|
+
shadowTree.commit(
|
|
46
|
+
[&](RootShadowNode const &oldRootShadowNode)
|
|
47
|
+
-> RootShadowNode::Unshared {
|
|
48
|
+
PropsMap propsMap;
|
|
49
|
+
|
|
50
|
+
RootShadowNode::Unshared rootNode =
|
|
51
|
+
std::static_pointer_cast<RootShadowNode>(
|
|
52
|
+
oldRootShadowNode.ShadowNode::clone({}));
|
|
53
|
+
{
|
|
54
|
+
auto lock = propsRegistry_->createLock();
|
|
55
|
+
|
|
56
|
+
propsRegistry_->for_each([&](const ShadowNodeFamily &family,
|
|
57
|
+
const folly::dynamic &props) {
|
|
58
|
+
propsMap[&family].emplace_back(props);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
rootNode =
|
|
62
|
+
cloneShadowTreeWithNewProps(oldRootShadowNode, propsMap);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Mark the commit as Reanimated commit so that we can
|
|
66
|
+
// distinguish it in ReanimatedCommitHook.
|
|
67
|
+
auto reaShadowNode =
|
|
68
|
+
std::reinterpret_pointer_cast<ReanimatedCommitShadowNode>(
|
|
69
|
+
rootNode);
|
|
70
|
+
reaShadowNode->setReanimatedCommitTrait();
|
|
71
|
+
|
|
72
|
+
return rootNode;
|
|
73
|
+
},
|
|
74
|
+
{/* .enableStateReconciliation = */
|
|
75
|
+
false,
|
|
76
|
+
/* .mountSynchronously = */ true});
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
} // namespace reanimated
|
|
81
|
+
|
|
82
|
+
#endif // RCT_NEW_ARCH_ENABLED
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
3
|
+
|
|
4
|
+
#include "PropsRegistry.h"
|
|
5
|
+
|
|
6
|
+
#include <react/renderer/uimanager/UIManagerMountHook.h>
|
|
7
|
+
#include "ShadowTreeCloner.h"
|
|
8
|
+
|
|
9
|
+
#include <memory>
|
|
10
|
+
|
|
11
|
+
namespace reanimated {
|
|
12
|
+
|
|
13
|
+
using namespace facebook::react;
|
|
14
|
+
|
|
15
|
+
class ReanimatedMountHook : public UIManagerMountHook {
|
|
16
|
+
public:
|
|
17
|
+
ReanimatedMountHook(
|
|
18
|
+
const std::shared_ptr<PropsRegistry> &propsRegistry,
|
|
19
|
+
const std::shared_ptr<UIManager> &uiManager);
|
|
20
|
+
~ReanimatedMountHook() noexcept override;
|
|
21
|
+
|
|
22
|
+
void shadowTreeDidMount(
|
|
23
|
+
RootShadowNode::Shared const &rootShadowNode,
|
|
24
|
+
double mountTime) noexcept override;
|
|
25
|
+
|
|
26
|
+
private:
|
|
27
|
+
const std::shared_ptr<PropsRegistry> propsRegistry_;
|
|
28
|
+
const std::shared_ptr<UIManager> uiManager_;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
} // namespace reanimated
|
|
32
|
+
|
|
33
|
+
#endif // RCT_NEW_ARCH_ENABLED
|
|
@@ -22,7 +22,8 @@ std::optional<MountingTransaction> LayoutAnimationsProxy::pullTransaction(
|
|
|
22
22
|
const TransactionTelemetry &telemetry,
|
|
23
23
|
ShadowViewMutationList mutations) const {
|
|
24
24
|
#ifdef LAYOUT_ANIMATIONS_LOGS
|
|
25
|
-
LOG(INFO) <<
|
|
25
|
+
LOG(INFO) << std::endl;
|
|
26
|
+
LOG(INFO) << "pullTransaction " << std::this_thread::get_id() << " "
|
|
26
27
|
<< surfaceId << std::endl;
|
|
27
28
|
#endif
|
|
28
29
|
auto lock = std::unique_lock<std::recursive_mutex>(mutex);
|
|
@@ -240,15 +241,15 @@ void LayoutAnimationsProxy::handleRemovals(
|
|
|
240
241
|
if (!startAnimationsRecursively(
|
|
241
242
|
node, true, true, false, filteredMutations)) {
|
|
242
243
|
filteredMutations.push_back(node->mutation);
|
|
243
|
-
nodeForTag_.erase(node->tag);
|
|
244
244
|
node->unflattenedParent->removeChildFromUnflattenedTree(node); //???
|
|
245
|
-
#ifdef LAYOUT_ANIMATIONS_LOGS
|
|
246
|
-
LOG(INFO) << "delete " << node->tag << std::endl;
|
|
247
|
-
#endif
|
|
248
245
|
if (node->state != MOVED) {
|
|
249
246
|
maybeCancelAnimation(node->tag);
|
|
250
247
|
filteredMutations.push_back(ShadowViewMutation::DeleteMutation(
|
|
251
248
|
node->mutation.oldChildShadowView));
|
|
249
|
+
nodeForTag_.erase(node->tag);
|
|
250
|
+
#ifdef LAYOUT_ANIMATIONS_LOGS
|
|
251
|
+
LOG(INFO) << "delete " << node->tag << std::endl;
|
|
252
|
+
#endif
|
|
252
253
|
}
|
|
253
254
|
}
|
|
254
255
|
}
|
|
@@ -268,6 +269,7 @@ void LayoutAnimationsProxy::handleUpdatesAndEnterings(
|
|
|
268
269
|
ShadowViewMutationList &mutations,
|
|
269
270
|
const PropsParserContext &propsParserContext,
|
|
270
271
|
SurfaceId surfaceId) const {
|
|
272
|
+
std::unordered_map<Tag, ShadowView> oldShadowViewsForReparentings;
|
|
271
273
|
for (auto &mutation : mutations) {
|
|
272
274
|
maybeUpdateWindowDimensions(mutation, surfaceId);
|
|
273
275
|
|
|
@@ -291,7 +293,14 @@ void LayoutAnimationsProxy::handleUpdatesAndEnterings(
|
|
|
291
293
|
if (movedViews.contains(tag)) {
|
|
292
294
|
auto layoutAnimationIt = layoutAnimations_.find(tag);
|
|
293
295
|
if (layoutAnimationIt == layoutAnimations_.end()) {
|
|
294
|
-
|
|
296
|
+
if (oldShadowViewsForReparentings.contains(tag)) {
|
|
297
|
+
filteredMutations.push_back(ShadowViewMutation::InsertMutation(
|
|
298
|
+
mutation.parentShadowView,
|
|
299
|
+
oldShadowViewsForReparentings[tag],
|
|
300
|
+
mutation.index));
|
|
301
|
+
} else {
|
|
302
|
+
filteredMutations.push_back(mutation);
|
|
303
|
+
}
|
|
295
304
|
continue;
|
|
296
305
|
}
|
|
297
306
|
|
|
@@ -338,6 +347,10 @@ void LayoutAnimationsProxy::handleUpdatesAndEnterings(
|
|
|
338
347
|
updateOngoingAnimationTarget(tag, mutation);
|
|
339
348
|
continue;
|
|
340
349
|
}
|
|
350
|
+
|
|
351
|
+
// store the oldChildShadowView, so that we can use this ShadowView when
|
|
352
|
+
// the view is inserted
|
|
353
|
+
oldShadowViewsForReparentings[tag] = mutation.oldChildShadowView;
|
|
341
354
|
startLayoutAnimation(tag, mutation);
|
|
342
355
|
break;
|
|
343
356
|
}
|
|
@@ -471,6 +484,7 @@ bool LayoutAnimationsProxy::startAnimationsRecursively(
|
|
|
471
484
|
hasAnimatedChildren = true;
|
|
472
485
|
} else {
|
|
473
486
|
endAnimationsRecursively(subNode, mutations);
|
|
487
|
+
toBeRemoved.push_back(subNode);
|
|
474
488
|
}
|
|
475
489
|
} else if (startAnimationsRecursively(
|
|
476
490
|
subNode,
|
|
@@ -486,7 +500,7 @@ bool LayoutAnimationsProxy::startAnimationsRecursively(
|
|
|
486
500
|
hasAnimatedChildren = true;
|
|
487
501
|
} else if (subNode->state == MOVED) {
|
|
488
502
|
mutations.push_back(subNode->mutation);
|
|
489
|
-
|
|
503
|
+
toBeRemoved.push_back(subNode);
|
|
490
504
|
} else if (shouldRemoveSubviewsWithoutAnimations) {
|
|
491
505
|
maybeCancelAnimation(subNode->tag);
|
|
492
506
|
mutations.push_back(subNode->mutation);
|
|
@@ -508,6 +522,14 @@ bool LayoutAnimationsProxy::startAnimationsRecursively(
|
|
|
508
522
|
}
|
|
509
523
|
|
|
510
524
|
if (node->state == MOVED) {
|
|
525
|
+
auto replacement = std::make_shared<Node>(*node);
|
|
526
|
+
for (auto subNode : node->children) {
|
|
527
|
+
subNode->parent = replacement;
|
|
528
|
+
}
|
|
529
|
+
for (auto subNode : node->unflattenedChildren) {
|
|
530
|
+
subNode->unflattenedParent = replacement;
|
|
531
|
+
}
|
|
532
|
+
nodeForTag_[replacement->tag] = replacement;
|
|
511
533
|
return false;
|
|
512
534
|
}
|
|
513
535
|
|
|
@@ -594,30 +616,37 @@ void LayoutAnimationsProxy::startEnteringAnimation(
|
|
|
594
616
|
LOG(INFO) << "start entering animation for tag " << tag << std::endl;
|
|
595
617
|
#endif
|
|
596
618
|
auto finalView = std::make_shared<ShadowView>(mutation.newChildShadowView);
|
|
597
|
-
auto current = std::make_shared<ShadowView>(mutation.
|
|
619
|
+
auto current = std::make_shared<ShadowView>(mutation.newChildShadowView);
|
|
598
620
|
auto parent = std::make_shared<ShadowView>(mutation.parentShadowView);
|
|
599
621
|
|
|
600
622
|
auto &viewProps =
|
|
601
623
|
static_cast<const ViewProps &>(*mutation.newChildShadowView.props);
|
|
602
|
-
|
|
603
|
-
|
|
624
|
+
auto opacity = viewProps.opacity;
|
|
625
|
+
|
|
626
|
+
uiScheduler_->scheduleOnUI(
|
|
627
|
+
[finalView, current, parent, mutation, opacity, this, tag]() {
|
|
628
|
+
Rect window{};
|
|
629
|
+
{
|
|
630
|
+
auto lock = std::unique_lock<std::recursive_mutex>(mutex);
|
|
631
|
+
layoutAnimations_.insert_or_assign(
|
|
632
|
+
tag, LayoutAnimation{finalView, current, parent, opacity});
|
|
633
|
+
window =
|
|
634
|
+
surfaceManager.getWindow(mutation.newChildShadowView.surfaceId);
|
|
635
|
+
}
|
|
604
636
|
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
layoutAnimationsManager_->startLayoutAnimation(
|
|
619
|
-
uiRuntime_, tag, LayoutAnimationType::ENTERING, yogaValues);
|
|
620
|
-
});
|
|
637
|
+
Snapshot values(mutation.newChildShadowView, window);
|
|
638
|
+
jsi::Object yogaValues(uiRuntime_);
|
|
639
|
+
yogaValues.setProperty(uiRuntime_, "targetOriginX", values.x);
|
|
640
|
+
yogaValues.setProperty(uiRuntime_, "targetGlobalOriginX", values.x);
|
|
641
|
+
yogaValues.setProperty(uiRuntime_, "targetOriginY", values.y);
|
|
642
|
+
yogaValues.setProperty(uiRuntime_, "targetGlobalOriginY", values.y);
|
|
643
|
+
yogaValues.setProperty(uiRuntime_, "targetWidth", values.width);
|
|
644
|
+
yogaValues.setProperty(uiRuntime_, "targetHeight", values.height);
|
|
645
|
+
yogaValues.setProperty(uiRuntime_, "windowWidth", values.windowWidth);
|
|
646
|
+
yogaValues.setProperty(uiRuntime_, "windowHeight", values.windowHeight);
|
|
647
|
+
layoutAnimationsManager_->startLayoutAnimation(
|
|
648
|
+
uiRuntime_, tag, LayoutAnimationType::ENTERING, yogaValues);
|
|
649
|
+
});
|
|
621
650
|
}
|
|
622
651
|
|
|
623
652
|
void LayoutAnimationsProxy::startExitingAnimation(
|
|
@@ -627,12 +656,18 @@ void LayoutAnimationsProxy::startExitingAnimation(
|
|
|
627
656
|
LOG(INFO) << "start exiting animation for tag " << tag << std::endl;
|
|
628
657
|
#endif
|
|
629
658
|
auto surfaceId = mutation.oldChildShadowView.surfaceId;
|
|
630
|
-
auto oldView = mutation.oldChildShadowView;
|
|
631
|
-
createLayoutAnimation(mutation, oldView, surfaceId, tag);
|
|
632
659
|
|
|
633
|
-
|
|
660
|
+
uiScheduler_->scheduleOnUI([this, tag, mutation, surfaceId]() {
|
|
661
|
+
auto oldView = mutation.oldChildShadowView;
|
|
662
|
+
Rect window{};
|
|
663
|
+
{
|
|
664
|
+
auto lock = std::unique_lock<std::recursive_mutex>(mutex);
|
|
665
|
+
createLayoutAnimation(mutation, oldView, surfaceId, tag);
|
|
666
|
+
window = surfaceManager.getWindow(surfaceId);
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
Snapshot values(oldView, window);
|
|
634
670
|
|
|
635
|
-
uiScheduler_->scheduleOnUI([values, this, tag]() {
|
|
636
671
|
jsi::Object yogaValues(uiRuntime_);
|
|
637
672
|
yogaValues.setProperty(uiRuntime_, "currentOriginX", values.x);
|
|
638
673
|
yogaValues.setProperty(uiRuntime_, "currentGlobalOriginX", values.x);
|
|
@@ -655,14 +690,19 @@ void LayoutAnimationsProxy::startLayoutAnimation(
|
|
|
655
690
|
LOG(INFO) << "start layout animation for tag " << tag << std::endl;
|
|
656
691
|
#endif
|
|
657
692
|
auto surfaceId = mutation.oldChildShadowView.surfaceId;
|
|
658
|
-
auto oldView = mutation.oldChildShadowView;
|
|
659
|
-
createLayoutAnimation(mutation, oldView, surfaceId, tag);
|
|
660
693
|
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
694
|
+
uiScheduler_->scheduleOnUI([this, mutation, surfaceId, tag]() {
|
|
695
|
+
auto oldView = mutation.oldChildShadowView;
|
|
696
|
+
Rect window{};
|
|
697
|
+
{
|
|
698
|
+
auto lock = std::unique_lock<std::recursive_mutex>(mutex);
|
|
699
|
+
createLayoutAnimation(mutation, oldView, surfaceId, tag);
|
|
700
|
+
window = surfaceManager.getWindow(surfaceId);
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
Snapshot currentValues(oldView, window);
|
|
704
|
+
Snapshot targetValues(mutation.newChildShadowView, window);
|
|
664
705
|
|
|
665
|
-
uiScheduler_->scheduleOnUI([currentValues, targetValues, this, tag]() {
|
|
666
706
|
jsi::Object yogaValues(uiRuntime_);
|
|
667
707
|
yogaValues.setProperty(uiRuntime_, "currentOriginX", currentValues.x);
|
|
668
708
|
yogaValues.setProperty(uiRuntime_, "currentGlobalOriginX", currentValues.x);
|
|
@@ -83,6 +83,10 @@ struct Node {
|
|
|
83
83
|
: children(std::move(node.children)),
|
|
84
84
|
unflattenedChildren(std::move(node.unflattenedChildren)),
|
|
85
85
|
tag(node.tag) {}
|
|
86
|
+
Node(Node &node)
|
|
87
|
+
: children(node.children),
|
|
88
|
+
unflattenedChildren(node.unflattenedChildren),
|
|
89
|
+
tag(node.tag) {}
|
|
86
90
|
virtual ~Node() = default;
|
|
87
91
|
};
|
|
88
92
|
|
|
@@ -195,7 +195,7 @@ void NativeReanimatedModule::scheduleOnUI(
|
|
|
195
195
|
const jsi::Value &worklet) {
|
|
196
196
|
auto shareableWorklet = extractShareableOrThrow<ShareableWorklet>(
|
|
197
197
|
rt, worklet, "[Reanimated] Only worklets can be scheduled to run on UI.");
|
|
198
|
-
uiScheduler_->scheduleOnUI([
|
|
198
|
+
uiScheduler_->scheduleOnUI([=, this] {
|
|
199
199
|
#if JS_RUNTIME_HERMES
|
|
200
200
|
// JSI's scope defined here allows for JSI-objects to be cleared up after
|
|
201
201
|
// each runtime loop. Within these loops we typically create some temporary
|
|
@@ -261,7 +261,7 @@ jsi::Value NativeReanimatedModule::registerEventHandler(
|
|
|
261
261
|
rt, worklet, "[Reanimated] Event handler must be a worklet.");
|
|
262
262
|
int emitterReactTagInt = emitterReactTag.asNumber();
|
|
263
263
|
|
|
264
|
-
uiScheduler_->scheduleOnUI([
|
|
264
|
+
uiScheduler_->scheduleOnUI([=, this] {
|
|
265
265
|
auto handler = std::make_shared<WorkletEventHandler>(
|
|
266
266
|
newRegistrationId, eventNameStr, emitterReactTagInt, handlerShareable);
|
|
267
267
|
eventHandlerRegistry_->registerEventHandler(std::move(handler));
|
|
@@ -275,7 +275,7 @@ void NativeReanimatedModule::unregisterEventHandler(
|
|
|
275
275
|
const jsi::Value ®istrationId) {
|
|
276
276
|
uint64_t id = registrationId.asNumber();
|
|
277
277
|
uiScheduler_->scheduleOnUI(
|
|
278
|
-
[
|
|
278
|
+
[=, this] { eventHandlerRegistry_->unregisterEventHandler(id); });
|
|
279
279
|
}
|
|
280
280
|
|
|
281
281
|
#ifdef RCT_NEW_ARCH_ENABLED
|
|
@@ -371,7 +371,7 @@ jsi::Value NativeReanimatedModule::getViewProp(
|
|
|
371
371
|
|
|
372
372
|
const int viewTagInt = viewTag.asNumber();
|
|
373
373
|
|
|
374
|
-
uiScheduler_->scheduleOnUI([
|
|
374
|
+
uiScheduler_->scheduleOnUI([=, this]() {
|
|
375
375
|
jsi::Runtime &uiRuntime = uiWorkletRuntime_->getJSIRuntime();
|
|
376
376
|
const jsi::Value propNameValue =
|
|
377
377
|
jsi::String::createFromUtf8(uiRuntime, propNameStr);
|
|
@@ -644,8 +644,9 @@ void NativeReanimatedModule::performOperations() {
|
|
|
644
644
|
{
|
|
645
645
|
auto lock = propsRegistry_->createLock();
|
|
646
646
|
|
|
647
|
-
if (copiedOperationsQueue.size() > 0
|
|
648
|
-
|
|
647
|
+
if (copiedOperationsQueue.size() > 0 &&
|
|
648
|
+
propsRegistry_->shouldReanimatedSkipCommit()) {
|
|
649
|
+
propsRegistry_->pleaseCommitAfterPause();
|
|
649
650
|
}
|
|
650
651
|
|
|
651
652
|
// remove recently unmounted ShadowNodes from PropsRegistry
|
|
@@ -722,15 +723,9 @@ void NativeReanimatedModule::performOperations() {
|
|
|
722
723
|
react_native_assert(family->getSurfaceId() == surfaceId_);
|
|
723
724
|
propsMap[family].emplace_back(rt, std::move(*props));
|
|
724
725
|
|
|
725
|
-
#if REACT_NATIVE_MINOR_VERSION >= 73
|
|
726
|
-
// Fix for catching nullptr returned from commit hook was
|
|
727
|
-
// introduced in 0.72.4 but we have only check for minor version
|
|
728
|
-
// of React Native so enable that optimization in React Native >=
|
|
729
|
-
// 0.73
|
|
730
726
|
if (propsRegistry_->shouldReanimatedSkipCommit()) {
|
|
731
727
|
return nullptr;
|
|
732
728
|
}
|
|
733
|
-
#endif
|
|
734
729
|
}
|
|
735
730
|
|
|
736
731
|
auto rootNode =
|
|
@@ -746,15 +741,12 @@ void NativeReanimatedModule::performOperations() {
|
|
|
746
741
|
|
|
747
742
|
return rootNode;
|
|
748
743
|
},
|
|
749
|
-
{
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
return propsRegistry_->shouldReanimatedSkipCommit();
|
|
756
|
-
}
|
|
757
|
-
});
|
|
744
|
+
{/* .enableStateReconciliation = */
|
|
745
|
+
false,
|
|
746
|
+
/* .mountSynchronously = */ true,
|
|
747
|
+
/* .shouldYield = */ [this]() {
|
|
748
|
+
return propsRegistry_->shouldReanimatedSkipCommit();
|
|
749
|
+
}});
|
|
758
750
|
});
|
|
759
751
|
}
|
|
760
752
|
|
|
@@ -840,6 +832,8 @@ void NativeReanimatedModule::initializeFabric(
|
|
|
840
832
|
|
|
841
833
|
initializeLayoutAnimations();
|
|
842
834
|
|
|
835
|
+
mountHook_ =
|
|
836
|
+
std::make_shared<ReanimatedMountHook>(propsRegistry_, uiManager_);
|
|
843
837
|
commitHook_ =
|
|
844
838
|
std::make_shared<ReanimatedCommitHook>(propsRegistry_, uiManager_);
|
|
845
839
|
}
|
|
@@ -878,7 +872,7 @@ jsi::Value NativeReanimatedModule::subscribeForKeyboardEvents(
|
|
|
878
872
|
handlerWorklet,
|
|
879
873
|
"[Reanimated] Keyboard event handler must be a worklet.");
|
|
880
874
|
return subscribeForKeyboardEventsFunction_(
|
|
881
|
-
[
|
|
875
|
+
[=, this](int keyboardState, int height) {
|
|
882
876
|
uiWorkletRuntime_->runGuarded(
|
|
883
877
|
shareableHandler, jsi::Value(keyboardState), jsi::Value(height));
|
|
884
878
|
},
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
#include "LayoutAnimationsProxy.h"
|
|
24
24
|
#include "PropsRegistry.h"
|
|
25
25
|
#include "ReanimatedCommitHook.h"
|
|
26
|
+
#include "ReanimatedMountHook.h"
|
|
26
27
|
#endif
|
|
27
28
|
|
|
28
29
|
namespace reanimated {
|
|
@@ -218,6 +219,7 @@ class NativeReanimatedModule : public NativeReanimatedModuleSpec {
|
|
|
218
219
|
|
|
219
220
|
std::shared_ptr<PropsRegistry> propsRegistry_;
|
|
220
221
|
std::shared_ptr<ReanimatedCommitHook> commitHook_;
|
|
222
|
+
std::shared_ptr<ReanimatedMountHook> mountHook_;
|
|
221
223
|
|
|
222
224
|
std::vector<Tag> tagsToRemove_; // from `propsRegistry_`
|
|
223
225
|
#else
|
|
@@ -36,11 +36,45 @@ export function setupCallGuard() {
|
|
|
36
36
|
};
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Currently there seems to be a bug in the JSI layer which causes a crash when
|
|
41
|
+
* we try to copy some of the console methods, i.e. `clear` or `dirxml`.
|
|
42
|
+
*
|
|
43
|
+
* The crash happens only in React Native 0.75. It's not reproducible in neither
|
|
44
|
+
* 0.76 nor 0.74. It also happens only in the configuration of a debug app and
|
|
45
|
+
* production bundle.
|
|
46
|
+
*
|
|
47
|
+
* I haven't yet discovered what exactly causes the crash. It's tied to the
|
|
48
|
+
* console methods sometimes being `HostFunction`s. Therefore, as a workaround
|
|
49
|
+
* we don't copy the methods as they are in the original console object, we copy
|
|
50
|
+
* JavaScript wrappers instead.
|
|
51
|
+
*/
|
|
52
|
+
function createMemorySafeCapturableConsole() {
|
|
53
|
+
const consoleCopy = Object.fromEntries(Object.entries(console).map(([methodName, method]) => {
|
|
54
|
+
const methodWrapper = function methodWrapper(...args) {
|
|
55
|
+
return method(...args);
|
|
56
|
+
};
|
|
57
|
+
if (method.name) {
|
|
58
|
+
/**
|
|
59
|
+
* Set the original method name as the wrapper name if available.
|
|
60
|
+
*
|
|
61
|
+
* It might be unnecessary but if we want to fully mimic the console
|
|
62
|
+
* object we should take into the account the fact some code might rely
|
|
63
|
+
* on the method name.
|
|
64
|
+
*/
|
|
65
|
+
Object.defineProperty(methodWrapper, 'name', {
|
|
66
|
+
value: method.name,
|
|
67
|
+
writable: false
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
return [methodName, methodWrapper];
|
|
71
|
+
}));
|
|
72
|
+
return consoleCopy;
|
|
73
|
+
}
|
|
74
|
+
|
|
39
75
|
// We really have to create a copy of console here. Function runOnJS we use on elements inside
|
|
40
76
|
// this object makes it not configurable
|
|
41
|
-
const capturableConsole =
|
|
42
|
-
...console
|
|
43
|
-
};
|
|
77
|
+
const capturableConsole = createMemorySafeCapturableConsole();
|
|
44
78
|
export function setupConsole() {
|
|
45
79
|
'worklet';
|
|
46
80
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["reportFatalErrorOnJS","isChromeDebugger","isJest","shouldBeUseWeb","runOnJS","setupMicrotasks","callMicrotasks","runOnUIImmediately","mockedRequestAnimationFrame","IS_JEST","SHOULD_BE_USE_WEB","IS_CHROME_DEBUGGER","callGuardDEV","fn","args","e","global","__ErrorUtils","reportFatalError","setupCallGuard","__callGuardDEV","error","message","stack","
|
|
1
|
+
{"version":3,"names":["reportFatalErrorOnJS","isChromeDebugger","isJest","shouldBeUseWeb","runOnJS","setupMicrotasks","callMicrotasks","runOnUIImmediately","mockedRequestAnimationFrame","IS_JEST","SHOULD_BE_USE_WEB","IS_CHROME_DEBUGGER","callGuardDEV","fn","args","e","global","__ErrorUtils","reportFatalError","setupCallGuard","__callGuardDEV","error","message","stack","createMemorySafeCapturableConsole","consoleCopy","Object","fromEntries","entries","console","map","methodName","method","methodWrapper","name","defineProperty","value","writable","capturableConsole","setupConsole","assert","debug","log","warn","info","setupRequestAnimationFrame","nativeRequestAnimationFrame","requestAnimationFrame","animationFrameCallbacks","flushRequested","__flushAnimationFrame","frameTimestamp","currentCallbacks","forEach","f","callback","push","timestamp","__frameTimestamp","undefined","initializeUIRuntime","globalThis"],"sources":["initializers.ts"],"sourcesContent":["'use strict';\nimport { reportFatalErrorOnJS } from './errors';\nimport { isChromeDebugger, isJest, shouldBeUseWeb } from './PlatformChecker';\nimport {\n runOnJS,\n setupMicrotasks,\n callMicrotasks,\n runOnUIImmediately,\n} from './threads';\nimport { mockedRequestAnimationFrame } from './mockedRequestAnimationFrame';\n\nconst IS_JEST = isJest();\nconst SHOULD_BE_USE_WEB = shouldBeUseWeb();\nconst IS_CHROME_DEBUGGER = isChromeDebugger();\n\n// callGuard is only used with debug builds\nexport function callGuardDEV<Args extends unknown[], ReturnValue>(\n fn: (...args: Args) => ReturnValue,\n ...args: Args\n): ReturnValue | void {\n 'worklet';\n try {\n return fn(...args);\n } catch (e) {\n if (global.__ErrorUtils) {\n global.__ErrorUtils.reportFatalError(e as Error);\n } else {\n throw e;\n }\n }\n}\n\nexport function setupCallGuard() {\n 'worklet';\n global.__callGuardDEV = callGuardDEV;\n global.__ErrorUtils = {\n reportFatalError: (error: Error) => {\n runOnJS(reportFatalErrorOnJS)({\n message: error.message,\n stack: error.stack,\n });\n },\n };\n}\n\n/**\n * Currently there seems to be a bug in the JSI layer which causes a crash when\n * we try to copy some of the console methods, i.e. `clear` or `dirxml`.\n *\n * The crash happens only in React Native 0.75. It's not reproducible in neither\n * 0.76 nor 0.74. It also happens only in the configuration of a debug app and\n * production bundle.\n *\n * I haven't yet discovered what exactly causes the crash. It's tied to the\n * console methods sometimes being `HostFunction`s. Therefore, as a workaround\n * we don't copy the methods as they are in the original console object, we copy\n * JavaScript wrappers instead.\n */\nfunction createMemorySafeCapturableConsole(): typeof console {\n const consoleCopy = Object.fromEntries(\n Object.entries(console).map(([methodName, method]) => {\n const methodWrapper = function methodWrapper(...args: unknown[]) {\n return method(...args);\n };\n if (method.name) {\n /**\n * Set the original method name as the wrapper name if available.\n *\n * It might be unnecessary but if we want to fully mimic the console\n * object we should take into the account the fact some code might rely\n * on the method name.\n */\n Object.defineProperty(methodWrapper, 'name', {\n value: method.name,\n writable: false,\n });\n }\n return [methodName, methodWrapper];\n })\n );\n\n return consoleCopy as unknown as typeof console;\n}\n\n// We really have to create a copy of console here. Function runOnJS we use on elements inside\n// this object makes it not configurable\nconst capturableConsole = createMemorySafeCapturableConsole();\n\nexport function setupConsole() {\n 'worklet';\n if (!IS_CHROME_DEBUGGER) {\n // @ts-ignore TypeScript doesn't like that there are missing methods in console object, but we don't provide all the methods for the UI runtime console version\n global.console = {\n /* eslint-disable @typescript-eslint/unbound-method */\n assert: runOnJS(capturableConsole.assert),\n debug: runOnJS(capturableConsole.debug),\n log: runOnJS(capturableConsole.log),\n warn: runOnJS(capturableConsole.warn),\n error: runOnJS(capturableConsole.error),\n info: runOnJS(capturableConsole.info),\n /* eslint-enable @typescript-eslint/unbound-method */\n };\n }\n}\n\nfunction setupRequestAnimationFrame() {\n 'worklet';\n\n // Jest mocks requestAnimationFrame API and it does not like if that mock gets overridden\n // so we avoid doing requestAnimationFrame batching in Jest environment.\n const nativeRequestAnimationFrame = global.requestAnimationFrame;\n\n let animationFrameCallbacks: Array<(timestamp: number) => void> = [];\n let flushRequested = false;\n\n global.__flushAnimationFrame = (frameTimestamp: number) => {\n const currentCallbacks = animationFrameCallbacks;\n animationFrameCallbacks = [];\n currentCallbacks.forEach((f) => f(frameTimestamp));\n callMicrotasks();\n };\n\n global.requestAnimationFrame = (\n callback: (timestamp: number) => void\n ): number => {\n animationFrameCallbacks.push(callback);\n if (!flushRequested) {\n flushRequested = true;\n nativeRequestAnimationFrame((timestamp) => {\n flushRequested = false;\n global.__frameTimestamp = timestamp;\n global.__flushAnimationFrame(timestamp);\n global.__frameTimestamp = undefined;\n });\n }\n // Reanimated currently does not support cancelling callbacks requested with\n // requestAnimationFrame. We return -1 as identifier which isn't in line\n // with the spec but it should give users better clue in case they actually\n // attempt to store the value returned from rAF and use it for cancelling.\n return -1;\n };\n}\n\nexport function initializeUIRuntime() {\n if (IS_JEST) {\n // requestAnimationFrame react-native jest's setup is incorrect as it polyfills\n // the method directly using setTimeout, therefore the callback doesn't get the\n // expected timestamp as the only argument: https://github.com/facebook/react-native/blob/main/packages/react-native/jest/setup.js#L28\n // We override this setup here to make sure that callbacks get the proper timestamps\n // when executed. For non-jest environments we define requestAnimationFrame in setupRequestAnimationFrame\n // @ts-ignore TypeScript uses Node definition for rAF, setTimeout, etc which returns a Timeout object rather than a number\n globalThis.requestAnimationFrame = mockedRequestAnimationFrame;\n }\n\n runOnUIImmediately(() => {\n 'worklet';\n setupCallGuard();\n setupConsole();\n if (!SHOULD_BE_USE_WEB) {\n setupMicrotasks();\n setupRequestAnimationFrame();\n }\n })();\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* with the version used to build the native part of the library in runtime.
|
|
6
6
|
* Remember to keep this in sync with the version declared in `package.json`
|
|
7
7
|
*/
|
|
8
|
-
export const jsVersion = '3.15.
|
|
8
|
+
export const jsVersion = '3.15.3';
|
|
9
9
|
//# sourceMappingURL=jsVersion.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["jsVersion"],"sources":["jsVersion.ts"],"sourcesContent":["'use strict';\n/**\n * We hardcode the version of Reanimated here in order to compare it\n * with the version used to build the native part of the library in runtime.\n * Remember to keep this in sync with the version declared in `package.json`\n */\nexport const jsVersion = '3.15.
|
|
1
|
+
{"version":3,"names":["jsVersion"],"sources":["jsVersion.ts"],"sourcesContent":["'use strict';\n/**\n * We hardcode the version of Reanimated here in order to compare it\n * with the version used to build the native part of the library in runtime.\n * Remember to keep this in sync with the version declared in `package.json`\n */\nexport const jsVersion = '3.15.3';\n"],"mappings":"AAAA,YAAY;;AACZ;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMA,SAAS,GAAG,QAAQ","ignoreList":[]}
|
package/package.json
CHANGED
package/src/initializers.ts
CHANGED
|
@@ -43,9 +43,48 @@ export function setupCallGuard() {
|
|
|
43
43
|
};
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Currently there seems to be a bug in the JSI layer which causes a crash when
|
|
48
|
+
* we try to copy some of the console methods, i.e. `clear` or `dirxml`.
|
|
49
|
+
*
|
|
50
|
+
* The crash happens only in React Native 0.75. It's not reproducible in neither
|
|
51
|
+
* 0.76 nor 0.74. It also happens only in the configuration of a debug app and
|
|
52
|
+
* production bundle.
|
|
53
|
+
*
|
|
54
|
+
* I haven't yet discovered what exactly causes the crash. It's tied to the
|
|
55
|
+
* console methods sometimes being `HostFunction`s. Therefore, as a workaround
|
|
56
|
+
* we don't copy the methods as they are in the original console object, we copy
|
|
57
|
+
* JavaScript wrappers instead.
|
|
58
|
+
*/
|
|
59
|
+
function createMemorySafeCapturableConsole(): typeof console {
|
|
60
|
+
const consoleCopy = Object.fromEntries(
|
|
61
|
+
Object.entries(console).map(([methodName, method]) => {
|
|
62
|
+
const methodWrapper = function methodWrapper(...args: unknown[]) {
|
|
63
|
+
return method(...args);
|
|
64
|
+
};
|
|
65
|
+
if (method.name) {
|
|
66
|
+
/**
|
|
67
|
+
* Set the original method name as the wrapper name if available.
|
|
68
|
+
*
|
|
69
|
+
* It might be unnecessary but if we want to fully mimic the console
|
|
70
|
+
* object we should take into the account the fact some code might rely
|
|
71
|
+
* on the method name.
|
|
72
|
+
*/
|
|
73
|
+
Object.defineProperty(methodWrapper, 'name', {
|
|
74
|
+
value: method.name,
|
|
75
|
+
writable: false,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
return [methodName, methodWrapper];
|
|
79
|
+
})
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
return consoleCopy as unknown as typeof console;
|
|
83
|
+
}
|
|
84
|
+
|
|
46
85
|
// We really have to create a copy of console here. Function runOnJS we use on elements inside
|
|
47
86
|
// this object makes it not configurable
|
|
48
|
-
const capturableConsole =
|
|
87
|
+
const capturableConsole = createMemorySafeCapturableConsole();
|
|
49
88
|
|
|
50
89
|
export function setupConsole() {
|
|
51
90
|
'worklet';
|