Inject some behavior from react/jni/ to react/
Summary: So, this makes it so a set of behaviors that require accessing java can be injected from the jni/ folder. The behaviors are logging, perf logging, log markers and loading script from assets. I'd argue that these should all actually be encapsulated by interfaces that are passed to the JSCExecutor/others (and I'd say that's regardless of whether they are injected from jni/ or not), but I wanted to stick to the least disruptive pattern for these changes. public Reviewed By: astreet Differential Revision: D2905168 fb-gh-sync-id: 7c8c16cb77b8fc3d42750dacc6574259ad512ac2
This commit is contained in:
parent
2c8802f316
commit
75ca46e332
|
@ -46,15 +46,14 @@ react_library(
|
|||
'JSCExecutor.cpp',
|
||||
'JSCTracing.cpp',
|
||||
'JSCMemory.cpp',
|
||||
'JSCPerfLogging.cpp',
|
||||
'JSCLegacyProfiler.cpp',
|
||||
'JSCWebWorker.cpp',
|
||||
'Platform.cpp',
|
||||
],
|
||||
headers = [
|
||||
'JSCTracing.h',
|
||||
'JSCPerfLogging.h',
|
||||
'JSCLegacyProfiler.h',
|
||||
'JSCMemory.h'
|
||||
'JSCMemory.h',
|
||||
],
|
||||
exported_headers = [
|
||||
'Bridge.h',
|
||||
|
@ -65,6 +64,7 @@ react_library(
|
|||
'MethodCall.h',
|
||||
'JSModulesUnbundle.h',
|
||||
'Value.h',
|
||||
'Platform.h',
|
||||
],
|
||||
compiler_flags = [
|
||||
'-Wall',
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "jni/JMessageQueueThread.h"
|
||||
#include "jni/OnLoad.h"
|
||||
#include <react/JSCHelpers.h>
|
||||
#include "Platform.h"
|
||||
|
||||
#ifdef WITH_JSC_EXTRA_TRACING
|
||||
#include <react/JSCTracing.h>
|
||||
|
@ -31,9 +32,6 @@
|
|||
using fbsystrace::FbSystraceSection;
|
||||
#endif
|
||||
|
||||
// Add native performance markers support
|
||||
#include <react/JSCPerfLogging.h>
|
||||
|
||||
#ifdef WITH_FB_MEMORY_PROFILING
|
||||
#include <react/JSCMemory.h>
|
||||
#endif
|
||||
|
@ -59,13 +57,6 @@ static JSValueRef nativeFlushQueueImmediate(
|
|||
size_t argumentCount,
|
||||
const JSValueRef arguments[],
|
||||
JSValueRef *exception);
|
||||
static JSValueRef nativeLoggingHook(
|
||||
JSContextRef ctx,
|
||||
JSObjectRef function,
|
||||
JSObjectRef thisObject,
|
||||
size_t argumentCount,
|
||||
const JSValueRef arguments[],
|
||||
JSValueRef *exception);
|
||||
static JSValueRef nativePerformanceNow(
|
||||
JSContextRef ctx,
|
||||
JSObjectRef function,
|
||||
|
@ -103,12 +94,13 @@ JSCExecutor::JSCExecutor(FlushImmediateCallback cb) :
|
|||
m_messageQueueThread = JMessageQueueThread::currentMessageQueueThread();
|
||||
s_globalContextRefToJSCExecutor[m_context] = this;
|
||||
installGlobalFunction(m_context, "nativeFlushQueueImmediate", nativeFlushQueueImmediate);
|
||||
installGlobalFunction(m_context, "nativeLoggingHook", nativeLoggingHook);
|
||||
installGlobalFunction(m_context, "nativePerformanceNow", nativePerformanceNow);
|
||||
installGlobalFunction(m_context, "nativeStartWorker", nativeStartWorker);
|
||||
installGlobalFunction(m_context, "nativePostMessageToWorker", nativePostMessageToWorker);
|
||||
installGlobalFunction(m_context, "nativeTerminateWorker", nativeTerminateWorker);
|
||||
|
||||
installGlobalFunction(m_context, "nativeLoggingHook", JSLogging::nativeHook);
|
||||
|
||||
#ifdef WITH_FB_JSC_TUNING
|
||||
configureJSCForAndroid();
|
||||
#endif
|
||||
|
@ -116,7 +108,7 @@ JSCExecutor::JSCExecutor(FlushImmediateCallback cb) :
|
|||
#ifdef WITH_JSC_EXTRA_TRACING
|
||||
addNativeTracingHooks(m_context);
|
||||
addNativeProfilingHooks(m_context);
|
||||
addNativePerfLoggingHooks(m_context);
|
||||
PerfLogging::installNativeHooks(m_context);
|
||||
#endif
|
||||
|
||||
#ifdef WITH_FB_MEMORY_PROFILING
|
||||
|
@ -164,17 +156,9 @@ std::string JSCExecutor::getDeviceCacheDir(){
|
|||
void JSCExecutor::executeApplicationScript(
|
||||
const std::string& script,
|
||||
const std::string& sourceURL) {
|
||||
JNIEnv* env = Environment::current();
|
||||
jclass markerClass = env->FindClass("com/facebook/react/bridge/ReactMarker");
|
||||
jmethodID logMarkerMethod = facebook::react::getLogMarkerMethod();
|
||||
jstring startStringMarker = env->NewStringUTF("executeApplicationScript_startStringConvert");
|
||||
jstring endStringMarker = env->NewStringUTF("executeApplicationScript_endStringConvert");
|
||||
|
||||
env->CallStaticVoidMethod(markerClass, logMarkerMethod, startStringMarker);
|
||||
ReactMarker::logMarker("executeApplicationScript_startStringConvert");
|
||||
String jsScript = String::createExpectingAscii(script);
|
||||
env->CallStaticVoidMethod(markerClass, logMarkerMethod, endStringMarker);
|
||||
env->DeleteLocalRef(startStringMarker);
|
||||
env->DeleteLocalRef(endStringMarker);
|
||||
ReactMarker::logMarker("executeApplicationScript_endStringConvert");
|
||||
|
||||
String jsSourceURL(sourceURL.c_str());
|
||||
#ifdef WITH_FBSYSTRACE
|
||||
|
@ -504,29 +488,6 @@ JSValueRef JSCExecutor::nativeTerminateWorker(
|
|||
return JSValueMakeUndefined(ctx);
|
||||
}
|
||||
|
||||
static 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) JSValueToNumber(ctx, arguments[1], NULL);
|
||||
// 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<android_LogPriority>(level + ANDROID_LOG_DEBUG),
|
||||
ANDROID_LOG_FATAL);
|
||||
}
|
||||
if (argumentCount > 0) {
|
||||
JSStringRef jsString = JSValueToStringCopy(ctx, arguments[0], NULL);
|
||||
String message = String::adopt(jsString);
|
||||
FBLOG_PRI(logLevel, "ReactNativeJS", "%s", message.str().c_str());
|
||||
}
|
||||
return JSValueMakeUndefined(ctx);
|
||||
}
|
||||
|
||||
static JSValueRef nativePerformanceNow(
|
||||
JSContextRef ctx,
|
||||
JSObjectRef function,
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "jni/JMessageQueueThread.h"
|
||||
#include "jni/JSLoader.h"
|
||||
#include "jni/WebWorkers.h"
|
||||
#include "Platform.h"
|
||||
#include "Value.h"
|
||||
|
||||
#include <JavaScriptCore/JSValueRef.h>
|
||||
|
@ -109,7 +110,7 @@ void JSCWebWorker::initJSVMAndLoadScript() {
|
|||
s_globalContextRefToJSCWebWorker[context_] = this;
|
||||
|
||||
// TODO(9604438): Protect against script does not exist
|
||||
std::string script = loadScriptFromAssets(scriptName_);
|
||||
std::string script = WebWorkerUtil::loadScriptFromAssets(scriptName_);
|
||||
evaluateScript(context_, String(script.c_str()), String(scriptName_.c_str()));
|
||||
|
||||
installGlobalFunction(context_, "postMessage", nativePostMessage);
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
namespace ReactMarker {
|
||||
LogMarker logMarker;
|
||||
};
|
||||
|
||||
namespace WebWorkerUtil {
|
||||
LoadScriptFromAssets loadScriptFromAssets;
|
||||
};
|
||||
|
||||
namespace PerfLogging {
|
||||
InstallNativeHooks installNativeHooks;
|
||||
}
|
||||
|
||||
namespace JSLogging {
|
||||
JSCNativeHook nativeHook = nullptr;
|
||||
}
|
||||
|
||||
} }
|
|
@ -0,0 +1,39 @@
|
|||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <JavaScriptCore/JSContextRef.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
namespace ReactMarker {
|
||||
using LogMarker = std::function<void(const std::string&)>;
|
||||
extern LogMarker logMarker;
|
||||
};
|
||||
|
||||
namespace WebWorkerUtil {
|
||||
using LoadScriptFromAssets = std::function<std::string(const std::string& assetName)>;
|
||||
extern LoadScriptFromAssets loadScriptFromAssets;
|
||||
};
|
||||
|
||||
namespace PerfLogging {
|
||||
using InstallNativeHooks = std::function<void(JSGlobalContextRef)>;
|
||||
extern InstallNativeHooks installNativeHooks;
|
||||
}
|
||||
|
||||
namespace JSLogging {
|
||||
using JSCNativeHook = JSValueRef (*) (
|
||||
JSContextRef ctx,
|
||||
JSObjectRef function,
|
||||
JSObjectRef thisObject,
|
||||
size_t argumentCount,
|
||||
const JSValueRef arguments[], JSValueRef *exception);
|
||||
extern JSCNativeHook nativeHook;
|
||||
}
|
||||
|
||||
} }
|
|
@ -5,6 +5,7 @@ SUPPORTED_PLATFORMS = '^android-(armv7|x86)$'
|
|||
|
||||
DEPS = [
|
||||
'//native/jni:jni',
|
||||
'//native/third-party/android-ndk:android',
|
||||
'//xplat/folly:molly',
|
||||
]
|
||||
|
||||
|
@ -28,14 +29,18 @@ jni_library(
|
|||
supported_platforms_regex = SUPPORTED_PLATFORMS,
|
||||
srcs = [
|
||||
'JMessageQueueThread.cpp',
|
||||
'JSCPerfLogging.cpp',
|
||||
'JSLoader.cpp',
|
||||
'NativeArray.cpp',
|
||||
'OnLoad.cpp',
|
||||
'ProxyExecutor.cpp',
|
||||
'JSLogging.cpp',
|
||||
],
|
||||
headers = [
|
||||
'JSLoader.h',
|
||||
'ProxyExecutor.h',
|
||||
'JSCPerfLogging.h',
|
||||
'JSLogging.h',
|
||||
],
|
||||
exported_headers = [
|
||||
'JMessageQueueThread.h',
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#include "JSCHelpers.h"
|
||||
#include "JSCPerfLogging.h"
|
||||
|
||||
#include <fb/log.h>
|
||||
#include <jni/fbjni.h>
|
||||
#include <react/JSCHelpers.h>
|
||||
|
||||
using namespace facebook::jni;
|
||||
|
|
@ -21,7 +21,7 @@ static jclass gApplicationHolderClass;
|
|||
static jmethodID gGetApplicationMethod;
|
||||
static jmethodID gGetAssetManagerMethod;
|
||||
|
||||
std::string loadScriptFromAssets(std::string assetName) {
|
||||
std::string loadScriptFromAssets(const std::string& assetName) {
|
||||
JNIEnv *env = jni::Environment::current();
|
||||
jobject application = env->CallStaticObjectMethod(
|
||||
gApplicationHolderClass,
|
||||
|
@ -32,7 +32,7 @@ std::string loadScriptFromAssets(std::string assetName) {
|
|||
|
||||
std::string loadScriptFromAssets(
|
||||
AAssetManager *manager,
|
||||
std::string assetName) {
|
||||
const std::string& assetName) {
|
||||
#ifdef WITH_FBSYSTRACE
|
||||
FbSystraceSection s(TRACE_TAG_REACT_CXX_BRIDGE, "reactbridge_jni_loadScriptFromAssets",
|
||||
"assetName", assetName);
|
||||
|
@ -59,7 +59,7 @@ std::string loadScriptFromAssets(
|
|||
return "";
|
||||
}
|
||||
|
||||
std::string loadScriptFromFile(std::string fileName) {
|
||||
std::string loadScriptFromFile(const std::string& fileName) {
|
||||
#ifdef WITH_FBSYSTRACE
|
||||
FbSystraceSection s(TRACE_TAG_REACT_CXX_BRIDGE, "reactbridge_jni_loadScriptFromFile",
|
||||
"fileName", fileName);
|
||||
|
|
|
@ -13,17 +13,17 @@ namespace react {
|
|||
* Helper method for loading a JS script from Android assets without
|
||||
* a reference to an AssetManager.
|
||||
*/
|
||||
std::string loadScriptFromAssets(std::string assetName);
|
||||
std::string loadScriptFromAssets(const std::string& assetName);
|
||||
|
||||
/**
|
||||
* Helper method for loading JS script from android asset
|
||||
*/
|
||||
std::string loadScriptFromAssets(AAssetManager *assetManager, std::string assetName);
|
||||
std::string loadScriptFromAssets(AAssetManager *assetManager, const std::string& assetName);
|
||||
|
||||
/**
|
||||
* Helper method for loading JS script from a file
|
||||
*/
|
||||
std::string loadScriptFromFile(std::string fileName);
|
||||
std::string loadScriptFromFile(const std::string& fileName);
|
||||
|
||||
void registerJSLoaderNatives();
|
||||
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#include "JSLogging.h"
|
||||
|
||||
#include <android/log.h>
|
||||
#include <algorithm>
|
||||
#include <react/Value.h>
|
||||
#include <fb/log.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
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) JSValueToNumber(ctx, arguments[1], NULL);
|
||||
// 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<android_LogPriority>(level + ANDROID_LOG_DEBUG),
|
||||
ANDROID_LOG_FATAL);
|
||||
}
|
||||
if (argumentCount > 0) {
|
||||
JSStringRef jsString = JSValueToStringCopy(ctx, arguments[0], NULL);
|
||||
String message = String::adopt(jsString);
|
||||
FBLOG_PRI(logLevel, "ReactNativeJS", "%s", message.str().c_str());
|
||||
}
|
||||
return JSValueMakeUndefined(ctx);
|
||||
}
|
||||
|
||||
}};
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <JavaScriptCore/JSContextRef.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
JSValueRef nativeLoggingHook(
|
||||
JSContextRef ctx,
|
||||
JSObjectRef function,
|
||||
JSObjectRef thisObject,
|
||||
size_t argumentCount,
|
||||
const JSValueRef arguments[], JSValueRef *exception);
|
||||
}}
|
|
@ -15,11 +15,14 @@
|
|||
#include <react/Executor.h>
|
||||
#include <react/JSCExecutor.h>
|
||||
#include <react/JSModulesUnbundle.h>
|
||||
#include <react/Platform.h>
|
||||
#include "JNativeRunnable.h"
|
||||
#include "JSLoader.h"
|
||||
#include "ReadableNativeArray.h"
|
||||
#include "ProxyExecutor.h"
|
||||
#include "OnLoad.h"
|
||||
#include "JSLogging.h"
|
||||
#include "JSCPerfLogging.h"
|
||||
#include <algorithm>
|
||||
|
||||
#ifdef WITH_FBSYSTRACE
|
||||
|
@ -561,6 +564,15 @@ static jmethodID gCallbackMethod;
|
|||
static jmethodID gOnBatchCompleteMethod;
|
||||
static jmethodID gLogMarkerMethod;
|
||||
|
||||
static void logMarker(const std::string& marker) {
|
||||
JNIEnv* env = Environment::current();
|
||||
jclass markerClass = env->FindClass("com/facebook/react/bridge/ReactMarker");
|
||||
jstring jmarker = env->NewStringUTF(marker.c_str());
|
||||
env->CallStaticVoidMethod(markerClass, gLogMarkerMethod, jmarker);
|
||||
env->DeleteLocalRef(markerClass);
|
||||
env->DeleteLocalRef(jmarker);
|
||||
}
|
||||
|
||||
static void makeJavaCall(JNIEnv* env, jobject callback, MethodCall&& call) {
|
||||
if (call.arguments.isNull()) {
|
||||
return;
|
||||
|
@ -801,6 +813,15 @@ jmethodID getLogMarkerMethod() {
|
|||
|
||||
extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
|
||||
return initialize(vm, [] {
|
||||
// Inject some behavior into react/
|
||||
ReactMarker::logMarker = bridge::logMarker;
|
||||
WebWorkerUtil::loadScriptFromAssets =
|
||||
[] (const std::string& assetName) {
|
||||
return loadScriptFromAssets(assetName);
|
||||
};
|
||||
PerfLogging::installNativeHooks = addNativePerfLoggingHooks;
|
||||
JSLogging::nativeHook = nativeLoggingHook;
|
||||
|
||||
// get the current env
|
||||
JNIEnv* env = Environment::current();
|
||||
|
||||
|
|
Loading…
Reference in New Issue