summaryrefslogtreecommitdiff
path: root/src/scripts.c
diff options
context:
space:
mode:
authorportix <none@none>2013-02-21 18:58:14 +0100
committerportix <none@none>2013-02-21 18:58:14 +0100
commit085ccf8c2f3e1f961e73bfe06dd109656b8c8c11 (patch)
tree160e1b38f6012b59ccfed4b9fe16e3a0979715a0 /src/scripts.c
parent6450b18eed2fb7793cc946980d116dce43363d84 (diff)
downloaddwb-085ccf8c2f3e1f961e73bfe06dd109656b8c8c11.zip
Use read-write lock instead of mutex to lock the global context; reload userscripts that use the javascript api
Diffstat (limited to 'src/scripts.c')
-rw-r--r--src/scripts.c366
1 files changed, 266 insertions, 100 deletions
diff --git a/src/scripts.c b/src/scripts.c
index 94a7f0f6..504d4dc8 100644
--- a/src/scripts.c
+++ b/src/scripts.c
@@ -16,11 +16,13 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#define _XOPEN_SOURCE 600
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <math.h>
#include <sys/wait.h>
+#include <errno.h>
#include <JavaScriptCore/JavaScript.h>
#include <glib.h>
#include "dwb.h"
@@ -40,13 +42,19 @@
#define EXCEPTION(X) "DWB EXCEPTION : "X
#define PROP_LENGTH 128
#define G_FILE_TEST_VALID (G_FILE_TEST_IS_REGULAR | G_FILE_TEST_IS_SYMLINK | G_FILE_TEST_IS_DIR | G_FILE_TEST_IS_EXECUTABLE | G_FILE_TEST_EXISTS)
+#define TRY_CONTEXT_LOCK (pthread_rwlock_tryrdlock(&s_context_lock) != EBUSY && s_global_context != NULL)
+#define CONTEXT_UNLOCK (pthread_rwlock_unlock(&s_context_lock))
-static pthread_mutex_t s_context_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_rwlock_t s_context_lock = PTHREAD_RWLOCK_INITIALIZER;
typedef struct Sigmap_s {
int sig;
const char *name;
} Sigmap;
+typedef struct SigData_s {
+ gulong id;
+ GObject *instance;
+} SigData;
typedef struct _CallbackData CallbackData;
typedef struct _SSignal SSignal;
@@ -145,9 +153,9 @@ static JSObjectRef s_completion_callback;
static GQuark s_ref_quark;
static JSObjectRef s_init_before, s_init_after;
static JSObjectRef s_constructors[CONSTRUCTOR_LAST];
-static gboolean s_opt_force = false;
static JSObjectRef s_soup_session;
static GSList *s_timers = NULL;
+static GPtrArray *s_gobject_signals = NULL;
/* Only defined once */
static JSValueRef UNDEFINED, NIL;
@@ -345,17 +353,40 @@ deferred_reject(JSContextRef ctx, JSObjectRef f, JSObjectRef this, size_t argc,
return UNDEFINED;
}/*}}}*/
+void
+sigdata_append(gulong sigid, GObject *instance)
+{
+ SigData *data = g_malloc(sizeof(SigData));
+ data->id = sigid;
+ data->instance = instance;
+ g_ptr_array_add(s_gobject_signals, data);
+
+}
+void
+sigdata_remove(gulong sigid, GObject *instance)
+{
+ for (guint i=0; i<s_gobject_signals->len; i++)
+ {
+ SigData *data = g_ptr_array_index(s_gobject_signals, i);
+ if (data->id == sigid && data->instance == instance)
+ {
+ g_ptr_array_remove_index_fast(s_gobject_signals, i);
+ g_free(data);
+ return;
+ }
+ }
+}
/* CALLBACK {{{*/
/* callback_data_new {{{*/
static CallbackData *
callback_data_new(GObject *gobject, JSObjectRef object, JSObjectRef callback, StopCallbackNotify notify)
{
- CallbackData *c = g_malloc(sizeof(CallbackData));
- c->gobject = gobject != NULL ? g_object_ref(gobject) : NULL;
- pthread_mutex_lock(&s_context_mutex);
- if (s_global_context)
+ CallbackData *c = NULL;
+ if (TRY_CONTEXT_LOCK)
{
+ CallbackData *c = g_malloc(sizeof(CallbackData));
+ c->gobject = gobject != NULL ? g_object_ref(gobject) : NULL;
if (object != NULL)
{
JSValueProtect(s_global_context, object);
@@ -366,9 +397,9 @@ callback_data_new(GObject *gobject, JSObjectRef object, JSObjectRef callback, St
JSValueProtect(s_global_context, callback);
c->callback = callback;
}
+ c->notify = notify;
+ CONTEXT_UNLOCK;
}
- pthread_mutex_unlock(&s_context_mutex);
- c->notify = notify;
return c;
}/*}}}*/
@@ -380,16 +411,15 @@ callback_data_free(CallbackData *c)
{
if (c->gobject != NULL)
g_object_unref(c->gobject);
- pthread_mutex_lock(&s_context_mutex);
- if (s_global_context)
+ if (TRY_CONTEXT_LOCK)
{
if (c->object != NULL)
JSValueUnprotect(s_global_context, c->object);
JSValueUnprotect(s_global_context, c->object);
if (c->object != NULL)
JSValueUnprotect(s_global_context, c->callback);
+ CONTEXT_UNLOCK;
}
- pthread_mutex_unlock(&s_context_mutex);
g_free(c);
}
}/*}}}*/
@@ -399,15 +429,14 @@ ssignal_free(SSignal *sig)
{
if (sig != NULL)
{
- pthread_mutex_lock(&s_context_mutex);
- if (s_global_context)
+ if (TRY_CONTEXT_LOCK)
{
if (sig->func)
JSValueUnprotect(s_global_context, sig->func);
if (sig->object)
JSValueUnprotect(s_global_context, sig->object);
+ CONTEXT_UNLOCK;
}
- pthread_mutex_unlock(&s_context_mutex);
g_free(sig->query);
g_free(sig);
}
@@ -446,14 +475,18 @@ static void
callback(CallbackData *c)
{
gboolean ret = false;
- JSValueRef val[] = { c->object != NULL ? c->object : NIL };
- JSValueRef jsret = JSObjectCallAsFunction(s_global_context, c->callback, NULL, 1, val, NULL);
- if (JSValueIsBoolean(s_global_context, jsret))
- ret = JSValueToBoolean(s_global_context, jsret);
- if (ret || (c != NULL && c->gobject != NULL && c->notify != NULL && c->notify(c)))
+ if (TRY_CONTEXT_LOCK)
{
- g_signal_handlers_disconnect_by_func(c->gobject, callback, c);
- callback_data_free(c);
+ JSValueRef val[] = { c->object != NULL ? c->object : NIL };
+ JSValueRef jsret = JSObjectCallAsFunction(s_global_context, c->callback, NULL, 1, val, NULL);
+ if (JSValueIsBoolean(s_global_context, jsret))
+ ret = JSValueToBoolean(s_global_context, jsret);
+ if (ret || (c != NULL && c->gobject != NULL && c->notify != NULL && c->notify(c)))
+ {
+ g_signal_handlers_disconnect_by_func(c->gobject, callback, c);
+ callback_data_free(c);
+ }
+ CONTEXT_UNLOCK;
}
}/*}}}*/
/*}}}*/
@@ -927,18 +960,20 @@ scripts_eval_key(KeyMap *m, Arg *arg)
char *json = NULL;
if (! (m->map->prop & CP_OVERRIDE))
CLEAR_COMMAND_TEXT();
- if (arg->p == NULL)
- json = util_create_json(1, INTEGER, "nummod", dwb.state.nummod);
- else
- json = util_create_json(2, INTEGER, "nummod", dwb.state.nummod, CHAR, "arg", arg->p);
-
- if (s_global_context)
+ if (TRY_CONTEXT_LOCK)
{
+ if (arg->p == NULL)
+ json = util_create_json(1, INTEGER, "nummod", dwb.state.nummod);
+ else
+ json = util_create_json(2, INTEGER, "nummod", dwb.state.nummod, CHAR, "arg", arg->p);
+
JSValueRef argv[] = { js_json_to_value(s_global_context, json) };
JSObjectCallAsFunction(s_global_context, arg->js, NULL, 1, argv, NULL);
+
+ CONTEXT_UNLOCK;
+ g_free(json);
}
- g_free(json);
return STATUS_OK;
}/*}}}*/
@@ -1142,7 +1177,7 @@ error_out:
/* global_send_request {{{*/
-static JSObjectRef
+static JSValueRef
get_message_data(SoupMessage *msg)
{
const char *name, *value;
@@ -1150,30 +1185,39 @@ get_message_data(SoupMessage *msg)
JSObjectRef o, ho;
JSStringRef s;
- o = JSObjectMake(s_global_context, NULL, NULL);
- js_set_object_property(s_global_context, o, "body", msg->response_body->data, NULL);
+ if (TRY_CONTEXT_LOCK)
+ {
+ o = JSObjectMake(s_global_context, NULL, NULL);
+ js_set_object_property(s_global_context, o, "body", msg->response_body->data, NULL);
- ho = JSObjectMake(s_global_context, NULL, NULL);
+ ho = JSObjectMake(s_global_context, NULL, NULL);
- soup_message_headers_iter_init(&iter, msg->response_headers);
- while (soup_message_headers_iter_next(&iter, &name, &value))
- js_set_object_property(s_global_context, ho, name, value, NULL);
+ soup_message_headers_iter_init(&iter, msg->response_headers);
+ while (soup_message_headers_iter_next(&iter, &name, &value))
+ js_set_object_property(s_global_context, ho, name, value, NULL);
- s = JSStringCreateWithUTF8CString("headers");
- JSObjectSetProperty(s_global_context, o, s, ho, kJSDefaultProperty, NULL);
- JSStringRelease(s);
- return o;
+ s = JSStringCreateWithUTF8CString("headers");
+ JSObjectSetProperty(s_global_context, o, s, ho, kJSDefaultProperty, NULL);
+ JSStringRelease(s);
+ CONTEXT_UNLOCK;
+ return o;
+ }
+ return NIL;
}
static void
request_callback(SoupSession *session, SoupMessage *message, JSObjectRef function)
{
- if (message->response_body->data != NULL)
+ if (TRY_CONTEXT_LOCK)
{
- JSObjectRef o = get_message_data(message);
- JSValueRef vals[] = { o, make_object(s_global_context, G_OBJECT(message)) };
- JSObjectCallAsFunction(s_global_context, function, NULL, 2, vals, NULL);
+ if (message->response_body->data != NULL)
+ {
+ JSValueRef o = get_message_data(message);
+ JSValueRef vals[] = { o, make_object(s_global_context, G_OBJECT(message)) };
+ JSObjectCallAsFunction(s_global_context, function, NULL, 2, vals, NULL);
+ }
+ JSValueUnprotect(s_global_context, function);
+ CONTEXT_UNLOCK;
}
- JSValueUnprotect(s_global_context, function);
}
static void
set_request(JSContextRef ctx, SoupMessage *msg, JSValueRef val, JSValueRef *exc)
@@ -1218,7 +1262,7 @@ global_send_request(JSContextRef ctx, JSObjectRef f, JSObjectRef thisObject, siz
msg = soup_message_new(method == NULL ? "GET" : method, uri);
if (msg == NULL)
goto error_out;
- if (argc > 3 && method != NULL && !strcasecmp("POST", method))
+ if (argc > 3 && method != NULL && !g_ascii_strcasecmp("POST", method))
set_request(ctx, msg, argv[3], exc);
JSValueProtect(ctx, function);
@@ -1237,6 +1281,7 @@ global_send_request_sync(JSContextRef ctx, JSObjectRef f, JSObjectRef thisObject
char *method = NULL, *uri = NULL;
SoupMessage *msg;
guint status;
+ JSValueRef val;
JSObjectRef o;
JSStringRef js_key;
JSValueRef js_value;
@@ -1256,10 +1301,12 @@ global_send_request_sync(JSContextRef ctx, JSObjectRef f, JSObjectRef thisObject
set_request(ctx, msg, argv[2], exc);
status = soup_session_send_message(webkit_get_default_session(), msg);
- o = get_message_data(msg);
+ val = get_message_data(msg);
js_key = JSStringCreateWithUTF8CString("status");
js_value = JSValueMakeNumber(ctx, status);
+
+ o = JSValueToObject(ctx, val, exc);
JSObjectSetProperty(ctx, o, js_key, js_value, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly, exc);
JSStringRelease(js_key);
@@ -1268,11 +1315,15 @@ global_send_request_sync(JSContextRef ctx, JSObjectRef f, JSObjectRef thisObject
void
scripts_completion_activate(void)
{
- const char *text = GET_TEXT();
- JSValueRef val[] = { js_char_to_value(s_global_context, text) };
- JSObjectCallAsFunction(s_global_context, s_completion_callback, NULL, 1, val, NULL);
- completion_clean_completion(false);
- dwb_change_mode(NORMAL_MODE, true);
+ if (TRY_CONTEXT_LOCK)
+ {
+ const char *text = GET_TEXT();
+ JSValueRef val[] = { js_char_to_value(s_global_context, text) };
+ JSObjectCallAsFunction(s_global_context, s_completion_callback, NULL, 1, val, NULL);
+ completion_clean_completion(false);
+ dwb_change_mode(NORMAL_MODE, true);
+ CONTEXT_UNLOCK;
+ }
}
static JSValueRef
global_tab_complete(JSContextRef ctx, JSObjectRef f, JSObjectRef thisObject, size_t argc, const JSValueRef argv[], JSValueRef* exc)
@@ -1336,12 +1387,16 @@ error_out:
static gboolean
timeout_callback(JSObjectRef obj)
{
- gboolean ret;
- JSValueRef val = JSObjectCallAsFunction(s_global_context, obj, NULL, 0, NULL, NULL);
- if (val == NULL)
- ret = false;
- else
- ret = !JSValueIsBoolean(s_global_context, val) || JSValueToBoolean(s_global_context, val);
+ gboolean ret = false;
+ if (TRY_CONTEXT_LOCK)
+ {
+ JSValueRef val = JSObjectCallAsFunction(s_global_context, obj, NULL, 0, NULL, NULL);
+ if (val == NULL)
+ ret = false;
+ else
+ ret = !JSValueIsBoolean(s_global_context, val) || JSValueToBoolean(s_global_context, val);
+ CONTEXT_UNLOCK;
+ }
return ret;
}/*}}}*/
@@ -1371,7 +1426,11 @@ global_timer_stop(JSContextRef ctx, JSObjectRef f, JSObjectRef thisObject, size_
void
timer_stopped_cb(JSObjectRef func)
{
- JSValueUnprotect(s_global_context, func);
+ if (TRY_CONTEXT_LOCK)
+ {
+ JSValueUnprotect(s_global_context, func);
+ CONTEXT_UNLOCK;
+ }
}
/* global_timer_start {{{*/
@@ -1478,11 +1537,13 @@ clipboard_set(JSContextRef ctx, JSObjectRef f, JSObjectRef thisObject, size_t ar
static void
got_clipboard(GtkClipboard *cb, const char *text, JSObjectRef callback)
{
- pthread_mutex_lock(&s_context_mutex);
- JSValueRef args[] = { text == NULL ? NIL : js_char_to_value(s_global_context, text) };
- JSObjectCallAsFunction(s_global_context, callback, NULL, 1, args, NULL);
- JSValueUnprotect(s_global_context, callback);
- pthread_mutex_unlock(&s_context_mutex);
+ if (TRY_CONTEXT_LOCK)
+ {
+ JSValueRef args[] = { text == NULL ? NIL : js_char_to_value(s_global_context, text) };
+ JSObjectCallAsFunction(s_global_context, callback, NULL, 1, args, NULL);
+ JSValueUnprotect(s_global_context, callback);
+ CONTEXT_UNLOCK;
+ }
}
static JSValueRef
clipboard_get(JSContextRef ctx, JSObjectRef f, JSObjectRef thisObject, size_t argc, const JSValueRef argv[], JSValueRef* exc)
@@ -1631,7 +1692,7 @@ spawn_output(GIOChannel *channel, GIOCondition condition, JSObjectRef callback)
g_io_channel_unref(channel);
return false;
}
- else if (g_io_channel_read_to_end(channel, &content, &length, NULL) == G_IO_STATUS_NORMAL && content != NULL)
+ else if (g_io_channel_read_to_end(channel, &content, &length, NULL) == G_IO_STATUS_NORMAL && content != NULL && TRY_CONTEXT_LOCK)
{
JSValueRef arg = js_char_to_value(s_global_context, content);
if (arg != NULL)
@@ -1640,6 +1701,7 @@ spawn_output(GIOChannel *channel, GIOCondition condition, JSObjectRef callback)
JSObjectCallAsFunction(s_global_context, callback, NULL, 1, argv , NULL);
}
g_free(content);
+ CONTEXT_UNLOCK;
return true;
}
return false;
@@ -1688,15 +1750,17 @@ watch_spawn(GPid pid, gint status, JSObjectRef deferred)
else if (WIFSTOPPED(status))
fail = WSTOPSIG(status);
- pthread_mutex_lock(&s_context_mutex);
- if (fail == 0)
- deferred_resolve(s_global_context, NULL, deferred, 0, NULL, NULL);
- else
+ if (TRY_CONTEXT_LOCK)
{
- JSValueRef args[] = { JSValueMakeNumber(s_global_context, fail) };
- deferred_reject(s_global_context, NULL, deferred, 1, args, NULL);
+ if (fail == 0)
+ deferred_resolve(s_global_context, NULL, deferred, 0, NULL, NULL);
+ else
+ {
+ JSValueRef args[] = { JSValueMakeNumber(s_global_context, fail) };
+ deferred_reject(s_global_context, NULL, deferred, 1, args, NULL);
+ }
+ CONTEXT_UNLOCK;
}
- pthread_mutex_unlock(&s_context_mutex);
}
/* system_spawn {{{*/
@@ -1711,9 +1775,13 @@ system_spawn(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, siz
JSObjectRef oc = NULL, ec = NULL;
GPid pid;
+
if (argc == 0)
return NIL;
+ if (!TRY_CONTEXT_LOCK)
+ return ret;
+
if (argc > 1)
{
oc = js_value_to_function(ctx, argv[1], NULL);
@@ -1755,6 +1823,7 @@ system_spawn(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, siz
ret = deferred;
error_out:
+ CONTEXT_UNLOCK;
g_free(cmdline);
g_strfreev(srgv);
return ret;
@@ -2340,6 +2409,10 @@ scripts_emit(ScriptSignal *sig)
if (function == NULL)
return false;
+ if (!TRY_CONTEXT_LOCK)
+ return false;
+
+ gboolean ret = false;
int additional = sig->jsobj != NULL ? 2 : 1;
int numargs = MIN(sig->numobj, SCRIPT_MAX_SIG_OBJECTS)+additional;
JSValueRef val[numargs];
@@ -2362,9 +2435,11 @@ scripts_emit(ScriptSignal *sig)
JSValueRef js_ret = JSObjectCallAsFunction(s_global_context, function, NULL, numargs, val, NULL);
if (JSValueIsBoolean(s_global_context, js_ret))
- return JSValueToBoolean(s_global_context, js_ret);
+ ret = JSValueToBoolean(s_global_context, js_ret);
- return false;
+ CONTEXT_UNLOCK;
+
+ return ret;
}/*}}}*/
/*}}}*/
@@ -2373,13 +2448,12 @@ scripts_emit(ScriptSignal *sig)
static void
object_destroy_cb(JSObjectRef o)
{
- pthread_mutex_lock(&s_context_mutex);
- if (s_global_context)
+ if (TRY_CONTEXT_LOCK)
{
JSObjectSetPrivate(o, NULL);
JSValueUnprotect(s_global_context, o);
+ CONTEXT_UNLOCK;
}
- pthread_mutex_unlock(&s_context_mutex);
}
static JSObjectRef
@@ -2393,7 +2467,7 @@ make_object_for_class(JSContextRef ctx, JSClassRef class, GObject *o, gboolean p
if (protect)
{
g_object_set_qdata_full(o, s_ref_quark, retobj, (GDestroyNotify)object_destroy_cb);
- JSValueProtect(s_global_context, retobj);
+ JSValueProtect(ctx, retobj);
}
else
g_object_set_qdata_full(o, s_ref_quark, retobj, NULL);
@@ -2434,6 +2508,10 @@ connect_callback(SSignal *sig, ...)
va_list args;
JSValueRef cur;
JSValueRef argv[sig->query->n_params + 1];
+ gboolean result = false;
+
+ if (!TRY_CONTEXT_LOCK)
+ return result;
va_start(args, sig);
#define CHECK_NUMBER(GTYPE, TYPE) G_STMT_START if (gtype == G_TYPE_##GTYPE) { \
TYPE MM_value = va_arg(args, TYPE); \
@@ -2485,9 +2563,10 @@ apply:
JSValueRef ret = JSObjectCallAsFunction(s_global_context, sig->func, NULL, sig->query->n_params+1, argv, NULL);
if (JSValueIsBoolean(s_global_context, ret))
{
- return JSValueToBoolean(s_global_context, ret);
+ result = JSValueToBoolean(s_global_context, ret);
}
- return false;
+ CONTEXT_UNLOCK;
+ return result;
}
static void
on_disconnect_object(SSignal *sig, GClosure *closure)
@@ -2496,16 +2575,21 @@ on_disconnect_object(SSignal *sig, GClosure *closure)
}
static void on_disconnect_notify(JSObjectRef func, GClosure *closure)
{
- pthread_mutex_lock(&s_context_mutex);
- if (s_global_context)
+ if (TRY_CONTEXT_LOCK)
+ {
JSValueUnprotect(s_global_context, func);
- pthread_mutex_unlock(&s_context_mutex);
+ CONTEXT_UNLOCK;
+ }
}
static void
notify_callback(GObject *o, GParamSpec *param, JSObjectRef func)
{
- JSValueRef argv[] = { make_object(s_global_context, o) };
- JSObjectCallAsFunction(s_global_context, func, NULL, 1, argv, NULL);
+ if (TRY_CONTEXT_LOCK)
+ {
+ JSValueRef argv[] = { make_object(s_global_context, o) };
+ JSObjectCallAsFunction(s_global_context, func, NULL, 1, argv, NULL);
+ CONTEXT_UNLOCK;
+ }
}
static JSValueRef
gobject_connect(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef* exc)
@@ -2536,8 +2620,9 @@ gobject_connect(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t
if (strncmp(name, "notify::", 8) == 0)
{
- JSValueProtect(s_global_context, func);
+ JSValueProtect(ctx, func);
id = g_signal_connect_data(o, name, G_CALLBACK(notify_callback), func, (GClosureNotify)on_disconnect_notify, flags);
+ sigdata_append(id, o);
}
else
{
@@ -2560,14 +2645,15 @@ gobject_connect(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t
}
sig->func = func;
- JSValueProtect(s_global_context, func);
+ JSValueProtect(ctx, func);
id = g_signal_connect_data(o, name, G_CALLBACK(connect_callback), sig, (GClosureNotify)on_disconnect_object, flags);
if (id > 0)
{
sig->id = id;
- JSValueProtect(s_global_context, this);
+ JSValueProtect(ctx, this);
sig->object = this;
+ sigdata_append(id, o);
}
else
ssignal_free(sig);
@@ -2611,6 +2697,7 @@ gobject_disconnect(JSContextRef ctx, JSObjectRef function, JSObjectRef this, siz
GObject *o = JSObjectGetPrivate(this);
if (o != NULL && g_signal_handler_is_connected(o, id))
{
+ sigdata_remove(id, o);
g_signal_handler_disconnect(o, id);
return JSValueMakeBoolean(ctx, true);
}
@@ -2646,6 +2733,16 @@ create_object(JSContextRef ctx, JSClassRef class, JSObjectRef obj, JSClassAttrib
return ret;
}/*}}}*/
+static void
+finalize(JSObjectRef o)
+{
+ GObject *ob = JSObjectGetPrivate(o);
+ if (ob != NULL)
+ {
+ g_object_steal_qdata(ob, s_ref_quark);
+ }
+}
+
/* set_property {{{*/
static bool
set_property(JSContextRef ctx, JSObjectRef object, JSStringRef js_name, JSValueRef jsvalue, JSValueRef* exception)
@@ -2805,6 +2902,7 @@ create_constructor(JSContextRef ctx, char *name, JSClassRef class, JSObjectCallA
static void
create_global_object()
{
+ pthread_rwlock_wrlock(&s_context_lock);
s_ref_quark = g_quark_from_static_string("dwb_js_ref");
JSStaticValue global_values[] = {
@@ -2931,6 +3029,7 @@ create_global_object()
cd.staticFunctions = default_functions;
cd.getProperty = get_property;
cd.setProperty = set_property;
+ cd.finalize = finalize;
s_gobject_class = JSClassCreate(&cd);
s_constructors[CONSTRUCTOR_DEFAULT] = create_constructor(s_global_context, "GObject", s_gobject_class, NULL, NULL);
@@ -3106,6 +3205,7 @@ create_global_object()
s_soup_session = make_object_for_class(s_global_context, s_gobject_class, G_OBJECT(webkit_get_default_session()), false);
JSValueProtect(s_global_context, s_soup_session);
+ pthread_rwlock_unlock(&s_context_lock);
}/*}}}*/
/*}}}*/
@@ -3179,7 +3279,7 @@ scripts_create_tab(GList *gl)
void
scripts_remove_tab(JSObjectRef obj)
{
- if (obj != NULL)
+ if (obj != NULL && TRY_CONTEXT_LOCK)
{
if (EMIT_SCRIPT(CLOSE_TAB))
{
@@ -3187,6 +3287,7 @@ scripts_remove_tab(JSObjectRef obj)
scripts_emit(&signal);
}
JSValueUnprotect(s_global_context, obj);
+ CONTEXT_UNLOCK;
}
}/*}}}*/
@@ -3210,9 +3311,13 @@ scripts_init_script(const char *path, const char *script)
void
evaluate(const char *script)
{
- JSStringRef js_script = JSStringCreateWithUTF8CString(script);
- JSEvaluateScript(s_global_context, js_script, NULL, NULL, 0, NULL);
- JSStringRelease(js_script);
+ if (TRY_CONTEXT_LOCK)
+ {
+ JSStringRef js_script = JSStringCreateWithUTF8CString(script);
+ JSEvaluateScript(s_global_context, js_script, NULL, NULL, 0, NULL);
+ JSStringRelease(js_script);
+ CONTEXT_UNLOCK;
+ }
}
JSObjectRef
@@ -3228,20 +3333,36 @@ get_private(JSContextRef ctx, char *name)
JSStringRelease(js_name);
return ret;
}
+void
+scripts_reapply()
+{
+ if (scripts_init(false))
+ {
+ for (GList *gl = dwb.state.views; gl; gl=gl->next)
+ {
+ JSObjectRef o = make_object(s_global_context, G_OBJECT(VIEW(gl)->web));
+ JSValueProtect(s_global_context, o);
+ VIEW(gl)->script_wv = o;
+ }
+ apply_scripts();
+ }
+
+}
/* scripts_init {{{*/
-void
+gboolean
scripts_init(gboolean force)
{
dwb.misc.script_signals = 0;
- s_opt_force = force;
if (s_global_context == NULL)
{
if (force)
create_global_object();
else
- return;
+ return false;
}
+ s_gobject_signals = g_ptr_array_new();
+
dwb.state.script_completion = NULL;
char *dir = util_get_data_dir(LIBJS_DIR);
@@ -3269,6 +3390,7 @@ scripts_init(gboolean force)
JSObjectRef o = JSObjectMakeArray(s_global_context, 0, NULL, NULL);
s_array_contructor = js_get_object_property(s_global_context, o, "constructor");
JSValueProtect(s_global_context, s_array_contructor);
+ return true;
}/*}}}*/
gboolean
@@ -3282,19 +3404,63 @@ scripts_execute_one(const char *script)
void
scripts_unbind(JSObjectRef obj)
{
- pthread_mutex_lock(&s_context_mutex);
- if (obj != NULL)
- JSValueUnprotect(s_global_context, obj);
- pthread_mutex_unlock(&s_context_mutex);
+ if (TRY_CONTEXT_LOCK)
+ {
+ if (obj != NULL)
+ JSValueUnprotect(s_global_context, obj);
+ CONTEXT_UNLOCK;
+ }
}
/* scripts_end {{{*/
void
scripts_end()
{
- pthread_mutex_lock(&s_context_mutex);
+ pthread_rwlock_wrlock(&s_context_lock);
if (s_global_context != NULL)
{
+ GList *next, *l;
+
+ next = dwb.override_keys;
+ while (next != NULL)
+ {
+ l = next;
+ next = next->next;
+ KeyMap *m = l->data;
+ if (m->map->prop & CP_SCRIPT)
+ dwb.override_keys = g_list_delete_link(dwb.override_keys, l);
+
+ }
+ next = dwb.keymap;
+ while(next != NULL)
+ {
+ l = next;
+ next = next->next;
+ KeyMap *m = l->data;
+ if (m->map->prop & CP_SCRIPT) {
+ scripts_unbind(m->map->arg.p);
+ g_free(m->map);
+ g_free(m);
+ m = NULL;
+ dwb.keymap = g_list_delete_link(dwb.keymap, l);
+ }
+ }
+ for (GList *gl = dwb.state.views; gl; gl=gl->next)
+ {
+ JSValueUnprotect(s_global_context, VIEW(gl)->script_wv);
+ VIEW(gl)->script_wv = NULL;
+ }
+ for (guint i=0; i<s_gobject_signals->len; i++)
+ {
+ SigData *data = g_ptr_array_index(s_gobject_signals, i);
+ g_signal_handler_disconnect(data->instance, data->id);
+ g_free(data);
+ }
+ g_ptr_array_free(s_gobject_signals, false);
+
+ g_slist_free(s_script_list);
+ s_script_list = NULL;
+ s_gobject_signals = NULL;
for (int i=0; i<CONSTRUCTOR_LAST; i++)
JSValueUnprotect(s_global_context, s_constructors[i]);
for (int i=SCRIPTS_SIG_FIRST; i<SCRIPTS_SIG_LAST; ++i)
@@ -3317,5 +3483,5 @@ scripts_end()
JSGlobalContextRelease(s_global_context);
s_global_context = NULL;
}
- pthread_mutex_unlock(&s_context_mutex);
+ pthread_rwlock_unlock(&s_context_lock);
}/*}}}*//*}}}*/