diff --git a/ReactAndroid/src/main/jni/react/jni/AndroidJSCFactory.cpp b/ReactAndroid/src/main/jni/react/jni/AndroidJSCFactory.cpp deleted file mode 100644 index 54b208a48d06b1..00000000000000 --- a/ReactAndroid/src/main/jni/react/jni/AndroidJSCFactory.cpp +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright (c) Facebook, Inc. and its affiliates. - -// This source code is licensed under the MIT license found in the -// LICENSE file in the root directory of this source tree. - -#include - -#include - -#include -#include -#include -#include -#include -#include - -#include "JSCPerfLogging.h" -#include "JSLogging.h" -#include "JReactMarker.h" - -using namespace facebook::jni; - -namespace facebook { -namespace react { - -namespace { - -ExceptionHandling::ExtractedEror extractJniError(const std::exception& ex, const char *context) { - auto jniEx = dynamic_cast(&ex); - if (!jniEx) { - return {}; - } - - auto stackTrace = jniEx->getThrowable()->getStackTrace(); - std::ostringstream stackStr; - for (int i = 0, count = stackTrace->size(); i < count; ++i) { - auto frame = stackTrace->getElement(i); - - auto methodName = folly::to(frame->getClassName(), ".", - frame->getMethodName()); - - // Cut off stack traces at the Android looper, to keep them simple - if (methodName == "android.os.Looper.loop") { - break; - } - - stackStr << std::move(methodName) << '@' << frame->getFileName(); - if (frame->getLineNumber() > 0) { - stackStr << ':' << frame->getLineNumber(); - } - stackStr << std::endl; - } - - auto msg = folly::to("Java exception in '", context, "'\n\n", jniEx->what()); - return {.message = msg, .stack = stackStr.str()}; -} - -JSValueRef nativePerformanceNow( - JSContextRef ctx, - JSObjectRef function, - JSObjectRef thisObject, - size_t argumentCount, - const JSValueRef arguments[], JSValueRef *exception) { - static const int64_t NANOSECONDS_IN_SECOND = 1000000000LL; - static const int64_t NANOSECONDS_IN_MILLISECOND = 1000000LL; - - // Since SystemClock.uptimeMillis() is commonly used for performance measurement in Java - // and uptimeMillis() internally uses clock_gettime(CLOCK_MONOTONIC), - // we use the same API here. - // We need that to make sure we use the same time system on both JS and Java sides. - // Links to the source code: - // https://android.googlesource.com/platform/frameworks/native/+/jb-mr1-release/libs/utils/SystemClock.cpp - // https://android.googlesource.com/platform/system/core/+/master/libutils/Timers.cpp - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - int64_t nano = now.tv_sec * NANOSECONDS_IN_SECOND + now.tv_nsec; - return Value::makeNumber(ctx, (nano / (double)NANOSECONDS_IN_MILLISECOND)); -} - -JSValueRef nativeLoggingHook( - JSContextRef ctx, - JSObjectRef function, - JSObjectRef thisObject, - size_t argumentCount, - const JSValueRef arguments[], - JSValueRef* exception) { - android_LogPriority logLevel = ANDROID_LOG_DEBUG; - if (argumentCount > 1) { - int level = (int)Value(ctx, arguments[1]).asNumber(); - // The lowest log level we get from JS is 0. We shift and cap it to be - // in the range the Android logging method expects. - logLevel = std::min( - static_cast(level + ANDROID_LOG_DEBUG), - ANDROID_LOG_FATAL); - } - if (argumentCount > 0) { - String message = Value(ctx, arguments[0]).toString(); - reactAndroidLoggingHook(message.str(), logLevel); - } - return Value::makeUndefined(ctx); -} - -} - -namespace detail { - -void injectJSCExecutorAndroidPlatform() { - // Inject some behavior into react/ - JReactMarker::setLogPerfMarkerIfNeeded(); - ExceptionHandling::platformErrorExtractor = extractJniError; - JSCNativeHooks::loggingHook = nativeLoggingHook; - JSCNativeHooks::nowHook = nativePerformanceNow; - JSCNativeHooks::installPerfHooks = addNativePerfLoggingHooks; -} - -} - -std::unique_ptr makeAndroidJSCExecutorFactory( - const folly::dynamic& jscConfig) { - detail::injectJSCExecutorAndroidPlatform(); - return folly::make_unique(std::move(jscConfig)); -} - -} -} diff --git a/ReactAndroid/src/main/jni/react/jni/AndroidJSCFactory.h b/ReactAndroid/src/main/jni/react/jni/AndroidJSCFactory.h deleted file mode 100644 index a71632262b49a5..00000000000000 --- a/ReactAndroid/src/main/jni/react/jni/AndroidJSCFactory.h +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) Facebook, Inc. and its 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 -#include - -namespace folly { - -class dynamic; - -} - -namespace facebook { -namespace react { - -class JSExecutorFactory; - -namespace detail { - -// This is only exposed so instrumentation tests can call it. -void injectJSCExecutorAndroidPlatform(); - -} - -std::unique_ptr makeAndroidJSCExecutorFactory( - const folly::dynamic& jscConfig); - -} -} diff --git a/ReactAndroid/src/main/jni/react/jni/JSCPerfLogging.cpp b/ReactAndroid/src/main/jni/react/jni/JSCPerfLogging.cpp deleted file mode 100644 index 5d1dd553dc9d6c..00000000000000 --- a/ReactAndroid/src/main/jni/react/jni/JSCPerfLogging.cpp +++ /dev/null @@ -1,308 +0,0 @@ -// Copyright (c) Facebook, Inc. and its affiliates. - -// This source code is licensed under the MIT license found in the -// LICENSE file in the root directory of this source tree. - -#include "JSCPerfLogging.h" - -#include - -#include -#include - -using namespace facebook::jni; - -namespace facebook { namespace react { - -struct JQuickPerformanceLogger : JavaClass { - static auto constexpr kJavaDescriptor = "Lcom/facebook/quicklog/QuickPerformanceLogger;"; - - void markerStart(int markerId, int instanceKey, long timestamp) { - static auto markerStartMethod = - javaClassStatic()->getMethod("markerStart"); - markerStartMethod(self(), markerId, instanceKey, timestamp); - } - - void markerEnd(int markerId, int instanceKey, short actionId, long timestamp) { - static auto markerEndMethod = - javaClassStatic()->getMethod("markerEnd"); - markerEndMethod(self(), markerId, instanceKey, actionId, timestamp); - } - - void markerTag(int markerId, int instanceKey, alias_ref tag) { - static auto markerTagMethod = - javaClassStatic()->getMethod)>("markerTag"); - markerTagMethod(self(), markerId, instanceKey, tag); - } - - void markerAnnotate( - int markerId, - int instanceKey, - alias_ref key, - alias_ref value) { - static auto markerAnnotateMethod = javaClassStatic()-> - getMethod, alias_ref)>("markerAnnotate"); - markerAnnotateMethod(self(), markerId, instanceKey, key, value); - } - - void markerNote(int markerId, int instanceKey, short actionId, long timestamp) { - static auto markerNoteMethod = - javaClassStatic()->getMethod("markerNote"); - markerNoteMethod(self(), markerId, instanceKey, actionId, timestamp); - } - - void markerCancel(int markerId, int instanceKey) { - static auto markerCancelMethod = - javaClassStatic()->getMethod("markerCancel"); - markerCancelMethod(self(), markerId, instanceKey); - } - - int64_t currentMonotonicTimestamp() { - static auto currentTimestampMethod = - javaClassStatic()->getMethod("currentMonotonicTimestamp"); - return currentTimestampMethod(self()); - } - - void markerPoint(int markerId, alias_ref name, int instanceKey) { - static auto markerPointMethod = - javaClassStatic()->getMethod)>("markerPoint"); - markerPointMethod(self(), markerId, instanceKey, name); - } -}; - -struct JQuickPerformanceLoggerProvider : JavaClass { - static auto constexpr kJavaDescriptor = "Lcom/facebook/quicklog/QuickPerformanceLoggerProvider;"; - - static alias_ref get() { - static auto getQPLInstMethod = - javaClassStatic()->getStaticMethod("getQPLInstance"); - static auto logger = make_global(getQPLInstMethod(javaClassStatic())); - return logger; - } -}; - -static bool isReady() { - static bool ready = false; - if (!ready) { - try { - // TODO: findClassStatic only does the lookup once. If we can't find - // QuickPerformanceLoggerProvider the first time we call this, we will always fail here. - findClassStatic("com/facebook/quicklog/QuickPerformanceLoggerProvider"); - } catch(...) { - // Swallow this exception - we don't want to crash the app, an error is enough. - FBLOGE("Calling QPL from JS before class has been loaded in Java. Ignored."); - return false; - } - if (JQuickPerformanceLoggerProvider::get()) { - ready = true; - } else { - FBLOGE("Calling QPL from JS before it has been initialized in Java. Ignored."); - return false; - } - } - return ready; -} - -// After having read the implementation of PNaN that is returned from JSValueToNumber, and some -// more material on how NaNs are constructed, I think this is the most consistent way to verify -// NaN with how we generate it. -// Once the integration completes, I'll play around with it some more and potentially change this -// implementation to use std::isnan() if it is exactly commensurate with our usage. -static bool isNan(double value) { - return (value != value); -} - -static double grabDouble( - JSContextRef ctx, - const JSValueRef arguments[], - size_t argumentIndex, - JSValueRef* exception) { - return JSValueToNumber(ctx, arguments[argumentIndex], exception); -} - -// Safely translates JSValues to an array of doubles. -static bool grabDoubles( - size_t targetsCount, - double targets[], - JSContextRef ctx, - size_t argumentCount, - const JSValueRef arguments[], - JSValueRef* exception) { - if (argumentCount < targetsCount) { - return false; - } - for (size_t i = 0 ; i < targetsCount ; i++) { - targets[i] = grabDouble(ctx, arguments, i, exception); - if (isNan(targets[i])) { - return false; - } - } - return true; -} - -static local_ref getJStringFromJSValueRef(JSContextRef ctx, JSValueRef ref) { - JSStringRef jsStringRef = JSValueToStringCopy(ctx, ref, nullptr); - const JSChar* chars = JSStringGetCharactersPtr(jsStringRef); - const size_t length = JSStringGetLength(jsStringRef); - local_ref returnStr = adopt_local(Environment::current()->NewString(chars, length)); - JSStringRelease(jsStringRef); - return returnStr; -} - -static JSValueRef nativeQPLMarkerStart( - JSContextRef ctx, - JSObjectRef function, - JSObjectRef thisObject, - size_t argumentCount, - const JSValueRef arguments[], - JSValueRef* exception) { - double targets[3]; - if (isReady() && grabDoubles(3, targets, ctx, argumentCount, arguments, exception)) { - int32_t markerId = (int32_t) targets[0]; - int32_t instanceKey = (int32_t) targets[1]; - int64_t timestamp = (int64_t) targets[2]; - JQuickPerformanceLoggerProvider::get()->markerStart(markerId, instanceKey, timestamp); - } - return JSValueMakeUndefined(ctx); -} - -static JSValueRef nativeQPLMarkerEnd( - JSContextRef ctx, - JSObjectRef function, - JSObjectRef thisObject, - size_t argumentCount, - const JSValueRef arguments[], - JSValueRef* exception) { - double targets[4]; - if (isReady() && grabDoubles(4, targets, ctx, argumentCount, arguments, exception)) { - int32_t markerId = (int32_t) targets[0]; - int32_t instanceKey = (int32_t) targets[1]; - // NOTE: avoid undefined behavior when the value does not find in int16_t. - int16_t actionId = (int16_t) (int32_t) targets[2]; - int64_t timestamp = (int64_t) targets[3]; - JQuickPerformanceLoggerProvider::get()->markerEnd(markerId, instanceKey, actionId, timestamp); - } - return JSValueMakeUndefined(ctx); -} - -static JSValueRef nativeQPLMarkerTag( - JSContextRef ctx, - JSObjectRef function, - JSObjectRef thisObject, - size_t argumentCount, - const JSValueRef arguments[], - JSValueRef* exception) { - double targets[2]; - if (isReady() && grabDoubles(2, targets, ctx, argumentCount, arguments, exception)) { - int32_t markerId = (int32_t) targets[0]; - int32_t instanceKey = (int32_t) targets[1]; - local_ref tag = getJStringFromJSValueRef(ctx, arguments[2]); - JQuickPerformanceLoggerProvider::get()->markerTag(markerId, instanceKey, tag); - } - return JSValueMakeUndefined(ctx); -} - -static JSValueRef nativeQPLMarkerAnnotate( - JSContextRef ctx, - JSObjectRef function, - JSObjectRef thisObject, - size_t argumentCount, - const JSValueRef arguments[], - JSValueRef* exception) { - double targets[2]; - if (isReady() && grabDoubles(2, targets, ctx, argumentCount, arguments, exception)) { - int32_t markerId = (int32_t) targets[0]; - int32_t instanceKey = (int32_t) targets[1]; - local_ref key = getJStringFromJSValueRef(ctx, arguments[2]); - local_ref value = getJStringFromJSValueRef(ctx, arguments[3]); - JQuickPerformanceLoggerProvider::get()->markerAnnotate(markerId, instanceKey, key, value); - } - return JSValueMakeUndefined(ctx); -} - -static JSValueRef nativeQPLMarkerNote( - JSContextRef ctx, - JSObjectRef function, - JSObjectRef thisObject, - size_t argumentCount, - const JSValueRef arguments[], - JSValueRef* exception) { - double targets[4]; - if (isReady() && grabDoubles(4, targets, ctx, argumentCount, arguments, exception)) { - int32_t markerId = (int32_t) targets[0]; - int32_t instanceKey = (int32_t) targets[1]; - // NOTE: avoid undefined behavior when the value does not find in int16_t. - int16_t actionId = (int16_t) (int32_t) targets[2]; - int64_t timestamp = (int64_t) targets[3]; - JQuickPerformanceLoggerProvider::get()->markerNote(markerId, instanceKey, actionId, timestamp); - } - return JSValueMakeUndefined(ctx); -} - -static JSValueRef nativeQPLMarkerCancel( - JSContextRef ctx, - JSObjectRef function, - JSObjectRef thisObject, - size_t argumentCount, - const JSValueRef arguments[], - JSValueRef* exception) { - double targets[2]; - if (isReady() && grabDoubles(2, targets, ctx, argumentCount, arguments, exception)) { - int32_t markerId = (int32_t) targets[0]; - int32_t instanceKey = (int32_t) targets[1]; - JQuickPerformanceLoggerProvider::get()->markerCancel(markerId, instanceKey); - } - return JSValueMakeUndefined(ctx); -} - -static JSValueRef nativeQPLTimestamp( - JSContextRef ctx, - JSObjectRef function, - JSObjectRef thisObject, - size_t argumentCount, - const JSValueRef arguments[], - JSValueRef* exception) { - if (!isReady()) { - return JSValueMakeNumber(ctx, 0); - } - int64_t timestamp = JQuickPerformanceLoggerProvider::get()->currentMonotonicTimestamp(); - // Since this is monotonic time, I assume the 52 bits of mantissa are enough in the double value. - return JSValueMakeNumber(ctx, timestamp); -} - -static JSValueRef nativeQPLMarkerPoint( - JSContextRef ctx, - JSObjectRef function, - JSObjectRef thisObject, - size_t argumentCount, - const JSValueRef arguments[], - JSValueRef* exception) { - if (isReady() && argumentCount == 4) { - double markerIdArgument = grabDouble(ctx, arguments, 0, exception); - double instanceKeyArgument = grabDouble(ctx, arguments, 2, exception); - if (isNan(markerIdArgument) || isNan(instanceKeyArgument)) { - return JSValueMakeUndefined(ctx); - } - - int32_t markerId = (int32_t) markerIdArgument; - local_ref name = getJStringFromJSValueRef(ctx, arguments[1]); - int32_t instanceKey = (int32_t) instanceKeyArgument; - // timestamp is not used as QuickPerformanceLogger::markerPoint with all - // params is missing - JQuickPerformanceLoggerProvider::get()->markerPoint(markerId, name, instanceKey); - } - return JSValueMakeUndefined(ctx); -} - -void addNativePerfLoggingHooks(JSGlobalContextRef ctx) { - installGlobalFunction(ctx, "nativeQPLMarkerStart", nativeQPLMarkerStart); - installGlobalFunction(ctx, "nativeQPLMarkerEnd", nativeQPLMarkerEnd); - installGlobalFunction(ctx, "nativeQPLMarkerTag", nativeQPLMarkerTag); - installGlobalFunction(ctx, "nativeQPLMarkerAnnotate", nativeQPLMarkerAnnotate); - installGlobalFunction(ctx, "nativeQPLMarkerNote", nativeQPLMarkerNote); - installGlobalFunction(ctx, "nativeQPLMarkerCancel", nativeQPLMarkerCancel); - installGlobalFunction(ctx, "nativeQPLTimestamp", nativeQPLTimestamp); - installGlobalFunction(ctx, "nativeQPLMarkerPoint", nativeQPLMarkerPoint); -} - -} } diff --git a/ReactAndroid/src/main/jni/react/jni/JSCPerfLogging.h b/ReactAndroid/src/main/jni/react/jni/JSCPerfLogging.h deleted file mode 100644 index 5a103febe6ae6d..00000000000000 --- a/ReactAndroid/src/main/jni/react/jni/JSCPerfLogging.h +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Facebook, Inc. and its 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 - -namespace facebook { -namespace react { - -void addNativePerfLoggingHooks(JSGlobalContextRef ctx); - -} } diff --git a/ReactCommon/cxxreact/JSCExecutor.cpp b/ReactCommon/cxxreact/JSCExecutor.cpp deleted file mode 100644 index 02308241028b2f..00000000000000 --- a/ReactCommon/cxxreact/JSCExecutor.cpp +++ /dev/null @@ -1,786 +0,0 @@ -// Copyright (c) Facebook, Inc. and its affiliates. - -// This source code is licensed under the MIT license found in the -// LICENSE file in the root directory of this source tree. - -#include "JSCExecutor.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "JSBigString.h" -#include "JSBundleType.h" -#include "JSCLegacyTracing.h" -#include "JSCMemory.h" -#include "JSCPerfStats.h" -#include "JSCSamplingProfiler.h" -#include "JSCTracing.h" -#include "JSCUtils.h" -#include "JSModulesUnbundle.h" -#include "MessageQueueThread.h" -#include "ModuleRegistry.h" -#include "Platform.h" -#include "RAMBundleRegistry.h" -#include "RecoverableError.h" -#include "SystraceSection.h" - -#if defined(WITH_FB_JSC_TUNING) && defined(__ANDROID__) -#include -#endif - -namespace facebook { -namespace react { - -namespace { - -template -inline JSObjectCallAsFunctionCallback exceptionWrapMethod() { - struct funcWrapper { - static JSValueRef call( - JSContextRef ctx, - JSObjectRef function, - JSObjectRef thisObject, - size_t argumentCount, - const JSValueRef arguments[], - JSValueRef* exception) { - try { - auto executor = Object::getGlobalObject(ctx).getPrivate(); - if (executor && - executor->getJavaScriptContext()) { // Executor not invalidated - return (executor->*method)(argumentCount, arguments); - } - } catch (...) { - *exception = translatePendingCppExceptionToJSError(ctx, function); - } - return Value::makeUndefined(ctx); - } - }; - - return &funcWrapper::call; -} - -template -inline JSObjectGetPropertyCallback exceptionWrapMethod() { - struct funcWrapper { - static JSValueRef call( - JSContextRef ctx, - JSObjectRef object, - JSStringRef propertyName, - JSValueRef* exception) { - try { - auto executor = Object::getGlobalObject(ctx).getPrivate(); - if (executor && - executor->getJavaScriptContext()) { // Executor not invalidated - return (executor->*method)(object, propertyName); - } - } catch (...) { - *exception = translatePendingCppExceptionToJSError(ctx, object); - } - return Value::makeUndefined(ctx); - } - }; - - return &funcWrapper::call; -} - -} // namespace - -#if DEBUG -static JSValueRef nativeInjectHMRUpdate( - JSContextRef ctx, - JSObjectRef function, - JSObjectRef thisObject, - size_t argumentCount, - const JSValueRef arguments[], - JSValueRef* exception) { - String execJSString = Value(ctx, arguments[0]).toString(); - String jsURL = Value(ctx, arguments[1]).toString(); - evaluateScript(ctx, execJSString, jsURL); - return Value::makeUndefined(ctx); -} -#endif - -std::unique_ptr JSCExecutorFactory::createJSExecutor( - std::shared_ptr delegate, - std::shared_ptr jsQueue) { - return folly::make_unique( - delegate, jsQueue, m_jscConfig); -} - -JSCExecutor::JSCExecutor( - std::shared_ptr delegate, - std::shared_ptr messageQueueThread, - const folly::dynamic& jscConfig) throw(JSException) - : m_delegate(delegate), - m_messageQueueThread(messageQueueThread), - m_nativeModules(delegate ? delegate->getModuleRegistry() : nullptr), - m_jscConfig(jscConfig) { - initOnJSVMThread(); - - { - SystraceSection s("nativeModuleProxy object"); - installGlobalProxy( - m_context, - "nativeModuleProxy", - exceptionWrapMethod<&JSCExecutor::getNativeModule>()); - } -} - -JSCExecutor::~JSCExecutor() { - CHECK(*m_isDestroyed) - << "JSCExecutor::destroy() must be called before its destructor!"; -} - -void JSCExecutor::destroy() { - *m_isDestroyed = true; - if (m_messageQueueThread.get()) { - m_messageQueueThread->runOnQueueSync([this]() { terminateOnJSVMThread(); }); - } else { - terminateOnJSVMThread(); - } -} - -void JSCExecutor::setContextName(const std::string& name) { - String jsName = String(m_context, name.c_str()); - JSC_JSGlobalContextSetName(m_context, jsName); -} - -static bool canUseInspector(JSContextRef context) { -#ifdef WITH_INSPECTOR -#if defined(__APPLE__) - return isCustomJSCPtr(context); // WITH_INSPECTOR && Apple -#else - return true; // WITH_INSPECTOR && Android -#endif -#else - return false; // !WITH_INSPECTOR -#endif -} - -static bool canUseSamplingProfiler(JSContextRef context) { -#if defined(__APPLE__) || defined(WITH_JSC_EXTRA_TRACING) - return JSC_JSSamplingProfilerEnabled(context); -#else - return false; -#endif -} - -void JSCExecutor::initOnJSVMThread() throw(JSException) { - SystraceSection s("JSCExecutor::initOnJSVMThread"); - -#if defined(__APPLE__) - const bool useCustomJSC = - m_jscConfig.getDefault("UseCustomJSC", false).getBool(); - if (useCustomJSC) { - JSC_configureJSCForIOS(true, toJson(m_jscConfig)); - } -#else - const bool useCustomJSC = false; -#endif - -#if defined(WITH_FB_JSC_TUNING) && defined(__ANDROID__) - configureJSCForAndroid(m_jscConfig); -#endif - - // Create a custom global class, so we can store data in it later using - // JSObjectSetPrivate - JSClassRef globalClass = nullptr; - { - SystraceSection s_("JSClassCreate"); - JSClassDefinition definition = kJSClassDefinitionEmpty; - definition.attributes |= kJSClassAttributeNoAutomaticPrototype; - globalClass = JSC_JSClassCreate(useCustomJSC, &definition); - } - { - SystraceSection s_("JSGlobalContextCreateInGroup"); - m_context = - JSC_JSGlobalContextCreateInGroup(useCustomJSC, nullptr, globalClass); - } - JSC_JSClassRelease(useCustomJSC, globalClass); - - // Add a pointer to ourselves so we can retrieve it later in our hooks - Object::getGlobalObject(m_context).setPrivate(this); - - if (canUseInspector(m_context)) { - const std::string ownerId = - m_jscConfig.getDefault("OwnerIdentity", "unknown").getString(); - const std::string appId = - m_jscConfig.getDefault("AppIdentity", "unknown").getString(); - const std::string deviceId = - m_jscConfig.getDefault("DeviceIdentity", "unknown").getString(); - auto checkIsInspectedRemote = [ownerId, appId, deviceId]() { - return isNetworkInspected(ownerId, appId, deviceId); - }; - - auto& globalInspector = facebook::react::getInspectorInstance(); - JSC_JSGlobalContextEnableDebugger( - m_context, globalInspector, ownerId.c_str(), checkIsInspectedRemote); - } - - installNativeHook<&JSCExecutor::nativeFlushQueueImmediate>( - "nativeFlushQueueImmediate"); - installNativeHook<&JSCExecutor::nativeCallSyncHook>("nativeCallSyncHook"); - - installGlobalFunction( - m_context, "nativeLoggingHook", JSCNativeHooks::loggingHook); - installGlobalFunction( - m_context, "nativePerformanceNow", JSCNativeHooks::nowHook); - -#if DEBUG - installGlobalFunction( - m_context, "nativeInjectHMRUpdate", nativeInjectHMRUpdate); -#endif - - addNativeTracingHooks(m_context); - addNativeTracingLegacyHooks(m_context); - addJSCMemoryHooks(m_context); - addJSCPerfStatsHooks(m_context); - - JSCNativeHooks::installPerfHooks(m_context); - - if (canUseSamplingProfiler(m_context)) { - initSamplingProfilerOnMainJSCThread(m_context); - } -} - -bool JSCExecutor::isNetworkInspected( - const std::string& owner, - const std::string& app, - const std::string& device) { -#ifdef WITH_FB_DBG_ATTACH_BEFORE_EXEC - auto connect_socket = [](int socket_desc, std::string address, int port) { - if (socket_desc < 0) { - ::close(socket_desc); - return false; - } - - struct timeval tv; - tv.tv_sec = 1; - tv.tv_usec = 0; - auto sock_opt_rcv_resp = setsockopt( - socket_desc, - SOL_SOCKET, - SO_RCVTIMEO, - (const char*)&tv, - sizeof(struct timeval)); - if (sock_opt_rcv_resp < 0) { - ::close(socket_desc); - return false; - } - - auto sock_opt_snd_resp = setsockopt( - socket_desc, - SOL_SOCKET, - SO_SNDTIMEO, - (const char*)&tv, - sizeof(struct timeval)); - if (sock_opt_snd_resp < 0) { - ::close(socket_desc); - return false; - } - - struct sockaddr_in server; - server.sin_addr.s_addr = inet_addr(address.c_str()); - server.sin_family = AF_INET; - server.sin_port = htons(port); - auto connect_resp = - ::connect(socket_desc, (struct sockaddr*)&server, sizeof(server)); - if (connect_resp < 0) { - ::close(socket_desc); - return false; - } - - return true; - }; - - int socket_desc = socket(AF_INET, SOCK_STREAM, 0); - - if (!connect_socket(socket_desc, "127.0.0.1", 8082)) { -#if defined(__ANDROID__) - socket_desc = socket(AF_INET, SOCK_STREAM, 0); - if (!connect_socket(socket_desc, "10.0.2.2", 8082) /* emulator */) { - socket_desc = socket(AF_INET, SOCK_STREAM, 0); - if (!connect_socket(socket_desc, "10.0.3.2", 8082) /* genymotion */) { - return false; - } - } -#else //! defined(__ANDROID__) - return false; -#endif // defined(__ANDROID__) - } - - std::string escapedOwner = - folly::uriEscape(owner, folly::UriEscapeMode::QUERY); - std::string escapedApp = - folly::uriEscape(app, folly::UriEscapeMode::QUERY); - std::string escapedDevice = - folly::uriEscape(device, folly::UriEscapeMode::QUERY); - std::string msg = folly::to( - "GET /autoattach?title=", - escapedOwner, - "&app=", - escapedApp, - "&device=", - escapedDevice, - " HTTP/1.1\r\n\r\n"); - auto send_resp = ::send(socket_desc, msg.c_str(), msg.length(), 0); - if (send_resp < 0) { - ::close(socket_desc); - return false; - } - - char server_reply[200]; - server_reply[199] = '\0'; - auto recv_resp = - ::recv(socket_desc, server_reply, sizeof(server_reply) - 1, 0); - if (recv_resp < 0) { - ::close(socket_desc); - return false; - } - - std::string response(server_reply); - if (response.size() < 25) { - ::close(socket_desc); - return false; - } - auto responseCandidate = response.substr(response.size() - 25); - auto found = - responseCandidate.find("{\"autoattach\":true}") != std::string::npos; - ::close(socket_desc); - return found; -#else //! WITH_FB_DBG_ATTACH_BEFORE_EXEC - return false; -#endif // WITH_FB_DBG_ATTACH_BEFORE_EXEC -} - -void JSCExecutor::terminateOnJSVMThread() { - JSGlobalContextRef context = m_context; - m_context = nullptr; - Object::getGlobalObject(context).setPrivate(nullptr); - m_nativeModules.reset(); - - if (canUseInspector(context)) { - auto& globalInspector = facebook::react::getInspectorInstance(); - JSC_JSGlobalContextDisableDebugger(context, globalInspector); - } - - JSC_JSGlobalContextRelease(context); -} - -#ifdef WITH_FBJSCEXTENSIONS -static const char* explainLoadSourceStatus(JSLoadSourceStatus status) { - switch (status) { - case JSLoadSourceIsCompiled: - return "No error encountered during source load"; - - case JSLoadSourceErrorOnRead: - return "Error reading source"; - - case JSLoadSourceIsNotCompiled: - return "Source is not compiled"; - - case JSLoadSourceErrorVersionMismatch: - return "Source version not supported"; - - default: - return "Bad error code"; - } -} -#endif - -// basename_r isn't in all iOS SDKs, so use this simple version instead. -static std::string simpleBasename(const std::string& path) { - size_t pos = path.rfind("/"); - return (pos != std::string::npos) ? path.substr(pos) : path; -} - -void JSCExecutor::loadApplicationScript( - std::unique_ptr script, - std::string sourceURL) { - SystraceSection s( - "JSCExecutor::loadApplicationScript", "sourceURL", sourceURL); - - std::string scriptName = simpleBasename(sourceURL); - ReactMarker::logTaggedMarker( - ReactMarker::RUN_JS_BUNDLE_START, scriptName.c_str()); - String jsSourceURL(m_context, sourceURL.c_str()); - -// TODO t15069155: reduce the number of overrides here -#ifdef WITH_FBJSCEXTENSIONS - if (auto fileStr = dynamic_cast(script.get())) { - JSContextLock lock(m_context); - JSLoadSourceStatus jsStatus; - auto bcSourceCode = JSCreateSourceCodeFromFile( - fileStr->fd(), jsSourceURL, nullptr, &jsStatus); - - switch (jsStatus) { - case JSLoadSourceIsCompiled: - if (!bcSourceCode) { - throw std::runtime_error("Unexpected error opening compiled bundle"); - } - evaluateSourceCode(m_context, bcSourceCode, jsSourceURL); - - flush(); - - ReactMarker::logMarker(ReactMarker::CREATE_REACT_CONTEXT_STOP); - ReactMarker::logTaggedMarker( - ReactMarker::RUN_JS_BUNDLE_STOP, scriptName.c_str()); - return; - - case JSLoadSourceErrorVersionMismatch: - throw RecoverableError(explainLoadSourceStatus(jsStatus)); - - case JSLoadSourceErrorOnRead: - case JSLoadSourceIsNotCompiled: - // Not bytecode, fall through. - break; - } - } -#elif defined(__APPLE__) - BundleHeader header; - memcpy( - &header, script->c_str(), std::min(script->size(), sizeof(BundleHeader))); - auto scriptTag = parseTypeFromHeader(header); - - if (scriptTag == ScriptTag::BCBundle) { - using file_ptr = std::unique_ptr; - file_ptr source(fopen(sourceURL.c_str(), "r"), fclose); - int sourceFD = fileno(source.get()); - - JSValueRef jsError; - JSValueRef result = JSC_JSEvaluateBytecodeBundle( - m_context, NULL, sourceFD, jsSourceURL, &jsError); - if (result == nullptr) { - throw JSException(m_context, jsError, jsSourceURL); - } - } else -#endif - { - String jsScript; - JSContextLock lock(m_context); - { - SystraceSection s_( - "JSCExecutor::loadApplicationScript-createExpectingAscii"); - ReactMarker::logMarker(ReactMarker::JS_BUNDLE_STRING_CONVERT_START); - jsScript = adoptString(std::move(script)); - ReactMarker::logMarker(ReactMarker::JS_BUNDLE_STRING_CONVERT_STOP); - } - - SystraceSection s_("JSCExecutor::loadApplicationScript-evaluateScript"); - evaluateScript(m_context, jsScript, jsSourceURL); - } - - flush(); - - ReactMarker::logMarker(ReactMarker::CREATE_REACT_CONTEXT_STOP); - ReactMarker::logTaggedMarker( - ReactMarker::RUN_JS_BUNDLE_STOP, scriptName.c_str()); -} - -void JSCExecutor::setBundleRegistry( - std::unique_ptr bundleRegistry) { - if (!m_bundleRegistry) { - installNativeHook<&JSCExecutor::nativeRequire>("nativeRequire"); - } - m_bundleRegistry = std::move(bundleRegistry); -} - -void JSCExecutor::registerBundle( - uint32_t bundleId, - const std::string& bundlePath) { - if (m_bundleRegistry) { - m_bundleRegistry->registerBundle(bundleId, bundlePath); - } else { - auto stPath = JSCExecutor::getSyntheticBundlePath(bundleId, bundlePath); - auto sourceUrlStr = String(m_context, stPath.c_str()); - auto source = adoptString(JSBigFileString::fromPath(bundlePath)); - evaluateScript(m_context, source, sourceUrlStr); - } -} - -void JSCExecutor::bindBridge() throw(JSException) { - SystraceSection s("JSCExecutor::bindBridge"); - std::call_once(m_bindFlag, [this] { - auto global = Object::getGlobalObject(m_context); - auto batchedBridgeValue = global.getProperty("__fbBatchedBridge"); - if (batchedBridgeValue.isUndefined()) { - auto requireBatchedBridge = - global.getProperty("__fbRequireBatchedBridge"); - if (!requireBatchedBridge.isUndefined()) { - batchedBridgeValue = requireBatchedBridge.asObject().callAsFunction({}); - } - if (batchedBridgeValue.isUndefined()) { - throw JSException( - "Could not get BatchedBridge, make sure your bundle is packaged correctly"); - } - } - - auto batchedBridge = batchedBridgeValue.asObject(); - m_callFunctionReturnFlushedQueueJS = - batchedBridge.getProperty("callFunctionReturnFlushedQueue").asObject(); - m_invokeCallbackAndReturnFlushedQueueJS = - batchedBridge.getProperty("invokeCallbackAndReturnFlushedQueue") - .asObject(); - m_flushedQueueJS = batchedBridge.getProperty("flushedQueue").asObject(); - m_callFunctionReturnResultAndFlushedQueueJS = - batchedBridge.getProperty("callFunctionReturnResultAndFlushedQueue") - .asObject(); - }); -} - -void JSCExecutor::callNativeModules(Value&& value) { - SystraceSection s("JSCExecutor::callNativeModules"); - // If this fails, you need to pass a fully functional delegate with a - // module registry to the factory/ctor. - CHECK(m_delegate) << "Attempting to use native modules without a delegate"; - try { - auto calls = value.toJSONString(); - m_delegate->callNativeModules(*this, folly::parseJson(calls), true); - } catch (...) { - std::string message = "Error in callNativeModules()"; - try { - message += ":" + value.toString().str(); - } catch (...) { - // ignored - } - std::throw_with_nested(std::runtime_error(message)); - } -} - -void JSCExecutor::flush() { - SystraceSection s("JSCExecutor::flush"); - - if (m_flushedQueueJS) { - callNativeModules(m_flushedQueueJS->callAsFunction({})); - return; - } - - // When a native module is called from JS, BatchedBridge.enqueueNativeCall() - // is invoked. For that to work, require('BatchedBridge') has to be called, - // and when that happens, __fbBatchedBridge is set as a side effect. - auto global = Object::getGlobalObject(m_context); - auto batchedBridgeValue = global.getProperty("__fbBatchedBridge"); - // So here, if __fbBatchedBridge doesn't exist, then we know no native calls - // have happened, and we were able to determine this without forcing - // BatchedBridge to be loaded as a side effect. - if (!batchedBridgeValue.isUndefined()) { - // If calls were made, we bind to the JS bridge methods, and use them to - // get the pending queue of native calls. - bindBridge(); - callNativeModules(m_flushedQueueJS->callAsFunction({})); - } else if (m_delegate) { - // If we have a delegate, we need to call it; we pass a null list to - // callNativeModules, since we know there are no native calls, without - // calling into JS again. If no calls were made and there's no delegate, - // nothing happens, which is correct. - callNativeModules(Value::makeNull(m_context)); - } -} - -void JSCExecutor::callFunction( - const std::string& moduleId, - const std::string& methodId, - const folly::dynamic& arguments) { - SystraceSection s("JSCExecutor::callFunction"); - // This weird pattern is because Value is not default constructible. - // The lambda is inlined, so there's no overhead. - auto result = [&] { - JSContextLock lock(m_context); - try { - if (!m_callFunctionReturnResultAndFlushedQueueJS) { - bindBridge(); - } - return m_callFunctionReturnFlushedQueueJS->callAsFunction( - {Value(m_context, String::createExpectingAscii(m_context, moduleId)), - Value(m_context, String::createExpectingAscii(m_context, methodId)), - Value::fromDynamic(m_context, std::move(arguments))}); - } catch (...) { - std::throw_with_nested( - std::runtime_error("Error calling " + moduleId + "." + methodId)); - } - }(); - callNativeModules(std::move(result)); -} - -void JSCExecutor::invokeCallback( - const double callbackId, - const folly::dynamic& arguments) { - SystraceSection s("JSCExecutor::invokeCallback"); - auto result = [&] { - JSContextLock lock(m_context); - try { - if (!m_invokeCallbackAndReturnFlushedQueueJS) { - bindBridge(); - } - return m_invokeCallbackAndReturnFlushedQueueJS->callAsFunction( - {Value::makeNumber(m_context, callbackId), - Value::fromDynamic(m_context, std::move(arguments))}); - } catch (...) { - std::throw_with_nested(std::runtime_error( - folly::to("Error invoking callback ", callbackId))); - } - }(); - callNativeModules(std::move(result)); -} - -void JSCExecutor::setGlobalVariable( - std::string propName, - std::unique_ptr jsonValue) { - try { - SystraceSection s("JSCExecutor::setGlobalVariable", "propName", propName); - auto valueToInject = Value::fromJSON(adoptString(std::move(jsonValue))); - Object::getGlobalObject(m_context).setProperty( - propName.c_str(), valueToInject); - } catch (...) { - std::throw_with_nested( - std::runtime_error("Error setting global variable: " + propName)); - } -} - -std::string JSCExecutor::getDescription() { -#if defined(__APPLE__) - if (isCustomJSCPtr(m_context)) { - return "Custom JSC"; - } else { - return "System JSC"; - } -#else - return "JSC"; -#endif -} - -String JSCExecutor::adoptString(std::unique_ptr script) { -#if defined(WITH_FBJSCEXTENSIONS) - const JSBigString* string = script.release(); - auto jsString = JSStringCreateAdoptingExternal( - string->c_str(), string->size(), (void*)string, [](void* s) { - delete static_cast(s); - }); - return String::adopt(m_context, jsString); -#else - return script->isAscii() - ? String::createExpectingAscii(m_context, script->c_str(), script->size()) - : String(m_context, script->c_str()); -#endif -} - -void* JSCExecutor::getJavaScriptContext() { - return m_context; -} - -bool JSCExecutor::isInspectable() { - return canUseInspector(m_context); -} - -void JSCExecutor::handleMemoryPressure(int pressureLevel) { -#ifdef WITH_JSC_MEMORY_PRESSURE - JSHandleMemoryPressure( - this, m_context, static_cast(pressureLevel)); -#endif -} - -void JSCExecutor::flushQueueImmediate(Value&& queue) { - auto queueStr = queue.toJSONString(); - m_delegate->callNativeModules(*this, folly::parseJson(queueStr), false); -} - -void JSCExecutor::loadModule(uint32_t bundleId, uint32_t moduleId) { - auto module = m_bundleRegistry->getModule(bundleId, moduleId); - auto sourceUrl = String::createExpectingAscii(m_context, module.name); - auto source = adoptString( - std::unique_ptr(new JSBigStdString(module.code))); - evaluateScript(m_context, source, sourceUrl); -} - -// Native JS hooks -template -void JSCExecutor::installNativeHook(const char* name) { - installGlobalFunction(m_context, name, exceptionWrapMethod()); -} - -JSValueRef JSCExecutor::getNativeModule( - JSObjectRef object, - JSStringRef propertyName) { - if (JSC_JSStringIsEqualToUTF8CString(m_context, propertyName, "name")) { - return Value(m_context, String(m_context, "NativeModules")); - } - - return m_nativeModules.getModule(m_context, propertyName); -} - -JSValueRef JSCExecutor::nativeRequire( - size_t count, - const JSValueRef arguments[]) { - if (count > 2 || count == 0) { - throw std::invalid_argument("Got wrong number of args"); - } - - uint32_t moduleId = - folly::to(Value(m_context, arguments[0]).getNumberOrThrow()); - uint32_t bundleId = count == 2 - ? folly::to(Value(m_context, arguments[1]).getNumberOrThrow()) - : 0; - - ReactMarker::logMarker(ReactMarker::NATIVE_REQUIRE_START); - loadModule(bundleId, moduleId); - ReactMarker::logMarker(ReactMarker::NATIVE_REQUIRE_STOP); - return Value::makeUndefined(m_context); -} - -JSValueRef JSCExecutor::nativeFlushQueueImmediate( - size_t argumentCount, - const JSValueRef arguments[]) { - if (argumentCount != 1) { - throw std::invalid_argument("Got wrong number of args"); - } - - flushQueueImmediate(Value(m_context, arguments[0])); - return Value::makeUndefined(m_context); -} - -JSValueRef JSCExecutor::nativeCallSyncHook( - size_t argumentCount, - const JSValueRef arguments[]) { - if (argumentCount != 3) { - throw std::invalid_argument("Got wrong number of args"); - } - - unsigned int moduleId = Value(m_context, arguments[0]).asUnsignedInteger(); - unsigned int methodId = Value(m_context, arguments[1]).asUnsignedInteger(); - folly::dynamic args = - folly::parseJson(Value(m_context, arguments[2]).toJSONString()); - - if (!args.isArray()) { - throw std::invalid_argument(folly::to( - "method parameters should be array, but are ", args.typeName())); - } - - MethodCallResult result = m_delegate->callSerializableNativeHook( - *this, moduleId, methodId, std::move(args)); - if (!result.hasValue()) { - return Value::makeUndefined(m_context); - } - return Value::fromDynamic(m_context, result.value()); -} - -} // namespace react -} // namespace facebook diff --git a/ReactCommon/cxxreact/JSCExecutor.h b/ReactCommon/cxxreact/JSCExecutor.h deleted file mode 100644 index 5c75fcce87d2c9..00000000000000 --- a/ReactCommon/cxxreact/JSCExecutor.h +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright (c) Facebook, Inc. and its 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 -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef RN_EXPORT -#define RN_EXPORT __attribute__((visibility("default"))) -#endif - -namespace facebook { -namespace react { - -class MessageQueueThread; -class RAMBundleRegistry; - -class RN_EXPORT JSCExecutorFactory : public JSExecutorFactory { -public: - JSCExecutorFactory(const folly::dynamic& jscConfig) : - m_jscConfig(jscConfig) {} - std::unique_ptr createJSExecutor( - std::shared_ptr delegate, - std::shared_ptr jsQueue) override; -private: - std::string m_cacheDir; - folly::dynamic m_jscConfig; -}; - -template -struct JSCValueEncoder { - // If you get a build error here, it means the compiler can't see the template instantation of toJSCValue - // applicable to your type. - static const Value toJSCValue(JSGlobalContextRef ctx, T&& value); -}; - -template<> -struct JSCValueEncoder { - static const Value toJSCValue(JSGlobalContextRef ctx, const folly::dynamic &&value) { - return Value::fromDynamic(ctx, value); - } -}; - -class RN_EXPORT JSCExecutor : public JSExecutor, public PrivateDataBase { -public: - /** - * Must be invoked from thread this Executor will run on. - */ - explicit JSCExecutor(std::shared_ptr delegate, - std::shared_ptr messageQueueThread, - const folly::dynamic& jscConfig) throw(JSException); - ~JSCExecutor() override; - - virtual void loadApplicationScript( - std::unique_ptr script, - std::string sourceURL) override; - - virtual void setBundleRegistry(std::unique_ptr bundleRegistry) override; - virtual void registerBundle(uint32_t bundleId, const std::string& bundlePath) override; - - virtual void callFunction( - const std::string& moduleId, - const std::string& methodId, - const folly::dynamic& arguments) override; - - virtual void invokeCallback( - const double callbackId, - const folly::dynamic& arguments) override; - - virtual void setGlobalVariable( - std::string propName, - std::unique_ptr jsonValue) override; - - virtual std::string getDescription() override; - - virtual void* getJavaScriptContext() override; - - virtual bool isInspectable() override; - - virtual void handleMemoryPressure(int pressureLevel) override; - - virtual void destroy() override; - - void setContextName(const std::string& name); - -private: - JSGlobalContextRef m_context; - std::shared_ptr m_delegate; - std::shared_ptr m_isDestroyed = std::shared_ptr(new bool(false)); - std::shared_ptr m_messageQueueThread; - std::unique_ptr m_bundleRegistry; - JSCNativeModules m_nativeModules; - folly::dynamic m_jscConfig; - std::once_flag m_bindFlag; - - folly::Optional m_invokeCallbackAndReturnFlushedQueueJS; - folly::Optional m_callFunctionReturnFlushedQueueJS; - folly::Optional m_flushedQueueJS; - folly::Optional m_callFunctionReturnResultAndFlushedQueueJS; - - void initOnJSVMThread() throw(JSException); - static bool isNetworkInspected(const std::string &owner, const std::string &app, const std::string &device); - void terminateOnJSVMThread(); - void bindBridge() throw(JSException); - void callNativeModules(Value&&); - void flush(); - void flushQueueImmediate(Value&&); - void loadModule(uint32_t bundleId, uint32_t moduleId); - - String adoptString(std::unique_ptr); - - template - void installNativeHook(const char* name); - - JSValueRef getNativeModule(JSObjectRef object, JSStringRef propertyName); - - JSValueRef nativeRequire( - size_t argumentCount, - const JSValueRef arguments[]); - JSValueRef nativeFlushQueueImmediate( - size_t argumentCount, - const JSValueRef arguments[]); - JSValueRef nativeCallSyncHook( - size_t argumentCount, - const JSValueRef arguments[]); -}; - -} } diff --git a/ReactCommon/cxxreact/JSCLegacyTracing.cpp b/ReactCommon/cxxreact/JSCLegacyTracing.cpp deleted file mode 100644 index bf91c333de5ca6..00000000000000 --- a/ReactCommon/cxxreact/JSCLegacyTracing.cpp +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) Facebook, Inc. and its affiliates. - -// This source code is licensed under the MIT license found in the -// LICENSE file in the root directory of this source tree. - -#include "JSCLegacyTracing.h" - -#if defined(WITH_JSC_EXTRA_TRACING) - -#include -#include -#include -#include - -static const char *ENABLED_FBSYSTRACE_PROFILE_NAME = "__fbsystrace__"; - -using namespace facebook::react; - -static int64_t int64FromJSValue(JSContextRef ctx, JSValueRef value, JSValueRef* exception) { - return static_cast(JSC_JSValueToNumber(ctx, value, exception)); -} - -static JSValueRef nativeTraceBeginLegacy( - JSContextRef ctx, - JSObjectRef function, - JSObjectRef thisObject, - size_t argumentCount, - const JSValueRef arguments[], - JSValueRef* exception) { - if (FBSYSTRACE_LIKELY(argumentCount >= 1)) { - uint64_t tag = int64FromJSValue(ctx, arguments[0], exception); - if (!fbsystrace_is_tracing(tag)) { - return Value::makeUndefined(ctx); - } - } - - JSStartProfiling(ctx, String(ctx, ENABLED_FBSYSTRACE_PROFILE_NAME), true); - - return Value::makeUndefined(ctx); -} - -static JSValueRef nativeTraceEndLegacy( - JSContextRef ctx, - JSObjectRef function, - JSObjectRef thisObject, - size_t argumentCount, - const JSValueRef arguments[], - JSValueRef* exception) { - if (FBSYSTRACE_LIKELY(argumentCount >= 1)) { - uint64_t tag = int64FromJSValue(ctx, arguments[0], exception); - if (!fbsystrace_is_tracing(tag)) { - return Value::makeUndefined(ctx); - } - } - - JSEndProfiling(ctx, String(ctx, ENABLED_FBSYSTRACE_PROFILE_NAME)); - - return Value::makeUndefined(ctx); -} - -#endif - -namespace facebook { -namespace react { - -void addNativeTracingLegacyHooks(JSGlobalContextRef ctx) { -#if defined(WITH_JSC_EXTRA_TRACING) - installGlobalFunction(ctx, "nativeTraceBeginLegacy", nativeTraceBeginLegacy); - installGlobalFunction(ctx, "nativeTraceEndLegacy", nativeTraceEndLegacy); -#endif -} - -} } diff --git a/ReactCommon/cxxreact/JSCLegacyTracing.h b/ReactCommon/cxxreact/JSCLegacyTracing.h deleted file mode 100644 index fa57d584494a07..00000000000000 --- a/ReactCommon/cxxreact/JSCLegacyTracing.h +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Facebook, Inc. and its 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 - -namespace facebook { -namespace react { - -void addNativeTracingLegacyHooks(JSGlobalContextRef ctx); - -} } diff --git a/ReactCommon/cxxreact/JSCMemory.cpp b/ReactCommon/cxxreact/JSCMemory.cpp deleted file mode 100644 index 1b1e252dee7f66..00000000000000 --- a/ReactCommon/cxxreact/JSCMemory.cpp +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) Facebook, Inc. and its affiliates. - -// This source code is licensed under the MIT license found in the -// LICENSE file in the root directory of this source tree. - -#include "JSCMemory.h" - -#ifdef WITH_FB_MEMORY_PROFILING - -#include -#include -#include -#include -#include - -using namespace facebook::react; - -static JSValueRef nativeCaptureHeap( - JSContextRef ctx, - JSObjectRef function, - JSObjectRef thisObject, - size_t argumentCount, - const JSValueRef arguments[], - JSValueRef* exception) { - if (argumentCount < 1) { - if (exception) { - *exception = Value::makeError( - ctx, - "nativeCaptureHeap requires the path to save the capture"); - } - return Value::makeUndefined(ctx); - } - - auto outputFilename = Value(ctx, arguments[0]).toString(); - JSCaptureHeap(ctx, outputFilename.str().c_str(), exception); - return Value::makeUndefined(ctx); -} - -#endif // WITH_FB_MEMORY_PROFILING - -namespace facebook { -namespace react { - -void addJSCMemoryHooks(JSGlobalContextRef ctx) { -#ifdef WITH_FB_MEMORY_PROFILING - installGlobalFunction(ctx, "nativeCaptureHeap", nativeCaptureHeap); -#endif // WITH_FB_MEMORY_PROFILING -} - -} } diff --git a/ReactCommon/cxxreact/JSCMemory.h b/ReactCommon/cxxreact/JSCMemory.h deleted file mode 100644 index 110fe917751562..00000000000000 --- a/ReactCommon/cxxreact/JSCMemory.h +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Facebook, Inc. and its 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 - -namespace facebook { -namespace react { - -void addJSCMemoryHooks(JSGlobalContextRef ctx); - -} } diff --git a/ReactCommon/cxxreact/JSCNativeModules.cpp b/ReactCommon/cxxreact/JSCNativeModules.cpp deleted file mode 100644 index 4ad35dbe2d6b25..00000000000000 --- a/ReactCommon/cxxreact/JSCNativeModules.cpp +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) Facebook, Inc. and its affiliates. - -// This source code is licensed under the MIT license found in the -// LICENSE file in the root directory of this source tree. - -#include "JSCNativeModules.h" - -#include - -#include "ModuleRegistry.h" -#include "ReactMarker.h" - -namespace facebook { -namespace react { - -JSCNativeModules::JSCNativeModules(std::shared_ptr moduleRegistry) : - m_moduleRegistry(std::move(moduleRegistry)) {} - -JSValueRef JSCNativeModules::getModule(JSContextRef context, JSStringRef jsName) { - if (!m_moduleRegistry) { - return nullptr; - } - - std::string moduleName = String::ref(context, jsName).str(); - - const auto it = m_objects.find(moduleName); - if (it != m_objects.end()) { - return static_cast(it->second); - } - - auto module = createModule(moduleName, context); - if (!module.hasValue()) { - // Allow lookup to continue in the objects own properties, which allows for overrides of NativeModules - return nullptr; - } - - // Protect since we'll be holding on to this value, even though JS may not - module->makeProtected(); - - auto result = m_objects.emplace(std::move(moduleName), std::move(*module)).first; - return static_cast(result->second); -} - -void JSCNativeModules::reset() { - m_genNativeModuleJS = nullptr; - m_objects.clear(); -} - -folly::Optional JSCNativeModules::createModule(const std::string& name, JSContextRef context) { - ReactMarker::logTaggedMarker(ReactMarker::NATIVE_MODULE_SETUP_START, name.c_str()); - - if (!m_genNativeModuleJS) { - auto global = Object::getGlobalObject(context); - m_genNativeModuleJS = global.getProperty("__fbGenNativeModule").asObject(); - m_genNativeModuleJS->makeProtected(); - } - - auto result = m_moduleRegistry->getConfig(name); - if (!result.hasValue()) { - return nullptr; - } - - Value moduleInfo = m_genNativeModuleJS->callAsFunction({ - Value::fromDynamic(context, result->config), - Value::makeNumber(context, result->index) - }); - CHECK(!moduleInfo.isNull()) << "Module returned from genNativeModule is null"; - - folly::Optional module(moduleInfo.asObject().getProperty("module").asObject()); - - ReactMarker::logTaggedMarker(ReactMarker::NATIVE_MODULE_SETUP_STOP, name.c_str()); - - return module; -} - -} } diff --git a/ReactCommon/cxxreact/JSCNativeModules.h b/ReactCommon/cxxreact/JSCNativeModules.h deleted file mode 100644 index 6f61263518cf49..00000000000000 --- a/ReactCommon/cxxreact/JSCNativeModules.h +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) Facebook, Inc. and its 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 -#include - -#include -#include - -namespace facebook { -namespace react { - -class ModuleRegistry; - -/** - * Holds and creates JS representations of the modules in ModuleRegistry - */ -class JSCNativeModules { - -public: - explicit JSCNativeModules(std::shared_ptr moduleRegistry); - JSValueRef getModule(JSContextRef context, JSStringRef name); - void reset(); - -private: - folly::Optional m_genNativeModuleJS; - std::shared_ptr m_moduleRegistry; - std::unordered_map m_objects; - - folly::Optional createModule(const std::string& name, JSContextRef context); -}; - -} -} diff --git a/ReactCommon/cxxreact/JSCPerfStats.cpp b/ReactCommon/cxxreact/JSCPerfStats.cpp deleted file mode 100644 index 95a71e22b40f65..00000000000000 --- a/ReactCommon/cxxreact/JSCPerfStats.cpp +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright (c) Facebook, Inc. and its affiliates. - -// This source code is licensed under the MIT license found in the -// LICENSE file in the root directory of this source tree. - -#include "JSCPerfStats.h" - -#ifdef JSC_HAS_PERF_STATS_API - -#include - -#include -#include - -#include -#include -#include - -using namespace facebook::react; - -static uint64_t toMillis(struct timeval tv) { - return tv.tv_sec * 1000ULL + tv.tv_usec / 1000ULL; -} - -static JSValueRef nativeGetProcessPerfStats( - JSContextRef ctx, - JSObjectRef function, - JSObjectRef thisObject, - size_t argumentCount, - const JSValueRef arguments[], - JSValueRef* exception) { - struct rusage usage{}; - if (getrusage(RUSAGE_SELF, &usage) != 0) { - return Value::makeUndefined(ctx); - } - - auto result = Object::create(ctx); - uint64_t cpu_time_ms = toMillis(usage.ru_utime) + toMillis(usage.ru_stime); - result.setProperty("major_faults", Value::makeNumber(ctx, usage.ru_majflt)); - result.setProperty("minor_faults", Value::makeNumber(ctx, usage.ru_minflt)); - result.setProperty("cpu_time_ms", Value::makeNumber(ctx, cpu_time_ms)); - result.setProperty("input_blocks", Value::makeNumber(ctx, usage.ru_inblock)); - result.setProperty("output_blocks", Value::makeNumber(ctx, usage.ru_oublock)); - return static_cast(result); -} - -static JSValueRef nativeGetHeapStats( - JSContextRef ctx, - JSObjectRef function, - JSObjectRef thisObject, - size_t argumentCount, - const JSValueRef arguments[], - JSValueRef* exception) { - JSHeapStats heapStats = {0}; - JSGetHeapStats(ctx, &heapStats); - - auto result = Object::create(ctx); - result.setProperty("size", Value::makeNumber(ctx, heapStats.size)); - result.setProperty("extra_size", Value::makeNumber(ctx, heapStats.extraSize)); - result.setProperty("capacity", Value::makeNumber(ctx, heapStats.capacity)); - result.setProperty("object_count", Value::makeNumber(ctx, heapStats.objectCount)); - result.setProperty("object_size", Value::makeNumber(ctx, heapStats.objectSizeAfterLastCollect)); - result.setProperty("object_capacity", Value::makeNumber(ctx, heapStats.objectCapacityAfterLastCollect)); - result.setProperty("block_size", Value::makeNumber(ctx, heapStats.blockSize)); - result.setProperty("malloc_size", Value::makeNumber(ctx, heapStats.mallocSize)); - return static_cast(result); -} - -static JSValueRef nativeGetGCStats( - JSContextRef ctx, - JSObjectRef function, - JSObjectRef thisObject, - size_t argumentCount, - const JSValueRef arguments[], - JSValueRef* exception) { - JSGCStats gcStats = {0}; - JSGetGCStats(ctx, &gcStats); - - auto result = Object::create(ctx); - result.setProperty("last_full_gc_length", Value::makeNumber(ctx, gcStats.lastFullGCLength)); - result.setProperty("last_eden_gc_length", Value::makeNumber(ctx, gcStats.lastEdenGCLength)); - return static_cast(result); -} - -#endif - -namespace facebook { -namespace react { - -void addJSCPerfStatsHooks(JSGlobalContextRef ctx) { -#ifdef JSC_HAS_PERF_STATS_API - installGlobalFunction(ctx, "nativeGetProcessPerfStats", nativeGetProcessPerfStats); - installGlobalFunction(ctx, "nativeGetHeapStats", nativeGetHeapStats); - installGlobalFunction(ctx, "nativeGetGCStats", nativeGetGCStats); -#endif -} - -} } diff --git a/ReactCommon/cxxreact/JSCPerfStats.h b/ReactCommon/cxxreact/JSCPerfStats.h deleted file mode 100644 index d4a682eb3f6bbd..00000000000000 --- a/ReactCommon/cxxreact/JSCPerfStats.h +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Facebook, Inc. and its 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 - -namespace facebook { -namespace react { - -void addJSCPerfStatsHooks(JSGlobalContextRef ctx); - -} } diff --git a/ReactCommon/cxxreact/JSCSamplingProfiler.cpp b/ReactCommon/cxxreact/JSCSamplingProfiler.cpp deleted file mode 100644 index 3fb5d74a462b07..00000000000000 --- a/ReactCommon/cxxreact/JSCSamplingProfiler.cpp +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) Facebook, Inc. and its affiliates. - -// This source code is licensed under the MIT license found in the -// LICENSE file in the root directory of this source tree. - -#include "JSCSamplingProfiler.h" - -#include - -static JSValueRef pokeSamplingProfiler( - JSContextRef ctx, - JSObjectRef function, - JSObjectRef thisObject, - size_t argumentCount, - const JSValueRef arguments[], - JSValueRef* exception) { - return JSC_JSPokeSamplingProfiler(ctx); -} - -namespace facebook { -namespace react { - -void initSamplingProfilerOnMainJSCThread(JSGlobalContextRef ctx) { - JSC_JSStartSamplingProfilingOnMainJSCThread(ctx); - - // Allow the profiler to be poked from JS as well - // (see SamplingProfiler.js for an example of how it could be used with the JSCSamplingProfiler module). - installGlobalFunction(ctx, "pokeSamplingProfiler", pokeSamplingProfiler); -} - -} } diff --git a/ReactCommon/cxxreact/JSCSamplingProfiler.h b/ReactCommon/cxxreact/JSCSamplingProfiler.h deleted file mode 100644 index 78b2267b555616..00000000000000 --- a/ReactCommon/cxxreact/JSCSamplingProfiler.h +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Facebook, Inc. and its 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 - -namespace facebook { -namespace react { - -void initSamplingProfilerOnMainJSCThread(JSGlobalContextRef ctx); - -} } diff --git a/ReactCommon/cxxreact/JSCTracing.cpp b/ReactCommon/cxxreact/JSCTracing.cpp deleted file mode 100644 index 0c08705b922158..00000000000000 --- a/ReactCommon/cxxreact/JSCTracing.cpp +++ /dev/null @@ -1,323 +0,0 @@ -// Copyright (c) Facebook, Inc. and its affiliates. - -// This source code is licensed under the MIT license found in the -// LICENSE file in the root directory of this source tree. - -#include "JSCTracing.h" - -#if defined(WITH_FBSYSTRACE) && (defined(WITH_JSC_EXTRA_TRACING) || DEBUG) -#define USE_JSCTRACING 1 -#else -#define USE_JSCTRACING 0 -#endif - -#if USE_JSCTRACING - -#include -#include -#include -#include - -#include -#include -#include - -using std::min; -using namespace facebook::react; - -static int64_t int64FromJSValue(JSContextRef ctx, JSValueRef value, JSValueRef* exception) { - return static_cast(JSC_JSValueToNumber(ctx, value, exception)); -} - -static size_t copyTruncatedAsciiChars( - char* buf, - size_t bufLen, - JSContextRef ctx, - JSValueRef value, - size_t maxLen) { - JSStringRef jsString = JSC_JSValueToStringCopy(ctx, value, NULL); - size_t stringLen = JSC_JSStringGetLength(ctx, jsString); - // Unlike the Java version, we truncate from the end of the string, - // rather than the beginning. - size_t toWrite = min(stringLen, min(bufLen, maxLen)); - - const char *startBuf = buf; - const JSChar* chars = JSC_JSStringGetCharactersPtr(ctx, jsString); - while (toWrite-- > 0) { - *(buf++) = (char)*(chars++); - } - - JSC_JSStringRelease(ctx, jsString); - - // Return the number of bytes written - return buf - startBuf; -} - -static size_t copyArgsToBuffer( - char* buf, - size_t bufLen, - size_t pos, - JSContextRef ctx, - size_t argumentCount, - const JSValueRef arguments[]) { - char separator = '|'; - for ( - size_t idx = 0; - idx + 1 < argumentCount; // Make sure key and value are present. - idx += 2) { - JSValueRef key = arguments[idx]; - JSValueRef value = arguments[idx+1]; - - buf[pos++] = separator; - separator = ';'; - if (FBSYSTRACE_UNLIKELY(pos >= bufLen)) { break; } - pos += copyTruncatedAsciiChars( - buf + pos, bufLen - pos, ctx, key, FBSYSTRACE_MAX_MESSAGE_LENGTH); - if (FBSYSTRACE_UNLIKELY(pos >= bufLen)) { break; } - buf[pos++] = '='; - if (FBSYSTRACE_UNLIKELY(pos >= bufLen)) { break; } - pos += copyTruncatedAsciiChars( - buf + pos, bufLen - pos, ctx, value, FBSYSTRACE_MAX_MESSAGE_LENGTH); - if (FBSYSTRACE_UNLIKELY(pos >= bufLen)) { break; } - } - return pos; -} - -static JSValueRef nativeTraceBeginSection( - JSContextRef ctx, - JSObjectRef function, - JSObjectRef thisObject, - size_t argumentCount, - const JSValueRef arguments[], - JSValueRef* exception) { - if (FBSYSTRACE_UNLIKELY(argumentCount < 2)) { - if (exception) { - *exception = Value::makeError( - ctx, - "nativeTraceBeginSection: requires at least 2 arguments"); - } - return Value::makeUndefined(ctx); - } - - uint64_t tag = int64FromJSValue(ctx, arguments[0], exception); - if (!fbsystrace_is_tracing(tag)) { - return Value::makeUndefined(ctx); - } - - char buf[FBSYSTRACE_MAX_MESSAGE_LENGTH]; - size_t pos = 0; - - pos += snprintf(buf + pos, sizeof(buf) - pos, "B|%d|", getpid()); - // Skip the overflow check here because the int will be small. - pos += copyTruncatedAsciiChars(buf + pos, sizeof(buf) - pos, ctx, arguments[1], FBSYSTRACE_MAX_SECTION_NAME_LENGTH); - // Skip the overflow check here because the section name will be small-ish. - - pos = copyArgsToBuffer(buf, sizeof(buf), pos, ctx, argumentCount - 2, arguments + 2); - if (FBSYSTRACE_UNLIKELY(pos >= sizeof(buf))) { - goto flush; - } - -flush: - fbsystrace_trace_raw(buf, min(pos, sizeof(buf)-1)); - - return Value::makeUndefined(ctx); -} - -static JSValueRef nativeTraceEndSection( - JSContextRef ctx, - JSObjectRef function, - JSObjectRef thisObject, - size_t argumentCount, - const JSValueRef arguments[], - JSValueRef* exception) { - if (FBSYSTRACE_UNLIKELY(argumentCount < 1)) { - if (exception) { - *exception = Value::makeError( - ctx, - "nativeTraceEndSection: requires at least 1 argument"); - } - return Value::makeUndefined(ctx); - } - - uint64_t tag = int64FromJSValue(ctx, arguments[0], exception); - if (!fbsystrace_is_tracing(tag)) { - return Value::makeUndefined(ctx); - } - - if (FBSYSTRACE_LIKELY(argumentCount == 1)) { - fbsystrace_end_section(tag); - } else { - char buf[FBSYSTRACE_MAX_MESSAGE_LENGTH]; - size_t pos = 0; - - buf[pos++] = 'E'; - buf[pos++] = '|'; - buf[pos++] = '|'; - pos = copyArgsToBuffer(buf, sizeof(buf), pos, ctx, argumentCount - 1, arguments + 1); - if (FBSYSTRACE_UNLIKELY(pos >= sizeof(buf))) { - goto flush; - } - -flush: - fbsystrace_trace_raw(buf, min(pos, sizeof(buf)-1)); - } - - return Value::makeUndefined(ctx); -} - -static JSValueRef beginOrEndAsync( - bool isEnd, - bool isFlow, - JSContextRef ctx, - size_t argumentCount, - const JSValueRef arguments[], - JSValueRef* exception) { - if (FBSYSTRACE_UNLIKELY(argumentCount < 3)) { - if (exception) { - *exception = Value::makeError( - ctx, - "beginOrEndAsync: requires at least 3 arguments"); - } - return Value::makeUndefined(ctx); - } - - uint64_t tag = int64FromJSValue(ctx, arguments[0], exception); - if (!fbsystrace_is_tracing(tag)) { - return Value::makeUndefined(ctx); - } - - char buf[FBSYSTRACE_MAX_MESSAGE_LENGTH]; - size_t pos = 0; - - // This uses an if-then-else instruction in ARMv7, which should be cheaper - // than a full branch. - buf[pos++] = ((isFlow) ? (isEnd ? 'f' : 's') : (isEnd ? 'F' : 'S')); - pos += snprintf(buf + pos, sizeof(buf) - pos, "|%d|", getpid()); - // Skip the overflow check here because the int will be small. - pos += copyTruncatedAsciiChars(buf + pos, sizeof(buf) - pos, ctx, arguments[1], FBSYSTRACE_MAX_SECTION_NAME_LENGTH); - // Skip the overflow check here because the section name will be small-ish. - - // I tried some trickery to avoid a branch here, but gcc did not cooperate. - // We could consider changing the implementation to be lest branchy in the - // future. - // This is not required for flow use an or to avoid introducing another branch - if (!(isEnd | isFlow)) { - buf[pos++] = '<'; - buf[pos++] = '0'; - buf[pos++] = '>'; - } - buf[pos++] = '|'; - - // Append the cookie. It should be an integer, but copyTruncatedAsciiChars - // will automatically convert it to a string. We might be able to get more - // performance by just getting the number and doing to string - // conversion ourselves. We truncate to FBSYSTRACE_MAX_SECTION_NAME_LENGTH - // just to make sure we can avoid the overflow check even if the caller - // passes in something bad. - pos += copyTruncatedAsciiChars(buf + pos, sizeof(buf) - pos, ctx, arguments[2], FBSYSTRACE_MAX_SECTION_NAME_LENGTH); - - pos = copyArgsToBuffer(buf, sizeof(buf), pos, ctx, argumentCount - 3, arguments + 3); - if (FBSYSTRACE_UNLIKELY(pos >= sizeof(buf))) { - goto flush; - } - -flush: - fbsystrace_trace_raw(buf, min(pos, sizeof(buf)-1)); - - return Value::makeUndefined(ctx); -} - -static JSValueRef nativeTraceBeginAsyncSection( - JSContextRef ctx, - JSObjectRef function, - JSObjectRef thisObject, - size_t argumentCount, - const JSValueRef arguments[], - JSValueRef* exception) { - return beginOrEndAsync(false /* isEnd */, false /* isFlow */, - ctx, argumentCount, arguments, exception); -} - -static JSValueRef nativeTraceEndAsyncSection( - JSContextRef ctx, - JSObjectRef function, - JSObjectRef thisObject, - size_t argumentCount, - const JSValueRef arguments[], - JSValueRef* exception) { - return beginOrEndAsync(true /* isEnd */, false /* isFlow */, - ctx, argumentCount, arguments, exception); -} - -static JSValueRef nativeTraceBeginAsyncFlow( - JSContextRef ctx, - JSObjectRef function, - JSObjectRef thisObject, - size_t argumentCount, - const JSValueRef arguments[], - JSValueRef* exception) { - return beginOrEndAsync(false /* isEnd */, true /* isFlow */, - ctx, argumentCount, arguments, exception); -} - -static JSValueRef nativeTraceEndAsyncFlow( - JSContextRef ctx, - JSObjectRef function, - JSObjectRef thisObject, - size_t argumentCount, - const JSValueRef arguments[], - JSValueRef* exception) { - return beginOrEndAsync(true /* isEnd */, true /* isFlow */, - ctx, argumentCount, arguments, exception); -} - -static JSValueRef nativeTraceCounter( - JSContextRef ctx, - JSObjectRef function, - JSObjectRef thisObject, - size_t argumentCount, - const JSValueRef arguments[], - JSValueRef* exception) { - if (FBSYSTRACE_UNLIKELY(argumentCount < 3)) { - if (exception) { - *exception = Value::makeError( - ctx, - "nativeTraceCounter: requires at least 3 arguments"); - } - return Value::makeUndefined(ctx); - } - - uint64_t tag = int64FromJSValue(ctx, arguments[0], exception); - if (!fbsystrace_is_tracing(tag)) { - return Value::makeUndefined(ctx); - } - - char buf[FBSYSTRACE_MAX_MESSAGE_LENGTH]; - size_t len = copyTruncatedAsciiChars(buf, sizeof(buf), ctx, - arguments[1], FBSYSTRACE_MAX_SECTION_NAME_LENGTH); - buf[min(len,(FBSYSTRACE_MAX_MESSAGE_LENGTH-1))] = 0; - int64_t value = int64FromJSValue(ctx, arguments[2], exception); - - fbsystrace_counter(tag, buf, value); - - return Value::makeUndefined(ctx); -} - -#endif - -namespace facebook { -namespace react { - -void addNativeTracingHooks(JSGlobalContextRef ctx) { -#if USE_JSCTRACING - installGlobalFunction(ctx, "nativeTraceBeginSection", nativeTraceBeginSection); - installGlobalFunction(ctx, "nativeTraceEndSection", nativeTraceEndSection); - installGlobalFunction(ctx, "nativeTraceBeginAsyncSection", nativeTraceBeginAsyncSection); - installGlobalFunction(ctx, "nativeTraceEndAsyncSection", nativeTraceEndAsyncSection); - installGlobalFunction(ctx, "nativeTraceBeginAsyncFlow", nativeTraceBeginAsyncFlow); - installGlobalFunction(ctx, "nativeTraceEndAsyncFlow", nativeTraceEndAsyncFlow); - installGlobalFunction(ctx, "nativeTraceCounter", nativeTraceCounter); -#endif -} - -} } diff --git a/ReactCommon/cxxreact/JSCTracing.h b/ReactCommon/cxxreact/JSCTracing.h deleted file mode 100644 index c68c3556dddbd9..00000000000000 --- a/ReactCommon/cxxreact/JSCTracing.h +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Facebook, Inc. and its 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 - -namespace facebook { -namespace react { - -void addNativeTracingHooks(JSGlobalContextRef ctx); - -} } diff --git a/ReactCommon/cxxreact/JSCUtils.cpp b/ReactCommon/cxxreact/JSCUtils.cpp deleted file mode 100644 index 69ea803b7479e1..00000000000000 --- a/ReactCommon/cxxreact/JSCUtils.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Facebook, Inc. and its affiliates. - -// This source code is licensed under the MIT license found in the -// LICENSE file in the root directory of this source tree. - -#include "JSCUtils.h" - -#include "RAMBundleRegistry.h" - -#include - -namespace facebook { -namespace react { - -String jsStringFromBigString(JSContextRef ctx, const JSBigString& bigstr) { - if (bigstr.isAscii()) { - return String::createExpectingAscii(ctx, bigstr.c_str(), bigstr.size()); - } else { - return String(ctx, bigstr.c_str()); - } -} - -} -} diff --git a/ReactCommon/cxxreact/JSCUtils.h b/ReactCommon/cxxreact/JSCUtils.h deleted file mode 100644 index 55300044515e7b..00000000000000 --- a/ReactCommon/cxxreact/JSCUtils.h +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) Facebook, Inc. and its 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 -#include -#include - -namespace facebook { -namespace react { - -String jsStringFromBigString(JSContextRef ctx, const JSBigString& bigstr); - -} -} diff --git a/ReactCommon/cxxreact/Platform.cpp b/ReactCommon/cxxreact/Platform.cpp deleted file mode 100644 index a9a096fa9c6c06..00000000000000 --- a/ReactCommon/cxxreact/Platform.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) Facebook, Inc. and its affiliates. - -// This source code is licensed under the MIT license found in the -// LICENSE file in the root directory of this source tree. - -#include "Platform.h" - -namespace facebook { -namespace react { - -#if __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wglobal-constructors" -#endif - -namespace JSCNativeHooks { - -Hook loggingHook = nullptr; -Hook nowHook = nullptr; -ConfigurationHook installPerfHooks = nullptr; - -} - -#if __clang__ -#pragma clang diagnostic pop -#endif - -} } diff --git a/ReactCommon/cxxreact/Platform.h b/ReactCommon/cxxreact/Platform.h deleted file mode 100644 index bf7182f0bdc1d7..00000000000000 --- a/ReactCommon/cxxreact/Platform.h +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) Facebook, Inc. and its 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 -#include -#include - -#include -#include - -#ifndef RN_EXPORT -#define RN_EXPORT __attribute__((visibility("default"))) -#endif - -namespace facebook { -namespace react { - -namespace JSCNativeHooks { - -using Hook = JSValueRef(*)( - JSContextRef ctx, - JSObjectRef function, - JSObjectRef thisObject, - size_t argumentCount, - const JSValueRef arguments[], - JSValueRef *exception); -extern RN_EXPORT Hook loggingHook; -extern RN_EXPORT Hook nowHook; - -typedef void(*ConfigurationHook)(JSGlobalContextRef); -extern RN_EXPORT ConfigurationHook installPerfHooks; - -} - -} } diff --git a/ReactCommon/cxxreact/tests/jscexecutor.cpp b/ReactCommon/cxxreact/tests/jscexecutor.cpp deleted file mode 100644 index 1988d5796fe742..00000000000000 --- a/ReactCommon/cxxreact/tests/jscexecutor.cpp +++ /dev/null @@ -1,273 +0,0 @@ -// Copyright (c) Facebook, Inc. and its affiliates. - -// This source code is licensed under the MIT license found in the -// LICENSE file in the root directory of this source tree. - -#include -#include -#include -#include - -using namespace facebook; -using namespace facebook::react; - - -// TODO(12340362): Fix these tests. And add checks for sizes. -/* - -namespace { - -std::string capturedMethodCalls; - -struct NullDelegate : ExecutorDelegate { - virtual void registerExecutor(std::unique_ptr executor, - std::shared_ptr queue) { - std::terminate(); - } - - virtual std::unique_ptr unregisterExecutor(JSExecutor& executor) { - std::terminate(); - } - - virtual std::vector moduleNames() { - return std::vector{}; - } - - virtual folly::dynamic getModuleConfig(const std::string& name) { - std::terminate(); - } - virtual void callNativeModules( - JSExecutor& executor, std::string callJSON, bool isEndOfBatch) { - // TODO: capture calljson - std::terminate(); - } - virtual MethodCallResult callSerializableNativeHook( - JSExecutor& executor, unsigned int moduleId, unsigned int methodId, folly::dynamic&& args) { - std::terminate(); - } -}; - -struct FakeMessageQueue : MessageQueueThread { - virtual void runOnQueue(std::function&& runnable) { - // This is wrong, but oh well. - runnable(); - } - - virtual void runOnQueueSync(std::function&& runnable) { - runnable(); - } - - virtual void quitSynchronous() { - std::terminate(); - } -}; - -std::vector executeForMethodCalls( - JSCExecutor& e, - int moduleId, - int methodId, - folly::dynamic args = folly::dynamic::array()) { - e.callFunction(folly::to(moduleId), folly::to(methodId), std::move(args)); - return parseMethodCalls(capturedMethodCalls); -} - -void loadApplicationScript(JSCExecutor& e, std::string jsText) { - e.loadApplicationScript(std::unique_ptr(new JSBigStdString(jsText)), ""); -} - -void setGlobalVariable(JSCExecutor& e, std::string name, std::string jsonObject) { - e.setGlobalVariable(name, std::unique_ptr(new JSBigStdString(jsonObject))); -} - -} - -TEST(JSCExecutor, Initialize) { - JSCExecutor executor(std::make_shared(), std::make_shared(), "", folly::dynamic::object); -} - -TEST(JSCExecutor, Two) { - JSCExecutor exec1(std::make_shared(), std::make_shared(), "", folly::dynamic::object); - JSCExecutor exec2(std::make_shared(), std::make_shared(), "", folly::dynamic::object); -} - -TEST(JSCExecutor, CallFunction) { - auto jsText = "" - "var Bridge = {" - " callFunctionReturnFlushedQueue: function (module, method, args) {" - " return [[module + 1], [method + 1], [args]];" - " }," - "};" - "function require() { return Bridge; }" - ""; - JSCExecutor e(std::make_shared(), std::make_shared(), "", folly::dynamic::object); - loadApplicationScript(e, jsText); - folly::dynamic args = folly::dynamic::array(); - args.push_back(true); - args.push_back(0.4); - args.push_back("hello, world"); - args.push_back(4.0); - auto returnedCalls = executeForMethodCalls(e, 10, 9, args); - ASSERT_EQ(1, returnedCalls.size()); - auto returnedCall = returnedCalls[0]; - EXPECT_EQ(11, returnedCall.moduleId); - EXPECT_EQ(10, returnedCall.methodId); - ASSERT_EQ(4, returnedCall.arguments.size()); - EXPECT_EQ(args[0], returnedCall.arguments[0]); - EXPECT_EQ(args[1], returnedCall.arguments[1]); - EXPECT_EQ(args[2], returnedCall.arguments[2]); - EXPECT_EQ(folly::dynamic(4.0), returnedCall.arguments[3]); -} - -TEST(JSCExecutor, CallFunctionWithMap) { - auto jsText = "" - "var Bridge = {" - " callFunctionReturnFlushedQueue: function (module, method, args) {" - " var s = args[0].foo + args[0].bar + args[0].baz;" - " return [[module], [method], [[s]]];" - " }," - "};" - "function require() { return Bridge; }" - ""; - JSCExecutor e(std::make_shared(), std::make_shared(), "", folly::dynamic::object); - loadApplicationScript(e, jsText); - folly::dynamic args = folly::dynamic::array(); - folly::dynamic map = folly::dynamic::object - ("foo", folly::dynamic("hello")) - ("bar", folly::dynamic(4.0)) - ("baz", folly::dynamic(true)) - ; - args.push_back(std::move(map)); - auto returnedCalls = executeForMethodCalls(e, 10, 9, args); - ASSERT_EQ(1, returnedCalls.size()); - auto returnedCall = returnedCalls[0]; - ASSERT_EQ(1, returnedCall.arguments.size()); - EXPECT_EQ("hello4true", returnedCall.arguments[0].getString()); -} - -TEST(JSCExecutor, CallFunctionReturningMap) { - auto jsText = "" - "var Bridge = {" - " callFunctionReturnFlushedQueue: function (module, method, args) {" - " var s = { foo: 4, bar: true };" - " return [[module], [method], [[s]]];" - " }," - "};" - "function require() { return Bridge; }" - ""; - JSCExecutor e(std::make_shared(), std::make_shared(), "", folly::dynamic::object); - loadApplicationScript(e, jsText); - auto returnedCalls = executeForMethodCalls(e, 10, 9); - ASSERT_EQ(1, returnedCalls.size()); - auto returnedCall = returnedCalls[0]; - ASSERT_EQ(1, returnedCall.arguments.size()); - ASSERT_EQ(folly::dynamic::OBJECT, returnedCall.arguments[0].type()); - auto& returnedMap = returnedCall.arguments[0]; - auto foo = returnedMap.at("foo"); - EXPECT_EQ(folly::dynamic(4.0), foo); - auto bar = returnedMap.at("bar"); - EXPECT_EQ(folly::dynamic(true), bar); -} - -TEST(JSCExecutor, CallFunctionWithArray) { - auto jsText = "" - "var Bridge = {" - " callFunctionReturnFlushedQueue: function (module, method, args) {" - " var s = args[0][0]+ args[0][1] + args[0][2] + args[0].length;" - " return [[module], [method], [[s]]];" - " }," - "};" - "function require() { return Bridge; }" - ""; - JSCExecutor e(std::make_shared(), std::make_shared(), "", folly::dynamic::object); - loadApplicationScript(e, jsText); - std::vector args; - std::vector array { - folly::dynamic("hello"), - folly::dynamic(4.0), - folly::dynamic(true), - }; - args.push_back(std::move(array)); - auto returnedCalls = executeForMethodCalls(e, 10, 9, args); - ASSERT_EQ(1, returnedCalls.size()); - auto returnedCall = returnedCalls[0]; - ASSERT_EQ(1, returnedCall.arguments.size()); - EXPECT_EQ("hello4true3", returnedCall.arguments[0].getString()); -} - -TEST(JSCExecutor, CallFunctionReturningNumberArray) { - auto jsText = "" - "var Bridge = {" - " callFunctionReturnFlushedQueue: function (module, method, args) {" - " var s = [3, 1, 4];" - " return [[module], [method], [[s]]];" - " }," - "};" - "function require() { return Bridge; }" - ""; - JSCExecutor e(std::make_shared(), std::make_shared(), "", folly::dynamic::object); - loadApplicationScript(e, jsText); - auto returnedCalls = executeForMethodCalls(e, 10, 9); - ASSERT_EQ(1, returnedCalls.size()); - auto returnedCall = returnedCalls[0]; - ASSERT_EQ(1, returnedCall.arguments.size()); - ASSERT_EQ(folly::dynamic::ARRAY, returnedCall.arguments[0].type()); - - auto& array = returnedCall.arguments[0]; - EXPECT_EQ(3, array.size()); - EXPECT_EQ(folly::dynamic(3.0), array[0]); - EXPECT_EQ(folly::dynamic(4.0), array[2]); -} - -TEST(JSCExecutor, SetSimpleGlobalVariable) { - auto jsText = "" - "var Bridge = {" - " callFunctionReturnFlushedQueue: function (module, method, args) {" - " return [[module], [method], [[__foo]]];" - " }," - "};" - "function require() { return Bridge; }" - ""; - JSCExecutor e(std::make_shared(), std::make_shared(), "", folly::dynamic::object); - loadApplicationScript(e, jsText); - setGlobalVariable(e, "__foo", "42"); - auto returnedCalls = executeForMethodCalls(e, 10, 9); - ASSERT_EQ(1, returnedCalls.size()); - auto returnedCall = returnedCalls[0]; - ASSERT_EQ(1, returnedCall.arguments.size()); - ASSERT_EQ(42.0, returnedCall.arguments[0].getDouble()); -} - -TEST(JSCExecutor, SetObjectGlobalVariable) { - auto jsText = "" - "var Bridge = {" - " callFunctionReturnFlushedQueue: function (module, method, args) {" - " return [[module], [method], [[__foo]]];" - " }," - "};" - "function require() { return Bridge; }" - ""; - JSCExecutor e(std::make_shared(), std::make_shared(), "", folly::dynamic::object); - loadApplicationScript(e, jsText); - auto jsonObject = "" - "{" - " \"foo\": \"hello\"," - " \"bar\": 4," - " \"baz\": true" - "}" - ""; - setGlobalVariable(e, "__foo", jsonObject); - auto returnedCalls = executeForMethodCalls(e, 10, 9); - ASSERT_EQ(1, returnedCalls.size()); - auto returnedCall = returnedCalls[0]; - ASSERT_EQ(1, returnedCall.arguments.size()); - ASSERT_EQ(folly::dynamic::OBJECT, returnedCall.arguments[0].type()); - auto& returnedMap = returnedCall.arguments[0]; - auto foo = returnedMap.at("foo"); - EXPECT_EQ(folly::dynamic("hello"), foo); - auto bar = returnedMap.at("bar"); - EXPECT_EQ(folly::dynamic(4.0), bar); - auto baz = returnedMap.at("baz"); - EXPECT_EQ(folly::dynamic(true), baz); -} - -*/ diff --git a/ReactCommon/cxxreact/tests/jsclogging.cpp b/ReactCommon/cxxreact/tests/jsclogging.cpp deleted file mode 100644 index 632d3aa2fd14be..00000000000000 --- a/ReactCommon/cxxreact/tests/jsclogging.cpp +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) Facebook, Inc. and its affiliates. - -// This source code is licensed under the MIT license found in the -// LICENSE file in the root directory of this source tree. - -#include -#include - -using namespace facebook; -using namespace facebook::react; - -/* -static const char* expectedLogMessageSubstring = NULL; -static bool hasSeenExpectedLogMessage = false; - -static void mockLogHandler(int pri, const char *tag, const char *msg) { - if (expectedLogMessageSubstring == NULL) { - return; - } - - hasSeenExpectedLogMessage |= (strstr(msg, expectedLogMessageSubstring) != NULL); -} - -class JSCLoggingTest : public testing::Test { - protected: - virtual void SetUp() override { - setLogHandler(&mockLogHandler); - } - - virtual void TearDown() override { - setLogHandler(NULL); - expectedLogMessageSubstring = NULL; - hasSeenExpectedLogMessage = false; - } - -}; - -TEST_F(JSCLoggingTest, LogException) { - auto jsText = "throw new Error('I am a banana!');"; - expectedLogMessageSubstring = "I am a banana!"; - - JSCExecutor e; - e.loadApplicationScript(jsText, ""); - - ASSERT_TRUE(hasSeenExpectedLogMessage); -} -*/ diff --git a/ReactCommon/cxxreact/tests/value.cpp b/ReactCommon/cxxreact/tests/value.cpp deleted file mode 100644 index d001d03bcb2426..00000000000000 --- a/ReactCommon/cxxreact/tests/value.cpp +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright (c) Facebook, Inc. and its affiliates. - -// This source code is licensed under the MIT license found in the -// LICENSE file in the root directory of this source tree. -#include -#include -#include -#include - -#ifdef WITH_FBJSCEXTENSION -#undef ASSERT -#include -#include "OpaqueJSString.h" -#endif - -#include - -using namespace facebook::react; - -#ifdef ANDROID -#include -static void prepare() { - ALooper_prepare(0); -} -#else -static void prepare() {} -#endif - -TEST(Value, Undefined) { - prepare(); - JSGlobalContextRef ctx = JSC_JSGlobalContextCreateInGroup(false, nullptr, nullptr); - auto v = Value::makeUndefined(ctx); - auto s = String::adopt(ctx, JSC_JSValueToStringCopy(ctx, v, nullptr)); - EXPECT_EQ("undefined", s.str()); - JSC_JSGlobalContextRelease(ctx); -} - -TEST(Value, FromJSON) { - prepare(); - JSGlobalContextRef ctx = JSC_JSGlobalContextCreateInGroup(false, nullptr, nullptr); - String s(ctx, "{\"a\": 4}"); - Value v(Value::fromJSON(s)); - EXPECT_TRUE(v.isObject()); - JSC_JSGlobalContextRelease(ctx); -} - -TEST(Value, ToJSONString) { - prepare(); - JSGlobalContextRef ctx = JSC_JSGlobalContextCreateInGroup(false, nullptr, nullptr); - String s(ctx, "{\"a\": 4}"); - Value v(Value::fromJSON(s)); - folly::dynamic dyn = folly::parseJson(v.toJSONString()); - ASSERT_NE(nullptr, dyn); - EXPECT_TRUE(dyn.isObject()); - auto val = dyn.at("a"); - ASSERT_NE(nullptr, val); - ASSERT_TRUE(val.isNumber()); - EXPECT_EQ(4, val.asInt()); - EXPECT_EQ(4.0f, val.asDouble()); - - JSC_JSGlobalContextRelease(ctx); -} - -#ifdef WITH_FBJSCEXTENSION -// Just test that handling invalid data doesn't crash. -TEST(Value, FromBadUtf8) { - prepare(); - JSGlobalContextRef ctx = JSC_JSGlobalContextCreateInGroup(false, nullptr, nullptr); - // 110xxxxx 10xxxxxx - auto dyn = folly::dynamic("\xC0"); - Value::fromDynamic(ctx, dyn); - dyn = folly::dynamic("\xC0\x00"); - Value::fromDynamic(ctx, dyn); - // 1110xxxx 10xxxxxx 10xxxxxx - dyn = "\xE0"; - Value::fromDynamic(ctx, dyn); - Value(ctx, Value::fromDynamic(ctx, dyn)).toJSONString(); - dyn = "\xE0\x00"; - Value::fromDynamic(ctx, dyn); - Value(ctx, Value::fromDynamic(ctx, dyn)).toJSONString(); - dyn = "\xE0\x00\x00"; - Value::fromDynamic(ctx, dyn); - Value(ctx, Value::fromDynamic(ctx, dyn)).toJSONString(); - dyn = "\xE0\xA0\x00"; - Value::fromDynamic(ctx, dyn); - // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - dyn = "\xF0"; - Value::fromDynamic(ctx, dyn); - Value(ctx, Value::fromDynamic(ctx, dyn)).toJSONString(); - dyn = "\xF0\x00\x00\x00"; - Value::fromDynamic(ctx, dyn); - dyn = "\xF0\x80\x80\x00"; - Value::fromDynamic(ctx, dyn); - Value(ctx, Value::fromDynamic(ctx, dyn)).toJSONString(); - JSC_JSGlobalContextRelease(ctx); -} - -// Just test that handling invalid data doesn't crash. -TEST(Value, BadUtf16) { - prepare(); - JSGlobalContextRef ctx = JSC_JSGlobalContextCreateInGroup(false, nullptr, nullptr); - UChar buf[] = { 0xDD00, 0xDD00, 0xDD00, 0x1111 }; - JSStringRef ref = OpaqueJSString::create(buf, 4).leakRef(); - Value v(ctx, ref); - v.toJSONString(0); - JSC_JSGlobalContextRelease(ctx); -} -#endif