Created
September 14, 2016 23:52
-
-
Save terryjsmith/b1b247205b4b6db5de16f5d80314f7af to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Getter and setter functions for our classes to V8 | |
*/ | |
typedef v8::Local<v8::Value> (*ScriptGlobalGetterFunc)(v8::Isolate*); | |
/** | |
* A storage for getter and setter to variable pairs | |
*/ | |
class ScriptGlobalCallbackPair { | |
public: | |
ScriptGlobalCallbackPair() : variableName(0), getter(0), next(0) { } | |
~ScriptGlobalCallbackPair() { } | |
public: | |
char* variableName; | |
ScriptGlobalGetterFunc getter; | |
ScriptGlobalCallbackPair* next; | |
}; | |
/** | |
* A scripted type that can be accessed and created in JS | |
*/ | |
template<class T> | |
class ScriptGlobal : public ScriptObject { | |
public: | |
ScriptGlobal() { } | |
~ScriptGlobal() { } | |
static void StartTemplate(v8::Isolate* isolate) { | |
// Start template | |
v8::Local<v8::ObjectTemplate> tpl = v8::ObjectTemplate::New(isolate); | |
m_objectTemplate.Reset(isolate, tpl); | |
m_isolate = isolate; | |
} | |
static void SetGlobalName(char* name) { | |
m_typeName = (char*)malloc(strlen(name) + 1); | |
strcpy(m_typeName, name); | |
} | |
static void AddVariable(char* name, ScriptGlobalGetterFunc getter) { | |
// Create a new variable function callback | |
ScriptGlobalCallbackPair* pair = new ScriptGlobalCallbackPair(); | |
// Copy params | |
pair->variableName = (char*)malloc(strlen(name) + 1); | |
strcpy(pair->variableName, name); | |
pair->getter = getter; | |
// Set this up as an accessible variable name | |
v8::Local<v8::ObjectTemplate> tpl = m_objectTemplate.Get(m_isolate); | |
tpl->SetAccessor(v8::String::NewFromUtf8(m_isolate, name), Getter); | |
if(m_varList == 0) { | |
m_varList = pair; | |
return; | |
} | |
ScriptGlobalCallbackPair* current = m_varList; | |
while(current->next) { | |
current = current->next; | |
} | |
current->next = pair; | |
} | |
static void EndTemplate(v8::Local<v8::Context> context) { | |
// Inject this type name into V8 | |
v8::Local<v8::ObjectTemplate> tpl = m_objectTemplate.Get(m_isolate); | |
context->Global()->Set(v8::String::NewFromUtf8(m_isolate, m_typeName), tpl->NewInstance()); | |
} | |
static void AddFunction(char* name, v8::FunctionCallback func) { | |
v8::Local<v8::ObjectTemplate> tpl = m_objectTemplate.Get(m_isolate); | |
tpl->Set(v8::String::NewFromUtf8(m_isolate, name), v8::FunctionTemplate::New(m_isolate, func)); | |
} | |
static void Getter(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) { | |
// Iterate through the callback list, looking for a registered callback function | |
ScriptGlobalCallbackPair* current = m_varList; | |
while(current) { | |
v8::String::Utf8Value propName(property); | |
if(strcmp(current->variableName, *propName) == 0) { | |
if(current->getter != 0) { | |
v8::Local<v8::Value> val = current->getter(m_isolate); | |
info.GetReturnValue().Set(val); | |
return; | |
} | |
} | |
} | |
} | |
protected: | |
// The function template | |
static v8::Persistent<v8::ObjectTemplate> m_objectTemplate; | |
// The name of this type inside the JS context | |
static char* m_typeName; | |
// The current isolate | |
static v8::Isolate* m_isolate; | |
// Linked list of getter/setter combinations for vars | |
static ScriptGlobalCallbackPair* m_varList; | |
}; | |
template<class T> v8::Persistent<v8::ObjectTemplate> ScriptGlobal<T>::m_objectTemplate; | |
template<class T> char* ScriptGlobal<T>::m_typeName = 0; | |
template<class T> v8::Isolate* ScriptGlobal<T>::m_isolate = 0; | |
template<class T> ScriptGlobalCallbackPair* ScriptGlobal<T>::m_varList = 0; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment