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

Route JS errors from UI runtime throught RN's LogBox module #3846

Merged
merged 24 commits into from
Dec 15, 2022
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 14 additions & 8 deletions Common/cpp/NativeModules/NativeReanimatedModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,12 @@ NativeReanimatedModule::NativeReanimatedModule(
platformDepMethodsHolder.configurePropsFunction)
#endif
{
auto requestAnimationFrame = [=](FrameCallback callback) {
frameCallbacks.push_back(callback);
auto requestAnimationFrame = [=](jsi::Runtime &rt, const jsi::Value &fn) {
auto jsFunction = std::make_shared<jsi::Value>(rt, fn);
frameCallbacks.push_back([=](double timestamp) {
jsi::Runtime &rt = *runtimeHelper->uiRuntime();
runtimeHelper->callGuard->call(rt, *jsFunction, jsi::Value(timestamp));
});
maybeRequestRender();
};

Expand Down Expand Up @@ -174,20 +178,23 @@ NativeReanimatedModule::NativeReanimatedModule(

void NativeReanimatedModule::installCoreFunctions(
jsi::Runtime &rt,
const jsi::Value &valueUnpacker,
const jsi::Value &layoutAnimationStartFunction) {
const jsi::Value &callGuard,
const jsi::Value &valueUnpacker) {
if (!runtimeHelper) {
// initialize runtimeHelper here if not already present. We expect only one
// instace of the helper to exists.
runtimeHelper =
std::make_shared<JSRuntimeHelper>(&rt, this->runtime.get(), scheduler);
}
runtimeHelper->callGuard =
std::make_unique<CoreFunction>(runtimeHelper.get(), callGuard);
runtimeHelper->valueUnpacker =
std::make_shared<CoreFunction>(runtimeHelper.get(), valueUnpacker);
std::make_unique<CoreFunction>(runtimeHelper.get(), valueUnpacker);
}

NativeReanimatedModule::~NativeReanimatedModule() {
if (runtimeHelper) {
runtimeHelper->callGuard = nullptr;
runtimeHelper->valueUnpacker = nullptr;
// event handler registry and frame callbacks store some JSI values from UI
// runtime, so they have to go away before we tear down the runtime
Expand All @@ -206,11 +213,10 @@ void NativeReanimatedModule::scheduleOnUI(
assert(
shareableWorklet->valueType() == Shareable::WorkletType &&
"only worklets can be scheduled to run on UI");
auto uiRuntime = runtimeHelper->uiRuntime();
frameCallbacks.push_back([=](double timestamp) {
jsi::Runtime &rt = *uiRuntime;
jsi::Runtime &rt = *runtimeHelper->uiRuntime();
auto workletValue = shareableWorklet->getJSValue(rt);
workletValue.asObject(rt).asFunction(rt).call(rt);
runtimeHelper->callGuard->call(rt, workletValue);
kmagiera marked this conversation as resolved.
Show resolved Hide resolved
});
maybeRequestRender();
}
Expand Down
4 changes: 2 additions & 2 deletions Common/cpp/NativeModules/NativeReanimatedModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ class NativeReanimatedModule : public NativeReanimatedModuleSpec,

void installCoreFunctions(
jsi::Runtime &rt,
const jsi::Value &workletMaker,
const jsi::Value &layoutAnimationStartFunction) override;
const jsi::Value &callGuard,
const jsi::Value &valueUnpacker) override;

jsi::Value makeShareableClone(jsi::Runtime &rt, const jsi::Value &value)
override;
Expand Down
4 changes: 2 additions & 2 deletions Common/cpp/NativeModules/NativeReanimatedModuleSpec.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ class JSI_EXPORT NativeReanimatedModuleSpec : public TurboModule {
public:
virtual void installCoreFunctions(
jsi::Runtime &rt,
const jsi::Value &valueUnpacker,
const jsi::Value &layoutAnimationStartFunction) = 0;
const jsi::Value &callGuard,
const jsi::Value &valueUnpacker) = 0;

// SharedValue
virtual jsi::Value makeShareableClone(
Expand Down
30 changes: 30 additions & 0 deletions Common/cpp/ReanimatedRuntime/ReanimatedHermesRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <jsi/jsi.h>

#include <memory>
#include <string>
#include <utility>

#if __has_include(<reacthermes/HermesExecutorFactory.h>)
Expand Down Expand Up @@ -79,6 +80,35 @@ ReanimatedHermesRuntime::ReanimatedHermesRuntime(
// that the thread was indeed `quit` before
jsQueue->quitSynchronous();
#endif

#ifdef DEBUG
facebook::hermes::HermesRuntime *wrappedRuntime = runtime_.get();
jsi::Value evalWithSourceMap = jsi::Function::createFromHostFunction(
*runtime_,
jsi::PropNameID::forAscii(*runtime_, "evalWithSourceMap"),
3,
[wrappedRuntime](
jsi::Runtime &rt,
const jsi::Value &thisValue,
const jsi::Value *args,
size_t count) -> jsi::Value {
auto code = std::make_shared<const jsi::StringBuffer>(
args[0].asString(rt).utf8(rt));
std::string sourceURL;
if (count > 1 && args[1].isString()) {
sourceURL = args[1].asString(rt).utf8(rt);
}
std::shared_ptr<const jsi::Buffer> sourceMap;
if (count > 2 && args[2].isString()) {
sourceMap = std::make_shared<const jsi::StringBuffer>(
args[2].asString(rt).utf8(rt));
}
return wrappedRuntime->evaluateJavaScriptWithSourceMap(
tomekzaw marked this conversation as resolved.
Show resolved Hide resolved
code, sourceMap, sourceURL);
});
runtime_->global().setProperty(
*runtime_, "evalWithSourceMap", evalWithSourceMap);
#endif // DEBUG
}

ReanimatedHermesRuntime::~ReanimatedHermesRuntime() {
Expand Down
2 changes: 1 addition & 1 deletion Common/cpp/ReanimatedRuntime/ReanimatedHermesRuntime.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ class ReanimatedHermesRuntime
~ReanimatedHermesRuntime();

private:
std::shared_ptr<facebook::hermes::HermesRuntime> runtime_;
std::unique_ptr<facebook::hermes::HermesRuntime> runtime_;
ReanimatedReentrancyCheck reentrancyCheck_;
};

Expand Down
5 changes: 4 additions & 1 deletion Common/cpp/SharedItems/Shareables.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ CoreFunction::CoreFunction(
rnFunction_ = std::make_unique<jsi::Function>(workletObject.asFunction(rt));
functionBody_ =
workletObject.getProperty(rt, "asString").asString(rt).utf8(rt);
location_ = workletObject.getProperty(rt, "__location").asString(rt).utf8(rt);
location_ = "worklet_" +
std::to_string((unsigned long long)workletObject
kmagiera marked this conversation as resolved.
Show resolved Hide resolved
.getProperty(rt, "__workletHash")
.getNumber());
}

std::unique_ptr<jsi::Function> &CoreFunction::getFunction(jsi::Runtime &rt) {
Expand Down
3 changes: 2 additions & 1 deletion Common/cpp/SharedItems/Shareables.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ class JSRuntimeHelper {
: rnRuntime_(rnRuntime), uiRuntime_(uiRuntime), scheduler_(scheduler) {}

volatile bool uiRuntimeDestroyed;
std::shared_ptr<CoreFunction> valueUnpacker;
std::unique_ptr<CoreFunction> callGuard;
std::unique_ptr<CoreFunction> valueUnpacker;

inline jsi::Runtime *uiRuntime() const {
return uiRuntime_;
Expand Down
31 changes: 25 additions & 6 deletions Common/cpp/Tools/RuntimeDecorator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,30 @@ void RuntimeDecorator::decorateRuntime(

rt.global().setProperty(rt, "global", rt.global());
kmagiera marked this conversation as resolved.
Show resolved Hide resolved

rt.global().setProperty(rt, "jsThis", jsi::Value::undefined());
#ifdef DEBUG
auto evalWithSourceUrl = [](jsi::Runtime &rt,
const jsi::Value &thisValue,
const jsi::Value *args,
size_t count) -> jsi::Value {
auto code = std::make_shared<const jsi::StringBuffer>(
args[0].asString(rt).utf8(rt));
std::string url;
if (count > 1 && args[1].isString()) {
url = args[1].asString(rt).utf8(rt);
}

return rt.evaluateJavaScript(code, url);
};

rt.global().setProperty(
rt,
"evalWithSourceUrl",
jsi::Function::createFromHostFunction(
rt,
jsi::PropNameID::forAscii(rt, "evalWithSourceUrl"),
1,
evalWithSourceUrl));
#endif // DEBUG

auto callback = [](jsi::Runtime &rt,
const jsi::Value &thisValue,
Expand Down Expand Up @@ -208,11 +231,7 @@ void RuntimeDecorator::decorateUIRuntime(
const jsi::Value &thisValue,
const jsi::Value *args,
const size_t count) -> jsi::Value {
auto fun =
std::make_shared<jsi::Function>(args[0].asObject(rt).asFunction(rt));
requestFrame([&rt, fun](double timestampMs) {
fun->call(rt, jsi::Value(timestampMs));
});
requestFrame(rt, std::move(args[0]));
return jsi::Value::undefined();
};
jsi::Value requestAnimationFrame = jsi::Function::createFromHostFunction(
Expand Down
3 changes: 2 additions & 1 deletion Common/cpp/Tools/RuntimeDecorator.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ using namespace facebook;

namespace reanimated {

using RequestFrameFunction = std::function<void(std::function<void(double)>)>;
using RequestFrameFunction =
std::function<void(jsi::Runtime &, const jsi::Value &)>;
using ScheduleOnJSFunction =
std::function<void(jsi::Runtime &, const jsi::Value &, const jsi::Value &)>;
using MakeShareableCloneFunction =
Expand Down
Loading