Created
May 11, 2015 18:40
-
-
Save dannote/ec83a263188e04f84a9b to your computer and use it in GitHub Desktop.
Revisions
-
dannote created this gist
May 11, 2015 .There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,146 @@ 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