Changeset View
Changeset View
Standalone View
Standalone View
source/scriptinterface/ScriptInterface.h
Show First 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | |||||
class ScriptRuntime; | class ScriptRuntime; | ||||
// Using a global object for the runtime is a workaround until Simulation, AI, etc, | // Using a global object for the runtime is a workaround until Simulation, AI, etc, | ||||
// use their own threads and also their own runtimes. | // use their own threads and also their own runtimes. | ||||
extern thread_local shared_ptr<ScriptRuntime> g_ScriptRuntime; | extern thread_local shared_ptr<ScriptRuntime> g_ScriptRuntime; | ||||
/** | /** | ||||
* Abstraction around a SpiderMonkey JSContext. | * Abstraction around a SpiderMonkey JSCompartment. | ||||
* | * | ||||
* Thread-safety: | * Thread-safety: | ||||
* - May be used in non-main threads. | * - May be used in non-main threads. | ||||
* - Each ScriptInterface must be created, used, and destroyed, all in a single thread | * - Each ScriptInterface must be created, used, and destroyed, all in a single thread | ||||
* (it must never be shared between threads). | * (it must never be shared between threads). | ||||
*/ | */ | ||||
class ScriptInterface | class ScriptInterface | ||||
{ | { | ||||
Show All 9 Lines | public: | ||||
* @param runtime ScriptRuntime to use when initializing this interface. | * @param runtime ScriptRuntime to use when initializing this interface. | ||||
*/ | */ | ||||
ScriptInterface(const char* nativeScopeName, const char* debugName, const shared_ptr<ScriptRuntime>& runtime); | ScriptInterface(const char* nativeScopeName, const char* debugName, const shared_ptr<ScriptRuntime>& runtime); | ||||
~ScriptInterface(); | ~ScriptInterface(); | ||||
struct CmptPrivate | struct CmptPrivate | ||||
{ | { | ||||
ScriptInterface* pScriptInterface; // the ScriptInterface object the current context belongs to | ScriptInterface* pScriptInterface; // the ScriptInterface object the compartment belongs to | ||||
void* pCBData; // meant to be used as the "this" object for callback functions | void* pCBData; // meant to be used as the "this" object for callback functions | ||||
} m_CmptPrivate; | } m_CmptPrivate; | ||||
void SetCallbackData(void* pCBData); | void SetCallbackData(void* pCBData); | ||||
static CmptPrivate* GetScriptInterfaceAndCBData(JSContext* cx); | static CmptPrivate* GetScriptInterfaceAndCBData(JSContext* cx); | ||||
JSRuntime* GetJSRuntime() const; | JSRuntime* GetJSRuntime() const; | ||||
shared_ptr<ScriptRuntime> GetRuntime() const; | shared_ptr<ScriptRuntime> GetRuntime() const; | ||||
/** | /** | ||||
* RAII structure which encapsulates an access to the context of a ScriptInterface. | * RAII structure which encapsulates an access to the context and compartment of a ScriptInterface. | ||||
* This struct provides a pointer to the context, and it acts like JSAutoRequest. This | * This struct provides: | ||||
* way, getting the context is safe with respect to the GC. | * - a pointer to the context, while acting like JSAutoRequest | ||||
* - a pointer to the global object of the compartment, while acting like JSAutoCompartment | |||||
* | |||||
* This way, getting and using those pointers is safe with respect to the GC | |||||
* and to the separation of compartments. | |||||
*/ | */ | ||||
struct Request | struct Request | ||||
{ | { | ||||
Request() = delete; | Request() = delete; | ||||
Request(const Request& rq) = delete; | Request(const Request& rq) = delete; | ||||
Request& operator=(const Request& rq) = delete; | Request& operator=(const Request& rq) = delete; | ||||
Request(const ScriptInterface& scriptInterface); | Request(const ScriptInterface& scriptInterface); | ||||
Request(const ScriptInterface* scriptInterface) : Request(*scriptInterface) {} | Request(const ScriptInterface* scriptInterface) : Request(*scriptInterface) {} | ||||
Request(shared_ptr<ScriptInterface> scriptInterface) : Request(*scriptInterface) {} | Request(shared_ptr<ScriptInterface> scriptInterface) : Request(*scriptInterface) {} | ||||
Request(const CmptPrivate* CmptPrivate) : Request(CmptPrivate->pScriptInterface) {} | Request(const CmptPrivate* cmptPrivate) : Request(cmptPrivate->pScriptInterface) {} | ||||
~Request(); | ~Request(); | ||||
JS::Value globalValue() const; | |||||
JSContext* cx; | JSContext* cx; | ||||
JSObject* glob; | |||||
private: | |||||
JSCompartment* m_formerCompartment; | |||||
Stan: smart pointer? | |||||
}; | }; | ||||
friend struct Request; | friend struct Request; | ||||
/** | /** | ||||
* Load global scripts that most script contexts need, | * Load global scripts that most script interfaces need, | ||||
* located in the /globalscripts directory. VFS must be initialized. | * located in the /globalscripts directory. VFS must be initialized. | ||||
*/ | */ | ||||
bool LoadGlobalScripts(); | bool LoadGlobalScripts(); | ||||
/** | /** | ||||
* Replace the default JS random number geenrator with a seeded, network-sync'd one. | * Replace the default JS random number geenrator with a seeded, network-sync'd one. | ||||
*/ | */ | ||||
bool ReplaceNondeterministicRNG(boost::rand48& rng); | bool ReplaceNondeterministicRNG(boost::rand48& rng); | ||||
Show All 27 Lines | static bool CreateObject(JSContext* cx, JS::MutableHandleValue objectValue, Args const&... args) | ||||
return true; | return true; | ||||
} | } | ||||
/** | /** | ||||
* Sets the given value to a new JS object or Null Value in case of out-of-memory. | * Sets the given value to a new JS object or Null Value in case of out-of-memory. | ||||
*/ | */ | ||||
static void CreateArray(JSContext* cx, JS::MutableHandleValue objectValue, size_t length = 0); | static void CreateArray(JSContext* cx, JS::MutableHandleValue objectValue, size_t length = 0); | ||||
JS::Value GetGlobalObject() const; | |||||
/** | /** | ||||
* Set the named property on the global object. | * Set the named property on the global object. | ||||
* Optionally makes it {ReadOnly, DontEnum}. We do not allow to make it DontDelete, so that it can be hotloaded | * Optionally makes it {ReadOnly, DontEnum}. We do not allow to make it DontDelete, so that it can be hotloaded | ||||
* by deleting it and re-creating it, which is done by setting @p replace to true. | * by deleting it and re-creating it, which is done by setting @p replace to true. | ||||
*/ | */ | ||||
template<typename T> | template<typename T> | ||||
bool SetGlobal(const char* name, const T& value, bool replace = false, bool constant = true, bool enumerate = true); | bool SetGlobal(const char* name, const T& value, bool replace = false, bool constant = true, bool enumerate = true); | ||||
▲ Show 20 Lines • Show All 115 Lines • ▼ Show 20 Lines | public: | ||||
/** | /** | ||||
* Load and execute the given script in the global scope. | * Load and execute the given script in the global scope. | ||||
* @return true on successful compilation and execution; false otherwise | * @return true on successful compilation and execution; false otherwise | ||||
*/ | */ | ||||
bool LoadGlobalScriptFile(const VfsPath& path) const; | bool LoadGlobalScriptFile(const VfsPath& path) const; | ||||
/** | /** | ||||
* Construct a new value (usable in this ScriptInterface's context) by cloning | * Construct a new value (usable in this ScriptInterface's compartment) by cloning | ||||
* a value from a different context. | * a value from a different compartment. | ||||
* Complex values (functions, XML, etc) won't be cloned correctly, but basic | * Complex values (functions, XML, etc) won't be cloned correctly, but basic | ||||
* types and cyclic references should be fine. | * types and cyclic references should be fine. | ||||
*/ | */ | ||||
JS::Value CloneValueFromOtherContext(const ScriptInterface& otherContext, JS::HandleValue val) const; | JS::Value CloneValueFromOtherCompartment(const ScriptInterface& otherCompartment, JS::HandleValue val) const; | ||||
/** | /** | ||||
* Convert a JS::Value to a C++ type. (This might trigger GC.) | * Convert a JS::Value to a C++ type. (This might trigger GC.) | ||||
*/ | */ | ||||
template<typename T> static bool FromJSVal(JSContext* cx, const JS::HandleValue val, T& ret); | template<typename T> static bool FromJSVal(JSContext* cx, const JS::HandleValue val, T& ret); | ||||
/** | /** | ||||
* Convert a C++ type to a JS::Value. (This might trigger GC. The return | * Convert a C++ type to a JS::Value. (This might trigger GC. The return | ||||
Show All 14 Lines | public: | ||||
* returns the generated number. | * returns the generated number. | ||||
* Math_random (with underscore, not this function) is a global function, but different random number generators can be | * Math_random (with underscore, not this function) is a global function, but different random number generators can be | ||||
* stored per ScriptInterface. It calls MathRandom of the current ScriptInterface instance. | * stored per ScriptInterface. It calls MathRandom of the current ScriptInterface instance. | ||||
*/ | */ | ||||
bool MathRandom(double& nbr); | bool MathRandom(double& nbr); | ||||
/** | /** | ||||
* Structured clones are a way to serialize 'simple' JS::Values into a buffer | * Structured clones are a way to serialize 'simple' JS::Values into a buffer | ||||
* that can safely be passed between contexts and runtimes and threads. | * that can safely be passed between compartments and between threads. | ||||
* A StructuredClone can be stored and read multiple times if desired. | * A StructuredClone can be stored and read multiple times if desired. | ||||
* We wrap them in shared_ptr so memory management is automatic and | * We wrap them in shared_ptr so memory management is automatic and | ||||
* thread-safe. | * thread-safe. | ||||
*/ | */ | ||||
class StructuredClone | class StructuredClone | ||||
{ | { | ||||
NONCOPYABLE(StructuredClone); | NONCOPYABLE(StructuredClone); | ||||
public: | public: | ||||
▲ Show 20 Lines • Show All 279 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator
smart pointer?