From 3e528b10145a13896b6610bfa690aefb99e7dbbd Mon Sep 17 00:00:00 2001 From: Theo Yaung Date: Tue, 14 Mar 2017 11:40:20 -0700 Subject: [PATCH] Remove Inspector Logic (cannot work on iOS / System JSC) Reviewed By: javache Differential Revision: D4620530 fbshipit-source-id: 52abc6178b1ad1b52ba1b1825702c9c254a04520 --- ReactAndroid/src/main/jni/xreact/jni/BUCK | 1 - .../src/main/jni/xreact/jni/JInspector.cpp | 4 + .../src/main/jni/xreact/jni/JInspector.h | 4 + ReactCommon/cxxreact/BUCK | 3 +- ReactCommon/inspector/Agent.cpp | 50 ----- ReactCommon/inspector/Agent.h | 33 --- ReactCommon/inspector/Android.mk | 28 --- ReactCommon/inspector/BUCK | 60 ------ ReactCommon/inspector/ConsoleAgent.cpp | 152 -------------- ReactCommon/inspector/ConsoleAgent.h | 43 ---- ReactCommon/inspector/Dispatcher.cpp | 3 - ReactCommon/inspector/Dispatcher.h | 41 ---- ReactCommon/inspector/Error.cpp | 19 -- ReactCommon/inspector/Error.h | 34 ---- ReactCommon/inspector/Inspector.cpp | 162 --------------- ReactCommon/inspector/Inspector.h | 94 --------- ReactCommon/inspector/InspectorAgent.cpp | 22 -- ReactCommon/inspector/InspectorAgent.h | 22 -- ReactCommon/inspector/InspectorController.cpp | 192 ------------------ ReactCommon/inspector/InspectorController.h | 42 ---- ReactCommon/inspector/JSDispatcher.cpp | 135 ------------ ReactCommon/inspector/JSDispatcher.h | 46 ----- ReactCommon/inspector/LegacyAgents.cpp | 35 ---- ReactCommon/inspector/LegacyAgents.h | 32 --- ReactCommon/inspector/LegacyDebuggerAgent.cpp | 44 ---- ReactCommon/inspector/LegacyDebuggerAgent.h | 40 ---- ReactCommon/inspector/LegacyDispatcher.cpp | 54 ----- ReactCommon/inspector/LegacyDispatcher.h | 52 ----- .../inspector/LegacyInspectorEnvironment.cpp | 34 ---- .../inspector/LegacyInspectorEnvironment.h | 35 ---- ReactCommon/inspector/LegacyRuntimeAgent.cpp | 63 ------ ReactCommon/inspector/LegacyRuntimeAgent.h | 39 ---- .../inspector/LegacyScriptDebugServer.cpp | 64 ------ .../inspector/LegacyScriptDebugServer.h | 45 ---- ReactCommon/inspector/PageAgent.cpp | 31 --- ReactCommon/inspector/PageAgent.h | 20 -- ReactCommon/inspector/Protocol.cpp | 86 -------- ReactCommon/inspector/Protocol.h | 77 ------- ReactCommon/inspector/README.md | 17 -- ReactCommon/inspector/Util.cpp | 9 - ReactCommon/inspector/Util.h | 45 ---- 41 files changed, 9 insertions(+), 2003 deletions(-) delete mode 100644 ReactCommon/inspector/Agent.cpp delete mode 100644 ReactCommon/inspector/Agent.h delete mode 100644 ReactCommon/inspector/Android.mk delete mode 100644 ReactCommon/inspector/BUCK delete mode 100644 ReactCommon/inspector/ConsoleAgent.cpp delete mode 100644 ReactCommon/inspector/ConsoleAgent.h delete mode 100644 ReactCommon/inspector/Dispatcher.cpp delete mode 100644 ReactCommon/inspector/Dispatcher.h delete mode 100644 ReactCommon/inspector/Error.cpp delete mode 100644 ReactCommon/inspector/Error.h delete mode 100644 ReactCommon/inspector/Inspector.cpp delete mode 100644 ReactCommon/inspector/Inspector.h delete mode 100644 ReactCommon/inspector/InspectorAgent.cpp delete mode 100644 ReactCommon/inspector/InspectorAgent.h delete mode 100644 ReactCommon/inspector/InspectorController.cpp delete mode 100644 ReactCommon/inspector/InspectorController.h delete mode 100644 ReactCommon/inspector/JSDispatcher.cpp delete mode 100644 ReactCommon/inspector/JSDispatcher.h delete mode 100644 ReactCommon/inspector/LegacyAgents.cpp delete mode 100644 ReactCommon/inspector/LegacyAgents.h delete mode 100644 ReactCommon/inspector/LegacyDebuggerAgent.cpp delete mode 100644 ReactCommon/inspector/LegacyDebuggerAgent.h delete mode 100644 ReactCommon/inspector/LegacyDispatcher.cpp delete mode 100644 ReactCommon/inspector/LegacyDispatcher.h delete mode 100644 ReactCommon/inspector/LegacyInspectorEnvironment.cpp delete mode 100644 ReactCommon/inspector/LegacyInspectorEnvironment.h delete mode 100644 ReactCommon/inspector/LegacyRuntimeAgent.cpp delete mode 100644 ReactCommon/inspector/LegacyRuntimeAgent.h delete mode 100644 ReactCommon/inspector/LegacyScriptDebugServer.cpp delete mode 100644 ReactCommon/inspector/LegacyScriptDebugServer.h delete mode 100644 ReactCommon/inspector/PageAgent.cpp delete mode 100644 ReactCommon/inspector/PageAgent.h delete mode 100644 ReactCommon/inspector/Protocol.cpp delete mode 100644 ReactCommon/inspector/Protocol.h delete mode 100644 ReactCommon/inspector/README.md delete mode 100644 ReactCommon/inspector/Util.cpp delete mode 100644 ReactCommon/inspector/Util.h diff --git a/ReactAndroid/src/main/jni/xreact/jni/BUCK b/ReactAndroid/src/main/jni/xreact/jni/BUCK index 6c2be6899..ef06da174 100644 --- a/ReactAndroid/src/main/jni/xreact/jni/BUCK +++ b/ReactAndroid/src/main/jni/xreact/jni/BUCK @@ -51,6 +51,5 @@ cxx_library( "//xplat/fbsystrace:fbsystrace", react_native_xplat_target("cxxreact:bridge"), react_native_xplat_target("cxxreact:module"), - react_native_xplat_target("inspector:inspector"), ], ) diff --git a/ReactAndroid/src/main/jni/xreact/jni/JInspector.cpp b/ReactAndroid/src/main/jni/xreact/jni/JInspector.cpp index 4146fc0fd..cad09b1cc 100644 --- a/ReactAndroid/src/main/jni/xreact/jni/JInspector.cpp +++ b/ReactAndroid/src/main/jni/xreact/jni/JInspector.cpp @@ -2,6 +2,8 @@ #include "JInspector.h" +#ifdef WITH_INSPECTOR + namespace facebook { namespace react { @@ -88,3 +90,5 @@ void JInspector::registerNatives() { } } + +#endif diff --git a/ReactAndroid/src/main/jni/xreact/jni/JInspector.h b/ReactAndroid/src/main/jni/xreact/jni/JInspector.h index 3335deccb..0b9db509a 100644 --- a/ReactAndroid/src/main/jni/xreact/jni/JInspector.h +++ b/ReactAndroid/src/main/jni/xreact/jni/JInspector.h @@ -2,6 +2,8 @@ #pragma once +#ifdef WITH_INSPECTOR + #include #include @@ -59,3 +61,5 @@ private: } } + +#endif diff --git a/ReactCommon/cxxreact/BUCK b/ReactCommon/cxxreact/BUCK index da1ae7991..45496978a 100644 --- a/ReactCommon/cxxreact/BUCK +++ b/ReactCommon/cxxreact/BUCK @@ -27,8 +27,7 @@ if THIS_IS_FBANDROID: '-Wno-pessimizing-move', ], deps = [ - '//xplat/folly:molly', - react_native_xplat_target('inspector:inspector'), + '//xplat/folly:molly' ]) cxx_library( diff --git a/ReactCommon/inspector/Agent.cpp b/ReactCommon/inspector/Agent.cpp deleted file mode 100644 index 1a3720cd6..000000000 --- a/ReactCommon/inspector/Agent.cpp +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#include "Agent.h" - -#include "Error.h" -#include "Protocol.h" - -#include - -namespace facebook { -namespace react { - -void Agent::onConnect(std::shared_ptr channel) { - channel_ = std::move(channel); - - channel_->registerDomain(getDomain(), [this](std::string, int callId, const std::string& method, folly::dynamic args) { - auto result = handle(method, std::move(args)); - if (result.isNull()) { - result = folly::dynamic::object; - } - auto message = folly::dynamic::object("id", callId)("result", std::move(result)); - channel_->sendMessage(folly::toJson(std::move(message))); - }); -} - -void Agent::onDisconnect() { - channel_.reset(); -} - -folly::dynamic Agent::handle(const std::string& method, folly::dynamic args) { - try { - return methods_.at(method)(std::move(args)); - } catch (const std::out_of_range& e) { - throw InspectorException(ErrorCode::MethodNotFound, "Unknown method: '" + method + "'"); - } -} - -void Agent::registerMethod(std::string name, Method method) { - methods_.emplace(std::move(name), std::move(method)); -} - -void Agent::sendEvent(std::string name, folly::dynamic params) { - if (!channel_) { - return; - } - channel_->sendMessage(Event(getDomain(), std::move(name), std::move(params))); -} - -} -} diff --git a/ReactCommon/inspector/Agent.h b/ReactCommon/inspector/Agent.h deleted file mode 100644 index 94443231f..000000000 --- a/ReactCommon/inspector/Agent.h +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#pragma once - -#include "Dispatcher.h" - -#include - -namespace facebook { -namespace react { - -/* - * An dispatcher that makes it simple to implement an agent that serves a single domain. - */ -class Agent : public Dispatcher { -public: - void onConnect(std::shared_ptr channel) override; - void onDisconnect() override; -protected: - using Method = std::function; - void registerMethod(std::string name, Method method); - void sendEvent(std::string name, folly::dynamic params = nullptr); - - virtual std::string getDomain() = 0; -private: - folly::dynamic handle(const std::string& method, folly::dynamic args); - - std::shared_ptr channel_; - std::unordered_map methods_; -}; - -} -} diff --git a/ReactCommon/inspector/Android.mk b/ReactCommon/inspector/Android.mk deleted file mode 100644 index bd13be66e..000000000 --- a/ReactCommon/inspector/Android.mk +++ /dev/null @@ -1,28 +0,0 @@ -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) - -LOCAL_MODULE := inspector - -LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) - -LOCAL_C_INCLUDES := $(LOCAL_PATH)/.. -LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES) - -LOCAL_CFLAGS := \ - -DLOG_TAG=\"ReactNative\" - -LOCAL_CFLAGS += -Wall -Werror -fexceptions -frtti -CXX11_FLAGS := -std=c++11 -LOCAL_CFLAGS += $(CXX11_FLAGS) -LOCAL_EXPORT_CPPFLAGS := $(CXX11_FLAGS) - -LOCAL_STATIC_LIBRARIES := jschelpers -LOCAL_SHARED_LIBRARIES := libfolly_json libjsc libglog - -include $(BUILD_STATIC_LIBRARY) - -$(call import-module,folly) -$(call import-module,jsc) -$(call import-module,glog) -$(call import-module,jschelpers) diff --git a/ReactCommon/inspector/BUCK b/ReactCommon/inspector/BUCK deleted file mode 100644 index d98a369ec..000000000 --- a/ReactCommon/inspector/BUCK +++ /dev/null @@ -1,60 +0,0 @@ -EXPORTED_HEADERS = [ - "Inspector.h", -] - -def library(**kwargs): - if THIS_IS_FBANDROID: - include_defs('//ReactAndroid/DEFS') - - cxx_library( - force_static = True, - # We depend on JSC, support the same platforms - supported_platforms_regex = '^android-(armv7|x86)$', - deps = [ - '//xplat/folly:molly', - react_native_xplat_target('jschelpers:jschelpers'), - ], - **kwargs - ) - elif THIS_IS_FBOBJC: - ios_library( - inherited_buck_flags = STATIC_LIBRARY_IOS_FLAGS, - frameworks = [ - '$SDKROOT/System/Library/Frameworks/JavaScriptCore.framework', - ], - deps = [ - '//xplat/folly:molly', - react_native_xplat_target('jschelpers:jschelpers'), - ], - **kwargs - ) - else: - raise Error('Unknown repo') - -library( - name = "inspector", - srcs = glob(["*.cpp"]), - compiler_flags = [ - "-Wall", - "-Wno-shadow", - "-Wno-inconsistent-missing-override", - "-Wno-unused-local-typedef", - "-Wno-unused-private-field", - "-Wno-undefined-bool-conversion", - "-fexceptions", - "-fvisibility=hidden", - "-std=gnu++1y", - ], - exported_headers = EXPORTED_HEADERS, - header_namespace = "inspector", - headers = subdir_glob( - [("inspector", "*.h")], - excludes = EXPORTED_HEADERS, - ), - preprocessor_flags = [ - "-DENABLE_INSPECTOR=1", - ], - visibility = [ - "PUBLIC", - ], -) diff --git a/ReactCommon/inspector/ConsoleAgent.cpp b/ReactCommon/inspector/ConsoleAgent.cpp deleted file mode 100644 index 665a1df45..000000000 --- a/ReactCommon/inspector/ConsoleAgent.cpp +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#include "ConsoleAgent.h" - -#include "Protocol.h" -#include "Util.h" - -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -namespace facebook { -namespace react { - -namespace { - -static JSValueRef inspectorLog( - ConsoleAgent* agent, - JSContextRef ctx, - JSObjectRef thisObject, - size_t argumentCount, - const JSValueRef arguments[]) { - CHECK(argumentCount == 4) << "__inspectorLog takes 4 args"; - auto execState = toJS(ctx); - JSC::JSLockHolder lock(execState); - auto params = toJS(execState, arguments[2]); - agent->log( - execState, - Value(ctx, arguments[0]).toString().str(), - Value(ctx, arguments[1]).toString().str(), - JSC::asArray(params), - Value(ctx, arguments[3]).asUnsignedInteger()); - return JSValueMakeUndefined(ctx); -} - -size_t skipNativeCode(const Inspector::ScriptCallStack& callStack, size_t offset) { - for (; offset < callStack.size(); offset++) { - auto& frame = callStack.at(offset); - if (frame.sourceURL() != "[native code]") { - return offset; - } - } - - return callStack.size(); -} - -const Inspector::ScriptCallFrame* firstUserFrame(const Inspector::ScriptCallStack& callStack, size_t framesToSkip) { - // Skip out of native code - size_t offset = skipNativeCode(callStack, 0); - - // Skip frames of console polyfill - offset = skipNativeCode(callStack, offset + framesToSkip); - if (offset >= callStack.size()) { - return nullptr; - } - - if (callStack.at(offset).functionName() == "infoLog") { - offset += 1; - } - - if (offset >= callStack.size()) { - return nullptr; - } - - return &callStack.at(offset); -} - -} - -ConsoleAgent::ConsoleAgent(JSC::JSGlobalObject& globalObject, Inspector::InjectedScriptManager* injectedScriptManager) - : globalObject_(globalObject) - , injectedScriptManager_(injectedScriptManager) { - registerMethod("enable", [this](folly::dynamic) -> folly::dynamic { - using namespace std::placeholders; - enabled_ = true; - JSGlobalContextRef context = toGlobalRef(globalObject_.globalExec()); - installGlobalFunction(context, "__inspectorLog", std::bind(&inspectorLog, this, _1, _2, _3, _4)); - return nullptr; - }); - registerMethod("disable", [this](folly::dynamic) -> folly::dynamic { - JSGlobalContextRef context = toGlobalRef(globalObject_.globalExec()); - removeGlobal(context, "__inspectorLog"); - enabled_ = false; - return nullptr; - }); -} - -void ConsoleAgent::log(JSC::ExecState* execState, std::string message) { - log(execState, "log", std::move(message), nullptr, 0); -} - -void ConsoleAgent::log(JSC::ExecState* execState, std::string level, std::string message, JSC::JSArray* params, size_t framesToSkip) { - if (!enabled_) { - return; - } - - auto callStack = Inspector::createScriptCallStack(execState, Inspector::ScriptCallStack::maxCallStackSizeToCapture); - - auto logEntry = folly::dynamic::object - ("source", "console-api") - ("level", level) - ("text", std::move(message)) - ("timestamp", Timestamp::now()) - ("stackTrace", folly::parseJson(toStdString(callStack->buildInspectorArray()->toJSONString()))); - - if (params) { - logEntry("parameters", convertParams(execState, params)); - } - - if (auto frame = firstUserFrame(*callStack, framesToSkip)) { - logEntry - ("url", toStdString(frame->sourceURL())) - ("line", frame->lineNumber()) - ("column", frame->columnNumber()); - } - - sendEvent("messageAdded", folly::dynamic::object("message", std::move(logEntry))); -} - -folly::dynamic ConsoleAgent::convertParams(JSC::ExecState* execState, JSC::JSArray* params) { - auto injectedScript = injectedScriptManager_->injectedScriptFor(execState->lexicalGlobalObject()->globalExec()); - if (injectedScript.hasNoValue()) { - return nullptr; - } - - folly::dynamic remoteParams = folly::dynamic::array; - for (size_t i = 0, size = params->length(); i < size; i++) { - auto scriptValue = Deprecated::ScriptValue(execState->vm(), params->getIndex(execState, i)); - auto remoteValue = injectedScript.wrapObject(std::move(scriptValue), "console", true); - remoteParams.push_back(folly::parseJson(toStdString(remoteValue->toJSONString()))); - } - - return remoteParams; -} - -} -} diff --git a/ReactCommon/inspector/ConsoleAgent.h b/ReactCommon/inspector/ConsoleAgent.h deleted file mode 100644 index 961271923..000000000 --- a/ReactCommon/inspector/ConsoleAgent.h +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#pragma once - -#include "Agent.h" - -namespace JSC { -class JSGlobalObject; -class ExecState; -class JSArray; -} - -namespace Inspector { -class InjectedScriptManager; -} - -namespace facebook { -namespace react { - -/** - * Implements the Console agent. Relies on Javascript to call the globally exposed method __inspectorLog - * to send logging events. - */ -class ConsoleAgent : public Agent { -public: - ConsoleAgent(JSC::JSGlobalObject& globalObject, Inspector::InjectedScriptManager* injectedScriptManager); - - void log(JSC::ExecState* execState, std::string message); - void log(JSC::ExecState* execState, std::string level, std::string message, JSC::JSArray* params, size_t framesToSkip); -private: - bool enabled_{false}; - JSC::JSGlobalObject& globalObject_; - Inspector::InjectedScriptManager* injectedScriptManager_; - - folly::dynamic convertParams(JSC::ExecState* execState, JSC::JSArray* params); - - std::string getDomain() override { - return "Console"; - } -}; - -} -} diff --git a/ReactCommon/inspector/Dispatcher.cpp b/ReactCommon/inspector/Dispatcher.cpp deleted file mode 100644 index 54bbd03f2..000000000 --- a/ReactCommon/inspector/Dispatcher.cpp +++ /dev/null @@ -1,3 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#include "Dispatcher.h" diff --git a/ReactCommon/inspector/Dispatcher.h b/ReactCommon/inspector/Dispatcher.h deleted file mode 100644 index c864bea0a..000000000 --- a/ReactCommon/inspector/Dispatcher.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#pragma once - -#include - -#include -// Both double-conversions and WTF define the ASSERT macro -#undef ASSERT - -namespace facebook { -namespace react { - -/* - * A bidrectional channel that allows both sending events to the remote inspector and registering - * to receive events for a specific domain. - */ -class Channel { -public: - using MessageHandler = std::function; - - virtual ~Channel() = default; - - virtual void sendMessage(std::string message) = 0; - virtual void registerDomain(std::string domain, MessageHandler handler) = 0; -}; - -/* - * A dispatcher is responsible for one or multiple domains and registering them with the Channel - * when it is connected. - */ -class Dispatcher { -public: - virtual ~Dispatcher() {} - - virtual void onConnect(std::shared_ptr channel) = 0; - virtual void onDisconnect() = 0; -}; - -} -} diff --git a/ReactCommon/inspector/Error.cpp b/ReactCommon/inspector/Error.cpp deleted file mode 100644 index 5bb780f44..000000000 --- a/ReactCommon/inspector/Error.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#include "Error.h" - -namespace facebook { -namespace react { - -InspectorException::InspectorException(int callId, ErrorCode code, std::string message) - : error_(callId, code, std::move(message)) {} - -InspectorException::InspectorException(ErrorCode code, std::string message) - : error_(code, std::move(message)) {} - -InspectorException InspectorException::withCallId(int callId) const { - return InspectorException(callId, error_.code(), error_.message()); -} - -} -} diff --git a/ReactCommon/inspector/Error.h b/ReactCommon/inspector/Error.h deleted file mode 100644 index f373035a3..000000000 --- a/ReactCommon/inspector/Error.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#pragma once - -#include "Protocol.h" - -#include -#include - -#include - -namespace facebook { -namespace react { - -class InspectorException : public std::exception { -public: - InspectorException(int callId, ErrorCode code, std::string message); - explicit InspectorException(ErrorCode code, std::string message); - - const char* what() const throw() override { - return error_.message().c_str(); - } - - const Error& error() const { - return error_; - } - - InspectorException withCallId(int callId) const; -private: - Error error_; -}; - -} -} diff --git a/ReactCommon/inspector/Inspector.cpp b/ReactCommon/inspector/Inspector.cpp deleted file mode 100644 index 68233b15e..000000000 --- a/ReactCommon/inspector/Inspector.cpp +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#include "Inspector.h" - -#include "InspectorController.h" - -#include - -#include -#include -#include - -#include - -namespace facebook { -namespace react { - -namespace { - -JSC::JSGlobalObject& getGlobalObject(JSContextRef ctx) { - JSC::ExecState* exec = toJS(ctx); - JSC::JSLockHolder locker(exec); - - JSC::JSGlobalObject* globalObject = exec->vmEntryGlobalObject(); - return *globalObject; -} - -} - -Inspector::LocalConnection::LocalConnection(std::shared_ptr duplexConnection) - : duplexConnection_(std::move(duplexConnection)) {} - -void Inspector::LocalConnection::sendMessage(std::string message) { - duplexConnection_->sendToLocal(std::move(message)); -} - -void Inspector::LocalConnection::disconnect() { - duplexConnection_->terminate(false); -} - -Inspector::PageHolder::PageHolder(std::string name, std::unique_ptr controller) -: name(name) -, controller(std::move(controller)) {} - -Inspector::PageHolder::~PageHolder() = default; - -Inspector& Inspector::instance() { - static Inspector inspector; - return inspector; -} - -std::vector Inspector::getPages() const { - std::lock_guard lock(registrationMutex_); - std::vector pages; - pages.reserve(pages_.size()); - for (auto& entry : pages_) { - pages.emplace_back(Page{entry.first, entry.second.name}); - } - return pages; -} - -void Inspector::registerGlobalContext(std::string title, JSGlobalContextRef ctx) { - std::lock_guard lock(registrationMutex_); - auto controller = folly::make_unique(getGlobalObject(ctx)); - auto pageId = numPages_++; - pages_.emplace( - std::piecewise_construct, - std::forward_as_tuple(pageId), - std::forward_as_tuple(std::move(title), std::move(controller))); -} - -void Inspector::unregisterGlobalContext(JSGlobalContextRef ctx) { - std::lock_guard lock(registrationMutex_); - auto& globalObject = getGlobalObject(ctx); - for (auto it = pages_.begin(); it != pages_.end(); it++) { - auto& page = it->second; - if (page.controller->getGlobalObject().globalExec() == globalObject.globalExec()) { - if (page.connection_) { - page.connection_->terminate(true); - } - pages_.erase(it); - return; - } - } -} - -std::unique_ptr Inspector::connect(int pageId, std::unique_ptr remote) { - std::lock_guard lock(registrationMutex_); - return folly::make_unique(pages_.at(pageId).connect(std::move(remote))); -} - -void Inspector::disconnect(int pageId) { - std::lock_guard lock(registrationMutex_); - pages_.at(pageId).controller->onDisconnect(); -} - -std::shared_ptr Inspector::PageHolder::connect(std::unique_ptr remote) { - if (connection_) { - throw std::runtime_error("Already connected"); - } - connection_ = std::make_shared(*this, std::move(remote)); - controller->onConnect([connection = connection_](std::string message) { - connection->sendToRemote(std::move(message)); - }); - return connection_; -} - -Inspector::DuplexConnection::DuplexConnection(PageHolder& page, std::unique_ptr remoteConnection) - : page_(page) - , remoteConnection_(std::move(remoteConnection)) {} - -Inspector::DuplexConnection::~DuplexConnection() { - if (remoteConnection_) { - LOG(FATAL) << "DuplexConnection wasn't terminated before destruction"; - } -} - -void Inspector::DuplexConnection::sendToRemote(std::string message) { - std::lock_guard lock(remoteMutex_); - if (!remoteConnection_) { - return; - } - - remoteConnection_->onMessage(std::move(message)); -} - -void Inspector::DuplexConnection::sendToLocal(std::string message) { - std::lock_guard lock(localMutex_); - if (!remoteConnection_) { - return; - } - - page_.controller->onMessage(std::move(message)); -} - -void Inspector::DuplexConnection::terminate(bool local) { - std::lock_guard lockLocal(localMutex_); - { - // Temp lock here so we can still send going away message - std::lock_guard lockRemote(remoteMutex_); - if (!remoteConnection_) { - // Already disconnected - return; - } - } - - if (local) { - page_.controller->onGoingAway(); - } - std::lock_guard lockRemote(remoteMutex_); - - auto remoteConnection = std::move(remoteConnection_); - if (local) { - remoteConnection->onDisconnect(); - } - page_.controller->onDisconnect(); - // This kills us - page_.connection_.reset(); -} - -} -} diff --git a/ReactCommon/inspector/Inspector.h b/ReactCommon/inspector/Inspector.h deleted file mode 100644 index 0f4177b53..000000000 --- a/ReactCommon/inspector/Inspector.h +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#pragma once - -#include -#include -#include -#include -#include - -#include -#undef WTF_EXPORT_PRIVATE - -namespace facebook { -namespace react { - -class InspectorController; -class Sender; -/** - * The inspector exposes method to query for available 'pages' and connect to a specific one. - * Available Javascript contextes needs to be registered when they are created and removed when - * they are torn down. - */ -class Inspector { -private: - class DuplexConnection; -public: - struct Page { - const int id; - const std::string title; - }; - - struct RemoteConnection { - virtual ~RemoteConnection() = default; - virtual void onMessage(std::string message) = 0; - virtual void onDisconnect() = 0; - }; - - class LocalConnection { - public: - void sendMessage(std::string message); - void disconnect(); - - LocalConnection(std::shared_ptr duplexConnection); - private: - std::shared_ptr duplexConnection_; - }; - - static Inspector& instance(); - - void registerGlobalContext(std::string title, JSGlobalContextRef ctx); - void unregisterGlobalContext(JSGlobalContextRef ctx); - - std::vector getPages() const; - std::unique_ptr connect(int pageId, std::unique_ptr remote); -private: - struct PageHolder; - - class DuplexConnection { - public: - DuplexConnection(PageHolder& page, std::unique_ptr remoteConnection); - ~DuplexConnection(); - - void sendToRemote(std::string message); - void sendToLocal(std::string message); - void terminate(bool local); - private: - PageHolder& page_; - std::unique_ptr remoteConnection_; - std::mutex localMutex_; - std::mutex remoteMutex_; - }; - - struct PageHolder { - PageHolder(std::string name, std::unique_ptr controller); - ~PageHolder(); - - std::shared_ptr connect(std::unique_ptr remote); - - const std::string name; - std::unique_ptr controller; - std::shared_ptr connection_; - }; - - Inspector() {}; - void disconnect(int pageId); - - int numPages_ = 0; - std::unordered_map pages_; - mutable std::mutex registrationMutex_; -}; - -} -} diff --git a/ReactCommon/inspector/InspectorAgent.cpp b/ReactCommon/inspector/InspectorAgent.cpp deleted file mode 100644 index d94176059..000000000 --- a/ReactCommon/inspector/InspectorAgent.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#include "InspectorAgent.h" - -namespace facebook { -namespace react { - -InspectorAgent::InspectorAgent() { - auto emptyMethod = [](folly::dynamic) -> folly::dynamic { - return nullptr; - }; - - registerMethod("enable", emptyMethod); - registerMethod("disable", emptyMethod); -} - -void InspectorAgent::detach() { - sendEvent("detached", folly::dynamic::object("reason", "target_closed")); -} - -} -} diff --git a/ReactCommon/inspector/InspectorAgent.h b/ReactCommon/inspector/InspectorAgent.h deleted file mode 100644 index 569e73f79..000000000 --- a/ReactCommon/inspector/InspectorAgent.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#pragma once - -#include "Agent.h" - -namespace facebook { -namespace react { - -class InspectorAgent : public Agent { -public: - InspectorAgent(); - - void detach(); -private: - std::string getDomain() override { - return "Inspector"; - } -}; - -} -} diff --git a/ReactCommon/inspector/InspectorController.cpp b/ReactCommon/inspector/InspectorController.cpp deleted file mode 100644 index d04525cdd..000000000 --- a/ReactCommon/inspector/InspectorController.cpp +++ /dev/null @@ -1,192 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#include "InspectorController.h" - -#include "Error.h" -#include "Agent.h" -#include "LegacyInspectorEnvironment.h" -#include "InspectorAgent.h" -#include "PageAgent.h" -#include "ConsoleAgent.h" -#include "JSDispatcher.h" -#include "LegacyAgents.h" - -#include -#include -#include - -namespace facebook { -namespace react { - -class ConcreteChannel : public Channel { -public: - ConcreteChannel(Receiver receiver) - : receiver_(std::move(receiver)) {} - - void sendMessage(std::string message) override { - receiver_(std::move(message)); - } - - void registerDomain(std::string domain, MessageHandler handler) override { - domains_.emplace(std::move(domain), std::move(handler)); - } - - std::unordered_map& getDomains() { - return domains_; - } -private: - std::unordered_map domains_; - Receiver receiver_; -}; - -class MessageRouter { -public: - MessageRouter(ConcreteChannel* channel) - : channel_(channel) { - CHECK(channel_) << "Channel is null"; - } - - /* - * Messages are in JSON, formatted like: - * { - * "id": 1, - * "method": "Debugger.removeBreakpoint", - * "params": { "removeBreakpoint": "xyz" } - * } - */ - void route(std::string message) { - try { - auto json = parseJson(message); - auto callId = getCallId(json); - receive(callId, std::move(message), std::move(json)); - } catch (const InspectorException& e) { - channel_->sendMessage(e.error()); - } - } -private: - void receive(int callId, std::string message, folly::dynamic json) { - try { - auto method = Method::parse(json["method"].asString()); - auto& handler = getHandler(method.domain()); - handler(std::move(message), callId, method.name(), std::move(json["params"])); - } catch (const InspectorException& e) { - throw e.withCallId(callId); - } catch (const std::exception& e) { - LOG(ERROR) << "Dispatcher failed: " << e.what(); - throw InspectorException(callId, ErrorCode::ServerError, "Internal error"); - } catch (...) { - throw InspectorException(callId, ErrorCode::ServerError, "Internal error"); - } - } - - folly::dynamic parseJson(const std::string& message) { - try { - return folly::parseJson(message); - } catch (const std::runtime_error& e) { - throw InspectorException(ErrorCode::ParseError, "Message must be in JSON format"); - } - } - - int getCallId(folly::dynamic& json) { - auto& id = json["id"]; - if (!id.isInt()) { - throw InspectorException(ErrorCode::InvalidRequest, "The type of 'id' property must be number"); - } else { - return id.asInt(); - } - } - - Channel::MessageHandler& getHandler(const std::string& domain) { - try { - auto& domains = channel_->getDomains(); - return domains.at(domain); - } catch (const std::out_of_range& e) { - throw InspectorException(ErrorCode::MethodNotFound, folly::to("Unknown domain: '", domain, "'")); - } - } - - ConcreteChannel* channel_; -}; - -class SchemaAgent : public Agent { -public: - SchemaAgent() { - registerMethod("getDomains", [this](folly::dynamic) -> folly::dynamic { - CHECK(channel_) << "Channel is null"; - folly::dynamic names = folly::dynamic::array; - auto& domains = channel_->getDomains(); - for (auto& entry : domains) { - // TODO(blom): Actually get version? - names.push_back(folly::dynamic::object("name", entry.first)("version", "1.0")); - } - return names; - }); - } - - void onConnect(std::shared_ptr channel) override { - Agent::onConnect(channel); - channel_ = std::static_pointer_cast(channel); - } -private: - std::shared_ptr channel_; - - std::string getDomain() override { - return "Schema"; - } -}; - -InspectorController::InspectorController(JSC::JSGlobalObject& globalObject) - : globalObject_(globalObject) { - auto environment = folly::make_unique(); - auto inspectorAgent = folly::make_unique(); - inspectorAgent_ = inspectorAgent.get(); - dispatchers_.push_back(std::move(inspectorAgent)); - dispatchers_.push_back(folly::make_unique()); - dispatchers_.push_back(folly::make_unique()); - dispatchers_.push_back(folly::make_unique(globalObject)); - - auto consoleAgent = folly::make_unique(globalObject, environment->injectedScriptManager()); - auto legacyAgents = folly::make_unique(globalObject, std::move(environment), consoleAgent.get()); - - dispatchers_.push_back(std::move(consoleAgent)); - dispatchers_.push_back(std::move(legacyAgents)); -} - -InspectorController::~InspectorController() { - CHECK(!channel_) << "Wasn't disconnected"; -} - -void InspectorController::onConnect(Receiver receiver) { - CHECK(!channel_) << "Already connected"; - - channel_ = std::make_shared(std::move(receiver)); - - for (auto& dispatcher : dispatchers_) { - dispatcher->onConnect(channel_); - } -} - -void InspectorController::onMessage(std::string message) { - CHECK(channel_) << "Not connected"; - - MessageRouter(channel_.get()).route(message); -} - -void InspectorController::onGoingAway() { - CHECK(channel_) << "Not connected"; - - inspectorAgent_->detach(); -} - -void InspectorController::onDisconnect() { - CHECK(channel_) << "Not connected"; - - for (auto& dispatcher : dispatchers_) { - dispatcher->onDisconnect(); - } - - channel_.reset(); -} - -} -} diff --git a/ReactCommon/inspector/InspectorController.h b/ReactCommon/inspector/InspectorController.h deleted file mode 100644 index 2281e9929..000000000 --- a/ReactCommon/inspector/InspectorController.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#pragma once - -#include "Dispatcher.h" - -#include -#include -#include - -namespace JSC { -class JSGlobalObject; -} - -namespace facebook { -namespace react { - -class ConcreteChannel; -class InspectorAgent; - -using Receiver = std::function; - -class InspectorController { -public: - InspectorController(JSC::JSGlobalObject& globalObject); - ~InspectorController(); - - JSC::JSGlobalObject& getGlobalObject() const { return globalObject_; } - - void onConnect(Receiver receiver); - void onMessage(std::string message); - void onGoingAway(); - void onDisconnect(); -private: - JSC::JSGlobalObject& globalObject_; - std::shared_ptr channel_; - std::vector> dispatchers_; - InspectorAgent* inspectorAgent_; -}; - -} -} diff --git a/ReactCommon/inspector/JSDispatcher.cpp b/ReactCommon/inspector/JSDispatcher.cpp deleted file mode 100644 index 2920626db..000000000 --- a/ReactCommon/inspector/JSDispatcher.cpp +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#include "JSDispatcher.h" - -#include "Protocol.h" -#include "Util.h" - -#include - -#include -#include -#include -#include - -#include - -#include - -namespace facebook { -namespace react { - -namespace { - -static JSValueRef nativeRegisterAgent( - JSDispatcher* agent, - JSContextRef ctx, - JSObjectRef thisObject, - size_t argumentCount, - const JSValueRef arguments[]) { - CHECK(argumentCount == 1) << "__registerInspectorAgent takes 1 arg"; - auto execState = toJS(ctx); - JSC::JSLockHolder lock(execState); - auto globalContext = JSContextGetGlobalContext(ctx); - agent->addAgent( - execState, - Value(globalContext, arguments[0]).asObject()); - return JSValueMakeUndefined(ctx); -} - -static JSValueRef nativeSendEvent( - JSDispatcher* agent, - const std::string& domain, - JSContextRef ctx, - JSObjectRef thisObject, - size_t argumentCount, - const JSValueRef arguments[]) { - CHECK(argumentCount == 2) << "sendEvent takes 2 args"; - auto execState = toJS(ctx); - JSC::JSLockHolder lock(execState); - auto globalContext = JSContextGetGlobalContext(ctx); - auto params = folly::parseJson(Value(globalContext, arguments[1]).toJSONString()); - agent->sendEvent( - domain, - Value(globalContext, arguments[0]).toString().str(), - std::move(params)); - return JSValueMakeUndefined(ctx); -} - -static JSValueRef nativeInspectorTimestamp( - JSContextRef ctx, - JSObjectRef function, - JSObjectRef thisObject, - size_t argumentCount, - const JSValueRef arguments[], - JSValueRef *exception) { - return JSValueMakeNumber(ctx, Timestamp::now()); -} - -} - -JSDispatcher::JSDispatcher(JSC::JSGlobalObject& globalObject) { - using namespace std::placeholders; - JSGlobalContextRef context = toGlobalRef(globalObject.globalExec()); - installGlobalFunction(context, "__registerInspectorAgent", std::bind(&nativeRegisterAgent, this, _1, _2, _3, _4)); - installGlobalFunction(context, "__inspectorTimestamp", &nativeInspectorTimestamp); -} - -void JSDispatcher::onConnect(std::shared_ptr channel) { - channel_ = std::move(channel); - - for (auto& pair : agents_) { - registerAgent(pair.first); - } -} - -void JSDispatcher::onDisconnect() { - channel_.reset(); -} - -void JSDispatcher::addAgent(JSC::ExecState* execState, Object agentType) { - auto context = agentType.context(); - auto domainObject = agentType.getProperty("DOMAIN"); - if (domainObject.isUndefined()) { - throw std::invalid_argument("DOMAIN should be string"); - } - auto domain = domainObject.toString().str(); - // Bind the domain to the send event function - using namespace std::placeholders; - Value sendEventFunction = Object( - context, - makeFunction(context, "sendEvent", std::bind(&nativeSendEvent, this, domain, _1, _2, _3, _4))); - auto agent = agentType.callAsConstructor({ sendEventFunction }); - agent.makeProtected(); - - if (channel_) { - registerAgent(domain); - } - agents_.emplace(std::move(domain), std::move(agent)); -} - -void JSDispatcher::registerAgent(const std::string& name) { - channel_->registerDomain( - name, - [this, name](std::string, int callId, const std::string& methodName, folly::dynamic args) { - Object& agent = agents_.at(name); - auto context = agent.context(); - JSC::JSLockHolder lock(toJS(context)); - // TODO(blom): Check undefined before asObject - auto method = agent.getProperty(methodName.c_str()).asObject(); - if (args.isNull()) { - args = folly::dynamic::object; - } - auto response = method.callAsFunction(agent, { Value::fromDynamic(context, args) }); - auto result = (response.isUndefined() || response.isNull()) ? folly::dynamic::object() : folly::parseJson(response.toJSONString()); - auto message = folly::dynamic::object("id", callId)("result", std::move(result)); - channel_->sendMessage(folly::toJson(std::move(message))); - }); -} - -void JSDispatcher::sendEvent(std::string domain, std::string name, folly::dynamic params) { - channel_->sendMessage(Event(std::move(domain), std::move(name), std::move(params))); -} - -} -} diff --git a/ReactCommon/inspector/JSDispatcher.h b/ReactCommon/inspector/JSDispatcher.h deleted file mode 100644 index b9330301e..000000000 --- a/ReactCommon/inspector/JSDispatcher.h +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#pragma once - -#include "Dispatcher.h" - -#include -#include - -#include - -#include - -namespace JSC { -class JSGlobalObject; -class JSObject; -class ExecState; -class JSArray; -} - -namespace facebook { -namespace react { - -/* - * A dispatcher that allows agents to be implemented in Javascript. Provides the global method - * __registerInspectorAgent to register a JS agent. - */ -class JSDispatcher : public Dispatcher { -public: - JSDispatcher(JSC::JSGlobalObject& globalObject); - - void onConnect(std::shared_ptr channel) override; - void onDisconnect() override; - - void addAgent(JSC::ExecState* execState, Object agentType); - void registerAgent(const std::string& name); - - void sendEvent(std::string domain, std::string name, folly::dynamic params); -private: - std::shared_ptr channel_; - - std::unordered_map agents_; -}; - -} -} diff --git a/ReactCommon/inspector/LegacyAgents.cpp b/ReactCommon/inspector/LegacyAgents.cpp deleted file mode 100644 index 2ccd2eb69..000000000 --- a/ReactCommon/inspector/LegacyAgents.cpp +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#include "LegacyAgents.h" - -#include "LegacyInspectorEnvironment.h" -#include "LegacyRuntimeAgent.h" -#include "LegacyDebuggerAgent.h" - -#include -#include -#include - -namespace facebook { -namespace react { - -using namespace Inspector; - -LegacyAgents::LegacyAgents( - JSC::JSGlobalObject& globalObject, - std::unique_ptr environment, - ConsoleAgent* consoleAgent) - : LegacyDispatcher(globalObject) - , environment_(std::move(environment)) { - auto injectedScriptManager = environment_->injectedScriptManager(); - auto runtimeAgent = folly::make_unique(injectedScriptManager, globalObject); - auto debuggerAgent = folly::make_unique(injectedScriptManager, globalObject, consoleAgent); - - runtimeAgent->setScriptDebugServer(&debuggerAgent->scriptDebugServer()); - - addAgent("Runtime", std::move(runtimeAgent)); - addAgent("Debugger", std::move(debuggerAgent)); -} - -} -} diff --git a/ReactCommon/inspector/LegacyAgents.h b/ReactCommon/inspector/LegacyAgents.h deleted file mode 100644 index 36650d7a8..000000000 --- a/ReactCommon/inspector/LegacyAgents.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#pragma once - -#include "LegacyDispatcher.h" - -namespace JSC { -class JSGlobalObject; -} - -namespace facebook { -namespace react { - -class LegacyInspectorEnvironment; -class ConsoleAgent; - -/* - * An dispatcher that provides the existing agents in JavaScriptCore. - */ -class LegacyAgents : public LegacyDispatcher { -public: - LegacyAgents( - JSC::JSGlobalObject& globalObject, - std::unique_ptr environment, - ConsoleAgent* consoleAgent); -private: - std::unique_ptr environment_; - ConsoleAgent* consoleAgent_; -}; - -} -} diff --git a/ReactCommon/inspector/LegacyDebuggerAgent.cpp b/ReactCommon/inspector/LegacyDebuggerAgent.cpp deleted file mode 100644 index 20b71a0da..000000000 --- a/ReactCommon/inspector/LegacyDebuggerAgent.cpp +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#include "LegacyDebuggerAgent.h" - -#include "Util.h" - -#include -#include -#include - -namespace facebook { -namespace react { - -using namespace Inspector; - -LegacyDebuggerAgent::LegacyDebuggerAgent(InjectedScriptManager* injectedScriptManager, JSC::JSGlobalObject& globalObject, ConsoleAgent* consoleAgent) - : InspectorDebuggerAgent(injectedScriptManager) - , scriptDebugServer_(globalObject) - , consoleAgent_(consoleAgent) {} - -void LegacyDebuggerAgent::startListeningScriptDebugServer() { - scriptDebugServer().addListener(this); -} - -void LegacyDebuggerAgent::stopListeningScriptDebugServer(bool isBeingDestroyed) { - scriptDebugServer().removeListener(this, isBeingDestroyed); -} - -InjectedScript LegacyDebuggerAgent::injectedScriptForEval(ErrorString* error, const int* executionContextId) { - if (executionContextId) { - *error = ASCIILiteral("Execution context id is not supported for JSContext inspection as there is only one execution context."); - return InjectedScript(); - } - - JSC::ExecState* exec = scriptDebugServer_.globalObject().globalExec(); - return injectedScriptManager()->injectedScriptFor(exec); -} - -void LegacyDebuggerAgent::breakpointActionLog(JSC::ExecState* exec, const String& message) { - consoleAgent_->log(exec, toStdString(message)); -} - -} -} diff --git a/ReactCommon/inspector/LegacyDebuggerAgent.h b/ReactCommon/inspector/LegacyDebuggerAgent.h deleted file mode 100644 index 08bf34ce5..000000000 --- a/ReactCommon/inspector/LegacyDebuggerAgent.h +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#pragma once - -#include "ConsoleAgent.h" -#include "LegacyScriptDebugServer.h" - -#include -#include -#include - -namespace JSC { -class JSGlobalObject; -} - -namespace facebook { -namespace react { - -class LegacyDebuggerAgent : public Inspector::InspectorDebuggerAgent { -public: - LegacyDebuggerAgent(Inspector::InjectedScriptManager*, JSC::JSGlobalObject&, ConsoleAgent*); - - virtual LegacyScriptDebugServer& scriptDebugServer() override { return scriptDebugServer_; } - - virtual void startListeningScriptDebugServer() override; - virtual void stopListeningScriptDebugServer(bool isBeingDestroyed) override; - virtual Inspector::InjectedScript injectedScriptForEval(Inspector::ErrorString*, const int* executionContextId) override; - - virtual void breakpointActionLog(JSC::ExecState*, const String&) override; - - virtual void muteConsole() override { } - virtual void unmuteConsole() override { } - -private: - LegacyScriptDebugServer scriptDebugServer_; - ConsoleAgent* consoleAgent_; -}; - -} -} diff --git a/ReactCommon/inspector/LegacyDispatcher.cpp b/ReactCommon/inspector/LegacyDispatcher.cpp deleted file mode 100644 index 8fa7d7aeb..000000000 --- a/ReactCommon/inspector/LegacyDispatcher.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#include "LegacyDispatcher.h" - -#include "Util.h" - -#include -#include -#include - -namespace facebook { -namespace react { - -using namespace Inspector; - -LegacyDispatcher::FrontendChannel::FrontendChannel(std::shared_ptr channel) -: channel_(channel) {} - -bool LegacyDispatcher::FrontendChannel::sendMessageToFrontend(const WTF::String& message) { - channel_->sendMessage(toStdString(message)); - return true; -} - -LegacyDispatcher::LegacyDispatcher(JSC::JSGlobalObject& globalObject) - : globalObject_(globalObject) {} - -void LegacyDispatcher::addAgent(std::string domain, std::unique_ptr agent) { - domains_.emplace_back(std::move(domain)); - agents_.append(std::move(agent)); -} - -void LegacyDispatcher::onConnect(std::shared_ptr channel) { - // TODO: Should perhaps only create this once and then connect each time instead - frontendChannel_ = std::make_unique(channel); - dispatcher_.reset(InspectorBackendDispatcher::create(frontendChannel_.get()).leakRef()); - - auto messageHandler = [this](std::string message, int, const std::string&, folly::dynamic) { - JSC::JSLockHolder lock(globalObject_.globalExec()); - dispatcher_->dispatch(message.c_str()); - }; - for (auto& domain : domains_) { - channel->registerDomain(domain, messageHandler); - } - - agents_.didCreateFrontendAndBackend(frontendChannel_.get(), dispatcher_.get()); -} - -void LegacyDispatcher::onDisconnect() { - // TODO: Perhaps support InspectedTargetDestroyed - agents_.willDestroyFrontendAndBackend(InspectorDisconnectReason::InspectorDestroyed); -} - -} -} diff --git a/ReactCommon/inspector/LegacyDispatcher.h b/ReactCommon/inspector/LegacyDispatcher.h deleted file mode 100644 index 96e617d73..000000000 --- a/ReactCommon/inspector/LegacyDispatcher.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#pragma once - -#include "Dispatcher.h" - -#include -#include -#include -#include -#include - -#include -#include - -namespace JSC { -class JSGlobalObject; -} - -namespace facebook { -namespace react { - -/* - * An dispatcher that is able to register JavaScriptCore agents that extend the InspectorAgentBase - * base class. - */ -class LegacyDispatcher : public Dispatcher { -public: - LegacyDispatcher(JSC::JSGlobalObject& globalObject); - void addAgent(std::string domain, std::unique_ptr agent); - - void onConnect(std::shared_ptr channel) override; - void onDisconnect() override; -private: - class FrontendChannel : public Inspector::InspectorFrontendChannel { - public: - FrontendChannel(std::shared_ptr channel); - bool sendMessageToFrontend(const WTF::String& message) override; - private: - std::shared_ptr channel_; - }; - - JSC::JSGlobalObject& globalObject_; - std::vector domains_; - Inspector::InspectorAgentRegistry agents_; - - std::unique_ptr frontendChannel_; - std::unique_ptr dispatcher_; -}; - -} -} diff --git a/ReactCommon/inspector/LegacyInspectorEnvironment.cpp b/ReactCommon/inspector/LegacyInspectorEnvironment.cpp deleted file mode 100644 index 2a010d923..000000000 --- a/ReactCommon/inspector/LegacyInspectorEnvironment.cpp +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#include "LegacyInspectorEnvironment.h" - -#include -#include -#include -#include -#include - -#include - -namespace facebook { -namespace react { - -using namespace Inspector; - -LegacyInspectorEnvironment::LegacyInspectorEnvironment() - : injectedScriptManager_(folly::make_unique(*this, InjectedScriptHost::create())) {} - -LegacyInspectorEnvironment::~LegacyInspectorEnvironment() { - injectedScriptManager_->disconnect(); -} - -InspectorFunctionCallHandler LegacyInspectorEnvironment::functionCallHandler() const { - return JSC::call; -} - -InspectorEvaluateHandler LegacyInspectorEnvironment::evaluateHandler() const { - return JSC::evaluate; -} - -} -} diff --git a/ReactCommon/inspector/LegacyInspectorEnvironment.h b/ReactCommon/inspector/LegacyInspectorEnvironment.h deleted file mode 100644 index 00ec90205..000000000 --- a/ReactCommon/inspector/LegacyInspectorEnvironment.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#pragma once - -#include -#include - -namespace Inspector { -class InjectedScriptManager; -} - -namespace facebook { -namespace react { - -class LegacyInspectorEnvironment : public Inspector::InspectorEnvironment { -public: - LegacyInspectorEnvironment(); - ~LegacyInspectorEnvironment(); - - Inspector::InjectedScriptManager* injectedScriptManager() const { - return injectedScriptManager_.get(); - } -private: - std::unique_ptr injectedScriptManager_; - - bool developerExtrasEnabled() const override { return true; } - bool canAccessInspectedScriptState(JSC::ExecState*) const override { return true; } - Inspector::InspectorFunctionCallHandler functionCallHandler() const override; - Inspector::InspectorEvaluateHandler evaluateHandler() const override; - void willCallInjectedScriptFunction(JSC::ExecState*, const WTF::String& scriptName, int scriptLine) override {}; - void didCallInjectedScriptFunction(JSC::ExecState*) override {} -}; - -} -} diff --git a/ReactCommon/inspector/LegacyRuntimeAgent.cpp b/ReactCommon/inspector/LegacyRuntimeAgent.cpp deleted file mode 100644 index f08a9d178..000000000 --- a/ReactCommon/inspector/LegacyRuntimeAgent.cpp +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#include "LegacyRuntimeAgent.h" - -#include -#include -#include - -namespace facebook { -namespace react { - -using namespace Inspector; - -LegacyRuntimeAgent::LegacyRuntimeAgent(InjectedScriptManager* injectedScriptManager, JSC::JSGlobalObject& globalObject) - : InspectorRuntimeAgent(injectedScriptManager) - , m_globalObject(globalObject) {} - -void LegacyRuntimeAgent::didCreateFrontendAndBackend(InspectorFrontendChannel* frontendChannel, InspectorBackendDispatcher* backendDispatcher) { - // m_frontendDispatcher = folly::make_unique(frontendChannel); - frontendChannel_ = frontendChannel; - m_backendDispatcher.reset(InspectorRuntimeBackendDispatcher::create(backendDispatcher, this).leakRef()); -} - -void LegacyRuntimeAgent::enable(ErrorString* error) { - InspectorRuntimeAgent::enable(error); - - auto contextObject = InspectorObject::create(); - contextObject->setNumber(ASCIILiteral("id"), 1); - contextObject->setBoolean(ASCIILiteral("isDefault"), true); - contextObject->setBoolean(ASCIILiteral("isPageContext"), true); - contextObject->setString(ASCIILiteral("origin"), ASCIILiteral("")); - contextObject->setString(ASCIILiteral("name"), ASCIILiteral("React Native")); - - auto jsonMessage = InspectorObject::create(); - jsonMessage->setString(ASCIILiteral("method"), ASCIILiteral("Runtime.executionContextCreated")); - auto paramsObject = InspectorObject::create(); - paramsObject->setValue(ASCIILiteral("context"), contextObject); - jsonMessage->setObject(ASCIILiteral("params"), paramsObject); - - frontendChannel_->sendMessageToFrontend(jsonMessage->toJSONString()); -} - -void LegacyRuntimeAgent::willDestroyFrontendAndBackend(InspectorDisconnectReason) { - frontendChannel_ = nullptr; - m_backendDispatcher = nullptr; -} - -JSC::VM& LegacyRuntimeAgent::globalVM() { - return m_globalObject.vm(); -} - -InjectedScript LegacyRuntimeAgent::injectedScriptForEval(ErrorString* error, const int* executionContextId) { - JSC::ExecState* scriptState = m_globalObject.globalExec(); - InjectedScript injectedScript = injectedScriptManager()->injectedScriptFor(scriptState); - if (injectedScript.hasNoValue()) { - *error = ASCIILiteral("Internal error: main world execution context not found."); - } - - return injectedScript; -} - -} -} diff --git a/ReactCommon/inspector/LegacyRuntimeAgent.h b/ReactCommon/inspector/LegacyRuntimeAgent.h deleted file mode 100644 index e0b04aa74..000000000 --- a/ReactCommon/inspector/LegacyRuntimeAgent.h +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#pragma once - -#include - -#include -#include - -namespace JSC { -class JSGlobalObject; -} - -namespace facebook { -namespace react { - -class LegacyRuntimeAgent : public Inspector::InspectorRuntimeAgent { -public: - LegacyRuntimeAgent(Inspector::InjectedScriptManager*, JSC::JSGlobalObject&); - - void enable(Inspector::ErrorString* error) override; - - void didCreateFrontendAndBackend(Inspector::InspectorFrontendChannel*, Inspector::InspectorBackendDispatcher*) override; - void willDestroyFrontendAndBackend(Inspector::InspectorDisconnectReason) override; - - JSC::VM& globalVM() override; - Inspector::InjectedScript injectedScriptForEval(Inspector::ErrorString* error, const int* executionContextId) override; - - void muteConsole() override { } - void unmuteConsole() override { } -private: - Inspector::InspectorFrontendChannel* frontendChannel_; - // std::unique_ptr m_frontendDispatcher; - std::unique_ptr m_backendDispatcher; - JSC::JSGlobalObject& m_globalObject; -}; - -} -} diff --git a/ReactCommon/inspector/LegacyScriptDebugServer.cpp b/ReactCommon/inspector/LegacyScriptDebugServer.cpp deleted file mode 100644 index 3453e708d..000000000 --- a/ReactCommon/inspector/LegacyScriptDebugServer.cpp +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#include "LegacyScriptDebugServer.h" - -#include - -namespace facebook { -namespace react { - -using namespace Inspector; - -LegacyScriptDebugServer::LegacyScriptDebugServer(JSC::JSGlobalObject& globalObject) - : Inspector::ScriptDebugServer(false) - , globalObject_(globalObject) {} - -void LegacyScriptDebugServer::addListener(ScriptDebugListener* listener) -{ - if (!listener) { - return; - } - - bool wasEmpty = listeners_.isEmpty(); - listeners_.add(listener); - - // First listener. Attach the debugger to the JSGlobalObject. - if (wasEmpty) { - attach(&globalObject_); - recompileAllJSFunctions(); - } -} - -void LegacyScriptDebugServer::removeListener(ScriptDebugListener* listener, bool isBeingDestroyed) { - if (!listener) { - return; - } - - listeners_.remove(listener); - - // Last listener. Detach the debugger from the JSGlobalObject. - if (listeners_.isEmpty()) { - detach(&globalObject_, isBeingDestroyed ? Debugger::GlobalObjectIsDestructing : Debugger::TerminatingDebuggingSession); - if (!isBeingDestroyed) { - recompileAllJSFunctions(); - } - } -} - -void LegacyScriptDebugServer::recompileAllJSFunctions() { - JSC::Debugger::recompileAllJSFunctions(&globalObject_.vm()); -} - -void LegacyScriptDebugServer::runEventLoopWhilePaused() { - // Drop all locks so another thread can work in the VM while we are nested. - JSC::JSLock::DropAllLocks dropAllLocks(&globalObject_.vm()); - - // Spinning here is our best option, we could override the method - // notifyDoneProcessingDebuggerEvents but it's marked as final :( - while (!m_doneProcessingDebuggerEvents) { - usleep(10 * 1000); - } -} - -} -} diff --git a/ReactCommon/inspector/LegacyScriptDebugServer.h b/ReactCommon/inspector/LegacyScriptDebugServer.h deleted file mode 100644 index fe8380451..000000000 --- a/ReactCommon/inspector/LegacyScriptDebugServer.h +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#pragma once - -#include -#include - -namespace JSC { -class JSGlobalObject; -} - -namespace facebook { -namespace react { - -class LegacyScriptDebugServer : public Inspector::ScriptDebugServer { -public: - LegacyScriptDebugServer(JSC::JSGlobalObject& object); - - void addListener(Inspector::ScriptDebugListener* listener); - void removeListener(Inspector::ScriptDebugListener* listener, bool isBeingDestroyed); - - JSC::JSGlobalObject& globalObject() const { return globalObject_; } - - void recompileAllJSFunctions() override; - -private: - ListenerSet* getListenersForGlobalObject(JSC::JSGlobalObject*) override { return &listeners_; } - void didPause(JSC::JSGlobalObject*) override { } - void didContinue(JSC::JSGlobalObject*) override { } - void runEventLoopWhilePaused() override; - bool isContentScript(JSC::ExecState*) const override { return false; } - - // NOTE: Currently all exceptions are reported at the API boundary through reportAPIException. - // Until a time comes where an exception can be caused outside of the API (e.g. setTimeout - // or some other async operation in a pure JSContext) we can ignore exceptions reported here. - // TODO: Should we actually ignore them? - void reportException(JSC::ExecState*, JSC::JSValue) const override { } - - ListenerSet listeners_; - JSC::JSGlobalObject& globalObject_; -}; - - -} -} diff --git a/ReactCommon/inspector/PageAgent.cpp b/ReactCommon/inspector/PageAgent.cpp deleted file mode 100644 index 02dbb5861..000000000 --- a/ReactCommon/inspector/PageAgent.cpp +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#include "PageAgent.h" - -namespace facebook { -namespace react { - -PageAgent::PageAgent() { - auto emptyMethod = [](folly::dynamic args) -> folly::dynamic { - return nullptr; - }; - - registerMethod("enable", emptyMethod); - registerMethod("disable", emptyMethod); - registerMethod("getResourceTree", [](folly::dynamic args) -> folly::dynamic { - return folly::dynamic::object - ("frameTree", folly::dynamic::object - ("childFrames", folly::dynamic::array) - ("resources", folly::dynamic::array) - ("frame", folly::dynamic::object - ("id", "1") - ("loaderId", "1") - ("name", "main") - ("url", "") - ("securityOrigin", "") - ("mimeType", "application/octet-stream"))); - }); -} - -} -} diff --git a/ReactCommon/inspector/PageAgent.h b/ReactCommon/inspector/PageAgent.h deleted file mode 100644 index c2f747eb7..000000000 --- a/ReactCommon/inspector/PageAgent.h +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#pragma once - -#include "Agent.h" - -namespace facebook { -namespace react { - -class PageAgent : public Agent { -public: - PageAgent(); -private: - std::string getDomain() override { - return "Page"; - } -}; - -} -} diff --git a/ReactCommon/inspector/Protocol.cpp b/ReactCommon/inspector/Protocol.cpp deleted file mode 100644 index eb7428ede..000000000 --- a/ReactCommon/inspector/Protocol.cpp +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#include "Protocol.h" - -#include "Error.h" - -#include -#include -#include - -#include - -namespace facebook { -namespace react { - -namespace { - -folly::dynamic getCallId(const folly::Optional& callId) { - if (callId.hasValue()) { - return callId.value(); - } else { - return nullptr; - } -} - -} - -Method Method::parse(const std::string& formatted) { - auto splitPos = formatted.find_first_of('.'); - if (splitPos == std::string::npos) { - throw InspectorException(ErrorCode::InvalidRequest, "Invalid method format"); - } - return Method(formatted.substr(0, splitPos), formatted.substr(splitPos + 1)); -} - -Method::Method(std::string domain, std::string name) - : domain_(std::move(domain)) - , name_(std::move(name)) {} - -std::string Method::formatted() const { - return folly::to(domain_, '.', name_); -} - -Event::Event(std::string domain, std::string method, folly::dynamic params) - : method_(std::move(domain), std::move(method)) - , params_(std::move(params)) {} - -Event::operator std::string() const { - auto event = folly::dynamic::object("method", method_.formatted()); - if (!params_.isNull()) { - event("params", params_); - } - - return folly::toJson(std::move(event)); -} - -namespace Timestamp { -double now() { - using duration = std::chrono::duration>; - auto epoch = std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch() - ); - return epoch.count(); -} -} - -Error::Error(int callId, ErrorCode code, std::string message) - : callId_(callId) - , code_(code) - , message_(std::move(message)) {} - -Error::Error(ErrorCode code, std::string message) - : code_(code) - , message_(std::move(message)) {} - -Error::operator std::string() const { - auto errorCode = static_cast(code_); - return folly::toJson( - folly::dynamic::object("id", getCallId(callId_)) - ("error", folly::dynamic::object("code", errorCode)("message", message_)) - ); -} - - -} -} diff --git a/ReactCommon/inspector/Protocol.h b/ReactCommon/inspector/Protocol.h deleted file mode 100644 index 3b36ae797..000000000 --- a/ReactCommon/inspector/Protocol.h +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#pragma once - -#include - -#include -#include - -namespace facebook { -namespace react { - -class Method { -public: - static Method parse(const std::string& formatted); - - Method(std::string domain, std::string name); - - const std::string& domain() const { - return domain_; - } - - const std::string& name() const { - return name_; - } - - std::string formatted() const; -private: - std::string domain_; - std::string name_; -}; - -class Event { -public: - explicit Event(std::string domain, std::string method, folly::dynamic params); - - operator std::string() const; -private: - Method method_; - folly::dynamic params_; -}; - -namespace Timestamp { - double now(); -} - -enum class ErrorCode { - ParseError = -32700, - InvalidRequest = -32600, - MethodNotFound = -32601, - InvalidParams = -32602, - InternalError = -32603, - ServerError = -32000, -}; - -class Error { -public: - Error(int callId, ErrorCode code, std::string message); - Error(ErrorCode code, std::string message); - - const std::string& message() const { - return message_; - } - - ErrorCode code() const { - return code_; - } - - operator std::string() const; -private: - folly::Optional callId_; - ErrorCode code_; - std::string message_; -}; - -} -} diff --git a/ReactCommon/inspector/README.md b/ReactCommon/inspector/README.md deleted file mode 100644 index 67da1c7c3..000000000 --- a/ReactCommon/inspector/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# Inspector - -This directory implements an the Chrome debugging protocol [1]. The version used is roughly 1.1 of -the protocol. The code here doesn't specify a transport and doesn't implement an actual server. This -is left up to higher parts of the stack. - -The implementation uses multiple "dispatchers" to route messages for a specific domain. It reuses -existing code in JavaScriptCore to handle the domains for Debugger and Runtime. For Console, Page -and Inspector there are new implementations. - -## Open source - -The inspector currently doesn't compile in open source. This is due to how the build on Android -where we download the JSC sources and build an artifact separately, later download the headers we -need. The number of headers download would have to be expanded and verify that it builds correctly. - -[1]: https://developer.chrome.com/devtools/docs/debugger-protocol diff --git a/ReactCommon/inspector/Util.cpp b/ReactCommon/inspector/Util.cpp deleted file mode 100644 index 23c9ee6e1..000000000 --- a/ReactCommon/inspector/Util.cpp +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#include "Util.h" - -namespace facebook { -namespace react { - -} -} diff --git a/ReactCommon/inspector/Util.h b/ReactCommon/inspector/Util.h deleted file mode 100644 index fb858bf30..000000000 --- a/ReactCommon/inspector/Util.h +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#pragma once - -#include -#include -#include -#include -#include - -#include -#include - -namespace facebook { -namespace react { - -inline std::string toStdString(const WTF::String& str) { - return std::string(str.utf8().data()); -} - -template -class AgentMap { -public: - void add(JSGlobalContextRef ctx, T* agent) { - map_[ctx] = agent; - } - - void remove(T* agent) { - auto it = std::find_if( - map_.begin(), - map_.end(), - [agent](const typename MapType::value_type& entry) { return entry.second == agent; }); - map_.erase(it); - } - - T* get(JSGlobalContextRef ctx) { - return map_.at(ctx); - } -private: - using MapType = std::unordered_map; - MapType map_; -}; - -} -}