Created
May 11, 2015 18:40
-
-
Save dannote/ec83a263188e04f84a9b to your computer and use it in GitHub Desktop.
JavaScriptCore Lua bindings
This file contains 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
local ffi = require "ffi" | |
local lgi = require "lgi" | |
local WebKit = lgi.WebKit | |
ffi.cdef [[ | |
typedef struct OpaqueJSValue* JSObjectRef; | |
typedef struct OpaqueJSValue* JSValueRef; | |
typedef struct OpaqueJSString* JSStringRef; | |
typedef struct OpaqueJSClass* JSClassRef; | |
typedef struct OpaqueJSContext* JSContextRef; | |
typedef struct OpaqueJSContext* JSGlobalContextRef; | |
typedef enum { | |
kJSTypeUndefined, | |
kJSTypeNull, | |
kJSTypeBoolean, | |
kJSTypeNumber, | |
kJSTypeString, | |
kJSTypeObject | |
} JSType; | |
]] | |
local Context = {} | |
Context.__index = Context | |
ffi.cdef [[ | |
typedef struct GObjectInternal WebKitWebFrame; | |
JSGlobalContextRef webkit_web_frame_get_global_context(WebKitWebFrame *frame); | |
]] | |
function Context:new(web_view) | |
local instance = {} | |
instance.context = ffi.C.webkit_web_frame_get_global_context(web_view:get_main_frame()._native) | |
setmetatable(instance, self) | |
return instance | |
end | |
ffi.cdef [[ | |
JSValueRef JSEvaluateScript(JSContextRef ctx, JSStringRef script, JSObjectRef thisObject, | |
JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception) | |
]] | |
function Context:eval(script, url, line) | |
local script = Context.make_string(script) | |
local url = url and Context.make_string(url) | |
local line = line or 0 | |
local exception = ffi.new("JSValueRef[1]") | |
local result = self:get_value(ffi.C.JSEvaluateScript(self.context, script, nil, url, line, exception)) | |
if exception[0] ~= nil then | |
return result, self:get_value(exception[0]) | |
end | |
return result | |
end | |
ffi.cdef "JSStringRef JSStringCreateWithUTF8CString(const char* string)" | |
function Context.make_string(str) | |
return ffi.gc(ffi.C.JSStringCreateWithUTF8CString(str), ffi.C.JSStringRelease) | |
end | |
ffi.cdef [[ | |
JSValueRef JSValueMakeNull(JSContextRef ctx); | |
JSValueRef JSValueMakeBoolean(JSContextRef ctx, bool value); | |
JSValueRef JSValueMakeNumber(JSContextRef ctx, double value); | |
JSValueRef JSValueMakeString(JSContextRef ctx, JSStringRef string); | |
]] | |
function Context:make_value(obj) | |
if type(obj) == "nil" then | |
return ffi.C.JSValueMakeNull(self.context) | |
elseif type(obj) == "boolean" then | |
return ffi.C.JSValueMakeBoolean(self.context, obj) | |
elseif type(obj) == "number" then | |
return ffi.C.JSValueMakeNumber(self.context, obj) | |
elseif type(obj) == "string" then | |
return ffi.C.JSValueMakeNumber(self.context, Context.make_string(obj)) | |
end | |
-- table is not supported | |
end | |
ffi.cdef "JSValueRef JSValueMakeFromJSONString(JSContextRef ctx, JSStringRef string)" | |
function Context:make_object(json) | |
return ffi.C.JSValueMakeFromJSONString(self.context, Context.make_string(json)) | |
end | |
ffi.cdef "JSType JSValueGetType(JSContextRef ctx, JSValueRef value)" | |
function Context:value_type(value) | |
local type = ffi.C.JSValueGetType(self.context, value) | |
if type == ffi.C.kJSTypeUndefined then | |
return "undefined" | |
elseif type == ffi.C.kJSTypeNull then | |
return "nil" | |
elseif type == ffi.C.kJSTypeBoolean then | |
return "boolean" | |
elseif type == ffi.C.kJSTypeNumber then | |
return "number" | |
elseif type == ffi.C.kJSTypeString then | |
return "string" | |
elseif type == ffi.C.kJSTypeObject then | |
return "object" | |
end | |
end | |
ffi.cdef [[ | |
size_t JSStringGetMaximumUTF8CStringSize(JSStringRef string); | |
size_t JSStringGetUTF8CString(JSStringRef string, char* buffer, size_t bufferSize); | |
void JSStringRelease(JSStringRef string); | |
]] | |
function Context.get_string(jsstr) | |
local len = ffi.C.JSStringGetMaximumUTF8CStringSize(jsstr) | |
local str = ffi.new("char[?]", len) | |
ffi.C.JSStringGetUTF8CString(jsstr, str, len) | |
return ffi.string(str, len) | |
end | |
ffi.cdef [[ | |
bool JSValueToBoolean(JSContextRef ctx, JSValueRef value); | |
double JSValueToNumber(JSContextRef ctx, JSValueRef value, JSValueRef* exception); | |
JSStringRef JSValueToStringCopy(JSContextRef ctx, JSValueRef value, JSValueRef* exception); | |
]] | |
function Context:get_value(value) | |
local type = ffi.C.JSValueGetType(self.context, value) | |
local exception = ffi.new("JSValueRef[1]") | |
local result | |
if type == ffi.C.kJSTypeUndefined or type == ffi.C.kJSTypeNull then | |
result = nil | |
elseif type == ffi.C.kJSTypeBoolean then | |
result = ffi.C.JSValueToBoolean(self.context, value) | |
elseif type == ffi.C.kJSTypeNumber then | |
result = ffi.C.JSValueToNumber(self.context, value, exception) | |
elseif type == ffi.C.kJSTypeString or type == ffi.C.kJSTypeObject then | |
local jsstr = ffi.gc(ffi.C.JSValueToStringCopy(self.context, value, exception), | |
ffi.C.JSStringRelease) | |
result = Context.get_string(jsstr) | |
end | |
if exception[0] ~= nil then | |
return result, self:get_value(exception[0]) | |
end | |
return result | |
end | |
local jscore = {} | |
jscore.Context = Context | |
return jscore |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment