react-native/ReactCommon/cxxreact/JSCWebWorker.h

95 lines
2.7 KiB
C++

// Copyright 2004-present Facebook. All Rights Reserved.
#include <atomic>
#include <functional>
#include <mutex>
#include <string>
#include <thread>
#include <queue>
#include <JavaScriptCore/JSValueRef.h>
#include "Value.h"
namespace facebook {
namespace react {
class MessageQueueThread;
/**
* A class that can own the lifecycle, receive messages from, and dispatch messages
* to JSCWebWorkers.
*/
class JSCWebWorkerOwner {
public:
/**
* Called when a worker has posted a message with `postMessage`.
*/
virtual void onMessageReceived(int workerId, const std::string& message) = 0;
virtual JSGlobalContextRef getContext() = 0;
/**
* Should return the owner's MessageQueueThread. Calls to onMessageReceived will be enqueued
* on this thread.
*/
virtual std::shared_ptr<MessageQueueThread> getMessageQueueThread() = 0;
};
/**
* Implementation of a web worker for JSC. The web worker should be created from the owner's
* (e.g., owning JSCExecutor instance) JS MessageQueueThread. The worker is responsible for
* creating its own MessageQueueThread.
*
* During operation, the JSCExecutor should call postMessage **from its own MessageQueueThread**
* to send messages to the worker. The worker will handle enqueueing those messages on its own
* MessageQueueThread as appropriate. When the worker has a message to post to the owner, it will
* enqueue a call to owner->onMessageReceived on the owner's MessageQueueThread.
*/
class JSCWebWorker {
public:
explicit JSCWebWorker(int id, JSCWebWorkerOwner *owner, std::string script);
~JSCWebWorker();
/**
* Post a message to be received by the worker on its thread. This must be called from
* ownerMessageQueueThread_.
*/
void postMessage(JSValueRef msg);
/**
* Synchronously quits the current worker and cleans up its VM.
*/
void terminate();
/**
* Whether terminate() has been called on this worker.
*/
bool isTerminated();
static Object createMessageObject(JSContextRef context, const std::string& msgData);
private:
void initJSVMAndLoadScript();
void postRunnableToEventLoop(std::function<void()>&& runnable);
void postMessageToOwner(JSValueRef result);
void terminateOnWorkerThread();
int id_;
std::atomic_bool isTerminated_ = ATOMIC_VAR_INIT(false);
std::string scriptName_;
JSCWebWorkerOwner *owner_ = nullptr;
std::shared_ptr<MessageQueueThread> ownerMessageQueueThread_;
std::unique_ptr<MessageQueueThread> workerMessageQueueThread_;
JSGlobalContextRef context_ = nullptr;
static JSValueRef nativePostMessage(
JSContextRef ctx,
JSObjectRef function,
JSObjectRef thisObject,
size_t argumentCount,
const JSValueRef arguments[],
JSValueRef *exception);
};
}
}