Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#include "ConsoleTask.h"
#include "ConsoleTaskOrchestrator.h"

namespace facebook::react::jsinspector_modern {

ConsoleTask::ConsoleTask(std::shared_ptr<ConsoleTaskContext> taskContext)
: taskContext_(std::move(taskContext)),
orchestrator_(ConsoleTaskOrchestrator::getInstance()) {
if (taskContext_) {
orchestrator_.startTask(taskContext_->id());
}
}

ConsoleTask::~ConsoleTask() {
if (taskContext_) {
orchestrator_.finishTask(taskContext_->id());
}
}

} // namespace facebook::react::jsinspector_modern
38 changes: 38 additions & 0 deletions packages/react-native/ReactCommon/jsinspector-modern/ConsoleTask.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#pragma once

#include <memory>

namespace facebook::react::jsinspector_modern {

class ConsoleTaskContext;
class RuntimeTargetDelegate;
class ConsoleTaskOrchestrator;

class ConsoleTask {
public:
/**
* \param runtimeTargetDelegate The delegate to the corresponding runtime.
* \param taskContext The context that tracks the task.
*/
explicit ConsoleTask(std::shared_ptr<ConsoleTaskContext> taskContext);
~ConsoleTask();

ConsoleTask(const ConsoleTask &) = default;
ConsoleTask &operator=(const ConsoleTask &) = delete;

ConsoleTask(ConsoleTask &&) = default;
ConsoleTask &operator=(ConsoleTask &&) = delete;

private:
std::shared_ptr<ConsoleTaskContext> taskContext_;
ConsoleTaskOrchestrator &orchestrator_;
};

} // namespace facebook::react::jsinspector_modern
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#include "ConsoleTaskContext.h"
#include "ConsoleTaskOrchestrator.h"
#include "RuntimeTarget.h"

namespace facebook::react::jsinspector_modern {

ConsoleTaskContext::ConsoleTaskContext(
jsi::Runtime& runtime,
RuntimeTargetDelegate& runtimeTargetDelegate,
std::string name)
: runtimeTargetDelegate_(runtimeTargetDelegate),
name_(std::move(name)),
orchestrator_(ConsoleTaskOrchestrator::getInstance()) {
stackTrace_ = runtimeTargetDelegate_.captureStackTrace(runtime);
}

ConsoleTaskContext::~ConsoleTaskContext() {
orchestrator_.cancelTask(id());
}

ConsoleTaskId ConsoleTaskContext::id() const {
return ConsoleTaskId{(void*)this};
}

std::optional<folly::dynamic> ConsoleTaskContext::getSerializedStackTrace()
const {
auto maybeValue = runtimeTargetDelegate_.serializeStackTrace(*stackTrace_);
if (maybeValue) {
maybeValue.value()["description"] = name_;
}

return maybeValue;
}

std::function<std::optional<folly::dynamic>()>
ConsoleTaskContext::getSerializedStackTraceProvider() const {
return [selfWeak = weak_from_this()]() -> std::optional<folly::dynamic> {
if (auto self = selfWeak.lock()) {
return self->getSerializedStackTrace();
}

return std::nullopt;
};
}

void ConsoleTaskContext::schedule() {
orchestrator_.scheduleTask(id(), weak_from_this());
}

} // namespace facebook::react::jsinspector_modern
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#pragma once

#include "StackTrace.h"

#include <folly/dynamic.h>
#include <jsi/jsi.h>

#include <cassert>
#include <functional>
#include <memory>
#include <string>

namespace facebook::react::jsinspector_modern {

class ConsoleTaskOrchestrator;
class RuntimeTargetDelegate;

class ConsoleTaskId {
public:
ConsoleTaskId() = default;
~ConsoleTaskId() = default;

ConsoleTaskId(const ConsoleTaskId &) = default;
ConsoleTaskId &operator=(const ConsoleTaskId &) = default;

ConsoleTaskId(ConsoleTaskId &&) = default;
ConsoleTaskId &operator=(ConsoleTaskId &&) = default;

bool operator==(const ConsoleTaskId &) const = default;
inline operator bool() const
{
return (bool)id_;
}

explicit inline operator void *() const
{
return id_;
}

private:
explicit inline ConsoleTaskId(void *id) : id_(id)
{
assert(id_ != nullptr);
}

void *id_{nullptr};

friend class ConsoleTaskContext;
};

class ConsoleTaskContext : public std::enable_shared_from_this<ConsoleTaskContext> {
public:
ConsoleTaskContext(jsi::Runtime &runtime, RuntimeTargetDelegate &runtimeTargetDelegate, std::string name);
~ConsoleTaskContext();

// Can't be moved or copied: the address of `ConsoleTaskContext` is used to
// identify this task and all corresponding invocations.
ConsoleTaskContext(const ConsoleTaskContext &) = delete;
ConsoleTaskContext &operator=(const ConsoleTaskContext &) = delete;

ConsoleTaskContext(ConsoleTaskContext &&) = delete;
ConsoleTaskContext &operator=(ConsoleTaskContext &&) = delete;

/**
* Unique identifier that is calculated based on the address of
* ConsoleTaskContext.
*/
ConsoleTaskId id() const;

/**
* Returns the serialized stack trace that was captured during the allocation
* of ConsoleTaskContext.
*/
std::optional<folly::dynamic> getSerializedStackTrace() const;

/**
* Returns a function that returns the serialized stack trace, if available.
*/
std::function<std::optional<folly::dynamic>()> getSerializedStackTraceProvider() const;

void schedule();

private:
RuntimeTargetDelegate &runtimeTargetDelegate_;
std::string name_;
ConsoleTaskOrchestrator &orchestrator_;
std::unique_ptr<StackTrace> stackTrace_;
};

} // namespace facebook::react::jsinspector_modern

namespace std {
template <>
struct hash<facebook::react::jsinspector_modern::ConsoleTaskId> {
size_t operator()(const facebook::react::jsinspector_modern::ConsoleTaskId &id) const
{
return std::hash<void *>{}(static_cast<void *>(id));
}
};
} // namespace std
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#include "ConsoleTaskOrchestrator.h"

namespace facebook::react::jsinspector_modern {

/* static */ ConsoleTaskOrchestrator& ConsoleTaskOrchestrator::getInstance() {
static ConsoleTaskOrchestrator instance;
return instance;
}

void ConsoleTaskOrchestrator::scheduleTask(
ConsoleTaskId taskId,
std::weak_ptr<ConsoleTaskContext> taskContext) {
std::lock_guard<std::mutex> lock(mutex_);
tasks_.emplace(taskId, taskContext);
}

void ConsoleTaskOrchestrator::cancelTask(ConsoleTaskId id) {
std::lock_guard<std::mutex> lock(mutex_);
tasks_.erase(id);
}

void ConsoleTaskOrchestrator::startTask(ConsoleTaskId id) {
std::lock_guard<std::mutex> lock(mutex_);
stack_.push(id);
}

void ConsoleTaskOrchestrator::finishTask(ConsoleTaskId id) {
std::lock_guard<std::mutex> lock(mutex_);
assert(stack_.top() == id);

stack_.pop();
}

std::shared_ptr<ConsoleTaskContext> ConsoleTaskOrchestrator::top() const {
std::lock_guard<std::mutex> lock(mutex_);
if (stack_.empty()) {
return nullptr;
}

auto it = tasks_.find(stack_.top());
if (it == tasks_.end()) {
return nullptr;
}

return it->second.lock();
}

} // namespace facebook::react::jsinspector_modern
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#pragma once

#include <memory>
#include <mutex>
#include <stack>

#include "ConsoleTaskContext.h"

namespace facebook::react::jsinspector_modern {

class ConsoleTaskOrchestrator {
public:
static ConsoleTaskOrchestrator &getInstance();

~ConsoleTaskOrchestrator() = default;

ConsoleTaskOrchestrator(const ConsoleTaskOrchestrator &) = delete;
ConsoleTaskOrchestrator &operator=(const ConsoleTaskOrchestrator &) = delete;

ConsoleTaskOrchestrator(ConsoleTaskOrchestrator &&) = delete;
ConsoleTaskOrchestrator &operator=(ConsoleTaskOrchestrator &&) = delete;

void scheduleTask(ConsoleTaskId taskId, std::weak_ptr<ConsoleTaskContext> taskContext);
void cancelTask(ConsoleTaskId taskId);

void startTask(ConsoleTaskId taskId);
void finishTask(ConsoleTaskId taskId);
std::shared_ptr<ConsoleTaskContext> top() const;

private:
ConsoleTaskOrchestrator() = default;

std::stack<ConsoleTaskId> stack_;
std::unordered_map<ConsoleTaskId, std::weak_ptr<ConsoleTaskContext>> tasks_;
/**
* Protects the stack_ and tasks_ members.
*/
mutable std::mutex mutex_;
};

} // namespace facebook::react::jsinspector_modern
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ class RuntimeAgent final {
* Lifetime of this agent is bound to the lifetime of the Tracing session -
* HostTargetTraceRecording and to the lifetime of the RuntimeTarget.
*/
class RuntimeTracingAgent : tracing::TargetTracingAgent {
class RuntimeTracingAgent : public tracing::TargetTracingAgent {
public:
explicit RuntimeTracingAgent(tracing::TraceRecordingState &state, RuntimeTargetController &targetController);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,18 @@ bool RuntimeTarget::isDomainEnabled(Domain domain) const {
return threadSafeDomainStatus_[domain];
}

bool RuntimeTarget::isConsoleCreateTaskEnabled() const {
if (isDomainEnabled(Domain::Runtime)) {
return true;
}

if (auto tracingAgent = tracingAgent_.lock()) {
return tracingAgent->isRunningInBackgroundMode();
}

return false;
}

RuntimeTargetController::RuntimeTargetController(RuntimeTarget& target)
: target_(target) {}

Expand Down
Loading
Loading