Skip to content

Commit

Permalink
[0.72] Fix V8 Node API Task Runner implementation (#10966) (#11572)
Browse files Browse the repository at this point in the history
* [0.72] Fix V8 Node API Task Runner implementation (#10966)

* Update change file
  • Loading branch information
vmoroz committed May 8, 2023
1 parent 0783647 commit 412f3c2
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 49 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "Fix V8 Node API task runner implementation",
"packageName": "react-native-windows",
"email": "vmorozov@microsoft.com",
"dependentChangeType": "patch"
}
2 changes: 1 addition & 1 deletion vnext/PropertySheets/JSEngine.props
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
<EnableDevServerHBCBundles Condition="'$(EnableDevServerHBCBundles)' == ''">false</EnableDevServerHBCBundles>

<UseV8 Condition="'$(UseV8)' == ''">false</UseV8>
<V8Version Condition="'$(V8Version)' == ''">0.71.2</V8Version>
<V8Version Condition="'$(V8Version)' == ''">0.71.3</V8Version>
<V8PackageName>ReactNative.V8Jsi.Windows</V8PackageName>
<V8PackageName Condition="'$(V8AppPlatform)' != 'win32'">$(V8PackageName).UWP</V8PackageName>
</PropertyGroup>
Expand Down
98 changes: 58 additions & 40 deletions vnext/Shared/JSI/NapiJsiV8RuntimeHolder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,57 +11,75 @@ using std::unique_ptr;

namespace Microsoft::JSI {

struct NapiTask {
NapiTask(
napi_env env,
napi_ext_task_callback taskCallback,
void *taskData,
napi_finalize finalizeCallback,
void *finalizeHint) noexcept
: m_env{env},
m_taskCallback{taskCallback},
m_taskData{taskData},
m_finalizeCallback{finalizeCallback},
m_finalizeHint{finalizeHint} {}

NapiTask(const NapiTask &) = delete;
NapiTask &operator=(const NapiTask &) = delete;
class NapiTask {
public:
NapiTask(void *task, v8_task_run_cb onTaskRun, v8_task_release_cb onTaskRelease)
: task_(task), onTaskRun_(onTaskRun), onTaskRelease_(onTaskRelease) {}

NapiTask(NapiTask &&other)
: task_(std::exchange(other.task_, nullptr)),
onTaskRun_(std::exchange(other.onTaskRun_, nullptr)),
onTaskRelease_(std::exchange(other.onTaskRelease_, nullptr)) {}

NapiTask &operator=(NapiTask &&other) {
if (this != &other) {
NapiTask taskToDelete(std::move(*this));
task_ = std::exchange(other.task_, nullptr);
onTaskRun_ = std::exchange(other.onTaskRun_, nullptr);
onTaskRelease_ = std::exchange(other.onTaskRelease_, nullptr);
}
return *this;
}

NapiTask(const NapiTask &other) = delete;
NapiTask &operator=(const NapiTask &other) = delete;

~NapiTask() {
if (m_finalizeCallback) {
m_finalizeCallback(m_env, m_taskData, m_finalizeHint);
if (task_ != nullptr) {
onTaskRelease_(task_);
}
}

void operator()() noexcept {
m_taskCallback(m_env, m_taskData);
void Run() const {
if (task_ != nullptr) {
onTaskRun_(task_);
}
}

private:
napi_env m_env;
napi_ext_task_callback m_taskCallback;
void *m_taskData;
napi_finalize m_finalizeCallback;
void *m_finalizeHint;
void *task_;
v8_task_run_cb onTaskRun_;
v8_task_release_cb onTaskRelease_;
};

// See napi_ext_schedule_task_callback definition.
/*static*/ void NapiJsiV8RuntimeHolder::ScheduleTaskCallback(
napi_env env,
napi_ext_task_callback taskCallback,
void *taskData,
uint32_t /*delayInMsec*/,
napi_finalize finalizeCallback,
void *finalizeHint) {
NapiJsiV8RuntimeHolder *holder;
auto result = napi_get_instance_data(env, (void **)&holder);
if (result != napi_status::napi_ok) {
std::terminate();
class NapiTaskRunner {
public:
NapiTaskRunner(std::shared_ptr<facebook::react::MessageQueueThread> jsQueue) : m_jsQueue(std::move(jsQueue)) {}

static v8_task_runner_t Create(std::shared_ptr<facebook::react::MessageQueueThread> jsQueue) {
NapiTaskRunner *taskRunner = new NapiTaskRunner(std::move(jsQueue));
return v8_create_task_runner(reinterpret_cast<void *>(taskRunner), &PostTask, &Release);
}

auto task = std::make_shared<NapiTask>(env, taskCallback, taskData, finalizeCallback, finalizeHint);
holder->m_jsQueue->runOnQueue([task = std::move(task)]() { task->operator()(); });
}
private:
static void __cdecl PostTask(
void *taskRunner,
void *task,
v8_task_run_cb onTaskRun,
v8_task_release_cb onTaskRelease) {
auto napiTask = std::make_shared<NapiTask>(task, onTaskRun, onTaskRelease);
reinterpret_cast<NapiTaskRunner *>(taskRunner)->m_jsQueue->runOnQueue([napiTask = std::move(napiTask)] {
napiTask->Run();
});
}

static void __cdecl Release(void *taskRunner) {
delete reinterpret_cast<NapiTaskRunner *>(taskRunner);
}

private:
std::shared_ptr<facebook::react::MessageQueueThread> m_jsQueue;
};

NapiJsiV8RuntimeHolder::NapiJsiV8RuntimeHolder(
shared_ptr<DevSettings> devSettings,
Expand All @@ -85,7 +103,7 @@ void NapiJsiV8RuntimeHolder::InitRuntime() noexcept {
settings.flags.enable_inspector = m_useDirectDebugger;
settings.flags.wait_for_debugger = m_debuggerBreakOnNextLine;
// TODO: args.debuggerRuntimeName = debuggerRuntimeName_;
settings.foreground_scheduler = &NapiJsiV8RuntimeHolder::ScheduleTaskCallback;
settings.foreground_task_runner = NapiTaskRunner::Create(m_jsQueue);

napi_ext_script_cache scriptCache = InitScriptCache(std::move(m_preparedScriptStore));
settings.script_cache = &scriptCache;
Expand Down
8 changes: 0 additions & 8 deletions vnext/Shared/JSI/NapiJsiV8RuntimeHolder.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,6 @@ class NapiJsiV8RuntimeHolder : public Microsoft::JSI::RuntimeHolderLazyInit {
std::unique_ptr<facebook::jsi::PreparedScriptStore> &&preparedScriptStore) noexcept;

private:
static void __cdecl ScheduleTaskCallback(
napi_env env,
napi_ext_task_callback taskCb,
void *taskData,
uint32_t delayMs,
napi_finalize finalizeCb,
void *finalizeHint);

void InitRuntime() noexcept;
napi_ext_script_cache InitScriptCache(
std::unique_ptr<facebook::jsi::PreparedScriptStore> &&preparedScriptStore) noexcept;
Expand Down

0 comments on commit 412f3c2

Please sign in to comment.