1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-12-04 14:46:47 -05:00

SMJS: add session object

Add session_class, which defines a JSObject wrapper for struct session.

Add location_array_class, which defines a JSObject wrapper for struct
ses_history.  The "history" member of struct session is a struct
ses_history, which is a linked list of struct location.

Add a pointer from struct session to the session_class object and the
location_array object.

Add smjs_get_session_object to return a session_class JSObject wrapper for
a given struct session.

Add smjs_get_session_location_array_object to return a location_array_class
JSObject wrapper for a given struct session.

Add "session" property to the "elinks" object, which uses
smjs_get_session_object to get a JSObject wrapper for smjs_ses.

Add smjs_location_array_get_property, which allows indexing
a location_array object using a positive number for history forward or
a negative number for history backward.

Add session_props, session_get_property, session_set_property,
session_funcs, smjs_session_goto_url (which implements the "goto" method),
and smjs_init_session_interface for session_class.

Add session_construct, which creates a new tab and returns the JSObject
session_class wrapper.

Add session_finalize and smjs_location_array_finalize, which clear the
pointers between struct session and the JSObject wrappers in question.

Add smjs_detach_session_object, which clears the pointers between a given
struct session and the corresponding JSObject wrappers.

In destroy_session, call smjs_detach_session_object.

Add jsval_to_object helper in ecmascript/spidermonkey/util.h;
jsval_to_object is used in smjs_session_goto_url.

Modify delayed_goto_uri_frame to allow the target to be NULL.
smjs_session_goto_url needs this modification.
This commit is contained in:
Miciah Dashiel Butler Masters 2011-11-13 07:12:08 +00:00
parent 3932af9b17
commit cdad9adf19
9 changed files with 709 additions and 3 deletions

View File

@ -65,4 +65,16 @@ jsval_to_boolean(JSContext *ctx, jsval *vp)
return JSVAL_TO_BOOLEAN(val);
}
static inline JSObject *
jsval_to_object(JSContext *ctx, jsval *vp)
{
jsval val;
if (JS_ConvertValue(ctx, *vp, JSTYPE_OBJECT, &val) == JS_FALSE) {
return NULL;
}
return JSVAL_TO_OBJECT(val);
}
#endif

View File

@ -5,6 +5,6 @@ INCLUDES += $(SPIDERMONKEY_CFLAGS)
OBJS = smjs.o core.o global_object.o hooks.o elinks_object.o cache_object.o \
view_state_object.o action_object.o bookmarks.o globhist.o \
keybinding.o load_uri.o
keybinding.o load_uri.o session_object.o
include $(top_srcdir)/Makefile.lib

View File

@ -9,6 +9,7 @@
#include "bfu/msgbox.h"
#include "config/home.h"
#include "ecmascript/spidermonkey-shared.h"
#include "ecmascript/spidermonkey/util.h"
#include "intl/gettext/libintl.h"
#include "protocol/uri.h"
#include "scripting/scripting.h"
@ -20,6 +21,7 @@
#include "scripting/smjs/globhist.h"
#include "scripting/smjs/keybinding.h"
#include "scripting/smjs/load_uri.h"
#include "scripting/smjs/session_object.h"
#include "scripting/smjs/view_state_object.h"
#include "session/location.h"
#include "session/session.h"
@ -87,11 +89,13 @@ elinks_execute(JSContext *ctx, uintN argc, jsval *rval)
enum elinks_prop {
ELINKS_HOME,
ELINKS_LOCATION,
ELINKS_SESSION,
};
static const JSPropertySpec elinks_props[] = {
{ "home", ELINKS_HOME, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY },
{ "location", ELINKS_LOCATION, JSPROP_ENUMERATE | JSPROP_PERMANENT },
{ "session", ELINKS_SESSION, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY },
{ NULL }
};
@ -133,6 +137,18 @@ elinks_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp)
return JS_TRUE;
}
case ELINKS_SESSION: {
JSObject *jsobj;
if (!smjs_ses) return JS_FALSE;
jsobj = smjs_get_session_object(smjs_ses);
if (!jsobj) return JS_FALSE;
object_to_jsval(ctx, vp, jsobj);
return JS_TRUE;
}
default:
INTERNAL("Invalid ID %d in elinks_get_property().",
JSID_TO_INT(id));
@ -218,6 +234,7 @@ smjs_init_elinks_object(void)
smjs_init_keybinding_interface();
smjs_init_load_uri_interface();
smjs_init_view_state_interface();
smjs_init_session_interface();
}
/* If elinks.<method> is defined, call it with the given arguments,

View File

@ -0,0 +1,645 @@
/* Exports struct session to the world of ECMAScript */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "elinks.h"
#include "ecmascript/spidermonkey/util.h"
#include "main/select.h"
#include "protocol/uri.h"
#include "scripting/smjs/core.h"
#include "scripting/smjs/elinks_object.h"
#include "scripting/smjs/global_object.h"
#include "scripting/smjs/session_object.h"
#include "scripting/smjs/view_state_object.h"
#include "session/history.h"
#include "session/location.h"
#include "session/session.h"
#include "session/task.h"
#include "terminal/tab.h"
#include "util/error.h"
#include "util/memory.h"
#include "viewer/text/vs.h"
static JSObject *smjs_session_object;
static const JSClass session_class; /* Defined below. */
static const JSClass location_array_class; /* Defined below. */
/* location_array_class is the class for array object, the elements of which
* correspond to the elements of session.history.
*
* session_class.history returns a location_array_class object, so define
* location_array_class and related routines before session_class. */
/* @location_array.getProperty */
static JSBool
smjs_location_array_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp)
{
struct session *ses;
int index;
struct location *loc;
/* This can be called if @obj if not itself an instance of the
* appropriate class but has one in its prototype chain. Fail
* such calls. */
if (!JS_InstanceOf(ctx, obj, (JSClass *) &location_array_class, NULL))
return JS_FALSE;
ses = JS_GetInstancePrivate(ctx, obj,
(JSClass *) &location_array_class, NULL);
if (!ses) return JS_FALSE;
undef_to_jsval(ctx, vp);
if (!JSID_IS_INT(id))
return JS_FALSE;
assert(ses);
if_assert_failed return JS_TRUE;
if (!have_location(ses)) return JS_FALSE;
index = JSID_TO_INT(id);
for (loc = cur_loc(ses);
loc != (struct location *) &ses->history.history;
loc = index > 0 ? loc->next : loc->prev) {
if (!index) {
JSObject *obj = smjs_get_view_state_object(&loc->vs);
if (obj) object_to_jsval(ctx, vp, obj);
return JS_TRUE;
}
index += index > 0 ? -1 : 1;
}
return JS_FALSE;
}
/** Pointed to by location_array_class.finalize. SpiderMonkey automatically
* finalizes all objects before it frees the JSRuntime, so
* session.history_jsobject won't be left dangling. */
static void
smjs_location_array_finalize(JSContext *ctx, JSObject *obj)
{
struct session *ses;
assert(JS_InstanceOf(ctx, obj, (JSClass *) &location_array_class, NULL));
if_assert_failed return;
ses = JS_GetInstancePrivate(ctx, obj,
(JSClass *) &location_array_class, NULL);
if (!ses) return; /* already detached */
JS_SetPrivate(ctx, obj, NULL); /* perhaps not necessary */
assert(ses->history_jsobject == obj);
if_assert_failed return;
ses->history_jsobject = NULL;
}
static const JSClass location_array_class = {
"location_array",
JSCLASS_HAS_PRIVATE, /* struct session *; a weak reference */
JS_PropertyStub, JS_PropertyStub,
smjs_location_array_get_property, JS_StrictPropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, smjs_location_array_finalize,
};
/** Return an SMJS object through which scripts can access @a ses.history. If
* there already is such an object, return that; otherwise create a new one.
* The SMJS object holds only a weak reference to @a ses. */
JSObject *
smjs_get_session_location_array_object(struct session *ses)
{
JSObject *obj;
if (ses->history_jsobject) return ses->history_jsobject;
assert(smjs_ctx);
if_assert_failed return NULL;
obj = JS_NewObject(smjs_ctx, (JSClass *) &location_array_class, NULL, NULL);
if (!obj) return NULL;
/* Do this last, so that if any previous step fails, we can
* just forget the object and its finalizer won't attempt to
* access @ses. */
if (JS_FALSE == JS_SetPrivate(smjs_ctx, obj, ses))
return NULL;
ses->history_jsobject = obj;
return obj;
}
/* There is no smjs_detach_session_location_array_object because
* smjs_detach_session_object detaches both session.jsobject and
* session.history.js_object. */
enum session_prop {
SESSION_VISITED,
SESSION_HISTORY,
SESSION_LOADING_URI,
SESSION_RELOADLEVEL,
SESSION_REDIRECT_CNT,
/* XXX: SESSION_DOC_VIEW, */
/* XXX: SESSION_FRAMES, */
SESSION_SEARCH_DIRECTION,
SESSION_KBDPREFIX,
SESSION_MARK_WAITING_FOR,
SESSION_EXIT_QUERY,
SESSION_INSERT_MODE,
SESSION_NAVIGATE_MODE,
SESSION_SEARCH_WORD,
SESSION_LAST_SEARCH_WORD,
/* XXX: SESSION_TYPE_QUERIES, */
};
static const JSPropertySpec session_props[] = {
{ "visited", SESSION_VISITED, JSPROP_ENUMERATE },
{ "history", SESSION_HISTORY, JSPROP_ENUMERATE | JSPROP_READONLY },
{ "loading_uri", SESSION_LOADING_URI, JSPROP_ENUMERATE | JSPROP_READONLY },
{ "reloadlevel", SESSION_RELOADLEVEL, JSPROP_ENUMERATE },
{ "redirect_cnt", SESSION_REDIRECT_CNT, JSPROP_ENUMERATE },
/* XXX: { "doc_view", SESSION_DOC_VIEW, JSPROP_ENUMERATE | JSPROP_READONLY }, */
/* XXX: { "frames", SESSION_FRAMES, JSPROP_ENUMERATE | JSPROP_READONLY }, */
{ "search_direction", SESSION_SEARCH_DIRECTION, JSPROP_ENUMERATE },
{ "kbdprefix", SESSION_KBDPREFIX, JSPROP_ENUMERATE },
{ "mark", SESSION_MARK_WAITING_FOR, JSPROP_ENUMERATE },
{ "exit_query", SESSION_EXIT_QUERY, JSPROP_ENUMERATE | JSPROP_READONLY },
{ "insert_mode", SESSION_INSERT_MODE, JSPROP_ENUMERATE },
{ "navigate_mode", SESSION_NAVIGATE_MODE, JSPROP_ENUMERATE },
{ "search_word", SESSION_SEARCH_WORD, JSPROP_ENUMERATE },
{ "last_search_word", SESSION_LAST_SEARCH_WORD, JSPROP_ENUMERATE },
/* XXX: { "type_queries", SESSION_TYPE_QUERIES, JSPROP_ENUMERATE }, */
{ NULL }
};
/* @session_class.getProperty */
static JSBool
session_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp)
{
struct session *ses;
/* This can be called if @obj if not itself an instance of the
* appropriate class but has one in its prototype chain. Fail
* such calls. */
if (!JS_InstanceOf(ctx, obj, (JSClass *) &session_class, NULL))
return JS_FALSE;
ses = JS_GetInstancePrivate(ctx, obj,
(JSClass *) &session_class, NULL);
if (!ses) return JS_FALSE;
if (!JSID_IS_INT(id)) {
/* Note: If we return JS_FALSE here, the object's methods do not
* work. */
return JS_TRUE;
}
/* XXX: Lock session here if it is ever changed to have an OBJECT_HEAD. */
undef_to_jsval(ctx, vp);
switch (JSID_TO_INT(id)) {
case SESSION_VISITED:
int_to_jsval(ctx, vp, ses->status.visited);
return JS_TRUE;
case SESSION_HISTORY: {
JSObject *obj = smjs_get_session_location_array_object(ses);
if (obj) object_to_jsval(ctx, vp, obj);
return JS_TRUE;
}
case SESSION_LOADING_URI: {
struct uri *uri = have_location(ses) ? cur_loc(ses)->vs.uri
: ses->loading_uri;
if (uri) string_to_jsval(ctx, vp, struri(uri));
return JS_TRUE;
}
case SESSION_RELOADLEVEL:
int_to_jsval(ctx, vp, ses->reloadlevel);
return JS_TRUE;
case SESSION_REDIRECT_CNT:
int_to_jsval(ctx, vp, ses->redirect_cnt);
return JS_TRUE;
case SESSION_SEARCH_DIRECTION:
string_to_jsval(ctx, vp, ses->search_direction == 1 ? "down"
: "up");
return JS_TRUE;
case SESSION_KBDPREFIX:
int_to_jsval(ctx, vp, ses->kbdprefix.repeat_count);
return JS_TRUE;
case SESSION_MARK_WAITING_FOR:
string_to_jsval(ctx, vp, ses->kbdprefix.mark == KP_MARK_NOTHING
? "nothing"
: ses->kbdprefix.mark == KP_MARK_SET
? "set"
: "goto");
return JS_TRUE;
case SESSION_EXIT_QUERY:
int_to_jsval(ctx, vp, ses->exit_query);
return JS_TRUE;
case SESSION_INSERT_MODE:
string_to_jsval(ctx, vp,
ses->insert_mode == INSERT_MODE_LESS
? "disabled"
: ses->insert_mode == INSERT_MODE_ON
? "on"
: "off");
return JS_TRUE;
case SESSION_NAVIGATE_MODE:
string_to_jsval(ctx, vp,
ses->navigate_mode == NAVIGATE_CURSOR_ROUTING
? "cursor"
: "linkwise");
return JS_TRUE;
case SESSION_SEARCH_WORD:
string_to_jsval(ctx, vp, ses->search_word);
return JS_TRUE;
case SESSION_LAST_SEARCH_WORD:
string_to_jsval(ctx, vp, ses->last_search_word);
return JS_TRUE;
default:
INTERNAL("Invalid ID %d in session_get_property().",
JSID_TO_INT(id));
}
return JS_FALSE;
}
static JSBool
session_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
{
struct session *ses;
/* This can be called if @obj if not itself an instance of the
* appropriate class but has one in its prototype chain. Fail
* such calls. */
if (!JS_InstanceOf(ctx, obj, (JSClass *) &session_class, NULL))
return JS_FALSE;
ses = JS_GetInstancePrivate(ctx, obj,
(JSClass *) &session_class, NULL);
if (!ses) return JS_FALSE;
if (!JSID_IS_INT(id))
return JS_FALSE;
switch (JSID_TO_INT(id)) {
case SESSION_VISITED:
ses->status.visited = atol(jsval_to_string(ctx, vp));
return JS_TRUE;
/* SESSION_HISTORY is RO */
/* SESSION_LOADING_URI is RO */
case SESSION_RELOADLEVEL:
ses->reloadlevel = atol(jsval_to_string(ctx, vp));
return JS_TRUE;
case SESSION_REDIRECT_CNT:
ses->redirect_cnt = atol(jsval_to_string(ctx, vp));
return JS_TRUE;
case SESSION_SEARCH_DIRECTION: {
unsigned char *str;
JSString *jsstr;
jsstr = JS_ValueToString(ctx, *vp);
if (!jsstr) return JS_TRUE;
str = JS_EncodeString(ctx, jsstr);
if (!str) return JS_TRUE;
if (!strcmp(str, "up"))
ses->search_direction = -1;
else if (!strcmp(str, "down"))
ses->search_direction = 1;
else
return JS_FALSE;
return JS_TRUE;
}
case SESSION_KBDPREFIX:
ses->kbdprefix.repeat_count = atol(jsval_to_string(ctx, vp));
return JS_TRUE;
case SESSION_MARK_WAITING_FOR: {
unsigned char *str;
JSString *jsstr;
jsstr = JS_ValueToString(ctx, *vp);
if (!jsstr) return JS_TRUE;
str = JS_EncodeString(ctx, jsstr);
if (!str) return JS_TRUE;
if (!strcmp(str, "nothing"))
ses->kbdprefix.mark = KP_MARK_NOTHING;
else if (!strcmp(str, "set"))
ses->kbdprefix.mark = KP_MARK_SET;
else if (!strcmp(str, "goto"))
ses->kbdprefix.mark = KP_MARK_GOTO;
else
return JS_FALSE;
return JS_TRUE;
}
/* SESSION_EXIT_QUERY is RO */
case SESSION_INSERT_MODE: {
unsigned char *str;
JSString *jsstr;
jsstr = JS_ValueToString(ctx, *vp);
if (!jsstr) return JS_TRUE;
str = JS_EncodeString(ctx, jsstr);
if (!str) return JS_TRUE;
if (!strcmp(str, "disabled"))
ses->insert_mode = INSERT_MODE_LESS;
else if (!strcmp(str, "on"))
ses->insert_mode = INSERT_MODE_ON;
else if (!strcmp(str, "off"))
ses->insert_mode = INSERT_MODE_OFF;
else
return JS_FALSE;
return JS_TRUE;
}
case SESSION_NAVIGATE_MODE: {
unsigned char *str;
JSString *jsstr;
jsstr = JS_ValueToString(ctx, *vp);
if (!jsstr) return JS_TRUE;
str = JS_EncodeString(ctx, jsstr);
if (!str) return JS_TRUE;
if (!strcmp(str, "cursor"))
ses->navigate_mode = NAVIGATE_CURSOR_ROUTING;
else if (!strcmp(str, "linkwise"))
ses->navigate_mode = NAVIGATE_LINKWISE;
else
return JS_FALSE;
return JS_TRUE;
}
case SESSION_SEARCH_WORD: {
unsigned char *str;
JSString *jsstr;
jsstr = JS_ValueToString(ctx, *vp);
if (!jsstr) return JS_TRUE;
str = JS_EncodeString(ctx, jsstr);
if (!str) return JS_TRUE;
mem_free_set(&ses->search_word, str);
return JS_TRUE;
}
case SESSION_LAST_SEARCH_WORD: {
unsigned char *str;
JSString *jsstr;
jsstr = JS_ValueToString(ctx, *vp);
if (!jsstr) return JS_TRUE;
str = JS_EncodeString(ctx, jsstr);
if (!str) return JS_TRUE;
mem_free_set(&ses->last_search_word, str);
return JS_TRUE;
}
default:
INTERNAL("Invalid ID %d in session_set_property().",
JSID_TO_INT(id));
}
return JS_FALSE;
}
/** Pointed to by session_class.construct. Create a new session (tab)
* and return the JSObject wrapper. */
static JSBool
session_construct(JSContext *ctx, uintN argc, jsval *rval)
{
jsval val;
jsval *argv = JS_ARGV(ctx, rval);
int bg; /* open new tab in background */
struct session *ses;
JSObject *jsobj;
if (argc > 1) {
return JS_TRUE;
}
if (argc >= 1) {
bg = jsval_to_boolean(ctx, &argv[0]);
}
if (!smjs_ses) return JS_FALSE;
ses = init_session(smjs_ses, smjs_ses->tab->term, NULL, bg);
if (!ses) return JS_FALSE;
jsobj = smjs_get_session_object(ses);
if (!jsobj) return JS_FALSE;
object_to_jsval(ctx, &val, jsobj);
JS_SET_RVAL(ctx, rval, val);
return JS_TRUE;
}
/** Pointed to by session_class.finalize. SpiderMonkey automatically
* finalizes all objects before it frees the JSRuntime, so session.jsobject
* won't be left dangling. */
static void
session_finalize(JSContext *ctx, JSObject *obj)
{
struct session *ses;
assert(JS_InstanceOf(ctx, obj, (JSClass *) &session_class, NULL));
if_assert_failed return;
ses = JS_GetInstancePrivate(ctx, obj,
(JSClass *) &session_class, NULL);
if (!ses) return; /* already detached */
JS_SetPrivate(ctx, obj, NULL); /* perhaps not necessary */
assert(ses->jsobject == obj);
if_assert_failed return;
ses->jsobject = NULL;
}
static const JSClass session_class = {
"session",
JSCLASS_HAS_PRIVATE, /* struct session *; a weak reference */
JS_PropertyStub, JS_PropertyStub,
session_get_property, session_set_property,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, session_finalize,
NULL, NULL, session_construct
};
/** Return an SMJS object through which scripts can access @a ses.
* If there already is such an object, return that; otherwise create a
* new one. The SMJS object holds only a weak reference to @a ses. */
JSObject *
smjs_get_session_object(struct session *ses)
{
JSObject *obj;
if (ses->jsobject) return ses->jsobject;
assert(smjs_ctx);
if_assert_failed return NULL;
obj = JS_NewObject(smjs_ctx, (JSClass *) &session_class, NULL, NULL);
if (!obj) return NULL;
if (JS_FALSE == JS_DefineProperties(smjs_ctx, obj,
(JSPropertySpec *) session_props))
return NULL;
/* Do this last, so that if any previous step fails, we can
* just forget the object and its finalizer won't attempt to
* access @ses. */
if (JS_FALSE == JS_SetPrivate(smjs_ctx, obj, ses)) /* to @session_class */
return NULL;
ses->jsobject = obj;
return obj;
}
/** Ensure that no JSObject contains the pointer @a ses. This is
* called from destroy_session before @a ses is freed. If a JSObject was
* previously attached to the session object, the object will remain in
* memory but it will no longer be able to access the session object. */
void
smjs_detach_session_object(struct session *ses)
{
assert(smjs_ctx);
assert(ses);
if_assert_failed return;
if (ses->jsobject) {
assert(JS_GetInstancePrivate(smjs_ctx, ses->jsobject,
(JSClass *) &session_class, NULL)
== ses);
if_assert_failed {}
JS_SetPrivate(smjs_ctx, ses->jsobject, NULL);
ses->jsobject = NULL;
}
if (ses->history_jsobject) {
assert(JS_GetInstancePrivate(smjs_ctx, ses->history_jsobject,
(JSClass *) &location_array_class,
NULL)
== ses);
if_assert_failed {}
JS_SetPrivate(smjs_ctx, ses->history_jsobject, NULL);
ses->history_jsobject = NULL;
}
}
static JSBool
smjs_session_goto_url(JSContext *ctx, uintN argc, jsval *rval)
{
jsval val;
struct delayed_open *deo;
struct uri *uri;
jsval *argv = JS_ARGV(ctx, rval);
JSString *jsstr;
unsigned char *url;
struct session *ses;
struct JSObject *this;
if (argc != 1) return JS_FALSE;
this = jsval_to_object(ctx, &argv[-1]);
if (!JS_InstanceOf(ctx, this, (JSClass *) &session_class, NULL))
return JS_FALSE;
ses = JS_GetInstancePrivate(ctx, this,
(JSClass *) &session_class, NULL);
if (!ses) return JS_FALSE; /* detached */
jsstr = JS_ValueToString(ctx, argv[0]);
if (!jsstr) return JS_FALSE;
url = JS_EncodeString(ctx, jsstr);
if (!url) return JS_FALSE;
uri = get_uri(url, 0);
if (!uri) return JS_FALSE;
deo = mem_calloc(1, sizeof(*deo));
if (!deo) {
done_uri(uri);
return JS_FALSE;
}
deo->ses = ses;
deo->uri = get_uri_reference(uri);
/* deo->target = NULL; */
register_bottom_half(delayed_goto_uri_frame, deo);
undef_to_jsval(ctx, &val);
JS_SET_RVAL(ctx, rval, val);
done_uri(uri);
return JS_TRUE;
}
static const spidermonkeyFunctionSpec session_funcs[] = {
{ "goto", smjs_session_goto_url, 1 },
{ NULL }
};
void
smjs_init_session_interface(void)
{
JSObject *jsobj;
assert(smjs_ctx);
assert(smjs_global_object);
smjs_session_object =
spidermonkey_InitClass(smjs_ctx, smjs_global_object, NULL,
(JSClass *) &session_class, session_construct,
0, (JSPropertySpec *) session_props,
session_funcs, NULL, NULL);
}

View File

@ -0,0 +1,16 @@
#ifndef EL__SCRIPTING_SMJS_SESSION_OBJECT_H
#define EL__SCRIPTING_SMJS_SESSION_OBJECT_H
#include "ecmascript/spidermonkey-shared.h"
struct session;
struct terminal;
JSObject *smjs_get_session_object(struct session *ses);
JSObject *smjs_get_session_array_object(struct terminal *term);
void smjs_detach_session_array_object(struct terminal *term);
void smjs_init_session_interface(void);
#endif

View File

@ -3,6 +3,7 @@
struct module;
struct cache_entry;
struct session;
extern struct module smjs_scripting_module;
@ -12,4 +13,6 @@ extern struct module smjs_scripting_module;
* scripting modules have pointers from there to their objects. */
void smjs_detach_cache_entry_object(struct cache_entry *cached);
void smjs_detach_session_object(struct session *ses);
#endif

View File

@ -33,6 +33,9 @@
#include "osdep/newwin.h"
#include "protocol/protocol.h"
#include "protocol/uri.h"
#ifdef CONFIG_SCRIPTING_SPIDERMONKEY
# include "scripting/smjs/smjs.h"
#endif
#include "session/download.h"
#include "session/history.h"
#include "session/location.h"
@ -1178,6 +1181,9 @@ destroy_session(struct session *ses)
assert(ses);
if_assert_failed return;
#ifdef CONFIG_SCRIPTING_SPIDERMONKEY
smjs_detach_session_object(ses);
#endif
destroy_downloads(ses);
abort_loading(ses, 0);
free_files(ses);

View File

@ -134,6 +134,10 @@ struct session {
LIST_HEAD(struct session);
#ifdef CONFIG_SCRIPTING_SPIDERMONKEY
struct JSObject *jsobject; /* Instance of session_class */
#endif
/** @name The vital session data
* @{ */
@ -148,6 +152,9 @@ struct session {
* @{ */
struct ses_history history;
#ifdef CONFIG_SCRIPTING_SPIDERMONKEY
struct JSObject *history_jsobject; /* Instance of location_array_class */
#endif
/** @} @name The current document

View File

@ -702,14 +702,14 @@ delayed_goto_uri_frame(void *data)
struct frame *frame;
assert(deo);
frame = ses_find_frame(deo->ses, deo->target);
frame = deo->target ? ses_find_frame(deo->ses, deo->target) : NULL;
if (frame)
goto_uri_frame(deo->ses, deo->uri, frame->name, CACHE_MODE_NORMAL);
else {
goto_uri_frame(deo->ses, deo->uri, NULL, CACHE_MODE_NORMAL);
}
done_uri(deo->uri);
mem_free(deo->target);
mem_free_if(deo->target);
mem_free(deo);
}