Garbage-collect SMJS objects before flushing caches.
[elinks.git] / src / scripting / smjs / hooks.c
blobf2c0289abbcbe1cbc263bb16028c7e57c0a09b7d
1 /* ECMAScript scripting hooks */
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
7 #include "elinks.h"
9 #include "cache/cache.h"
10 #include "ecmascript/spidermonkey/util.h"
11 #include "protocol/uri.h"
12 #include "main/event.h"
13 #include "main/module.h"
14 #include "scripting/smjs/cache_object.h"
15 #include "scripting/smjs/view_state_object.h"
16 #include "scripting/smjs/core.h"
17 #include "scripting/smjs/elinks_object.h"
18 #include "scripting/smjs/hooks.h"
19 #include "session/location.h"
20 #include "session/session.h"
21 #include "viewer/text/vs.h"
24 static enum evhook_status
25 script_hook_url(va_list ap, void *data)
27 unsigned char **url = va_arg(ap, unsigned char **);
28 struct session *ses = va_arg(ap, struct session *);
29 enum evhook_status ret = EVENT_HOOK_STATUS_NEXT;
30 jsval args[1], rval;
32 if (*url == NULL) return EVENT_HOOK_STATUS_NEXT;
34 smjs_ses = ses;
36 args[0] = STRING_TO_JSVAL(JS_NewStringCopyZ(smjs_ctx, *url));
38 if (JS_TRUE == smjs_invoke_elinks_object_method(data, args, 1, &rval)) {
39 if (JSVAL_IS_BOOLEAN(rval)) {
40 if (JS_FALSE == JSVAL_TO_BOOLEAN(rval))
41 ret = EVENT_HOOK_STATUS_LAST;
42 } else {
43 JSString *jsstr = JS_ValueToString(smjs_ctx, rval);
44 unsigned char *str = JS_GetStringBytes(jsstr);
46 mem_free_set(url, stracpy(str));
50 smjs_ses = NULL;
52 return ret;
55 static enum evhook_status
56 script_hook_pre_format_html(va_list ap, void *data)
58 struct session *ses = va_arg(ap, struct session *);
59 struct cache_entry *cached = va_arg(ap, struct cache_entry *);
60 enum evhook_status ret = EVENT_HOOK_STATUS_NEXT;
61 JSObject *cache_entry_object, *view_state_object = JSVAL_NULL;
62 jsval args[2], rval;
64 evhook_use_params(ses && cached);
66 if (!smjs_ctx || !cached->length) goto end;
68 smjs_ses = ses;
70 if (have_location(ses)) {
71 struct view_state *vs = &cur_loc(ses)->vs;
73 view_state_object = smjs_get_view_state_object(vs);
76 cache_entry_object = smjs_get_cache_entry_object(cached);
77 if (!cache_entry_object) goto end;
79 args[0] = OBJECT_TO_JSVAL(cache_entry_object);
80 args[1] = OBJECT_TO_JSVAL(view_state_object);
82 if (JS_TRUE == smjs_invoke_elinks_object_method("preformat_html",
83 args, 2, &rval))
84 if (JS_FALSE == JSVAL_TO_BOOLEAN(rval))
85 ret = EVENT_HOOK_STATUS_LAST;
87 end:
88 smjs_ses = NULL;
89 return ret;
92 static enum evhook_status
93 script_hook_flush_caches(va_list ap, void *data)
95 /* script_hook_pre_format_html() calls smjs_get_cache_entry_object()
96 * for each struct cache_entry. The resulting SMJS objects hold
97 * references to the structs, and these references prevent ELinks
98 * from freeing the cache entries. (The resource info dialog shows
99 * that the entries are "in use".) SMJS does not immediately collect
100 * these objects as garbage. If we're really trying to flush the
101 * caches then ask SMJS to run a check. */
102 if (smjs_ctx)
103 JS_GC(smjs_ctx);
104 return EVENT_HOOK_STATUS_NEXT;
107 struct event_hook_info smjs_scripting_hooks[] = {
108 { "goto-url", 0, script_hook_url, "goto_url_hook" },
109 { "follow-url", 0, script_hook_url, "follow_url_hook" },
110 { "pre-format-html", 0, script_hook_pre_format_html, NULL },
111 { "flush-caches", 0, script_hook_flush_caches, NULL },
113 NULL_EVENT_HOOK_INFO,