Move all hooks over to new helper

Reviewed By: astreet

Differential Revision: D3292927

fbshipit-source-id: baafa6ded3872391ae1319b2855b2616ec79c2ad
This commit is contained in:
Alexander Blom 2016-05-12 14:32:42 -07:00 committed by Facebook Github Bot 7
parent cafd63440a
commit e4bb9f52e5
2 changed files with 70 additions and 207 deletions

View File

@ -10,6 +10,7 @@
#include <glog/logging.h> #include <glog/logging.h>
#include <folly/json.h> #include <folly/json.h>
#include <folly/String.h> #include <folly/String.h>
#include <folly/Conv.h>
#include <sys/time.h> #include <sys/time.h>
#include "Bridge.h" #include "Bridge.h"
@ -80,8 +81,6 @@ inline JSObjectCallAsFunctionCallback exceptionWrapMethod() {
} }
static std::unordered_map<JSContextRef, JSCExecutor*> s_globalContextRefToJSCExecutor;
static JSValueRef nativeInjectHMRUpdate( static JSValueRef nativeInjectHMRUpdate(
JSContextRef ctx, JSContextRef ctx,
JSObjectRef function, JSObjectRef function,
@ -143,7 +142,7 @@ JSCExecutor::JSCExecutor(
m_messageQueueThread->runOnQueue([this, script, globalObjAsJSON] () { m_messageQueueThread->runOnQueue([this, script, globalObjAsJSON] () {
initOnJSVMThread(); initOnJSVMThread();
installGlobalFunction(m_context, "postMessage", nativePostMessage); installNativeHook<&JSCExecutor::nativePostMessage>("postMessage");
for (auto& it : globalObjAsJSON) { for (auto& it : globalObjAsJSON) {
setGlobalVariable(it.first, it.second); setGlobalVariable(it.first, it.second);
@ -189,13 +188,13 @@ void JSCExecutor::initOnJSVMThread() {
// Add a pointer to ourselves so we can retrieve it later in our hooks // Add a pointer to ourselves so we can retrieve it later in our hooks
JSObjectSetPrivate(JSContextGetGlobalObject(m_context), this); JSObjectSetPrivate(JSContextGetGlobalObject(m_context), this);
s_globalContextRefToJSCExecutor[m_context] = this; installNativeHook<&JSCExecutor::nativeFlushQueueImmediate>("nativeFlushQueueImmediate");
installGlobalFunction(m_context, "nativeFlushQueueImmediate", nativeFlushQueueImmediate); installNativeHook<&JSCExecutor::nativeFlushQueueImmediate>("nativeFlushQueueImmediate");
installGlobalFunction(m_context, "nativeStartWorker", nativeStartWorker); installNativeHook<&JSCExecutor::nativeStartWorker>("nativeStartWorker");
installGlobalFunction(m_context, "nativePostMessageToWorker", nativePostMessageToWorker); installNativeHook<&JSCExecutor::nativePostMessageToWorker>("nativePostMessageToWorker");
installGlobalFunction(m_context, "nativeTerminateWorker", nativeTerminateWorker); installNativeHook<&JSCExecutor::nativeTerminateWorker>("nativeTerminateWorker");
installGlobalFunction(m_context, "nativeInjectHMRUpdate", nativeInjectHMRUpdate); installGlobalFunction(m_context, "nativeInjectHMRUpdate", nativeInjectHMRUpdate);
installGlobalFunction(m_context, "nativeCallSyncHook", nativeCallSyncHook); installNativeHook<&JSCExecutor::nativeCallSyncHook>("nativeCallSyncHook");
installGlobalFunction(m_context, "nativeLoggingHook", JSNativeHooks::loggingHook); installGlobalFunction(m_context, "nativeLoggingHook", JSNativeHooks::loggingHook);
installGlobalFunction(m_context, "nativePerformanceNow", JSNativeHooks::nowHook); installGlobalFunction(m_context, "nativePerformanceNow", JSNativeHooks::nowHook);
@ -230,7 +229,6 @@ void JSCExecutor::terminateOnJSVMThread() {
terminateOwnedWebWorker(workerId); terminateOwnedWebWorker(workerId);
} }
s_globalContextRefToJSCExecutor.erase(m_context);
JSGlobalContextRelease(m_context); JSGlobalContextRelease(m_context);
m_context = nullptr; m_context = nullptr;
} }
@ -254,7 +252,7 @@ void JSCExecutor::loadApplicationScript(
void JSCExecutor::setJSModulesUnbundle(std::unique_ptr<JSModulesUnbundle> unbundle) { void JSCExecutor::setJSModulesUnbundle(std::unique_ptr<JSModulesUnbundle> unbundle) {
if (!m_unbundle) { if (!m_unbundle) {
installGlobalFunction(m_context, "nativeRequire", nativeRequire); installNativeHook<&JSCExecutor::nativeRequire>("nativeRequire");
} }
m_unbundle = std::move(unbundle); m_unbundle = std::move(unbundle);
} }
@ -388,7 +386,7 @@ int JSCExecutor::addWebWorker(
return workerId; return workerId;
} }
void JSCExecutor::postMessageToOwnedWebWorker(int workerId, JSValueRef message, JSValueRef *exn) { void JSCExecutor::postMessageToOwnedWebWorker(int workerId, JSValueRef message) {
auto worker = m_ownedWorkers.at(workerId).executor; auto worker = m_ownedWorkers.at(workerId).executor;
std::string msgString = Value(m_context, message).toJSONString(); std::string msgString = Value(m_context, message).toJSONString();
@ -468,227 +466,120 @@ void JSCExecutor::installNativeHook(const char* name) {
} }
JSValueRef JSCExecutor::nativePostMessage( JSValueRef JSCExecutor::nativePostMessage(
JSContextRef ctx,
JSObjectRef function,
JSObjectRef thisObject,
size_t argumentCount, size_t argumentCount,
const JSValueRef arguments[], const JSValueRef arguments[]) {
JSValueRef *exception) {
if (argumentCount != 1) { if (argumentCount != 1) {
*exception = makeJSCException(ctx, "postMessage got wrong number of arguments"); throw std::invalid_argument("Got wrong number of args");
return JSValueMakeUndefined(ctx);
} }
JSValueRef msg = arguments[0]; JSValueRef msg = arguments[0];
JSCExecutor *webWorker = s_globalContextRefToJSCExecutor.at(JSContextGetGlobalContext(ctx)); postMessageToOwner(msg);
webWorker->postMessageToOwner(msg); return JSValueMakeUndefined(m_context);
return JSValueMakeUndefined(ctx);
}
static JSValueRef makeInvalidModuleIdJSCException(
JSContextRef ctx,
const JSValueRef id,
JSValueRef *exception) {
std::string message = "Received invalid module ID: ";
message += String::adopt(JSValueToStringCopy(ctx, id, exception)).str();
return makeJSCException(ctx, message.c_str());
} }
JSValueRef JSCExecutor::nativeRequire( JSValueRef JSCExecutor::nativeRequire(
JSContextRef ctx,
JSObjectRef function,
JSObjectRef thisObject,
size_t argumentCount, size_t argumentCount,
const JSValueRef arguments[], const JSValueRef arguments[]) {
JSValueRef *exception) {
if (argumentCount != 1) { if (argumentCount != 1) {
*exception = makeJSCException(ctx, "Got wrong number of args"); throw std::invalid_argument("Got wrong number of args");
return JSValueMakeUndefined(ctx);
} }
JSCExecutor *executor; double moduleId = Value(m_context, arguments[0]).asNumber();
try {
executor = s_globalContextRefToJSCExecutor.at(JSContextGetGlobalContext(ctx));
} catch (std::out_of_range& e) {
*exception = makeJSCException(ctx, "Global JS context didn't map to a valid executor");
return JSValueMakeUndefined(ctx);
}
double moduleId = JSValueToNumber(ctx, arguments[0], exception);
if (moduleId <= (double) std::numeric_limits<uint32_t>::max() && moduleId >= 0.0) { if (moduleId <= (double) std::numeric_limits<uint32_t>::max() && moduleId >= 0.0) {
try { try {
executor->loadModule(moduleId); loadModule(moduleId);
} catch (JSModulesUnbundle::ModuleNotFound&) { } catch (JSModulesUnbundle::ModuleNotFound&) {
*exception = makeInvalidModuleIdJSCException(ctx, arguments[0], exception); throw std::invalid_argument(folly::to<std::string>("Received invalid module ID: ", moduleId));
} }
} else { } else {
*exception = makeInvalidModuleIdJSCException(ctx, arguments[0], exception); throw std::invalid_argument(folly::to<std::string>("Received invalid module ID: ", moduleId));
} }
return JSValueMakeUndefined(ctx); return JSValueMakeUndefined(m_context);
}
static JSValueRef createErrorString(JSContextRef ctx, const char *msg) {
return JSValueMakeString(ctx, String(msg));
} }
JSValueRef JSCExecutor::nativeFlushQueueImmediate( JSValueRef JSCExecutor::nativeFlushQueueImmediate(
JSContextRef ctx,
JSObjectRef function,
JSObjectRef thisObject,
size_t argumentCount, size_t argumentCount,
const JSValueRef arguments[], const JSValueRef arguments[]) {
JSValueRef *exception) {
if (argumentCount != 1) { if (argumentCount != 1) {
*exception = createErrorString(ctx, "Got wrong number of args"); throw std::invalid_argument("Got wrong number of args");
return JSValueMakeUndefined(ctx);
} }
JSCExecutor *executor; std::string resStr = Value(m_context, arguments[0]).toJSONString();
try { flushQueueImmediate(resStr);
executor = s_globalContextRefToJSCExecutor.at(JSContextGetGlobalContext(ctx)); return JSValueMakeUndefined(m_context);
} catch (std::out_of_range& e) {
*exception = createErrorString(ctx, "Global JS context didn't map to a valid executor");
return JSValueMakeUndefined(ctx);
}
std::string resStr = Value(ctx, arguments[0]).toJSONString();
executor->flushQueueImmediate(resStr);
return JSValueMakeUndefined(ctx);
} }
JSValueRef JSCExecutor::nativeStartWorker( JSValueRef JSCExecutor::nativeStartWorker(
JSContextRef ctx,
JSObjectRef function,
JSObjectRef thisObject,
size_t argumentCount, size_t argumentCount,
const JSValueRef arguments[], const JSValueRef arguments[]) {
JSValueRef *exception) {
if (argumentCount != 3) { if (argumentCount != 3) {
*exception = createErrorString(ctx, "Got wrong number of args"); throw std::invalid_argument("Got wrong number of args");
return JSValueMakeUndefined(ctx);
} }
std::string scriptFile = Value(ctx, arguments[0]).toString().str(); std::string scriptFile = Value(m_context, arguments[0]).toString().str();
JSValueRef worker = arguments[1]; JSValueRef worker = arguments[1];
JSValueRef globalObj = arguments[2]; JSValueRef globalObj = arguments[2];
JSCExecutor *executor; int workerId = addWebWorker(scriptFile, worker, globalObj);
try {
executor = s_globalContextRefToJSCExecutor.at(JSContextGetGlobalContext(ctx));
} catch (std::out_of_range& e) {
*exception = createErrorString(ctx, "Global JS context didn't map to a valid executor");
return JSValueMakeUndefined(ctx);
}
int workerId = executor->addWebWorker(scriptFile, worker, globalObj); return JSValueMakeNumber(m_context, workerId);
return JSValueMakeNumber(ctx, workerId);
} }
JSValueRef JSCExecutor::nativePostMessageToWorker( JSValueRef JSCExecutor::nativePostMessageToWorker(
JSContextRef ctx,
JSObjectRef function,
JSObjectRef thisObject,
size_t argumentCount, size_t argumentCount,
const JSValueRef arguments[], const JSValueRef arguments[]) {
JSValueRef *exception) {
if (argumentCount != 2) { if (argumentCount != 2) {
*exception = createErrorString(ctx, "Got wrong number of args"); throw std::invalid_argument("Got wrong number of args");
return JSValueMakeUndefined(ctx);
} }
double workerDouble = JSValueToNumber(ctx, arguments[0], exception); double workerDouble = Value(m_context, arguments[0]).asNumber();
if (workerDouble != workerDouble) { if (workerDouble != workerDouble) {
*exception = createErrorString(ctx, "Got invalid worker id"); throw std::invalid_argument("Got invalid worker id");
return JSValueMakeUndefined(ctx);
} }
JSCExecutor *executor; postMessageToOwnedWebWorker((int) workerDouble, arguments[1]);
try {
executor = s_globalContextRefToJSCExecutor.at(JSContextGetGlobalContext(ctx));
} catch (std::out_of_range& e) {
*exception = createErrorString(ctx, "Global JS context didn't map to a valid executor");
return JSValueMakeUndefined(ctx);
}
executor->postMessageToOwnedWebWorker((int) workerDouble, arguments[1], exception); return JSValueMakeUndefined(m_context);
return JSValueMakeUndefined(ctx);
} }
JSValueRef JSCExecutor::nativeTerminateWorker( JSValueRef JSCExecutor::nativeTerminateWorker(
JSContextRef ctx,
JSObjectRef function,
JSObjectRef thisObject,
size_t argumentCount, size_t argumentCount,
const JSValueRef arguments[], const JSValueRef arguments[]) {
JSValueRef *exception) {
if (argumentCount != 1) { if (argumentCount != 1) {
*exception = createErrorString(ctx, "Got wrong number of args"); throw std::invalid_argument("Got wrong number of args");
return JSValueMakeUndefined(ctx);
} }
double workerDouble = JSValueToNumber(ctx, arguments[0], exception); double workerDouble = Value(m_context, arguments[0]).asNumber();
if (workerDouble != workerDouble) { if (workerDouble != workerDouble) {
*exception = createErrorString(ctx, "Got invalid worker id"); std::invalid_argument("Got invalid worker id");
return JSValueMakeUndefined(ctx);
} }
JSCExecutor *executor; terminateOwnedWebWorker((int) workerDouble);
try {
executor = s_globalContextRefToJSCExecutor.at(JSContextGetGlobalContext(ctx));
} catch (std::out_of_range& e) {
*exception = createErrorString(ctx, "Global JS context didn't map to a valid executor");
return JSValueMakeUndefined(ctx);
}
executor->terminateOwnedWebWorker((int) workerDouble); return JSValueMakeUndefined(m_context);
return JSValueMakeUndefined(ctx);
} }
JSValueRef JSCExecutor::nativeCallSyncHook( JSValueRef JSCExecutor::nativeCallSyncHook(
JSContextRef ctx,
JSObjectRef function,
JSObjectRef thisObject,
size_t argumentCount, size_t argumentCount,
const JSValueRef arguments[], const JSValueRef arguments[]) {
JSValueRef *exception) {
if (argumentCount != 3) { if (argumentCount != 3) {
*exception = createErrorString(ctx, "Got wrong number of args for callSyncHook"); throw std::invalid_argument("Got wrong number of args");
return JSValueMakeUndefined(ctx);
} }
unsigned int moduleId = Value(ctx, arguments[0]).asUnsignedInteger(); unsigned int moduleId = Value(m_context, arguments[0]).asUnsignedInteger();
unsigned int methodId = Value(ctx, arguments[1]).asUnsignedInteger(); unsigned int methodId = Value(m_context, arguments[1]).asUnsignedInteger();
std::string argsJson = Value(ctx, arguments[2]).toJSONString(); std::string argsJson = Value(m_context, arguments[2]).toJSONString();
JSCExecutor *executor; MethodCallResult result = m_bridge->callSerializableNativeHook(
try { moduleId,
executor = s_globalContextRefToJSCExecutor.at(JSContextGetGlobalContext(ctx)); methodId,
} catch (std::out_of_range& e) { argsJson);
*exception = createErrorString(ctx, "Global JS context didn't map to a valid executor"); if (result.isUndefined) {
return JSValueMakeUndefined(ctx); return JSValueMakeUndefined(m_context);
}
try {
MethodCallResult result = executor->m_bridge->callSerializableNativeHook(
moduleId,
methodId,
argsJson);
if (result.isUndefined) {
return JSValueMakeUndefined(ctx);
}
return Value::fromJSON(ctx, String(folly::toJson(result.result).c_str()));
} catch (...) {
*exception = translatePendingCppExceptionToJSError(ctx, "nativeCallSyncHook");
return JSValueMakeUndefined(ctx);
} }
return Value::fromJSON(m_context, String(folly::toJson(result.result).c_str()));
} }
static JSValueRef nativeInjectHMRUpdate( static JSValueRef nativeInjectHMRUpdate(

View File

@ -108,7 +108,7 @@ private:
void loadModule(uint32_t moduleId); void loadModule(uint32_t moduleId);
int addWebWorker(const std::string& script, JSValueRef workerRef, JSValueRef globalObjRef); int addWebWorker(const std::string& script, JSValueRef workerRef, JSValueRef globalObjRef);
void postMessageToOwnedWebWorker(int worker, JSValueRef message, JSValueRef *exn); void postMessageToOwnedWebWorker(int worker, JSValueRef message);
void postMessageToOwner(JSValueRef result); void postMessageToOwner(JSValueRef result);
void receiveMessageFromOwnedWebWorker(int workerId, const std::string& message); void receiveMessageFromOwnedWebWorker(int workerId, const std::string& message);
void receiveMessageFromOwner(const std::string &msgString); void receiveMessageFromOwner(const std::string &msgString);
@ -118,55 +118,27 @@ private:
template< JSValueRef (JSCExecutor::*method)(size_t, const JSValueRef[])> template< JSValueRef (JSCExecutor::*method)(size_t, const JSValueRef[])>
void installNativeHook(const char* name); void installNativeHook(const char* name);
static JSValueRef nativeStartWorker( JSValueRef nativeStartWorker(
JSContextRef ctx,
JSObjectRef function,
JSObjectRef thisObject,
size_t argumentCount, size_t argumentCount,
const JSValueRef arguments[], const JSValueRef arguments[]);
JSValueRef *exception); JSValueRef nativePostMessageToWorker(
static JSValueRef nativePostMessageToWorker(
JSContextRef ctx,
JSObjectRef function,
JSObjectRef thisObject,
size_t argumentCount, size_t argumentCount,
const JSValueRef arguments[], const JSValueRef arguments[]);
JSValueRef *exception); JSValueRef nativeTerminateWorker(
static JSValueRef nativeTerminateWorker(
JSContextRef ctx,
JSObjectRef function,
JSObjectRef thisObject,
size_t argumentCount, size_t argumentCount,
const JSValueRef arguments[], const JSValueRef arguments[]);
JSValueRef *exception); JSValueRef nativePostMessage(
static JSValueRef nativePostMessage(
JSContextRef ctx,
JSObjectRef function,
JSObjectRef thisObject,
size_t argumentCount, size_t argumentCount,
const JSValueRef arguments[], const JSValueRef arguments[]);
JSValueRef *exception); JSValueRef nativeRequire(
static JSValueRef nativeRequire(
JSContextRef ctx,
JSObjectRef function,
JSObjectRef thisObject,
size_t argumentCount, size_t argumentCount,
const JSValueRef arguments[], const JSValueRef arguments[]);
JSValueRef *exception); JSValueRef nativeFlushQueueImmediate(
static JSValueRef nativeFlushQueueImmediate(
JSContextRef ctx,
JSObjectRef function,
JSObjectRef thisObject,
size_t argumentCount, size_t argumentCount,
const JSValueRef arguments[], const JSValueRef arguments[]);
JSValueRef *exception); JSValueRef nativeCallSyncHook(
static JSValueRef nativeCallSyncHook(
JSContextRef ctx,
JSObjectRef function,
JSObjectRef thisObject,
size_t argumentCount, size_t argumentCount,
const JSValueRef arguments[], const JSValueRef arguments[]);
JSValueRef *exception);
}; };
} } } }