Lukas Piatkowski bd524bd6e8 BREAKING: Change the toValue in JSCExecutor to ValueEncoder<T>::toValue
Summary:
The C++ standard requires that when a function is used in a template it's prototype needs to be defined not only before the template specialization, but also before the template itself.

Because of that one needs to (in certain compilers) be aware of the proper order of includes so that the function prototype is defined before the JSCExecutor.h is included.

As a workaround the toValue might be written as a template (ValueEncoder<T>::toValue) defined in JSCExecutor.h instead of being an non-existing symbol.
Thanks to that the JSCExecutor.h does not have to be included before the specialization of the ValueEncoder template.

Reviewed By: mhorowitz

Differential Revision: D4182724

fbshipit-source-id: 9bdf239ae66ef7a7d2c82daf7db5926472687bde
2016-11-24 09:28:29 -08:00

197 lines
6.3 KiB
C++

// Copyright 2004-present Facebook. All Rights Reserved.
#pragma once
#include <cstdint>
#include <memory>
#include <unordered_map>
#include <folly/json.h>
#include <folly/Optional.h>
#include <jschelpers/JavaScriptCore.h>
#include <jschelpers/JSCHelpers.h>
#include <jschelpers/Value.h>
#include "Executor.h"
#include "ExecutorToken.h"
#include "JSCNativeModules.h"
namespace facebook {
namespace react {
class MessageQueueThread;
#define RN_JSC_EXECUTOR_EXPORT __attribute__((visibility("default")))
class RN_JSC_EXECUTOR_EXPORT JSCExecutorFactory : public JSExecutorFactory {
public:
JSCExecutorFactory(const std::string& cacheDir, const folly::dynamic& jscConfig) :
m_cacheDir(cacheDir),
m_jscConfig(jscConfig) {}
virtual std::unique_ptr<JSExecutor> createJSExecutor(
std::shared_ptr<ExecutorDelegate> delegate,
std::shared_ptr<MessageQueueThread> jsQueue) override;
private:
std::string m_cacheDir;
folly::dynamic m_jscConfig;
};
class JSCExecutor;
class WorkerRegistration : public noncopyable {
public:
explicit WorkerRegistration(JSCExecutor* executor_, Object jsObj_) :
executor(executor_),
jsObj(std::move(jsObj_)) {}
JSCExecutor *executor;
Object jsObj;
};
template <typename T>
struct ValueEncoder;
class RN_JSC_EXECUTOR_EXPORT JSCExecutor : public JSExecutor {
public:
/**
* Must be invoked from thread this Executor will run on.
*/
explicit JSCExecutor(std::shared_ptr<ExecutorDelegate> delegate,
std::shared_ptr<MessageQueueThread> messageQueueThread,
const std::string& cacheDir,
const folly::dynamic& jscConfig) throw(JSException);
~JSCExecutor() override;
virtual void loadApplicationScript(
std::unique_ptr<const JSBigString> script,
std::string sourceURL) throw(JSException) override;
#ifdef WITH_FBJSCEXTENSIONS
virtual void loadApplicationScript(
std::string bundlePath,
std::string sourceURL,
int flags) override;
#endif
#ifdef WITH_FBJSCEXTENSIONS
virtual void loadApplicationScript(
int fd,
std::string sourceURL) override;
#endif
virtual void setJSModulesUnbundle(
std::unique_ptr<JSModulesUnbundle> unbundle) 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;
template <typename T>
Value callFunctionSync(
const std::string& module, const std::string& method, T&& args) {
return callFunctionSyncWithValue(
module, method, ValueEncoder<typename std::decay<T>::type>::toValue(
m_context, std::forward<T>(args)));
}
virtual void setGlobalVariable(
std::string propName,
std::unique_ptr<const JSBigString> jsonValue) override;
virtual void* getJavaScriptContext() override;
virtual bool supportsProfiling() override;
virtual void startProfiler(const std::string &titleString) override;
virtual void stopProfiler(const std::string &titleString, const std::string &filename) override;
virtual void handleMemoryPressureUiHidden() override;
virtual void handleMemoryPressureModerate() override;
virtual void handleMemoryPressureCritical() override;
virtual void destroy() override;
void setContextName(const std::string& name);
private:
JSGlobalContextRef m_context;
std::shared_ptr<ExecutorDelegate> m_delegate;
int m_workerId = 0; // if this is a worker executor, this is non-zero
JSCExecutor *m_owner = nullptr; // if this is a worker executor, this is non-null
std::shared_ptr<bool> m_isDestroyed = std::shared_ptr<bool>(new bool(false));
std::unordered_map<int, WorkerRegistration> m_ownedWorkers;
std::string m_deviceCacheDir;
std::shared_ptr<MessageQueueThread> m_messageQueueThread;
std::unique_ptr<JSModulesUnbundle> m_unbundle;
JSCNativeModules m_nativeModules;
folly::dynamic m_jscConfig;
folly::Optional<Object> m_invokeCallbackAndReturnFlushedQueueJS;
folly::Optional<Object> m_callFunctionReturnFlushedQueueJS;
folly::Optional<Object> m_flushedQueueJS;
folly::Optional<Object> m_callFunctionReturnResultAndFlushedQueueJS;
/**
* WebWorker constructor. Must be invoked from thread this Executor will run on.
*/
JSCExecutor(
std::shared_ptr<ExecutorDelegate> delegate,
std::shared_ptr<MessageQueueThread> messageQueueThread,
int workerId,
JSCExecutor *owner,
std::string scriptURL,
std::unordered_map<std::string, std::string> globalObjAsJSON,
const folly::dynamic& jscConfig);
void initOnJSVMThread() throw(JSException);
// This method is experimental, and may be modified or removed.
Value callFunctionSyncWithValue(
const std::string& module, const std::string& method, Value value);
void terminateOnJSVMThread();
void bindBridge() throw(JSException);
void callNativeModules(Value&&);
void flush();
void flushQueueImmediate(Value&&);
void loadModule(uint32_t moduleId);
int addWebWorker(std::string scriptURL, JSValueRef workerRef, JSValueRef globalObjRef);
void postMessageToOwnedWebWorker(int worker, JSValueRef message);
void postMessageToOwner(JSValueRef result);
void receiveMessageFromOwnedWebWorker(int workerId, const std::string& message);
void receiveMessageFromOwner(const std::string &msgString);
void terminateOwnedWebWorker(int worker);
Object createMessageObject(const std::string& msgData);
template<JSValueRef (JSCExecutor::*method)(size_t, const JSValueRef[])>
void installNativeHook(const char* name);
JSValueRef getNativeModule(JSObjectRef object, JSStringRef propertyName);
JSValueRef nativeStartWorker(
size_t argumentCount,
const JSValueRef arguments[]);
JSValueRef nativePostMessageToWorker(
size_t argumentCount,
const JSValueRef arguments[]);
JSValueRef nativeTerminateWorker(
size_t argumentCount,
const JSValueRef arguments[]);
JSValueRef nativePostMessage(
size_t argumentCount,
const JSValueRef arguments[]);
JSValueRef nativeRequire(
size_t argumentCount,
const JSValueRef arguments[]);
JSValueRef nativeFlushQueueImmediate(
size_t argumentCount,
const JSValueRef arguments[]);
JSValueRef nativeCallSyncHook(
size_t argumentCount,
const JSValueRef arguments[]);
};
} }