Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

iOS jsi value ~shared_ptr Crash when RCTHost dealloc #48214

Open
Prislashate opened this issue Dec 11, 2024 · 5 comments
Open

iOS jsi value ~shared_ptr Crash when RCTHost dealloc #48214

Prislashate opened this issue Dec 11, 2024 · 5 comments
Labels
API: Share Needs: Author Feedback Needs: Repro This issue could be improved with a clear list of steps to reproduce the issue. Newer Patch Available Platform: iOS iOS applications. Type: New Architecture Issues and PRs related to new architecture (Fabric/Turbo Modules)

Comments

@Prislashate
Copy link

Description

When a shared_ptr is created using a JSI Value, a crash occurs during the destruction of the shared_ptr when the RCTHost is deallocated.

Steps to reproduce

no

React Native Version

0.74.3

Affected Platforms

Runtime - iOS

Areas

JSI - Javascript Interface

Output of npx react-native info

System:
  OS: macOS 15.1.1
  CPU: (12) arm64 Apple M3 Pro
  Memory: 133.20 MB / 18.00 GB
  Shell:
    version: "5.9"
    path: /bin/zsh
Binaries:
  Node:
    version: 23.3.0
    path: /opt/homebrew/bin/node
  Yarn:
    version: 1.22.22
    path: /opt/homebrew/bin/yarn
  npm:
    version: 10.9.0
    path: /opt/homebrew/bin/npm
  Watchman:
    version: 2024.11.18.00
    path: /opt/homebrew/bin/watchman
Managers:
  CocoaPods:
    version: 1.12.1
    path: /Users/didi/.rbenv/shims/pod
SDKs:
  iOS SDK:
    Platforms:
      - DriverKit 24.0
      - iOS 18.0
      - macOS 15.0
      - tvOS 18.0
      - visionOS 2.0
      - watchOS 11.0
  Android SDK: Not Found
IDEs:
  Android Studio: Not Found
  Xcode:
    version: 16.0/16A242d
    path: /usr/bin/xcodebuild
Languages:
  Java: Not Found
  Ruby:
    version: 2.6.10
    path: /Users/xxx/.rbenv/shims/ruby
npmPackages:
  "@react-native-community/cli": Not Found
  react:
    installed: 18.2.0
    wanted: 18.2.0
  react-native:
    installed: 0.74.3
    wanted: 0.74.3
  react-native-macos: Not Found
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: true
  newArchEnabled: false
iOS:
  hermesEnabled: true
  newArchEnabled: true

info React Native v0.76.5 is now available (your project is running on v0.74.3).
info Changelog: https://github.com/facebook/react-native/releases/tag/v0.76.5
info Diff: https://react-native-community.github.io/upgrade-helper/?from=0.74.3
info For more info, check out "https://reactnative.dev/docs/upgrading?os=macos".

Stacktrace or Logs

Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x0000000000000010
Exception Codes: 0x0000000000000001, 0x0000000000000010
VM Region Info: 0x10 is not in any region.  Bytes before following region: 68719476720
      REGION TYPE                 START - END      [ VSIZE] PRT/MAX SHRMOD  REGION DETAIL
      UNUSED SPACE AT START
--->  
      commpage (reserved)     1000000000-7000000000 [384.0G] ---/--- SM=NUL  ...(unallocated)
Termination Reason: SIGNAL 11 Segmentation fault: 11
Terminating Process: exc handler [61876]

Triggered by Thread:  23


Crash Stack:
Thread 23 Crashed:
0   App                     	0x000000010516bc44 std::__1::__shared_weak_count::__release_shared[abi:ne180100]() + 56
1   App                     	0x000000010727a43c std::__1::shared_ptr<reanimated::Shareable>::~shared_ptr[abi:ne180100]() + 28
2   App                     	0x00000001072972d0 std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::shared_ptr<reanimated::Shareable>>::~pair() + 24
3   App                     	0x0000000107297588 std::__1::vector<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::shared_ptr<reanimated::Shareable>>, std::__1::allocator<std::__1::pai... + 40
4   App                     	0x0000000107297538 std::__1::vector<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::shared_ptr<reanimated::Shareable>>, std::__1::allocator<std::__1::pai... + 32
5   App                     	0x0000000107297504 std::__1::vector<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::shared_ptr<reanimated::Shareable>>, std::__1::allocator<std::__1::pai... + 32

6   App                     	0x0000000107295f28 reanimated::ShareableObject::~ShareableObject() + 48
7   App                     	0x000000010516bc50 std::__1::__shared_weak_count::__release_shared[abi:ne180100]() + 68
8   App                     	0x000000010727a43c std::__1::shared_ptr<reanimated::Shareable>::~shared_ptr[abi:ne180100]() + 28
9   App                     	0x0000000107296ff0 std::__1::vector<std::__1::shared_ptr<reanimated::Shareable>, std::__1::allocator<std::__1::shared_ptr<reanimated::Shareable>>>::__base_destruct_at_end[abi:ne180100](std::__1::shared_ptr<reanimated... + 40
10  App                     	0x0000000107296fa0 std::__1::vector<std::__1::shared_ptr<reanimated::Shareable>, std::__1::allocator<std::__1::shared_ptr<reanimated::Shareable>>>::__destroy_vector::operator()[abi:ne180100]() + 32
11  App                     	0x0000000107296f6c std::__1::vector<std::__1::shared_ptr<reanimated::Shareable>, std::__1::allocator<std::__1::shared_ptr<reanimated::Shareable>>>::~vector[abi:ne180100]() + 32

12  App                     	0x000000010729786c reanimated::ShareableArray::~ShareableArray() + 32
13  App                     	0x000000010516bc50 std::__1::__shared_weak_count::__release_shared[abi:ne180100]() + 68
14  App                     	0x000000010727a43c std::__1::shared_ptr<reanimated::Shareable>::~shared_ptr[abi:ne180100]() + 28
15  App                     	0x0000000107296ff0 std::__1::vector<std::__1::shared_ptr<reanimated::Shareable>, std::__1::allocator<std::__1::shared_ptr<reanimated::Shareable>>>::__base_destruct_at_end[abi:ne180100](std::__1::shared_ptr<reanimated... + 40
16  App                     	0x0000000107296fa0 std::__1::vector<std::__1::shared_ptr<reanimated::Shareable>, std::__1::allocator<std::__1::shared_ptr<reanimated::Shareable>>>::__destroy_vector::operator()[abi:ne180100]() + 32
17  App                     	0x0000000107296f6c std::__1::vector<std::__1::shared_ptr<reanimated::Shareable>, std::__1::allocator<std::__1::shared_ptr<reanimated::Shareable>>>::~vector[abi:ne180100]() + 32

18  App                     	0x000000010729786c reanimated::ShareableArray::~ShareableArray() + 32
19  App                     	0x000000010516bc50 std::__1::__shared_weak_count::__release_shared[abi:ne180100]() + 68
20  App                     	0x000000010727a43c std::__1::shared_ptr<reanimated::Shareable>::~shared_ptr[abi:ne180100]() + 28
21  App                     	0x00000001072972d0 std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::shared_ptr<reanimated::Shareable>>::~pair() + 24
22  App                     	0x0000000107297588 std::__1::vector<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::shared_ptr<reanimated::Shareable>>, std::__1::allocator<std::__1::pai... + 40
23  App                     	0x0000000107297538 std::__1::vector<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::shared_ptr<reanimated::Shareable>>, std::__1::allocator<std::__1::pai... + 32
24  App                     	0x0000000107297504 std::__1::vector<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::shared_ptr<reanimated::Shareable>>, std::__1::allocator<std::__1::pai... + 32

25  App                     	0x0000000107295f28 reanimated::ShareableObject::~ShareableObject() + 48
26  App                     	0x000000010516bc50 std::__1::__shared_weak_count::__release_shared[abi:ne180100]() + 68
27  App                     	0x000000010727a43c std::__1::shared_ptr<reanimated::Shareable>::~shared_ptr[abi:ne180100]() + 28
28  App                     	0x00000001072972d0 std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::shared_ptr<reanimated::Shareable>>::~pair() + 24
29  App                     	0x0000000107297588 std::__1::vector<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::shared_ptr<reanimated::Shareable>>, std::__1::allocator<std::__1::pai... + 40
30  App                     	0x0000000107297538 std::__1::vector<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::shared_ptr<reanimated::Shareable>>, std::__1::allocator<std::__1::pai... + 32
31  App                     	0x0000000107297504 std::__1::vector<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::shared_ptr<reanimated::Shareable>>, std::__1::allocator<std::__1::pai... + 32

32  App                     	0x0000000107295f28 reanimated::ShareableObject::~ShareableObject() + 48
33  App                     	0x000000010516bc50 std::__1::__shared_weak_count::__release_shared[abi:ne180100]() + 68
34  App                     	0x000000010727a43c std::__1::shared_ptr<reanimated::Shareable>::~shared_ptr[abi:ne180100]() + 28
35  App                     	0x0000000107295624 reanimated::ShareableJSRef::~ShareableJSRef() + 32
36  hermes                        	0x000000010d7b655c 0x10d7a0000 + 91484
37  hermes                        	0x000000010d90a5d0 0x10d7a0000 + 1484240
38  hermes                        	0x000000010d88234c 0x10d7a0000 + 926540
39  hermes                        	0x000000010d8827dc 0x10d7a0000 + 927708
40  hermes                        	0x000000010d7b3b08 0x10d7a0000 + 80648
41  hermes                        	0x000000010d7b02cc 0x10d7a0000 + 66252
42  App                     	0x000000010516bc50 std::__1::__shared_weak_count::__release_shared[abi:ne180100]() + 68
43  App                     	0x0000000107512610 std::__1::shared_ptr<facebook::hermes::HermesRuntime>::~shared_ptr[abi:ne180100]() + 28
44  App                     	0x00000001074fe844 facebook::react::HermesJSRuntime::~HermesJSRuntime() + 48
45  App                     	0x00000001074fe570 facebook::react::HermesJSRuntime::~HermesJSRuntime() + 12
46  App                     	0x000000010516bc50 std::__1::__shared_weak_count::__release_shared[abi:ne180100]() + 68
47  App                     	0x00000001074f2818 std::__1::shared_ptr<facebook::react::JSRuntime>::~shared_ptr[abi:ne180100]() + 28
48  App                     	0x00000001074f269c facebook::react::ReactInstance::~ReactInstance() + 80
49  App                     	0x00000001074f2644 std::__1::default_delete<facebook::react::ReactInstance>::operator()[abi:ne180100](facebook::react::ReactInstance*) const + 20
50  App                     	0x00000001074efd70 __25-[RCTInstance invalidate]_block_invoke + 48
51  App                     	0x00000001073841ac facebook::react::tryAndReturnError(std::__1::function<void ()> const&) + 16
52  App                     	0x00000001074f4a28 -[RCTJSThreadManager _tryAndHandleError:] + 56
53  App                     	0x00000001074f4c00 std::__1::__function::__func<-[RCTJSThreadManager dispatchToJSThread:]::$_0, std::__1::allocator<-[RCTJSThreadManager dispatchToJSThread:]::$_0>, void ()>::operator()() + 36
54  App                     	0x00000001073841ac facebook::react::tryAndReturnError(std::__1::function<void ()> const&) + 16
55  App                     	0x00000001073901ec facebook::react::RCTMessageThread::tryFunc(std::__1::function<void ()> const&) + 24
56  App                     	0x0000000107390070 invocation function for block in facebook::react::RCTMessageThread::runAsync(std::__1::function<void ()>) + 32
57  CoreFoundation                	0x00000001b4cb1138 __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 28 (CFRunLoop.c:1805)
58  CoreFoundation                	0x00000001b4caf92c __CFRunLoopDoBlocks + 356 (CFRunLoop.c:1847)
59  CoreFoundation                	0x00000001b4cad808 __CFRunLoopRun + 812 (CFRunLoop.c:2953)
60  CoreFoundation                	0x00000001b4cad3f8 CFRunLoopRunSpecific + 608 (CFRunLoop.c:3420)
61  App                     	0x00000001074f4990 +[RCTJSThreadManager runRunLoop] + 204
62  Foundation                    	0x00000001b3cc3d40 __NSThread__start__ + 732 (NSThread.m:991)
63  libsystem_pthread.dylib       	0x000000021ed744d4 _pthread_start + 136 (pthread.c:904)
64  libsystem_pthread.dylib       	0x000000021ed73a10 thread_start + 8 (:-1)

Thread 23 crashed with ARM Thread State (64-bit):
    x0: 0x0000000281b8d300   x1: 0x00000002826b7980   x2: 0x0000000000000000   x3: 0x000000028117d980
    x4: 0x00000002829c9940   x5: 0x000000011c1f84a0   x6: 0x0000000000000365   x7: 0x0000000000ffff7f
    x8: 0x0000000000000000   x9: 0x0000000000000000  x10: 0xffffffffffffffff  x11: 0x0000000000000000
   x12: 0x00000000000007fb  x13: 0x00000000000007fd  x14: 0x0000000097c11866  x15: 0x0000000000000066
   x16: 0x0000000097a1103d  x17: 0x0000000000011800  x18: 0x0000000000000000  x19: 0x0000000281b8d300
   x20: 0x00000002829c97e8  x21: 0x000000014b5c20d0  x22: 0x000000014b5c20e0  x23: 0x000000010dabb0a0
   x24: 0x00000000141300cd  x25: 0x0000000000000000  x26: 0x000000011a31d040  x27: 0x00000002811b9dc0
   x28: 0x0000000000000000   fp: 0x000000016bd456a0   lr: 0x000000010727a43c
    sp: 0x000000016bd45690   pc: 0x000000010516bc44 cpsr: 0x20000000
   esr: 0x92000006 (Data Abort) byte read Translation fault

Reproducer

no

Screenshots and Videos

#include "Shareables.h"

using namespace facebook;

namespace reanimated {

jsi::Function getValueUnpacker(jsi::Runtime &rt) {
  auto valueUnpacker = rt.global().getProperty(rt, "__valueUnpacker");
  assert(valueUnpacker.isObject() && "valueUnpacker not found");
  return valueUnpacker.asObject(rt).asFunction(rt);
}

#ifndef NDEBUG

static const auto callGuardLambda = [](facebook::jsi::Runtime &rt,
                                       const facebook::jsi::Value &thisVal,
                                       const facebook::jsi::Value *args,
                                       size_t count) {
  return args[0].asObject(rt).asFunction(rt).call(rt, args + 1, count - 1);
};

jsi::Function getCallGuard(jsi::Runtime &rt) {
  auto callGuard = rt.global().getProperty(rt, "__callGuardDEV");
  if (callGuard.isObject()) {
    // Use JS implementation if `__callGuardDEV` has already been installed.
    // This is the desired behavior.
    return callGuard.asObject(rt).asFunction(rt);
  }

  // Otherwise, fallback to C++ JSI implementation. This is necessary so that we
  // can install `__callGuardDEV` itself and should happen only once. Note that
  // the C++ implementation doesn't intercept errors and simply throws them as
  // C++ exceptions which crashes the app. We assume that installing the guard
  // doesn't throw any errors.
  return jsi::Function::createFromHostFunction(
      rt, jsi::PropNameID::forAscii(rt, "callGuard"), 1, callGuardLambda);
}

#endif // NDEBUG

jsi::Value makeShareableClone(
    jsi::Runtime &rt,
    const jsi::Value &value,
    const jsi::Value &shouldRetainRemote,
    const jsi::Value &nativeStateSource) {
  std::shared_ptr<Shareable> shareable;
  if (value.isObject()) {
    auto object = value.asObject(rt);
    if (!object.getProperty(rt, "__workletHash").isUndefined()) {
      shareable = std::make_shared<ShareableWorklet>(rt, object);
    } else if (!object.getProperty(rt, "__init").isUndefined()) {
      shareable = std::make_shared<ShareableHandle>(rt, object);
    } else if (object.isFunction(rt)) {
      auto function = object.asFunction(rt);
      if (function.isHostFunction(rt)) {
        shareable =
            std::make_shared<ShareableHostFunction>(rt, std::move(function));
      } else {
        shareable =
            std::make_shared<ShareableRemoteFunction>(rt, std::move(function));
      }
    } else if (object.isArray(rt)) {
      if (shouldRetainRemote.isBool() && shouldRetainRemote.getBool()) {
        shareable = std::make_shared<RetainingShareable<ShareableArray>>(
            rt, object.asArray(rt));
      } else {
        shareable = std::make_shared<ShareableArray>(rt, object.asArray(rt));
      }
    } else if (object.isArrayBuffer(rt)) {
      shareable =
          std::make_shared<ShareableArrayBuffer>(rt, object.getArrayBuffer(rt));
    } else if (object.isHostObject(rt)) {
      if (object.isHostObject<ShareableJSRef>(rt)) {
        return object;
      }
      shareable =
          std::make_shared<ShareableHostObject>(rt, object.getHostObject(rt));
    } else {
      if (shouldRetainRemote.isBool() && shouldRetainRemote.getBool()) {
        shareable = std::make_shared<RetainingShareable<ShareableObject>>(
            rt,
            object
#if SUPPORTS_NATIVE_STATE
            ,
            nativeStateSource
#endif // SUPPORTS_NATIVE_STATE
        );
      } else {
        shareable = std::make_shared<ShareableObject>(
            rt,
            object
#if SUPPORTS_NATIVE_STATE
            ,
            nativeStateSource
#endif // SUPPORTS_NATIVE_STATE
        );
      }
    }
  } else if (value.isString()) {
    shareable = std::make_shared<ShareableString>(value.asString(rt).utf8(rt));
  } else if (value.isUndefined()) {
    shareable = std::make_shared<ShareableScalar>();
  } else if (value.isNull()) {
    shareable = std::make_shared<ShareableScalar>(nullptr);
  } else if (value.isBool()) {
    shareable = std::make_shared<ShareableScalar>(value.getBool());
  } else if (value.isNumber()) {
    shareable = std::make_shared<ShareableScalar>(value.getNumber());
  } else if (value.isBigInt()) {
    shareable = std::make_shared<ShareableBigInt>(rt, value.getBigInt(rt));
  } else if (value.isSymbol()) {
    // TODO: this is only a placeholder implementation, here we replace symbols
    // with strings in order to make certain objects to be captured. There isn't
    // yet any usecase for using symbols on the UI runtime so it is fine to keep
    // it like this for now.
    shareable =
        std::make_shared<ShareableString>(value.getSymbol(rt).toString(rt));
  } else {
    throw std::runtime_error(
        "[Reanimated] Attempted to convert an unsupported value type.");
  }
  return ShareableJSRef::newHostObject(rt, shareable);
}

std::shared_ptr<Shareable> extractShareableOrThrow(
    jsi::Runtime &rt,
    const jsi::Value &maybeShareableValue,
    const std::string &errorMessage) {
  if (maybeShareableValue.isObject()) {
    auto object = maybeShareableValue.asObject(rt);
    if (object.isHostObject<ShareableJSRef>(rt)) {
      return object.getHostObject<ShareableJSRef>(rt)->value();
    }
    throw std::runtime_error(
        "[Reanimated] Attempted to extract from a HostObject that wasn't converted to a Shareable.");
  } else if (maybeShareableValue.isUndefined()) {
    return Shareable::undefined();
  }
  throw std::runtime_error(errorMessage);
}

Shareable::~Shareable() {}

std::shared_ptr<Shareable> Shareable::undefined() {
  static auto undefined = std::make_shared<ShareableScalar>();
  return undefined;
}

template <typename BaseClass>
jsi::Value RetainingShareable<BaseClass>::toJSValue(jsi::Runtime &rt) {
  if (&rt == primaryRuntime_) {
    // TODO: it is suboptimal to generate new object every time getJS is
    // called on host runtime – the objects we are generating already exists
    // and we should possibly just grab a hold of such object and use it here
    // instead of creating a new JS representation. As far as I understand the
    // only case where it can be realistically called this way is when a
    // shared value is created and then accessed on the same runtime
    return BaseClass::toJSValue(rt);
  }
  if (secondaryValue_ == nullptr) {
    auto value = BaseClass::toJSValue(rt);
    secondaryValue_ = std::make_unique<jsi::Value>(rt, value);
    secondaryRuntime_ = &rt;
    return value;
  }
  if (&rt == secondaryRuntime_) {
    return jsi::Value(rt, *secondaryValue_);
  }
  return BaseClass::toJSValue(rt);
}

ShareableJSRef::~ShareableJSRef() {}

ShareableArray::ShareableArray(jsi::Runtime &rt, const jsi::Array &array)
    : Shareable(ArrayType) {
  auto size = array.size(rt);
  data_.reserve(size);
  for (size_t i = 0; i < size; i++) {
    data_.push_back(extractShareableOrThrow(rt, array.getValueAtIndex(rt, i)));
  }
}

jsi::Value ShareableArray::toJSValue(jsi::Runtime &rt) {
  auto size = data_.size();
  auto ary = jsi::Array(rt, size);
  for (size_t i = 0; i < size; i++) {
    ary.setValueAtIndex(rt, i, data_[i]->toJSValue(rt));
  }
  return ary;
}

jsi::Value ShareableArrayBuffer::toJSValue(jsi::Runtime &rt) {
  auto size = static_cast<int>(data_.size());
  auto arrayBuffer = rt.global()
                         .getPropertyAsFunction(rt, "ArrayBuffer")
                         .callAsConstructor(rt, size)
                         .getObject(rt)
                         .getArrayBuffer(rt);
  memcpy(arrayBuffer.data(rt), data_.data(), size);
  return arrayBuffer;
}

ShareableObject::ShareableObject(jsi::Runtime &rt, const jsi::Object &object)
    : Shareable(ObjectType) {
  auto propertyNames = object.getPropertyNames(rt);
  auto size = propertyNames.size(rt);
  data_.reserve(size);
  for (size_t i = 0; i < size; i++) {
    auto key = propertyNames.getValueAtIndex(rt, i).asString(rt);
    auto value = extractShareableOrThrow(rt, object.getProperty(rt, key));
    data_.emplace_back(key.utf8(rt), value);
  }
#if SUPPORTS_NATIVE_STATE
  if (object.hasNativeState(rt)) {
    nativeState_ = object.getNativeState(rt);
  }
#endif // SUPPORTS_NATIVE_STATE
}

#if SUPPORTS_NATIVE_STATE
ShareableObject::ShareableObject(
    jsi::Runtime &rt,
    const jsi::Object &object,
    const jsi::Value &nativeStateSource)
    : ShareableObject(rt, object) {
  if (nativeStateSource.isObject() &&
      nativeStateSource.asObject(rt).hasNativeState(rt)) {
    nativeState_ = nativeStateSource.asObject(rt).getNativeState(rt);
  }
}
#endif // SUPPORTS_NATIVE_STATE

jsi::Value ShareableObject::toJSValue(jsi::Runtime &rt) {
  auto obj = jsi::Object(rt);
  for (size_t i = 0, size = data_.size(); i < size; i++) {
    obj.setProperty(rt, jsi::String::createFromUtf8(rt, data_[i].first), data_[i].second->toJSValue(rt));
  }
#if SUPPORTS_NATIVE_STATE
  if (nativeState_ != nullptr) {
    obj.setNativeState(rt, nativeState_);
  }
#endif // SUPPORTS_NATIVE_STATE
  return obj;
}

jsi::Value ShareableHostObject::toJSValue(jsi::Runtime &rt) {
  return jsi::Object::createFromHostObject(rt, hostObject_);
}

jsi::Value ShareableHostFunction::toJSValue(jsi::Runtime &rt) {
  return jsi::Function::createFromHostFunction(
      rt, jsi::PropNameID::forUtf8(rt, name_), paramCount_, hostFunction_);
}

jsi::Value ShareableWorklet::toJSValue(jsi::Runtime &rt) {
  assert(
      std::any_of(
          data_.cbegin(),
          data_.cend(),
          [](const auto &item) { return item.first == "__workletHash"; }) &&
      "ShareableWorklet doesn't have `__workletHash` property");
  jsi::Value obj = ShareableObject::toJSValue(rt);
  return getValueUnpacker(rt).call(
      rt, obj, jsi::String::createFromAscii(rt, "Worklet"));
}

jsi::Value ShareableRemoteFunction::toJSValue(jsi::Runtime &rt) {
  if (&rt == runtime_) {
    return jsi::Value(rt, *function_);
  } else {
#ifndef NDEBUG
    return getValueUnpacker(rt).call(
        rt,
        ShareableJSRef::newHostObject(rt, shared_from_this()),
        jsi::String::createFromAscii(rt, "RemoteFunction"),
        jsi::String::createFromUtf8(rt, name_));
#else
    return ShareableJSRef::newHostObject(rt, shared_from_this());
#endif
  }
}

jsi::Value ShareableHandle::toJSValue(jsi::Runtime &rt) {
  if (remoteValue_ == nullptr) {
    auto initObj = initializer_->toJSValue(rt);
    auto value = std::make_unique<jsi::Value>(getValueUnpacker(rt).call(
        rt, initObj, jsi::String::createFromAscii(rt, "Handle")));

    // We are locking the initialization here since the thread that is
    // initalizing can be pre-empted on runtime lock. E.g.
    // UI thread can be pre-empted on initialization of a shared value and then
    // JS thread can try to access the shared value, locking the whole runtime.
    // If we put the lock on `getValueUnpacker` part (basically any part that
    // requires runtime) we would get a deadlock since UI thread would never
    // release it.
    std::unique_lock<std::mutex> lock(initializationMutex_);
    if (remoteValue_ == nullptr) {
      remoteValue_ = std::move(value);
      remoteRuntime_ = &rt;
    }
  }
  return jsi::Value(rt, *remoteValue_);
}

jsi::Value ShareableString::toJSValue(jsi::Runtime &rt) {
  return jsi::String::createFromUtf8(rt, data_);
}

jsi::Value ShareableBigInt::toJSValue(jsi::Runtime &rt) {
  return rt.global()
      .getPropertyAsFunction(rt, "BigInt")
      .call(rt, jsi::String::createFromUtf8(rt, string_));
}

jsi::Value ShareableScalar::toJSValue(jsi::Runtime &) {
  switch (valueType_) {
    case Shareable::UndefinedType:
      return jsi::Value();
    case Shareable::NullType:
      return jsi::Value(nullptr);
    case Shareable::BooleanType:
      return jsi::Value(data_.boolean);
    case Shareable::NumberType:
      return jsi::Value(data_.number);
    default:
      throw std::runtime_error(
          "[Reanimated] Attempted to convert object that's not of a scalar type.");
  }
}

} /* namespace reanimated */
@Prislashate Prislashate added Needs: Triage 🔍 Type: New Architecture Issues and PRs related to new architecture (Fabric/Turbo Modules) labels Dec 11, 2024
@react-native-bot react-native-bot added Needs: Author Feedback Needs: Repro This issue could be improved with a clear list of steps to reproduce the issue. Newer Patch Available labels Dec 11, 2024
@react-native-bot
Copy link
Collaborator

Tip

Newer version available: You are on a supported minor version, but it looks like there's a newer patch available - 0.74.6. Please upgrade to the highest patch for your minor or latest and verify if the issue persists (alternatively, create a new project and repro the issue in it). If it does not repro, please let us know so we can close out this issue. This helps us ensure we are looking at issues that still exist in the most recent releases.

@react-native-bot
Copy link
Collaborator

Warning

Missing reproducer: We could not detect a reproducible example in your issue report. Please provide either:

@react-native-bot
Copy link
Collaborator

Tip

Newer version available: You are on a supported minor version, but it looks like there's a newer patch available - undefined. Please upgrade to the highest patch for your minor or latest and verify if the issue persists (alternatively, create a new project and repro the issue in it). If it does not repro, please let us know so we can close out this issue. This helps us ensure we are looking at issues that still exist in the most recent releases.

@cortinico
Copy link
Contributor

Reproducer

no

Can you create a reproducer for this one?

@cipolleschi
Copy link
Contributor

Does it reproduce on 0.76?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
API: Share Needs: Author Feedback Needs: Repro This issue could be improved with a clear list of steps to reproduce the issue. Newer Patch Available Platform: iOS iOS applications. Type: New Architecture Issues and PRs related to new architecture (Fabric/Turbo Modules)
Projects
None yet
Development

No branches or pull requests

4 participants