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

Changed ecmascript engine to mozjs-17.0.

Was not tested, especially smjs is likely buggy.
This commit is contained in:
Witold Filipczyk 2019-02-10 21:00:37 +01:00
parent 9cebc108fd
commit 25dd2ecae9
30 changed files with 3588 additions and 1094 deletions

View File

@ -608,21 +608,11 @@ case "$with_spidermonkey" in
;; ;;
esac esac
# The SpiderMonkey 1.8.5 standalone sources install mozjs185.pc, for package in mozjs-17.0; do
# but the Debian libmozjs-dev package installs mozilla-js.pc.
# Check mozjs185 first, because it has the version number in the name
# and therefore is less likely to be a newer incompatible version.
# (This configure script rejects older incompatible versions
# but can let newer ones through.)
for package in mozjs185 mozilla-js; do
if test -n "$CONFIG_SPIDERMONKEY"; then if test -n "$CONFIG_SPIDERMONKEY"; then
break break
else else
AC_MSG_CHECKING([for SpiderMonkey (1.8.5 or later) in pkg-config $package]) AC_MSG_CHECKING([for SpiderMonkey (mozjs-17.0) in pkg-config $package])
# In pkg-config 0.25, pkg-config --exists mozjs185
# returns 0 (success) even if mozjs185 depends on
# nspr, which has not been installed. However,
# pkg-config --cflags mozjs185 returns 1 then.
if $PKG_CONFIG --cflags --libs $package > /dev/null 2>&AS_MESSAGE_LOG_FD; then if $PKG_CONFIG --cflags --libs $package > /dev/null 2>&AS_MESSAGE_LOG_FD; then
SPIDERMONKEY_LIBS="$($PKG_CONFIG --libs $package)" SPIDERMONKEY_LIBS="$($PKG_CONFIG --libs $package)"
SPIDERMONKEY_CFLAGS="$($PKG_CONFIG --cflags $package)" SPIDERMONKEY_CFLAGS="$($PKG_CONFIG --cflags $package)"
@ -637,11 +627,7 @@ for package in mozjs185 mozilla-js; do
# define XP_UNIX 1 # define XP_UNIX 1
#endif #endif
#include <jsapi.h> #include <jsapi.h>
#ifndef JS_VERSION ]], [])],
# error <jsapi.h> did not define JS_VERSION
#elif JS_VERSION < 185
# error too old
#endif]], [])],
[CONFIG_SPIDERMONKEY=yes [CONFIG_SPIDERMONKEY=yes
AC_MSG_RESULT([yes])], AC_MSG_RESULT([yes])],
[# Leave CONFIG_SPIDERMONKEY blank, to continue the search. [# Leave CONFIG_SPIDERMONKEY blank, to continue the search.

View File

@ -110,7 +110,7 @@ spidermonkey_DefineFunctions(JSContext *cx, JSObject *obj,
JSObject * JSObject *
spidermonkey_InitClass(JSContext *cx, JSObject *obj, spidermonkey_InitClass(JSContext *cx, JSObject *obj,
JSObject *parent_proto, JSClass *clasp, JSObject *parent_proto, JSClass *clasp,
JSNative constructor, uintN nargs, JSNative constructor, unsigned int nargs,
JSPropertySpec *ps, JSPropertySpec *ps,
const spidermonkeyFunctionSpec *fs, const spidermonkeyFunctionSpec *fs,
JSPropertySpec *static_ps, JSPropertySpec *static_ps,

View File

@ -39,7 +39,7 @@ void spidermonkey_runtime_release(void);
typedef struct spidermonkeyFunctionSpec { typedef struct spidermonkeyFunctionSpec {
const char *name; const char *name;
JSNative call; JSNative call;
uint8 nargs; uint8_t nargs;
/* ELinks does not use "flags" and "extra" so omit them here. */ /* ELinks does not use "flags" and "extra" so omit them here. */
} spidermonkeyFunctionSpec; } spidermonkeyFunctionSpec;
@ -47,7 +47,7 @@ JSBool spidermonkey_DefineFunctions(JSContext *cx, JSObject *obj,
const spidermonkeyFunctionSpec *fs); const spidermonkeyFunctionSpec *fs);
JSObject *spidermonkey_InitClass(JSContext *cx, JSObject *obj, JSObject *spidermonkey_InitClass(JSContext *cx, JSObject *obj,
JSObject *parent_proto, JSClass *clasp, JSObject *parent_proto, JSClass *clasp,
JSNative constructor, uintN nargs, JSNative constructor, unsigned int nargs,
JSPropertySpec *ps, JSPropertySpec *ps,
const spidermonkeyFunctionSpec *fs, const spidermonkeyFunctionSpec *fs,
JSPropertySpec *static_ps, JSPropertySpec *static_ps,
@ -87,4 +87,7 @@ jsid_to_string(JSContext *ctx, jsid *id)
return jsval_to_string(ctx, &v); return jsval_to_string(ctx, &v);
} }
#define ELINKS_CAST_PROP_PARAMS JSObject *obj = *(hobj._); \
jsval *vp = (hvp._);
#endif #endif

View File

@ -169,72 +169,91 @@ spidermonkey_get_interpreter(struct ecmascript_interpreter *interpreter)
return NULL; return NULL;
interpreter->backend_data = ctx; interpreter->backend_data = ctx;
JS_SetContextPrivate(ctx, interpreter); JS_SetContextPrivate(ctx, interpreter);
JS_SetOptions(ctx, JSOPTION_VAROBJFIX | JSOPTION_JIT | JSOPTION_METHODJIT); JS_SetOptions(ctx, JSOPTION_VAROBJFIX | JSOPTION_METHODJIT);
JS_SetVersion(ctx, JSVERSION_LATEST); JS_SetVersion(ctx, JSVERSION_LATEST);
JS_SetErrorReporter(ctx, error_reporter); JS_SetErrorReporter(ctx, error_reporter);
#if defined(CONFIG_ECMASCRIPT_SMJS_HEARTBEAT) #if defined(CONFIG_ECMASCRIPT_SMJS_HEARTBEAT)
JS_SetOperationCallback(ctx, heartbeat_callback); JS_SetOperationCallback(ctx, heartbeat_callback);
#endif #endif
window_obj = JS_NewCompartmentAndGlobalObject(ctx, (JSClass *) &window_class, NULL); window_obj = JS_NewGlobalObject(ctx, &window_class, NULL);
if (!window_obj) goto release_and_fail; if (!window_obj) goto release_and_fail;
if (!JS_InitStandardClasses(ctx, window_obj)) goto release_and_fail;
if (!JS_DefineProperties(ctx, window_obj, (JSPropertySpec *) window_props)) if (!JS_InitStandardClasses(ctx, window_obj)) {
goto release_and_fail; goto release_and_fail;
if (!spidermonkey_DefineFunctions(ctx, window_obj, window_funcs)) }
if (!JS_DefineProperties(ctx, window_obj, window_props)) {
goto release_and_fail; goto release_and_fail;
if (!JS_SetPrivate(ctx, window_obj, interpreter->vs)) /* to @window_class */ }
if (!spidermonkey_DefineFunctions(ctx, window_obj, window_funcs)) {
goto release_and_fail; goto release_and_fail;
}
JS_SetPrivate(window_obj, interpreter->vs); /* to @window_class */
document_obj = spidermonkey_InitClass(ctx, window_obj, NULL, document_obj = spidermonkey_InitClass(ctx, window_obj, NULL,
(JSClass *) &document_class, NULL, 0, &document_class, NULL, 0,
(JSPropertySpec *) document_props, document_props,
document_funcs, document_funcs,
NULL, NULL); NULL, NULL);
if (!document_obj) goto release_and_fail; if (!document_obj) {
goto release_and_fail;
}
forms_obj = spidermonkey_InitClass(ctx, document_obj, NULL, forms_obj = spidermonkey_InitClass(ctx, document_obj, NULL,
(JSClass *) &forms_class, NULL, 0, &forms_class, NULL, 0,
(JSPropertySpec *) forms_props, forms_props,
forms_funcs, forms_funcs,
NULL, NULL); NULL, NULL);
if (!forms_obj) goto release_and_fail; if (!forms_obj) {
goto release_and_fail;
}
history_obj = spidermonkey_InitClass(ctx, window_obj, NULL, history_obj = spidermonkey_InitClass(ctx, window_obj, NULL,
(JSClass *) &history_class, NULL, 0, &history_class, NULL, 0,
(JSPropertySpec *) NULL, (JSPropertySpec *) NULL,
history_funcs, history_funcs,
NULL, NULL); NULL, NULL);
if (!history_obj) goto release_and_fail; if (!history_obj) {
goto release_and_fail;
}
location_obj = spidermonkey_InitClass(ctx, window_obj, NULL, location_obj = spidermonkey_InitClass(ctx, window_obj, NULL,
(JSClass *) &location_class, NULL, 0, &location_class, NULL, 0,
(JSPropertySpec *) location_props, location_props,
location_funcs, location_funcs,
NULL, NULL); NULL, NULL);
if (!location_obj) goto release_and_fail; if (!location_obj) {
goto release_and_fail;
}
menubar_obj = JS_InitClass(ctx, window_obj, NULL, menubar_obj = JS_InitClass(ctx, window_obj, NULL,
(JSClass *) &menubar_class, NULL, 0, &menubar_class, NULL, 0,
(JSPropertySpec *) unibar_props, NULL, unibar_props, NULL,
NULL, NULL); NULL, NULL);
if (!menubar_obj) goto release_and_fail; if (!menubar_obj) {
if (!JS_SetPrivate(ctx, menubar_obj, "t")) /* to @menubar_class */
goto release_and_fail; goto release_and_fail;
}
JS_SetPrivate(menubar_obj, "t"); /* to @menubar_class */
statusbar_obj = JS_InitClass(ctx, window_obj, NULL, statusbar_obj = JS_InitClass(ctx, window_obj, NULL,
(JSClass *) &statusbar_class, NULL, 0, &statusbar_class, NULL, 0,
(JSPropertySpec *) unibar_props, NULL, unibar_props, NULL,
NULL, NULL); NULL, NULL);
if (!statusbar_obj) goto release_and_fail; if (!statusbar_obj) {
if (!JS_SetPrivate(ctx, statusbar_obj, "s")) /* to @statusbar_class */
goto release_and_fail; goto release_and_fail;
}
JS_SetPrivate(statusbar_obj, "s"); /* to @statusbar_class */
navigator_obj = JS_InitClass(ctx, window_obj, NULL, navigator_obj = JS_InitClass(ctx, window_obj, NULL,
(JSClass *) &navigator_class, NULL, 0, &navigator_class, NULL, 0,
(JSPropertySpec *) navigator_props, NULL, navigator_props, NULL,
NULL, NULL); NULL, NULL);
if (!navigator_obj) goto release_and_fail; if (!navigator_obj) {
goto release_and_fail;
}
return ctx; return ctx;
@ -264,14 +283,18 @@ spidermonkey_eval(struct ecmascript_interpreter *interpreter,
jsval rval; jsval rval;
assert(interpreter); assert(interpreter);
if (!js_module_init_ok) return; if (!js_module_init_ok) {
return;
}
ctx = interpreter->backend_data; ctx = interpreter->backend_data;
#if defined(CONFIG_ECMASCRIPT_SMJS_HEARTBEAT) #if defined(CONFIG_ECMASCRIPT_SMJS_HEARTBEAT)
interpreter->heartbeat = add_heartbeat(interpreter); interpreter->heartbeat = add_heartbeat(interpreter);
#elif defined(HAVE_JS_SETBRANCHCALLBACK) #elif defined(HAVE_JS_SETBRANCHCALLBACK)
setup_safeguard(interpreter, ctx); setup_safeguard(interpreter, ctx);
#endif #endif
interpreter->ret = ret; interpreter->ret = ret;
JS_EvaluateScript(ctx, JS_GetGlobalObject(ctx), JS_EvaluateScript(ctx, JS_GetGlobalObject(ctx),
code->source, code->length, "", 0, &rval); code->source, code->length, "", 0, &rval);
#if defined(CONFIG_ECMASCRIPT_SMJS_HEARTBEAT) #if defined(CONFIG_ECMASCRIPT_SMJS_HEARTBEAT)
@ -297,6 +320,7 @@ spidermonkey_eval_stringback(struct ecmascript_interpreter *interpreter,
#elif defined(HAVE_JS_SETBRANCHCALLBACK) #elif defined(HAVE_JS_SETBRANCHCALLBACK)
setup_safeguard(interpreter, ctx); setup_safeguard(interpreter, ctx);
#endif #endif
ret = JS_EvaluateScript(ctx, JS_GetGlobalObject(ctx), ret = JS_EvaluateScript(ctx, JS_GetGlobalObject(ctx),
code->source, code->length, "", 0, &rval); code->source, code->length, "", 0, &rval);
#if defined(CONFIG_ECMASCRIPT_SMJS_HEARTBEAT) #if defined(CONFIG_ECMASCRIPT_SMJS_HEARTBEAT)
@ -327,7 +351,8 @@ spidermonkey_eval_boolback(struct ecmascript_interpreter *interpreter,
if (!js_module_init_ok) return 0; if (!js_module_init_ok) return 0;
ctx = interpreter->backend_data; ctx = interpreter->backend_data;
interpreter->ret = NULL; interpreter->ret = NULL;
fun = JS_CompileFunction(ctx, NULL, "", 0, NULL, code->source,
fun = JS_CompileFunction(ctx, JS_GetGlobalObject(ctx), "", 0, NULL, code->source,
code->length, "", 0); code->length, "", 0);
if (!fun) if (!fun)
return -1; return -1;
@ -337,7 +362,8 @@ spidermonkey_eval_boolback(struct ecmascript_interpreter *interpreter,
#elif defined(HAVE_JS_SETBRANCHCALLBACK) #elif defined(HAVE_JS_SETBRANCHCALLBACK)
setup_safeguard(interpreter, ctx); setup_safeguard(interpreter, ctx);
#endif #endif
ret = JS_CallFunction(ctx, NULL, fun, 0, NULL, &rval); ret = JS_CallFunction(ctx, JS_GetGlobalObject(ctx), fun, 0, NULL, &rval);
#if defined(CONFIG_ECMASCRIPT_SMJS_HEARTBEAT) #if defined(CONFIG_ECMASCRIPT_SMJS_HEARTBEAT)
done_heartbeat(interpreter->heartbeat); done_heartbeat(interpreter->heartbeat);
#endif #endif

View File

@ -47,149 +47,210 @@
#include "viewer/text/vs.h" #include "viewer/text/vs.h"
static JSBool document_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp); static JSBool document_get_property(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp);
static JSBool document_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp);
/* Each @document_class object must have a @window_class parent. */ /* Each @document_class object must have a @window_class parent. */
const JSClass document_class = { JSClass document_class = {
"document", "document",
JSCLASS_HAS_PRIVATE, JSCLASS_HAS_PRIVATE,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
document_get_property, document_set_property, document_get_property, JS_StrictPropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub
}; };
/* Tinyids of properties. Use negative values to distinguish these #ifdef CONFIG_COOKIES
* from array indexes (even though this object has no array elements).
* ECMAScript code should not use these directly as in document[-1];
* future versions of ELinks may change the numbers. */
enum document_prop {
JSP_DOC_LOC = -1,
JSP_DOC_REF = -2,
JSP_DOC_TITLE = -3,
JSP_DOC_URL = -4,
};
/* "cookie" is special; it isn't a regular property but we channel it to the
* cookie-module. XXX: Would it work if "cookie" was defined in this array? */
const JSPropertySpec document_props[] = {
{ "location", JSP_DOC_LOC, JSPROP_ENUMERATE },
{ "referrer", JSP_DOC_REF, JSPROP_ENUMERATE | JSPROP_READONLY },
{ "title", JSP_DOC_TITLE, JSPROP_ENUMERATE }, /* TODO: Charset? */
{ "url", JSP_DOC_URL, JSPROP_ENUMERATE },
{ NULL }
};
/* @document_class.getProperty */
static JSBool static JSBool
document_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp) document_get_property_cookie(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{ {
ELINKS_CAST_PROP_PARAMS
JSObject *parent_win; /* instance of @window_class */
struct view_state *vs;
struct string *cookies;
JSClass* classPtr = JS_GetClass(obj);
if (classPtr != &document_class)
return JS_FALSE;
parent_win = JS_GetParent(obj);
assert(JS_InstanceOf(ctx, parent_win, &window_class, NULL));
if_assert_failed return JS_FALSE;
vs = JS_GetInstancePrivate(ctx, parent_win,
&window_class, NULL);
cookies = send_cookies_js(vs->uri);
if (cookies) {
static unsigned char cookiestr[1024];
strncpy(cookiestr, cookies->source, 1024);
done_string(cookies);
string_to_jsval(ctx, vp, cookiestr);
} else {
string_to_jsval(ctx, vp, "");
}
return JS_TRUE;
}
static JSBool
document_set_property_cookie(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSBool strict, JSMutableHandleValue hvp)
{
ELINKS_CAST_PROP_PARAMS
JSObject *parent_win; /* instance of @window_class */
struct view_state *vs;
/* 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, &document_class, NULL))
return JS_FALSE;
parent_win = JS_GetParent(obj);
assert(JS_InstanceOf(ctx, parent_win, &window_class, NULL));
if_assert_failed return JS_FALSE;
vs = JS_GetInstancePrivate(ctx, parent_win,
&window_class, NULL);
set_cookie(vs->uri, jsval_to_string(ctx, vp));
return JS_TRUE;
}
#endif
static JSBool
document_get_property_location(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{
ELINKS_CAST_PROP_PARAMS
JSObject *parent_win; /* instance of @window_class */
JSClass* classPtr = JS_GetClass(obj);
if (classPtr != &document_class)
return JS_FALSE;
parent_win = JS_GetParent(obj);
assert(JS_InstanceOf(ctx, parent_win, &window_class, NULL));
if_assert_failed return JS_FALSE;
JS_GetProperty(ctx, parent_win, "location", vp);
return JS_TRUE;
}
static JSBool
document_set_property_location(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSBool strict, JSMutableHandleValue hvp)
{
ELINKS_CAST_PROP_PARAMS
JSObject *parent_win; /* instance of @window_class */
struct view_state *vs;
struct document_view *doc_view;
/* 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, &document_class, NULL))
return JS_FALSE;
parent_win = JS_GetParent(obj);
assert(JS_InstanceOf(ctx, parent_win, &window_class, NULL));
if_assert_failed return JS_FALSE;
vs = JS_GetInstancePrivate(ctx, parent_win,
&window_class, NULL);
doc_view = vs->doc_view;
location_goto(doc_view, jsval_to_string(ctx, vp));
return JS_TRUE;
}
static JSBool
document_get_property_referrer(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{
ELINKS_CAST_PROP_PARAMS
JSObject *parent_win; /* instance of @window_class */ JSObject *parent_win; /* instance of @window_class */
struct view_state *vs; struct view_state *vs;
struct document_view *doc_view; struct document_view *doc_view;
struct document *document; struct document *document;
struct session *ses; struct session *ses;
JSClass* classPtr = JS_GetClass(obj);
/* This can be called if @obj if not itself an instance of the if (classPtr != &document_class)
* appropriate class but has one in its prototype chain. Fail
* such calls. */
if (!JS_InstanceOf(ctx, obj, (JSClass *) &document_class, NULL))
return JS_FALSE; return JS_FALSE;
parent_win = JS_GetParent(ctx, obj);
assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL)); parent_win = JS_GetParent(obj);
assert(JS_InstanceOf(ctx, parent_win, &window_class, NULL));
if_assert_failed return JS_FALSE; if_assert_failed return JS_FALSE;
vs = JS_GetInstancePrivate(ctx, parent_win, vs = JS_GetInstancePrivate(ctx, parent_win,
(JSClass *) &window_class, NULL); &window_class, NULL);
doc_view = vs->doc_view; doc_view = vs->doc_view;
document = doc_view->document; document = doc_view->document;
ses = doc_view->session; ses = doc_view->session;
if (JSID_IS_STRING(id)) { switch (get_opt_int("protocol.http.referer.policy", NULL)) {
struct form *form; case REFERER_NONE:
unsigned char *string = jsid_to_string(ctx, &id); /* oh well */
undef_to_jsval(ctx, vp);
#ifdef CONFIG_COOKIES
if (!strcmp(string, "cookie")) {
struct string *cookies = send_cookies_js(vs->uri);
if (cookies) {
static unsigned char cookiestr[1024];
strncpy(cookiestr, cookies->source, 1024);
done_string(cookies);
string_to_jsval(ctx, vp, cookiestr);
} else {
string_to_jsval(ctx, vp, "");
}
return JS_TRUE;
}
#endif
foreach (form, document->forms) {
if (!form->name || c_strcasecmp(string, form->name))
continue;
object_to_jsval(ctx, vp, get_form_object(ctx, obj, find_form_view(doc_view, form)));
break;
}
return JS_TRUE;
}
if (!JSID_IS_INT(id))
return JS_TRUE;
undef_to_jsval(ctx, vp);
switch (JSID_TO_INT(id)) {
case JSP_DOC_LOC:
JS_GetProperty(ctx, parent_win, "location", vp);
break; break;
case JSP_DOC_REF:
switch (get_opt_int("protocol.http.referer.policy", NULL)) {
case REFERER_NONE:
/* oh well */
undef_to_jsval(ctx, vp);
break;
case REFERER_FAKE: case REFERER_FAKE:
string_to_jsval(ctx, vp, get_opt_str("protocol.http.referer.fake", NULL)); string_to_jsval(ctx, vp, get_opt_str("protocol.http.referer.fake", NULL));
break; break;
case REFERER_TRUE: case REFERER_TRUE:
/* XXX: Encode as in add_url_to_httset_prop_string(&prop, ) ? --pasky */ /* XXX: Encode as in add_url_to_httset_prop_string(&prop, ) ? --pasky */
if (ses->referrer) { if (ses->referrer) {
astring_to_jsval(ctx, vp, get_uri_string(ses->referrer, URI_HTTP_REFERRER)); astring_to_jsval(ctx, vp, get_uri_string(ses->referrer, URI_HTTP_REFERRER));
}
break;
case REFERER_SAME_URL:
astring_to_jsval(ctx, vp, get_uri_string(document->uri, URI_HTTP_REFERRER));
break;
} }
break; break;
case JSP_DOC_TITLE:
string_to_jsval(ctx, vp, document->title); case REFERER_SAME_URL:
break; astring_to_jsval(ctx, vp, get_uri_string(document->uri, URI_HTTP_REFERRER));
case JSP_DOC_URL:
astring_to_jsval(ctx, vp, get_uri_string(document->uri, URI_ORIGINAL));
break;
default:
/* Unrecognized integer property ID; someone is using
* the object as an array. SMJS builtin classes (e.g.
* js_RegExpClass) just return JS_TRUE in this case
* and leave *@vp unchanged. Do the same here.
* (Actually not quite the same, as we already used
* @undef_to_jsval.) */
break; break;
} }
return JS_TRUE; return JS_TRUE;
} }
/* @document_class.setProperty */
static JSBool static JSBool
document_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp) document_get_property_title(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{ {
ELINKS_CAST_PROP_PARAMS
JSObject *parent_win; /* instance of @window_class */
struct view_state *vs;
struct document_view *doc_view;
struct document *document;
JSClass* classPtr = JS_GetClass(obj);
if (classPtr != &document_class)
return JS_FALSE;
parent_win = JS_GetParent(obj);
assert(JS_InstanceOf(ctx, parent_win, &window_class, NULL));
if_assert_failed return JS_FALSE;
vs = JS_GetInstancePrivate(ctx, parent_win,
&window_class, NULL);
doc_view = vs->doc_view;
document = doc_view->document;
string_to_jsval(ctx, vp, document->title);
return JS_TRUE;
}
static JSBool
document_set_property_title(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSBool strict, JSMutableHandleValue hvp)
{
ELINKS_CAST_PROP_PARAMS
JSObject *parent_win; /* instance of @window_class */ JSObject *parent_win; /* instance of @window_class */
struct view_state *vs; struct view_state *vs;
struct document_view *doc_view; struct document_view *doc_view;
@ -198,52 +259,134 @@ document_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsv
/* This can be called if @obj if not itself an instance of the /* This can be called if @obj if not itself an instance of the
* appropriate class but has one in its prototype chain. Fail * appropriate class but has one in its prototype chain. Fail
* such calls. */ * such calls. */
if (!JS_InstanceOf(ctx, obj, (JSClass *) &document_class, NULL)) if (!JS_InstanceOf(ctx, obj, &document_class, NULL))
return JS_FALSE; return JS_FALSE;
parent_win = JS_GetParent(ctx, obj);
assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL)); parent_win = JS_GetParent(obj);
assert(JS_InstanceOf(ctx, parent_win, &window_class, NULL));
if_assert_failed return JS_FALSE; if_assert_failed return JS_FALSE;
vs = JS_GetInstancePrivate(ctx, parent_win, vs = JS_GetInstancePrivate(ctx, parent_win,
(JSClass *) &window_class, NULL); &window_class, NULL);
doc_view = vs->doc_view; doc_view = vs->doc_view;
document = doc_view->document; document = doc_view->document;
mem_free_set(&document->title, stracpy(jsval_to_string(ctx, vp)));
print_screen_status(doc_view->session);
if (JSID_IS_STRING(id)) { return JS_TRUE;
}
static JSBool
document_get_property_url(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{
ELINKS_CAST_PROP_PARAMS
JSObject *parent_win; /* instance of @window_class */
struct view_state *vs;
struct document_view *doc_view;
struct document *document;
JSClass* classPtr = JS_GetClass(obj);
if (classPtr != &document_class)
return JS_FALSE;
parent_win = JS_GetParent(obj);
assert(JS_InstanceOf(ctx, parent_win, &window_class, NULL));
if_assert_failed return JS_FALSE;
vs = JS_GetInstancePrivate(ctx, parent_win,
&window_class, NULL);
doc_view = vs->doc_view;
document = doc_view->document;
astring_to_jsval(ctx, vp, get_uri_string(document->uri, URI_ORIGINAL));
return JS_TRUE;
}
static JSBool
document_set_property_url(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSBool strict, JSMutableHandleValue hvp)
{
ELINKS_CAST_PROP_PARAMS
JSObject *parent_win; /* instance of @window_class */
struct view_state *vs;
struct document_view *doc_view;
/* 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, &document_class, NULL))
return JS_FALSE;
parent_win = JS_GetParent(obj);
assert(JS_InstanceOf(ctx, parent_win, &window_class, NULL));
if_assert_failed return JS_FALSE;
vs = JS_GetInstancePrivate(ctx, parent_win,
&window_class, NULL);
doc_view = vs->doc_view;
location_goto(doc_view, jsval_to_string(ctx, vp));
return JS_TRUE;
}
/* "cookie" is special; it isn't a regular property but we channel it to the
* cookie-module. XXX: Would it work if "cookie" was defined in this array? */
JSPropertySpec document_props[] = {
#ifdef CONFIG_COOKIES #ifdef CONFIG_COOKIES
if (!strcmp(jsid_to_string(ctx, &id), "cookie")) { { "cookie", 0, JSPROP_ENUMERATE | JSPROP_SHARED, JSOP_WRAPPER(document_get_property_cookie), JSOP_WRAPPER(document_set_property_cookie) },
set_cookie(vs->uri, jsval_to_string(ctx, vp));
/* Do NOT touch our .cookie property, evil
* SpiderMonkey!! */
return JS_FALSE;
}
#endif #endif
return JS_TRUE; { "location", 0, JSPROP_ENUMERATE | JSPROP_SHARED, JSOP_WRAPPER(document_get_property_location), JSOP_WRAPPER(document_set_property_location) },
} { "referrer", 0, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_SHARED, JSOP_WRAPPER(document_get_property_referrer), JSOP_NULLWRAPPER },
{ "title", 0, JSPROP_ENUMERATE | JSPROP_SHARED, JSOP_WRAPPER(document_get_property_title), JSOP_WRAPPER(document_set_property_title) }, /* TODO: Charset? */
{ "url", 0, JSPROP_ENUMERATE | JSPROP_SHARED, JSOP_WRAPPER(document_get_property_url), JSOP_WRAPPER(document_set_property_url) },
{ NULL }
};
if (!JSID_IS_INT(id))
return JS_TRUE;
switch (JSID_TO_INT(id)) { /* @document_class.getProperty */
case JSP_DOC_TITLE: static JSBool
mem_free_set(&document->title, stracpy(jsval_to_string(ctx, vp))); document_get_property(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
print_screen_status(doc_view->session); {
break; ELINKS_CAST_PROP_PARAMS
case JSP_DOC_LOC: jsid id = *(hid._);
case JSP_DOC_URL:
/* According to the specs this should be readonly but some JSObject *parent_win; /* instance of @window_class */
* broken sites still assign to it (i.e. struct view_state *vs;
* http://www.e-handelsfonden.dk/validering.asp?URL=www.polyteknisk.dk). struct document_view *doc_view;
* So emulate window.location. */ struct document *document;
location_goto(doc_view, jsval_to_string(ctx, vp)); struct form *form;
unsigned char *string;
JSClass* classPtr = JS_GetClass(obj);
if (classPtr != &document_class)
return JS_FALSE;
parent_win = JS_GetParent(obj);
assert(JS_InstanceOf(ctx, parent_win, &window_class, NULL));
if_assert_failed return JS_FALSE;
vs = JS_GetInstancePrivate(ctx, parent_win,
&window_class, NULL);
doc_view = vs->doc_view;
document = doc_view->document;
string = jsid_to_string(ctx, &id);
foreach (form, document->forms) {
if (!form->name || c_strcasecmp(string, form->name))
continue;
object_to_jsval(ctx, vp, get_form_object(ctx, obj, find_form_view(doc_view, form)));
break; break;
} }
return JS_TRUE; return JS_TRUE;
} }
static JSBool document_write(JSContext *ctx, uintN argc, jsval *rval); static JSBool document_write(JSContext *ctx, unsigned int argc, jsval *rval);
static JSBool document_writeln(JSContext *ctx, uintN argc, jsval *rval); static JSBool document_writeln(JSContext *ctx, unsigned int argc, jsval *rval);
const spidermonkeyFunctionSpec document_funcs[] = { const spidermonkeyFunctionSpec document_funcs[] = {
{ "write", document_write, 1 }, { "write", document_write, 1 },
@ -252,7 +395,7 @@ const spidermonkeyFunctionSpec document_funcs[] = {
}; };
static JSBool static JSBool
document_write_do(JSContext *ctx, uintN argc, jsval *rval, int newline) document_write_do(JSContext *ctx, unsigned int argc, jsval *rval, int newline)
{ {
jsval val; jsval val;
struct ecmascript_interpreter *interpreter = JS_GetContextPrivate(ctx); struct ecmascript_interpreter *interpreter = JS_GetContextPrivate(ctx);
@ -290,7 +433,7 @@ document_write_do(JSContext *ctx, uintN argc, jsval *rval, int newline)
/* @document_funcs{"write"} */ /* @document_funcs{"write"} */
static JSBool static JSBool
document_write(JSContext *ctx, uintN argc, jsval *rval) document_write(JSContext *ctx, unsigned int argc, jsval *rval)
{ {
return document_write_do(ctx, argc, rval, 0); return document_write_do(ctx, argc, rval, 0);
@ -298,7 +441,7 @@ document_write(JSContext *ctx, uintN argc, jsval *rval)
/* @document_funcs{"writeln"} */ /* @document_funcs{"writeln"} */
static JSBool static JSBool
document_writeln(JSContext *ctx, uintN argc, jsval *rval) document_writeln(JSContext *ctx, unsigned int argc, jsval *rval)
{ {
return document_write_do(ctx, argc, rval, 1); return document_write_do(ctx, argc, rval, 1);
} }

View File

@ -4,8 +4,8 @@
#include "ecmascript/spidermonkey/util.h" #include "ecmascript/spidermonkey/util.h"
extern const JSClass document_class; extern JSClass document_class;
extern const spidermonkeyFunctionSpec document_funcs[]; extern const spidermonkeyFunctionSpec document_funcs[];
extern const JSPropertySpec document_props[]; extern JSPropertySpec document_props[];
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -6,9 +6,9 @@
struct form_view; struct form_view;
extern const JSClass forms_class; extern JSClass forms_class;
extern const spidermonkeyFunctionSpec forms_funcs[]; extern const spidermonkeyFunctionSpec forms_funcs[];
extern const JSPropertySpec forms_props[]; extern JSPropertySpec forms_props[];
JSObject *get_form_object(JSContext *ctx, JSObject *jsdoc, struct form_view *fv); JSObject *get_form_object(JSContext *ctx, JSObject *jsdoc, struct form_view *fv);

View File

@ -36,7 +36,7 @@ static struct itimerval heartbeat_timer = { { 1, 0 }, { 1, 0 } };
JSBool JSBool
heartbeat_callback(JSContext *ctx) heartbeat_callback(JSContext *ctx)
{ {
return JS_FALSE; return JS_FALSE;
} }
/* Callback for SIGVTALRM. Go through all heartbeats, decrease each /* Callback for SIGVTALRM. Go through all heartbeats, decrease each
@ -45,31 +45,28 @@ heartbeat_callback(JSContext *ctx)
static void static void
check_heartbeats(void *data) check_heartbeats(void *data)
{ {
struct heartbeat *hb; struct heartbeat *hb;
foreach (hb, heartbeats) { foreach (hb, heartbeats) {
assert(hb->interpreter); assert(hb->interpreter);
--hb->ttl;
--hb->ttl; if (hb->ttl <= 0) {
if (hb->ttl <= 0) {
if (hb->interpreter->vs if (hb->interpreter->vs
&& hb->interpreter->vs->doc_view && hb->interpreter->vs->doc_view
&& hb->interpreter->vs->doc_view->session && hb->interpreter->vs->doc_view->session
&& hb->interpreter->vs->doc_view->session->tab && hb->interpreter->vs->doc_view->session->tab
&& hb->interpreter->vs->doc_view->session->tab->term) { && hb->interpreter->vs->doc_view->session->tab->term) {
struct session *ses = hb->interpreter->vs->doc_view->session; struct session *ses = hb->interpreter->vs->doc_view->session;
struct terminal *term = ses->tab->term; struct terminal *term = ses->tab->term;
int max_exec_time = get_opt_int("ecmascript.max_exec_time", ses); int max_exec_time = get_opt_int("ecmascript.max_exec_time", ses);
ecmascript_timeout_dialog(term, max_exec_time); ecmascript_timeout_dialog(term, max_exec_time);
} }
JS_TriggerOperationCallback(JS_GetRuntime(hb->interpreter->backend_data));
JS_TriggerOperationCallback(hb->interpreter->backend_data); }
} }
} install_signal_handler(SIGVTALRM, check_heartbeats, NULL, 1);
install_signal_handler(SIGVTALRM, check_heartbeats, NULL, 1);
} }
/* Create a new heartbeat for the given interpreter. */ /* Create a new heartbeat for the given interpreter. */
@ -77,7 +74,7 @@ struct heartbeat *
add_heartbeat(struct ecmascript_interpreter *interpreter) add_heartbeat(struct ecmascript_interpreter *interpreter)
{ {
struct session *ses; struct session *ses;
struct heartbeat *hb; struct heartbeat *hb;
assert(interpreter); assert(interpreter);
@ -85,27 +82,26 @@ add_heartbeat(struct ecmascript_interpreter *interpreter)
ses = NULL; ses = NULL;
else else
ses = interpreter->vs->doc_view->session; ses = interpreter->vs->doc_view->session;
hb = mem_alloc(sizeof(struct heartbeat));
hb = mem_alloc(sizeof(struct heartbeat)); if (!hb) return NULL;
if (!hb) return NULL;
hb->ttl = get_opt_int("ecmascript.max_exec_time", ses); hb->ttl = get_opt_int("ecmascript.max_exec_time", ses);
hb->interpreter = interpreter; hb->interpreter = interpreter;
add_to_list(heartbeats, hb);
add_to_list(heartbeats, hb); /* Update the heartbeat timer. */
if (list_is_singleton(*hb)) {
heartbeat_timer.it_value.tv_sec = 1;
setitimer(ITIMER_VIRTUAL, &heartbeat_timer, NULL);
}
/* Update the heartbeat timer. */ /* We install the handler every call to add_heartbeat instead of only on
if (list_is_singleton(*hb)) { * module initialisation because other code may set other handlers for
heartbeat_timer.it_value.tv_sec = 1; * the signal. */
setitimer(ITIMER_VIRTUAL, &heartbeat_timer, NULL); install_signal_handler(SIGVTALRM, check_heartbeats, NULL, 1);
}
/* We install the handler every call to add_heartbeat instead of only on return hb;
* module initialisation because other code may set other handlers for
* the signal. */
install_signal_handler(SIGVTALRM, check_heartbeats, NULL, 1);
return hb;
} }
/* Destroy the given heartbeat. */ /* Destroy the given heartbeat. */
@ -115,13 +111,13 @@ done_heartbeat(struct heartbeat *hb)
if (!hb) return; /* add_heartbeat returned NULL */ if (!hb) return; /* add_heartbeat returned NULL */
assert(hb->interpreter); assert(hb->interpreter);
/* Stop the heartbeat timer if this heartbeat is the only one. */ /* Stop the heartbeat timer if this heartbeat is the only one. */
if (list_is_singleton(*hb)) { if (list_is_singleton(*hb)) {
heartbeat_timer.it_value.tv_sec = 0; heartbeat_timer.it_value.tv_sec = 0;
setitimer(ITIMER_VIRTUAL, &heartbeat_timer, NULL); setitimer(ITIMER_VIRTUAL, &heartbeat_timer, NULL);
} }
del_from_list(hb); del_from_list(hb);
hb->interpreter->heartbeat = NULL; hb->interpreter->heartbeat = NULL;
mem_free(hb); mem_free(hb);
} }

View File

@ -45,16 +45,16 @@
#include "viewer/text/vs.h" #include "viewer/text/vs.h"
static JSBool history_back(JSContext *ctx, uintN argc, jsval *rval); static JSBool history_back(JSContext *ctx, unsigned int argc, jsval *rval);
static JSBool history_forward(JSContext *ctx, uintN argc, jsval *rval); static JSBool history_forward(JSContext *ctx, unsigned int argc, jsval *rval);
static JSBool history_go(JSContext *ctx, uintN argc, jsval *rval); static JSBool history_go(JSContext *ctx, unsigned int argc, jsval *rval);
const JSClass history_class = { JSClass history_class = {
"history", "history",
JSCLASS_HAS_PRIVATE, JSCLASS_HAS_PRIVATE,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_PropertyStub, JS_StrictPropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, NULL
}; };
const spidermonkeyFunctionSpec history_funcs[] = { const spidermonkeyFunctionSpec history_funcs[] = {
@ -66,7 +66,7 @@ const spidermonkeyFunctionSpec history_funcs[] = {
/* @history_funcs{"back"} */ /* @history_funcs{"back"} */
static JSBool static JSBool
history_back(JSContext *ctx, uintN argc, jsval *rval) history_back(JSContext *ctx, unsigned int argc, jsval *rval)
{ {
struct ecmascript_interpreter *interpreter = JS_GetContextPrivate(ctx); struct ecmascript_interpreter *interpreter = JS_GetContextPrivate(ctx);
struct document_view *doc_view = interpreter->vs->doc_view; struct document_view *doc_view = interpreter->vs->doc_view;
@ -84,7 +84,7 @@ history_back(JSContext *ctx, uintN argc, jsval *rval)
/* @history_funcs{"forward"} */ /* @history_funcs{"forward"} */
static JSBool static JSBool
history_forward(JSContext *ctx, uintN argc, jsval *rval) history_forward(JSContext *ctx, unsigned int argc, jsval *rval)
{ {
struct ecmascript_interpreter *interpreter = JS_GetContextPrivate(ctx); struct ecmascript_interpreter *interpreter = JS_GetContextPrivate(ctx);
struct document_view *doc_view = interpreter->vs->doc_view; struct document_view *doc_view = interpreter->vs->doc_view;
@ -98,7 +98,7 @@ history_forward(JSContext *ctx, uintN argc, jsval *rval)
/* @history_funcs{"go"} */ /* @history_funcs{"go"} */
static JSBool static JSBool
history_go(JSContext *ctx, uintN argc, jsval *rval) history_go(JSContext *ctx, unsigned int argc, jsval *rval)
{ {
struct ecmascript_interpreter *interpreter = JS_GetContextPrivate(ctx); struct ecmascript_interpreter *interpreter = JS_GetContextPrivate(ctx);
struct document_view *doc_view = interpreter->vs->doc_view; struct document_view *doc_view = interpreter->vs->doc_view;
@ -128,16 +128,16 @@ history_go(JSContext *ctx, uintN argc, jsval *rval)
} }
static JSBool location_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp); static JSBool location_get_property_href(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp);
static JSBool location_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp); static JSBool location_set_property_href(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSBool strict, JSMutableHandleValue hvp);
/* Each @location_class object must have a @window_class parent. */ /* Each @location_class object must have a @window_class parent. */
const JSClass location_class = { JSClass location_class = {
"location", "location",
JSCLASS_HAS_PRIVATE, JSCLASS_HAS_PRIVATE,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
location_get_property, location_set_property, JS_PropertyStub, JS_StrictPropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, NULL
}; };
/* Tinyids of properties. Use negative values to distinguish these /* Tinyids of properties. Use negative values to distinguish these
@ -147,56 +147,41 @@ const JSClass location_class = {
enum location_prop { enum location_prop {
JSP_LOC_HREF = -1, JSP_LOC_HREF = -1,
}; };
const JSPropertySpec location_props[] = { JSPropertySpec location_props[] = {
{ "href", JSP_LOC_HREF, JSPROP_ENUMERATE }, { "href", 0, JSPROP_ENUMERATE|JSPROP_SHARED, JSOP_WRAPPER(location_get_property_href), JSOP_WRAPPER(location_set_property_href) },
{ NULL } { NULL }
}; };
/* @location_class.getProperty */
static JSBool static JSBool
location_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp) location_get_property_href(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{ {
ELINKS_CAST_PROP_PARAMS
JSObject *parent_win; /* instance of @window_class */ JSObject *parent_win; /* instance of @window_class */
struct view_state *vs; struct view_state *vs;
/* This can be called if @obj if not itself an instance of the /* This can be called if @obj if not itself an instance of the
* appropriate class but has one in its prototype chain. Fail * appropriate class but has one in its prototype chain. Fail
* such calls. */ * such calls. */
if (!JS_InstanceOf(ctx, obj, (JSClass *) &location_class, NULL)) if (!JS_InstanceOf(ctx, obj, &location_class, NULL))
return JS_FALSE; return JS_FALSE;
parent_win = JS_GetParent(ctx, obj); parent_win = JS_GetParent(obj);
assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL)); assert(JS_InstanceOf(ctx, parent_win, &window_class, NULL));
if_assert_failed return JS_FALSE; if_assert_failed return JS_FALSE;
vs = JS_GetInstancePrivate(ctx, parent_win, vs = JS_GetInstancePrivate(ctx, parent_win,
(JSClass *) &window_class, NULL); &window_class, NULL);
if (!JSID_IS_INT(id)) astring_to_jsval(ctx, vp, get_uri_string(vs->uri, URI_ORIGINAL));
return JS_TRUE;
undef_to_jsval(ctx, vp);
switch (JSID_TO_INT(id)) {
case JSP_LOC_HREF:
astring_to_jsval(ctx, vp, get_uri_string(vs->uri, URI_ORIGINAL));
break;
default:
/* Unrecognized integer property ID; someone is using
* the object as an array. SMJS builtin classes (e.g.
* js_RegExpClass) just return JS_TRUE in this case
* and leave *@vp unchanged. Do the same here.
* (Actually not quite the same, as we already used
* @undef_to_jsval.) */
break;
}
return JS_TRUE; return JS_TRUE;
} }
/* @location_class.setProperty */
static JSBool static JSBool
location_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp) location_set_property_href(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSBool strict, JSMutableHandleValue hvp)
{ {
ELINKS_CAST_PROP_PARAMS
JSObject *parent_win; /* instance of @window_class */ JSObject *parent_win; /* instance of @window_class */
struct view_state *vs; struct view_state *vs;
struct document_view *doc_view; struct document_view *doc_view;
@ -204,29 +189,22 @@ location_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsv
/* This can be called if @obj if not itself an instance of the /* This can be called if @obj if not itself an instance of the
* appropriate class but has one in its prototype chain. Fail * appropriate class but has one in its prototype chain. Fail
* such calls. */ * such calls. */
if (!JS_InstanceOf(ctx, obj, (JSClass *) &location_class, NULL)) if (!JS_InstanceOf(ctx, obj, &location_class, NULL))
return JS_FALSE; return JS_FALSE;
parent_win = JS_GetParent(ctx, obj); parent_win = JS_GetParent(obj);
assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL)); assert(JS_InstanceOf(ctx, parent_win, &window_class, NULL));
if_assert_failed return JS_FALSE; if_assert_failed return JS_FALSE;
vs = JS_GetInstancePrivate(ctx, parent_win, vs = JS_GetInstancePrivate(ctx, parent_win,
(JSClass *) &window_class, NULL); &window_class, NULL);
doc_view = vs->doc_view; doc_view = vs->doc_view;
location_goto(doc_view, jsval_to_string(ctx, vp));
if (!JSID_IS_INT(id))
return JS_TRUE;
switch (JSID_TO_INT(id)) {
case JSP_LOC_HREF:
location_goto(doc_view, jsval_to_string(ctx, vp));
break;
}
return JS_TRUE; return JS_TRUE;
} }
static JSBool location_toString(JSContext *ctx, uintN argc, jsval *rval);
static JSBool location_toString(JSContext *ctx, unsigned int argc, jsval *rval);
const spidermonkeyFunctionSpec location_funcs[] = { const spidermonkeyFunctionSpec location_funcs[] = {
{ "toString", location_toString, 0 }, { "toString", location_toString, 0 },
@ -236,7 +214,7 @@ const spidermonkeyFunctionSpec location_funcs[] = {
/* @location_funcs{"toString"}, @location_funcs{"toLocaleString"} */ /* @location_funcs{"toString"}, @location_funcs{"toLocaleString"} */
static JSBool static JSBool
location_toString(JSContext *ctx, uintN argc, jsval *rval) location_toString(JSContext *ctx, unsigned int argc, jsval *rval)
{ {
jsval val; jsval val;
JSObject *obj = JS_THIS_OBJECT(ctx, rval); JSObject *obj = JS_THIS_OBJECT(ctx, rval);

View File

@ -6,12 +6,12 @@
struct document_view; struct document_view;
extern const JSClass history_class; extern JSClass history_class;
extern const spidermonkeyFunctionSpec history_funcs[]; extern const spidermonkeyFunctionSpec history_funcs[];
extern const JSClass location_class; extern JSClass location_class;
extern const spidermonkeyFunctionSpec location_funcs[]; extern const spidermonkeyFunctionSpec location_funcs[];
extern const JSPropertySpec location_props[]; extern JSPropertySpec location_props[];
void location_goto(struct document_view *doc_view, unsigned char *url); void location_goto(struct document_view *doc_view, unsigned char *url);

View File

@ -44,14 +44,19 @@
#include "viewer/text/vs.h" #include "viewer/text/vs.h"
static JSBool navigator_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp); static JSBool navigator_get_property_appCodeName(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp);
static JSBool navigator_get_property_appName(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp);
static JSBool navigator_get_property_appVersion(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp);
static JSBool navigator_get_property_language(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp);
static JSBool navigator_get_property_platform(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp);
static JSBool navigator_get_property_userAgent(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp);
const JSClass navigator_class = { JSClass navigator_class = {
"navigator", "navigator",
JSCLASS_HAS_PRIVATE, JSCLASS_HAS_PRIVATE,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
navigator_get_property, JS_StrictPropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, NULL
}; };
/* Tinyids of properties. Use negative values to distinguish these /* Tinyids of properties. Use negative values to distinguish these
@ -68,87 +73,112 @@ enum navigator_prop {
/* JSP_NAVIGATOR_PLUGINS = -7, */ /* JSP_NAVIGATOR_PLUGINS = -7, */
JSP_NAVIGATOR_USER_AGENT = -8, JSP_NAVIGATOR_USER_AGENT = -8,
}; };
const JSPropertySpec navigator_props[] = { JSPropertySpec navigator_props[] = {
{ "appCodeName", JSP_NAVIGATOR_APP_CODENAME, JSPROP_ENUMERATE | JSPROP_READONLY }, { "appCodeName",0, JSPROP_ENUMERATE | JSPROP_READONLY|JSPROP_SHARED, JSOP_WRAPPER(navigator_get_property_appCodeName), JSOP_NULLWRAPPER },
{ "appName", JSP_NAVIGATOR_APP_NAME, JSPROP_ENUMERATE | JSPROP_READONLY }, { "appName", 0, JSPROP_ENUMERATE | JSPROP_READONLY|JSPROP_SHARED, JSOP_WRAPPER(navigator_get_property_appName), JSOP_NULLWRAPPER },
{ "appVersion", JSP_NAVIGATOR_APP_VERSION, JSPROP_ENUMERATE | JSPROP_READONLY }, { "appVersion", 0, JSPROP_ENUMERATE | JSPROP_READONLY|JSPROP_SHARED, JSOP_WRAPPER(navigator_get_property_appVersion), JSOP_NULLWRAPPER },
{ "language", JSP_NAVIGATOR_LANGUAGE, JSPROP_ENUMERATE | JSPROP_READONLY }, { "language", 0, JSPROP_ENUMERATE | JSPROP_READONLY|JSPROP_SHARED, JSOP_WRAPPER(navigator_get_property_language), JSOP_NULLWRAPPER },
{ "platform", JSP_NAVIGATOR_PLATFORM, JSPROP_ENUMERATE | JSPROP_READONLY }, { "platform", 0, JSPROP_ENUMERATE | JSPROP_READONLY|JSPROP_SHARED, JSOP_WRAPPER(navigator_get_property_platform), JSOP_NULLWRAPPER },
{ "userAgent", JSP_NAVIGATOR_USER_AGENT, JSPROP_ENUMERATE | JSPROP_READONLY }, { "userAgent", 0, JSPROP_ENUMERATE | JSPROP_READONLY|JSPROP_SHARED, JSOP_WRAPPER(navigator_get_property_userAgent), JSOP_NULLWRAPPER },
{ NULL } { NULL }
}; };
/* @navigator_class.getProperty */ /* @navigator_class.getProperty */
static JSBool static JSBool
navigator_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp) navigator_get_property_appCodeName(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{ {
if (!JSID_IS_INT(id)) ELINKS_CAST_PROP_PARAMS
return JS_TRUE; (void)obj;
undef_to_jsval(ctx, vp); string_to_jsval(ctx, vp, "Mozilla"); /* More like a constant nowadays. */
switch (JSID_TO_INT(id)) { return JS_TRUE;
case JSP_NAVIGATOR_APP_CODENAME: }
string_to_jsval(ctx, vp, "Mozilla"); /* More like a constant nowadays. */
break; static JSBool
case JSP_NAVIGATOR_APP_NAME: navigator_get_property_appName(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
/* This evil hack makes the compatibility checking .indexOf() {
* code find what it's looking for. */ ELINKS_CAST_PROP_PARAMS
string_to_jsval(ctx, vp, "ELinks (roughly compatible with Netscape Navigator, Mozilla and Microsoft Internet Explorer)"); (void)obj;
break;
case JSP_NAVIGATOR_APP_VERSION: string_to_jsval(ctx, vp, "ELinks (roughly compatible with Netscape Navigator, Mozilla and Microsoft Internet Explorer)");
string_to_jsval(ctx, vp, VERSION);
break; return JS_TRUE;
case JSP_NAVIGATOR_LANGUAGE: }
#ifdef CONFIG_NLS
if (get_opt_bool("protocol.http.accept_ui_language", NULL)) static JSBool
string_to_jsval(ctx, vp, language_to_iso639(current_language)); navigator_get_property_appVersion(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{
#endif ELINKS_CAST_PROP_PARAMS
break; (void)obj;
case JSP_NAVIGATOR_PLATFORM:
string_to_jsval(ctx, vp, system_name); string_to_jsval(ctx, vp, VERSION);
break;
case JSP_NAVIGATOR_USER_AGENT: return JS_TRUE;
{ }
/* FIXME: Code duplication. */
unsigned char *optstr = get_opt_str("protocol.http.user_agent", static JSBool
NULL); navigator_get_property_language(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{
if (*optstr && strcmp(optstr, " ")) { ELINKS_CAST_PROP_PARAMS
unsigned char *ustr, ts[64] = ""; (void)obj;
static unsigned char custr[256];
/* TODO: Somehow get the terminal in which the undef_to_jsval(ctx, vp);
* document is actually being displayed. */ #ifdef CONFIG_NLS
struct terminal *term = get_default_terminal(); if (get_opt_bool("protocol.http.accept_ui_language", NULL))
string_to_jsval(ctx, vp, language_to_iso639(current_language));
if (term) {
unsigned int tslen = 0; #endif
return JS_TRUE;
ulongcat(ts, &tslen, term->width, 3, 0); }
ts[tslen++] = 'x';
ulongcat(ts, &tslen, term->height, 3, 0); static JSBool
} navigator_get_property_platform(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
ustr = subst_user_agent(optstr, VERSION_STRING, system_name, ts); {
ELINKS_CAST_PROP_PARAMS
if (ustr) { (void)obj;
safe_strncpy(custr, ustr, 256);
mem_free(ustr); string_to_jsval(ctx, vp, system_name);
string_to_jsval(ctx, vp, custr);
} return JS_TRUE;
} }
}
break; static JSBool
default: navigator_get_property_userAgent(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
/* Unrecognized integer property ID; someone is using {
* the object as an array. SMJS builtin classes (e.g. ELINKS_CAST_PROP_PARAMS
* js_RegExpClass) just return JS_TRUE in this case unsigned char *optstr;
* and leave *@vp unchanged. Do the same here. (void)obj;
* (Actually not quite the same, as we already used
* @undef_to_jsval.) */ optstr = get_opt_str("protocol.http.user_agent", NULL);
break;
} if (*optstr && strcmp(optstr, " ")) {
unsigned char *ustr, ts[64] = "";
static unsigned char custr[256];
/* TODO: Somehow get the terminal in which the
* document is actually being displayed. */
struct terminal *term = get_default_terminal();
if (term) {
unsigned int tslen = 0;
ulongcat(ts, &tslen, term->width, 3, 0);
ts[tslen++] = 'x';
ulongcat(ts, &tslen, term->height, 3, 0);
}
ustr = subst_user_agent(optstr, VERSION_STRING, system_name, ts);
if (ustr) {
safe_strncpy(custr, ustr, 256);
mem_free(ustr);
string_to_jsval(ctx, vp, custr);
return JS_TRUE;
}
}
string_to_jsval(ctx, vp, system_name);
return JS_TRUE; return JS_TRUE;
} }

View File

@ -4,7 +4,7 @@
#include "ecmascript/spidermonkey/util.h" #include "ecmascript/spidermonkey/util.h"
extern const JSClass navigator_class; extern JSClass navigator_class;
extern const JSPropertySpec navigator_props[]; extern JSPropertySpec navigator_props[];
#endif #endif

View File

@ -44,25 +44,24 @@
#include "viewer/text/link.h" #include "viewer/text/link.h"
#include "viewer/text/vs.h" #include "viewer/text/vs.h"
static JSBool unibar_get_property_visible(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp);
static JSBool unibar_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp); static JSBool unibar_set_property_visible(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSBool strict, JSMutableHandleValue hvp);
static JSBool unibar_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp);
/* Each @menubar_class object must have a @window_class parent. */ /* Each @menubar_class object must have a @window_class parent. */
const JSClass menubar_class = { JSClass menubar_class = {
"menubar", "menubar",
JSCLASS_HAS_PRIVATE, /* const char * "t" */ JSCLASS_HAS_PRIVATE, /* const char * "t" */
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
unibar_get_property, unibar_set_property, JS_PropertyStub, JS_StrictPropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, NULL
}; };
/* Each @statusbar_class object must have a @window_class parent. */ /* Each @statusbar_class object must have a @window_class parent. */
const JSClass statusbar_class = { JSClass statusbar_class = {
"statusbar", "statusbar",
JSCLASS_HAS_PRIVATE, /* const char * "s" */ JSCLASS_HAS_PRIVATE, /* const char * "s" */
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
unibar_get_property, unibar_set_property, JS_PropertyStub, JS_StrictPropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, NULL
}; };
/* Tinyids of properties. Use negative values to distinguish these /* Tinyids of properties. Use negative values to distinguish these
@ -72,16 +71,18 @@ const JSClass statusbar_class = {
enum unibar_prop { enum unibar_prop {
JSP_UNIBAR_VISIBLE = -1, JSP_UNIBAR_VISIBLE = -1,
}; };
const JSPropertySpec unibar_props[] = { JSPropertySpec unibar_props[] = {
{ "visible", JSP_UNIBAR_VISIBLE, JSPROP_ENUMERATE }, { "visible", 0, JSPROP_ENUMERATE|JSPROP_SHARED, JSOP_WRAPPER(unibar_get_property_visible), JSOP_WRAPPER(unibar_set_property_visible) },
{ NULL } { NULL }
}; };
/* @menubar_class.getProperty, @statusbar_class.getProperty */
static JSBool static JSBool
unibar_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp) unibar_get_property_visible(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{ {
ELINKS_CAST_PROP_PARAMS
JSObject *parent_win; /* instance of @window_class */ JSObject *parent_win; /* instance of @window_class */
struct view_state *vs; struct view_state *vs;
struct document_view *doc_view; struct document_view *doc_view;
@ -91,56 +92,44 @@ unibar_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp)
/* This can be called if @obj if not itself an instance of either /* This can be called if @obj if not itself an instance of either
* appropriate class but has one in its prototype chain. Fail * appropriate class but has one in its prototype chain. Fail
* such calls. */ * such calls. */
if (!JS_InstanceOf(ctx, obj, (JSClass *) &menubar_class, NULL) if (!JS_InstanceOf(ctx, obj, &menubar_class, NULL)
&& !JS_InstanceOf(ctx, obj, (JSClass *) &statusbar_class, NULL)) && !JS_InstanceOf(ctx, obj, &statusbar_class, NULL))
return JS_FALSE; return JS_FALSE;
parent_win = JS_GetParent(ctx, obj); parent_win = JS_GetParent(obj);
assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL)); assert(JS_InstanceOf(ctx, parent_win, &window_class, NULL));
if_assert_failed return JS_FALSE; if_assert_failed return JS_FALSE;
vs = JS_GetInstancePrivate(ctx, parent_win, vs = JS_GetInstancePrivate(ctx, parent_win,
(JSClass *) &window_class, NULL); &window_class, NULL);
doc_view = vs->doc_view; doc_view = vs->doc_view;
status = &doc_view->session->status; status = &doc_view->session->status;
bar = JS_GetPrivate(ctx, obj); /* from @menubar_class or @statusbar_class */ bar = JS_GetPrivate(obj); /* from @menubar_class or @statusbar_class */
if (!JSID_IS_INT(id))
return JS_TRUE;
switch (JSID_TO_INT(id)) {
case JSP_UNIBAR_VISIBLE:
#define unibar_fetch(bar) \ #define unibar_fetch(bar) \
boolean_to_jsval(ctx, vp, status->force_show_##bar##_bar >= 0 \ boolean_to_jsval(ctx, vp, status->force_show_##bar##_bar >= 0 \
? status->force_show_##bar##_bar \ ? status->force_show_##bar##_bar \
: status->show_##bar##_bar) : status->show_##bar##_bar)
switch (*bar) { switch (*bar) {
case 's': case 's':
unibar_fetch(status); unibar_fetch(status);
break; break;
case 't': case 't':
unibar_fetch(title); unibar_fetch(title);
break;
default:
boolean_to_jsval(ctx, vp, 0);
break;
}
#undef unibar_fetch
break; break;
default: default:
/* Unrecognized integer property ID; someone is using boolean_to_jsval(ctx, vp, 0);
* the object as an array. SMJS builtin classes (e.g.
* js_RegExpClass) just return JS_TRUE in this case
* and leave *@vp unchanged. Do the same here. */
break; break;
} }
#undef unibar_fetch
return JS_TRUE; return JS_TRUE;
} }
/* @menubar_class.setProperty, @statusbar_class.setProperty */
static JSBool static JSBool
unibar_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp) unibar_set_property_visible(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSBool strict, JSMutableHandleValue hvp)
{ {
ELINKS_CAST_PROP_PARAMS
JSObject *parent_win; /* instance of @window_class */ JSObject *parent_win; /* instance of @window_class */
struct view_state *vs; struct view_state *vs;
struct document_view *doc_view; struct document_view *doc_view;
@ -150,43 +139,30 @@ unibar_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval
/* This can be called if @obj if not itself an instance of either /* This can be called if @obj if not itself an instance of either
* appropriate class but has one in its prototype chain. Fail * appropriate class but has one in its prototype chain. Fail
* such calls. */ * such calls. */
if (!JS_InstanceOf(ctx, obj, (JSClass *) &menubar_class, NULL) if (!JS_InstanceOf(ctx, obj, &menubar_class, NULL)
&& !JS_InstanceOf(ctx, obj, (JSClass *) &statusbar_class, NULL)) && !JS_InstanceOf(ctx, obj, &statusbar_class, NULL))
return JS_FALSE; return JS_FALSE;
parent_win = JS_GetParent(ctx, obj); parent_win = JS_GetParent(obj);
assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL)); assert(JS_InstanceOf(ctx, parent_win, &window_class, NULL));
if_assert_failed return JS_FALSE; if_assert_failed return JS_FALSE;
vs = JS_GetInstancePrivate(ctx, parent_win, vs = JS_GetInstancePrivate(ctx, parent_win,
(JSClass *) &window_class, NULL); &window_class, NULL);
doc_view = vs->doc_view; doc_view = vs->doc_view;
status = &doc_view->session->status; status = &doc_view->session->status;
bar = JS_GetPrivate(ctx, obj); /* from @menubar_class or @statusbar_class */ bar = JS_GetPrivate(obj); /* from @menubar_class or @statusbar_class */
if (!JSID_IS_INT(id)) switch (*bar) {
return JS_TRUE; case 's':
status->force_show_status_bar = jsval_to_boolean(ctx, vp);
switch (JSID_TO_INT(id)) { break;
case JSP_UNIBAR_VISIBLE: case 't':
switch (*bar) { status->force_show_title_bar = jsval_to_boolean(ctx, vp);
case 's':
status->force_show_status_bar = jsval_to_boolean(ctx, vp);
break;
case 't':
status->force_show_title_bar = jsval_to_boolean(ctx, vp);
break;
default:
break;
}
register_bottom_half(update_status, NULL);
break; break;
default: default:
/* Unrecognized integer property ID; someone is using break;
* the object as an array. SMJS builtin classes (e.g.
* js_RegExpClass) just return JS_TRUE in this case.
* Do the same here. */
return JS_TRUE;
} }
register_bottom_half(update_status, NULL);
return JS_TRUE; return JS_TRUE;
} }

View File

@ -4,8 +4,8 @@
#include "ecmascript/spidermonkey/util.h" #include "ecmascript/spidermonkey/util.h"
extern const JSClass menubar_class; extern JSClass menubar_class;
extern const JSClass statusbar_class; extern JSClass statusbar_class;
extern const JSPropertySpec unibar_props[]; extern JSPropertySpec unibar_props[];
#endif #endif

View File

@ -44,15 +44,21 @@
#include "viewer/text/vs.h" #include "viewer/text/vs.h"
static JSBool window_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp); static JSBool window_get_property(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp);
static JSBool window_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp); static JSBool window_get_property_closed(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp);
static JSBool window_get_property_parent(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp);
static JSBool window_get_property_self(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp);
static JSBool window_get_property_status(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp);
static JSBool window_set_property_status(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSBool strict, JSMutableHandleValue hvp);
static JSBool window_get_property_top(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp);
static JSBool window_get_property_window(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp);
const JSClass window_class = { JSClass window_class = {
"window", "window",
JSCLASS_HAS_PRIVATE | JSCLASS_GLOBAL_FLAGS, /* struct view_state * */ JSCLASS_HAS_PRIVATE | JSCLASS_GLOBAL_FLAGS, /* struct view_state * */
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
window_get_property, window_set_property, window_get_property, JS_StrictPropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, NULL
}; };
@ -73,13 +79,13 @@ enum window_prop {
* (SpiderMonkey was still asking us about the "location" string after * (SpiderMonkey was still asking us about the "location" string after
* assigning to it once), instead we do just a little string * assigning to it once), instead we do just a little string
* comparing. */ * comparing. */
const JSPropertySpec window_props[] = { JSPropertySpec window_props[] = {
{ "closed", JSP_WIN_CLOSED, JSPROP_ENUMERATE | JSPROP_READONLY }, { "closed", 0, JSPROP_ENUMERATE | JSPROP_READONLY|JSPROP_SHARED, JSOP_WRAPPER(window_get_property_closed), JSOP_NULLWRAPPER },
{ "parent", JSP_WIN_PARENT, JSPROP_ENUMERATE | JSPROP_READONLY }, { "parent", 0, JSPROP_ENUMERATE | JSPROP_READONLY|JSPROP_SHARED, JSOP_WRAPPER(window_get_property_parent), JSOP_NULLWRAPPER },
{ "self", JSP_WIN_SELF, JSPROP_ENUMERATE | JSPROP_READONLY }, { "self", 0, JSPROP_ENUMERATE | JSPROP_READONLY|JSPROP_SHARED, JSOP_WRAPPER(window_get_property_self), JSOP_NULLWRAPPER },
{ "status", JSP_WIN_STATUS, JSPROP_ENUMERATE }, { "status", 0, JSPROP_ENUMERATE|JSPROP_SHARED, JSOP_WRAPPER(window_get_property_status), JSOP_WRAPPER(window_set_property_status) },
{ "top", JSP_WIN_TOP, JSPROP_ENUMERATE | JSPROP_READONLY }, { "top", 0, JSPROP_ENUMERATE | JSPROP_READONLY|JSPROP_SHARED, JSOP_WRAPPER(window_get_property_top), JSOP_NULLWRAPPER },
{ "window", JSP_WIN_SELF, JSPROP_ENUMERATE | JSPROP_READONLY }, { "window", 0, JSPROP_ENUMERATE | JSPROP_READONLY|JSPROP_SHARED, JSOP_WRAPPER(window_get_property_window), JSOP_NULLWRAPPER },
{ NULL } { NULL }
}; };
@ -122,17 +128,20 @@ find_child_frame(struct document_view *doc_view, struct frame_desc *tframe)
/* @window_class.getProperty */ /* @window_class.getProperty */
static JSBool static JSBool
window_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp) window_get_property(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{ {
ELINKS_CAST_PROP_PARAMS
jsid id = *(hid._);
struct view_state *vs; struct view_state *vs;
/* This can be called if @obj if not itself an instance of the /* This can be called if @obj if not itself an instance of the
* appropriate class but has one in its prototype chain. Fail * appropriate class but has one in its prototype chain. Fail
* such calls. */ * such calls. */
if (!JS_InstanceOf(ctx, obj, (JSClass *) &window_class, NULL)) if (!JS_InstanceOf(ctx, obj, &window_class, NULL))
return JS_FALSE; return JS_FALSE;
vs = JS_GetInstancePrivate(ctx, obj, (JSClass *) &window_class, NULL); vs = JS_GetInstancePrivate(ctx, obj, &window_class, NULL);
/* No need for special window.location measurements - when /* No need for special window.location measurements - when
* location is then evaluated in string context, toString() * location is then evaluated in string context, toString()
@ -140,9 +149,7 @@ window_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp)
* everything's fine. */ * everything's fine. */
if (JSID_IS_STRING(id)) { if (JSID_IS_STRING(id)) {
struct document_view *doc_view = vs->doc_view; struct document_view *doc_view = vs->doc_view;
JSObject *obj; JSObject *obj = try_resolve_frame(doc_view, jsid_to_string(ctx, &id));
obj = try_resolve_frame(doc_view, jsid_to_string(ctx, &id));
/* TODO: Try other lookups (mainly element lookup) until /* TODO: Try other lookups (mainly element lookup) until
* something yields data. */ * something yields data. */
if (obj) { if (obj) {
@ -252,55 +259,9 @@ found_parent:
void location_goto(struct document_view *doc_view, unsigned char *url); void location_goto(struct document_view *doc_view, unsigned char *url);
/* @window_class.setProperty */ static JSBool window_alert(JSContext *ctx, unsigned int argc, jsval *rval);
static JSBool static JSBool window_open(JSContext *ctx, unsigned int argc, jsval *rval);
window_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp) static JSBool window_setTimeout(JSContext *ctx, unsigned int argc, jsval *rval);
{
struct view_state *vs;
/* 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 *) &window_class, NULL))
return JS_FALSE;
vs = JS_GetInstancePrivate(ctx, obj, (JSClass *) &window_class, NULL);
if (JSID_IS_STRING(id)) {
if (!strcmp(jsid_to_string(ctx, &id), "location")) {
struct document_view *doc_view = vs->doc_view;
location_goto(doc_view, jsval_to_string(ctx, vp));
/* Do NOT touch our .location property, evil
* SpiderMonkey!! */
return JS_FALSE;
}
return JS_TRUE;
}
if (!JSID_IS_INT(id))
return JS_TRUE;
switch (JSID_TO_INT(id)) {
case JSP_WIN_STATUS:
mem_free_set(&vs->doc_view->session->status.window_status, stracpy(jsval_to_string(ctx, vp)));
print_screen_status(vs->doc_view->session);
return JS_TRUE;
default:
/* Unrecognized integer property ID; someone is using
* the object as an array. SMJS builtin classes (e.g.
* js_RegExpClass) just return JS_TRUE in this case.
* Do the same here. */
return JS_TRUE;
}
return JS_TRUE;
}
static JSBool window_alert(JSContext *ctx, uintN argc, jsval *rval);
static JSBool window_open(JSContext *ctx, uintN argc, jsval *rval);
static JSBool window_setTimeout(JSContext *ctx, uintN argc, jsval *rval);
const spidermonkeyFunctionSpec window_funcs[] = { const spidermonkeyFunctionSpec window_funcs[] = {
{ "alert", window_alert, 1 }, { "alert", window_alert, 1 },
@ -311,7 +272,7 @@ const spidermonkeyFunctionSpec window_funcs[] = {
/* @window_funcs{"alert"} */ /* @window_funcs{"alert"} */
static JSBool static JSBool
window_alert(JSContext *ctx, uintN argc, jsval *rval) window_alert(JSContext *ctx, unsigned int argc, jsval *rval)
{ {
jsval val; jsval val;
JSObject *obj = JS_THIS_OBJECT(ctx, rval); JSObject *obj = JS_THIS_OBJECT(ctx, rval);
@ -319,9 +280,9 @@ window_alert(JSContext *ctx, uintN argc, jsval *rval)
struct view_state *vs; struct view_state *vs;
unsigned char *string; unsigned char *string;
if (!JS_InstanceOf(ctx, obj, (JSClass *) &window_class, argv)) return JS_FALSE; if (!JS_InstanceOf(ctx, obj, &window_class, argv)) return JS_FALSE;
vs = JS_GetInstancePrivate(ctx, obj, (JSClass *) &window_class, argv); vs = JS_GetInstancePrivate(ctx, obj, &window_class, argv);
if (argc != 1) if (argc != 1)
return JS_TRUE; return JS_TRUE;
@ -340,7 +301,7 @@ window_alert(JSContext *ctx, uintN argc, jsval *rval)
/* @window_funcs{"open"} */ /* @window_funcs{"open"} */
static JSBool static JSBool
window_open(JSContext *ctx, uintN argc, jsval *rval) window_open(JSContext *ctx, unsigned int argc, jsval *rval)
{ {
jsval val; jsval val;
JSObject *obj = JS_THIS_OBJECT(ctx, rval); JSObject *obj = JS_THIS_OBJECT(ctx, rval);
@ -354,9 +315,9 @@ window_open(JSContext *ctx, uintN argc, jsval *rval)
static time_t ratelimit_start; static time_t ratelimit_start;
static int ratelimit_count; static int ratelimit_count;
if (!JS_InstanceOf(ctx, obj, (JSClass *) &window_class, argv)) return JS_FALSE; if (!JS_InstanceOf(ctx, obj, &window_class, argv)) return JS_FALSE;
vs = JS_GetInstancePrivate(ctx, obj, (JSClass *) &window_class, argv); vs = JS_GetInstancePrivate(ctx, obj, &window_class, argv);
doc_view = vs->doc_view; doc_view = vs->doc_view;
ses = doc_view->session; ses = doc_view->session;
@ -451,7 +412,7 @@ end:
/* @window_funcs{"setTimeout"} */ /* @window_funcs{"setTimeout"} */
static JSBool static JSBool
window_setTimeout(JSContext *ctx, uintN argc, jsval *rval) window_setTimeout(JSContext *ctx, unsigned int argc, jsval *rval)
{ {
jsval *argv = JS_ARGV(ctx, rval); jsval *argv = JS_ARGV(ctx, rval);
struct ecmascript_interpreter *interpreter = JS_GetContextPrivate(ctx); struct ecmascript_interpreter *interpreter = JS_GetContextPrivate(ctx);
@ -476,3 +437,150 @@ window_setTimeout(JSContext *ctx, uintN argc, jsval *rval)
ecmascript_set_timeout(interpreter, code, timeout); ecmascript_set_timeout(interpreter, code, timeout);
return JS_TRUE; return JS_TRUE;
} }
static JSBool
window_get_property_closed(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{
ELINKS_CAST_PROP_PARAMS
/* 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, &window_class, NULL))
return JS_FALSE;
boolean_to_jsval(ctx, vp, 0);
return JS_TRUE;
}
static JSBool
window_get_property_parent(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{
ELINKS_CAST_PROP_PARAMS
/* 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, &window_class, NULL))
return JS_FALSE;
/* XXX: It would be nice if the following worked, yes.
* The problem is that we get called at the point where
* document.frame properties are going to be mostly NULL.
* But the problem is deeper because at that time we are
* yet building scrn_frames so our parent might not be there
* yet (XXX: is this true?). The true solution will be to just
* have struct document_view *(document_view.parent). --pasky */
/* FIXME: So now we alias window.parent to window.top, which is
* INCORRECT but works for the most common cases of just two
* frames. Better something than nothing. */
undef_to_jsval(ctx, vp);
return JS_TRUE;
}
static JSBool
window_get_property_self(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{
ELINKS_CAST_PROP_PARAMS
/* 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, &window_class, NULL))
return JS_FALSE;
object_to_jsval(ctx, vp, obj);
return JS_TRUE;
}
static JSBool
window_get_property_status(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{
ELINKS_CAST_PROP_PARAMS
/* 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, &window_class, NULL))
return JS_FALSE;
undef_to_jsval(ctx, vp);
return JS_TRUE;
}
static JSBool
window_set_property_status(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSBool strict, JSMutableHandleValue hvp)
{
ELINKS_CAST_PROP_PARAMS
struct view_state *vs;
/* 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, &window_class, NULL))
return JS_FALSE;
vs = JS_GetInstancePrivate(ctx, obj, &window_class, NULL);
mem_free_set(&vs->doc_view->session->status.window_status, stracpy(jsval_to_string(ctx, vp)));
print_screen_status(vs->doc_view->session);
return JS_TRUE;
}
static JSBool
window_get_property_top(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{
ELINKS_CAST_PROP_PARAMS
struct view_state *vs;
struct document_view *doc_view;
struct document_view *top_view;
JSObject *newjsframe;
/* 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, &window_class, NULL))
return JS_FALSE;
vs = JS_GetInstancePrivate(ctx, obj, &window_class, NULL);
doc_view = vs->doc_view;
top_view = doc_view->session->doc_view;
undef_to_jsval(ctx, vp);
assert(top_view && top_view->vs);
if (top_view->vs->ecmascript_fragile)
ecmascript_reset_state(top_view->vs);
if (!top_view->vs->ecmascript)
return JS_TRUE;
newjsframe = JS_GetGlobalObject(top_view->vs->ecmascript->backend_data);
/* Keep this unrolled this way. Will have to check document.domain
* JS property. */
/* Note that this check is perhaps overparanoid. If top windows
* is alien but some other child window is not, we should still
* let the script walk thru. That'd mean moving the check to
* other individual properties in this switch. */
if (compare_uri(vs->uri, top_view->vs->uri, URI_HOST))
object_to_jsval(ctx, vp, newjsframe);
/* else */
/****X*X*X*** SECURITY VIOLATION! RED ALERT, SHIELDS UP! ***X*X*X****\
|* (Pasky was apparently looking at the Links2 JS code . ___ ^.^ *|
\* for too long.) `.(,_,)\o/ */
return JS_TRUE;
}
static JSBool
window_get_property_window(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{
return window_get_property_self(ctx, hobj, hid, hvp);
}

View File

@ -4,8 +4,8 @@
#include "ecmascript/spidermonkey/util.h" #include "ecmascript/spidermonkey/util.h"
extern const JSClass window_class; extern JSClass window_class;
extern const JSPropertySpec window_props[]; extern JSPropertySpec window_props[];
extern const spidermonkeyFunctionSpec window_funcs[]; extern const spidermonkeyFunctionSpec window_funcs[];
#endif #endif

View File

@ -27,22 +27,26 @@ static const JSClass action_fn_class; /* defined below */
/* @action_fn_class.finalize */ /* @action_fn_class.finalize */
static void static void
smjs_action_fn_finalize(JSContext *ctx, JSObject *obj) smjs_action_fn_finalize(JSFreeOp *op, JSObject *obj)
{ {
struct smjs_action_fn_callback_hop *hop; struct smjs_action_fn_callback_hop *hop;
#if 0
assert(JS_InstanceOf(ctx, obj, (JSClass *) &action_fn_class, NULL)); assert(JS_InstanceOf(ctx, obj, (JSClass *) &action_fn_class, NULL));
if_assert_failed return; if_assert_failed return;
hop = JS_GetInstancePrivate(ctx, obj, hop = JS_GetInstancePrivate(ctx, obj,
(JSClass *) &action_fn_class, NULL); (JSClass *) &action_fn_class, NULL);
#endif
hop = JS_GetPrivate(obj);
mem_free_if(hop); mem_free_if(hop);
} }
/* @action_fn_class.call */ /* @action_fn_class.call */
static JSBool static JSBool
smjs_action_fn_callback(JSContext *ctx, uintN argc, jsval *rval) smjs_action_fn_callback(JSContext *ctx, unsigned int argc, jsval *rval)
{ {
jsval value; jsval value;
jsval *argv = JS_ARGV(ctx, rval); jsval *argv = JS_ARGV(ctx, rval);
@ -95,7 +99,7 @@ smjs_action_fn_callback(JSContext *ctx, uintN argc, jsval *rval)
} }
if (argc >= 1) { if (argc >= 1) {
int32 val; int32_t val;
if (JS_TRUE == JS_ValueToInt32(smjs_ctx, argv[0], &val)) { if (JS_TRUE == JS_ValueToInt32(smjs_ctx, argv[0], &val)) {
set_kbd_repeat_count(hop->ses, val); set_kbd_repeat_count(hop->ses, val);
@ -117,7 +121,7 @@ static const JSClass action_fn_class = {
JS_PropertyStub, JS_StrictPropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub,
smjs_action_fn_finalize, smjs_action_fn_finalize,
NULL, NULL, NULL,
smjs_action_fn_callback, smjs_action_fn_callback,
}; };
@ -145,9 +149,9 @@ smjs_get_action_fn_object(unsigned char *action_str)
hop->action_id = get_action_from_string(KEYMAP_MAIN, action_str); hop->action_id = get_action_from_string(KEYMAP_MAIN, action_str);
if (-1 != hop->action_id if (-1 != hop->action_id) {
&& JS_TRUE == JS_SetPrivate(smjs_ctx, obj, hop)) { /* to @action_fn_class */ JS_SetPrivate(obj, hop); /* to @action_fn_class */
return obj; return obj;
} }
mem_free(hop); mem_free(hop);
@ -159,8 +163,12 @@ smjs_get_action_fn_object(unsigned char *action_str)
/* @action_class.getProperty */ /* @action_class.getProperty */
static JSBool static JSBool
action_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp) action_get_property(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{ {
ELINKS_CAST_PROP_PARAMS
jsid id = *(hid._);
(void)obj;
jsval val; jsval val;
JSObject *action_fn; JSObject *action_fn;
unsigned char *action_str; unsigned char *action_str;
@ -184,7 +192,7 @@ static const JSClass action_class = {
0, 0,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
action_get_property, JS_StrictPropertyStub, action_get_property, JS_StrictPropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, NULL,
}; };
static JSObject * static JSObject *

View File

@ -33,26 +33,24 @@ smjs_get_bookmark_generic_object(struct bookmark *bookmark, JSClass *clasp)
if (!bookmark) return jsobj; if (!bookmark) return jsobj;
if (JS_TRUE == JS_SetPrivate(smjs_ctx, jsobj, bookmark)) { /* to @bookmark_class or @bookmark_folder_class */ JS_SetPrivate(jsobj, bookmark); /* to @bookmark_class or @bookmark_folder_class */
object_lock(bookmark); object_lock(bookmark);
return jsobj; return jsobj;
}
return NULL;
}; };
/* @bookmark_class.finalize, @bookmark_folder_class.finalize */ /* @bookmark_class.finalize, @bookmark_folder_class.finalize */
static void static void
bookmark_finalize(JSContext *ctx, JSObject *obj) bookmark_finalize(JSFreeOp *op, JSObject *obj)
{ {
struct bookmark *bookmark; struct bookmark *bookmark;
#if 0
assert(JS_InstanceOf(ctx, obj, (JSClass *) &bookmark_class, NULL) assert(JS_InstanceOf(ctx, obj, (JSClass *) &bookmark_class, NULL)
|| JS_InstanceOf(ctx, obj, (JSClass *) &bookmark_folder_class, NULL)); || JS_InstanceOf(ctx, obj, (JSClass *) &bookmark_folder_class, NULL));
if_assert_failed return; if_assert_failed return;
#endif
bookmark = JS_GetPrivate(ctx, obj); /* from @bookmark_class or @bookmark_folder_class */ bookmark = JS_GetPrivate(obj); /* from @bookmark_class or @bookmark_folder_class */
if (bookmark) object_unlock(bookmark); if (bookmark) object_unlock(bookmark);
} }
@ -70,10 +68,16 @@ enum bookmark_prop {
BOOKMARK_CHILDREN = -3, BOOKMARK_CHILDREN = -3,
}; };
static JSBool bookmark_get_property_title(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp);
static JSBool bookmark_set_property_title(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSBool strict, JSMutableHandleValue hvp);
static JSBool bookmark_get_property_url(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp);
static JSBool bookmark_set_property_url(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSBool strict, JSMutableHandleValue hvp);
static JSBool bookmark_get_property_children(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp);
static const JSPropertySpec bookmark_props[] = { static const JSPropertySpec bookmark_props[] = {
{ "title", BOOKMARK_TITLE, JSPROP_ENUMERATE }, { "title", 0, JSPROP_ENUMERATE, JSOP_WRAPPER(bookmark_get_property_title), JSOP_WRAPPER(bookmark_set_property_title) },
{ "url", BOOKMARK_URL, JSPROP_ENUMERATE }, { "url", 0, JSPROP_ENUMERATE, JSOP_WRAPPER(bookmark_get_property_url), JSOP_WRAPPER(bookmark_set_property_url) },
{ "children", BOOKMARK_CHILDREN, JSPROP_ENUMERATE | JSPROP_READONLY }, { "children", 0, JSPROP_ENUMERATE | JSPROP_READONLY, JSOP_WRAPPER(bookmark_get_property_children), JSOP_NULLWRAPPER },
{ NULL } { NULL }
}; };
@ -145,10 +149,11 @@ jsval_to_bookmark_string(JSContext *ctx, jsval val, unsigned char **result)
return JS_TRUE; return JS_TRUE;
} }
/* @bookmark_class.getProperty */
static JSBool static JSBool
bookmark_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp) bookmark_get_property_title(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{ {
ELINKS_CAST_PROP_PARAMS
struct bookmark *bookmark; struct bookmark *bookmark;
/* This can be called if @obj if not itself an instance of the /* This can be called if @obj if not itself an instance of the
@ -162,35 +167,14 @@ bookmark_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp)
if (!bookmark) return JS_FALSE; if (!bookmark) return JS_FALSE;
undef_to_jsval(ctx, vp); return bookmark_string_to_jsval(ctx, bookmark->title, vp);
if (!JSID_IS_INT(id))
return JS_FALSE;
switch (JSID_TO_INT(id)) {
case BOOKMARK_TITLE:
return bookmark_string_to_jsval(ctx, bookmark->title, vp);
case BOOKMARK_URL:
return bookmark_string_to_jsval(ctx, bookmark->url, vp);
case BOOKMARK_CHILDREN:
*vp = OBJECT_TO_JSVAL(smjs_get_bookmark_folder_object(bookmark));
return JS_TRUE;
default:
/* Unrecognized integer property ID; someone is using
* the object as an array. SMJS builtin classes (e.g.
* js_RegExpClass) just return JS_TRUE in this case
* and leave *@vp unchanged. Do the same here.
* (Actually not quite the same, as we already used
* @undef_to_jsval.) */
return JS_TRUE;
}
} }
/* @bookmark_class.setProperty */
static JSBool static JSBool
bookmark_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp) bookmark_set_property_title(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSBool strict, JSMutableHandleValue hvp)
{ {
ELINKS_CAST_PROP_PARAMS
struct bookmark *bookmark; struct bookmark *bookmark;
unsigned char *title = NULL; unsigned char *title = NULL;
unsigned char *url = NULL; unsigned char *url = NULL;
@ -207,37 +191,94 @@ bookmark_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsv
if (!bookmark) return JS_FALSE; if (!bookmark) return JS_FALSE;
if (!JSID_IS_INT(id)) if (!jsval_to_bookmark_string(ctx, *vp, &title))
return JS_FALSE; return JS_FALSE;
switch (JSID_TO_INT(id)) {
case BOOKMARK_TITLE:
if (!jsval_to_bookmark_string(ctx, *vp, &title))
return JS_FALSE;
break;
case BOOKMARK_URL:
if (!jsval_to_bookmark_string(ctx, *vp, &url))
return JS_FALSE;
break;
default:
/* Unrecognized integer property ID; someone is using
* the object as an array. SMJS builtin classes (e.g.
* js_RegExpClass) just return JS_TRUE in this case.
* Do the same here. */
return JS_TRUE;
}
ok = update_bookmark(bookmark, get_cp_index("UTF-8"), title, url); ok = update_bookmark(bookmark, get_cp_index("UTF-8"), title, url);
mem_free_if(title); mem_free_if(title);
mem_free_if(url); mem_free_if(url);
return ok ? JS_TRUE : JS_FALSE; return ok ? JS_TRUE : JS_FALSE;
} }
static JSBool
bookmark_get_property_url(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{
ELINKS_CAST_PROP_PARAMS
struct bookmark *bookmark;
/* 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 *) &bookmark_class, NULL))
return JS_FALSE;
bookmark = JS_GetInstancePrivate(ctx, obj,
(JSClass *) &bookmark_class, NULL);
if (!bookmark) return JS_FALSE;
return bookmark_string_to_jsval(ctx, bookmark->url, vp);
}
static JSBool
bookmark_set_property_url(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSBool strict, JSMutableHandleValue hvp)
{
ELINKS_CAST_PROP_PARAMS
struct bookmark *bookmark;
unsigned char *title = NULL;
unsigned char *url = NULL;
int ok;
/* 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 *) &bookmark_class, NULL))
return JS_FALSE;
bookmark = JS_GetInstancePrivate(ctx, obj,
(JSClass *) &bookmark_class, NULL);
if (!bookmark) return JS_FALSE;
if (!jsval_to_bookmark_string(ctx, *vp, &url))
return JS_FALSE;
ok = update_bookmark(bookmark, get_cp_index("UTF-8"), title, url);
mem_free_if(title);
mem_free_if(url);
return ok ? JS_TRUE : JS_FALSE;
}
static JSBool
bookmark_get_property_children(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{
ELINKS_CAST_PROP_PARAMS
struct bookmark *bookmark;
/* 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 *) &bookmark_class, NULL))
return JS_FALSE;
bookmark = JS_GetInstancePrivate(ctx, obj,
(JSClass *) &bookmark_class, NULL);
if (!bookmark) return JS_FALSE;
*vp = OBJECT_TO_JSVAL(smjs_get_bookmark_folder_object(bookmark));
return JS_TRUE;
}
static const JSClass bookmark_class = { static const JSClass bookmark_class = {
"bookmark", "bookmark",
JSCLASS_HAS_PRIVATE, /* struct bookmark * */ JSCLASS_HAS_PRIVATE, /* struct bookmark * */
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
bookmark_get_property, bookmark_set_property, JS_PropertyStub, JS_StrictPropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, bookmark_finalize, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, bookmark_finalize,
}; };
@ -262,8 +303,11 @@ smjs_get_bookmark_object(struct bookmark *bookmark)
/* @bookmark_folder_class.getProperty */ /* @bookmark_folder_class.getProperty */
static JSBool static JSBool
bookmark_folder_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp) bookmark_folder_get_property(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{ {
ELINKS_CAST_PROP_PARAMS
jsid id = *(hid._);
struct bookmark *bookmark; struct bookmark *bookmark;
struct bookmark *folder; struct bookmark *folder;
jsval title_jsval = JSVAL_VOID; jsval title_jsval = JSVAL_VOID;

View File

@ -29,20 +29,31 @@ enum cache_entry_prop {
CACHE_ENTRY_URI = -5, CACHE_ENTRY_URI = -5,
}; };
static JSBool cache_entry_get_property_content(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp);
static JSBool cache_entry_set_property_content(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSBool strict, JSMutableHandleValue hvp);
static JSBool cache_entry_get_property_type(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp);
static JSBool cache_entry_set_property_type(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSBool strict, JSMutableHandleValue hvp);
static JSBool cache_entry_get_property_length(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp);
static JSBool cache_entry_get_property_head(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp);
static JSBool cache_entry_set_property_head(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSBool strict, JSMutableHandleValue hvp);
static JSBool cache_entry_get_property_uri(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp);
static const JSPropertySpec cache_entry_props[] = { static const JSPropertySpec cache_entry_props[] = {
{ "content", CACHE_ENTRY_CONTENT, JSPROP_ENUMERATE }, { "content", 0, JSPROP_ENUMERATE, JSOP_WRAPPER(cache_entry_get_property_content), JSOP_WRAPPER(cache_entry_set_property_content) },
{ "type", CACHE_ENTRY_TYPE, JSPROP_ENUMERATE }, { "type", 0, JSPROP_ENUMERATE, JSOP_WRAPPER(cache_entry_get_property_type), JSOP_WRAPPER(cache_entry_set_property_type)},
{ "length", CACHE_ENTRY_LENGTH, JSPROP_ENUMERATE | JSPROP_READONLY }, { "length", 0, JSPROP_ENUMERATE | JSPROP_READONLY, JSOP_WRAPPER(cache_entry_get_property_length), JSOP_NULLWRAPPER },
{ "head", CACHE_ENTRY_HEAD, JSPROP_ENUMERATE }, { "head", 0, JSPROP_ENUMERATE, JSOP_WRAPPER(cache_entry_get_property_head), JSOP_WRAPPER(cache_entry_set_property_head) },
{ "uri", CACHE_ENTRY_URI, JSPROP_ENUMERATE | JSPROP_READONLY }, { "uri", 0, JSPROP_ENUMERATE | JSPROP_READONLY, JSOP_WRAPPER(cache_entry_get_property_uri), JSOP_NULLWRAPPER },
{ NULL } { NULL }
}; };
/* @cache_entry_class.getProperty */
static JSBool static JSBool
cache_entry_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp) cache_entry_get_property_content(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{ {
ELINKS_CAST_PROP_PARAMS
struct cache_entry *cached; struct cache_entry *cached;
struct fragment *fragment;
JSBool ret; JSBool ret;
/* This can be called if @obj if not itself an instance of the /* This can be called if @obj if not itself an instance of the
@ -65,69 +76,28 @@ cache_entry_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp)
object_lock(cached); object_lock(cached);
undef_to_jsval(ctx, vp); undef_to_jsval(ctx, vp);
fragment = get_cache_fragment(cached);
if (!JSID_IS_INT(id)) if (!fragment) {
ret = JS_FALSE; ret = JS_FALSE;
else switch (JSID_TO_INT(id)) { } else {
case CACHE_ENTRY_CONTENT: { *vp = STRING_TO_JSVAL(JS_NewStringCopyN(smjs_ctx, fragment->data, fragment->length));
struct fragment *fragment = get_cache_fragment(cached);
if (!fragment) {
ret = JS_FALSE;
break;
}
*vp = STRING_TO_JSVAL(JS_NewStringCopyN(smjs_ctx,
fragment->data,
fragment->length));
ret = JS_TRUE; ret = JS_TRUE;
break;
}
case CACHE_ENTRY_TYPE:
*vp = STRING_TO_JSVAL(JS_NewStringCopyZ(smjs_ctx,
cached->content_type));
ret = JS_TRUE;
break;
case CACHE_ENTRY_HEAD:
*vp = STRING_TO_JSVAL(JS_NewStringCopyZ(smjs_ctx,
cached->head));
ret = JS_TRUE;
break;
case CACHE_ENTRY_LENGTH:
*vp = INT_TO_JSVAL(cached->length);
ret = JS_TRUE;
break;
case CACHE_ENTRY_URI:
*vp = STRING_TO_JSVAL(JS_NewStringCopyZ(smjs_ctx,
struri(cached->uri)));
ret = JS_TRUE;
break;
default:
/* Unrecognized integer property ID; someone is using
* the object as an array. SMJS builtin classes (e.g.
* js_RegExpClass) just return JS_TRUE in this case
* and leave *@vp unchanged. Do the same here.
* (Actually not quite the same, as we already used
* @undef_to_jsval.) */
ret = JS_TRUE;
break;
} }
object_unlock(cached); object_unlock(cached);
return ret; return ret;
} }
/* @cache_entry_class.setProperty */
static JSBool static JSBool
cache_entry_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp) cache_entry_set_property_content(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSBool strict, JSMutableHandleValue hvp)
{ {
ELINKS_CAST_PROP_PARAMS
struct cache_entry *cached; struct cache_entry *cached;
JSBool ret; JSString *jsstr;
unsigned char *str;
size_t len;
/* This can be called if @obj if not itself an instance of the /* This can be called if @obj if not itself an instance of the
* appropriate class but has one in its prototype chain. Fail * appropriate class but has one in its prototype chain. Fail
@ -148,68 +118,105 @@ cache_entry_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict,
* eventually unlock the object. */ * eventually unlock the object. */
object_lock(cached); object_lock(cached);
if (!JSID_IS_INT(id)) jsstr = JS_ValueToString(smjs_ctx, *vp);
ret = JS_FALSE; str = JS_EncodeString(smjs_ctx, jsstr);
else switch (JSID_TO_INT(id)) { len = JS_GetStringLength(jsstr);
case CACHE_ENTRY_CONTENT: { add_fragment(cached, 0, str, len);
JSString *jsstr = JS_ValueToString(smjs_ctx, *vp); normalize_cache_entry(cached, len);
unsigned char *str = JS_EncodeString(smjs_ctx, jsstr);
size_t len = JS_GetStringLength(jsstr);
add_fragment(cached, 0, str, len);
normalize_cache_entry(cached, len);
ret = JS_TRUE;
break;
}
case CACHE_ENTRY_TYPE: {
JSString *jsstr = JS_ValueToString(smjs_ctx, *vp);
unsigned char *str = JS_EncodeString(smjs_ctx, jsstr);
mem_free_set(&cached->content_type, stracpy(str));
ret = JS_TRUE;
break;
}
case CACHE_ENTRY_HEAD: {
JSString *jsstr = JS_ValueToString(smjs_ctx, *vp);
unsigned char *str = JS_EncodeString(smjs_ctx, jsstr);
mem_free_set(&cached->head, stracpy(str));
ret = JS_TRUE;
break;
}
default:
/* Unrecognized integer property ID; someone is using
* the object as an array. SMJS builtin classes (e.g.
* js_RegExpClass) just return JS_TRUE in this case.
* Do the same here. */
ret = JS_TRUE;
break;
}
object_unlock(cached); object_unlock(cached);
return ret; return JS_TRUE;
} }
static JSBool
cache_entry_get_property_type(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{
ELINKS_CAST_PROP_PARAMS
struct cache_entry *cached;
/* 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 *) &cache_entry_class, NULL))
return JS_FALSE;
cached = JS_GetInstancePrivate(ctx, obj,
(JSClass *) &cache_entry_class, NULL);
if (!cached) return JS_FALSE; /* already detached */
assert(cache_entry_is_valid(cached));
if_assert_failed return JS_FALSE;
/* Get a strong reference to the cache entry to prevent it
* from being deleted if some function called below decides to
* collect garbage. After this, all code paths must
* eventually unlock the object. */
object_lock(cached);
*vp = STRING_TO_JSVAL(JS_NewStringCopyZ(smjs_ctx, cached->content_type));
object_unlock(cached);
return JS_TRUE;
}
static JSBool
cache_entry_set_property_type(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSBool strict, JSMutableHandleValue hvp)
{
ELINKS_CAST_PROP_PARAMS
struct cache_entry *cached;
JSString *jsstr;
unsigned char *str;
/* 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 *) &cache_entry_class, NULL))
return JS_FALSE;
cached = JS_GetInstancePrivate(ctx, obj,
(JSClass *) &cache_entry_class, NULL);
if (!cached) return JS_FALSE; /* already detached */
assert(cache_entry_is_valid(cached));
if_assert_failed return JS_FALSE;
/* Get a strong reference to the cache entry to prevent it
* from being deleted if some function called below decides to
* collect garbage. After this, all code paths must
* eventually unlock the object. */
object_lock(cached);
jsstr = JS_ValueToString(smjs_ctx, *vp);
str = JS_EncodeString(smjs_ctx, jsstr);
mem_free_set(&cached->content_type, stracpy(str));
object_unlock(cached);
return JS_TRUE;
}
/** Pointed to by cache_entry_class.finalize. SpiderMonkey /** Pointed to by cache_entry_class.finalize. SpiderMonkey
* automatically finalizes all objects before it frees the JSRuntime, * automatically finalizes all objects before it frees the JSRuntime,
* so cache_entry.jsobject won't be left dangling. */ * so cache_entry.jsobject won't be left dangling. */
static void static void
cache_entry_finalize(JSContext *ctx, JSObject *obj) cache_entry_finalize(JSFreeOp *op, JSObject *obj)
{ {
struct cache_entry *cached; struct cache_entry *cached;
#if 0
assert(JS_InstanceOf(ctx, obj, (JSClass *) &cache_entry_class, NULL)); assert(JS_InstanceOf(ctx, obj, (JSClass *) &cache_entry_class, NULL));
if_assert_failed return; if_assert_failed return;
#endif
cached = JS_GetInstancePrivate(ctx, obj, cached = JS_GetPrivate(obj);
(JSClass *) &cache_entry_class, NULL);
if (!cached) return; /* already detached */ if (!cached) return; /* already detached */
JS_SetPrivate(ctx, obj, NULL); /* perhaps not necessary */ JS_SetPrivate(obj, NULL); /* perhaps not necessary */
assert(cached->jsobject == obj); assert(cached->jsobject == obj);
if_assert_failed return; if_assert_failed return;
cached->jsobject = NULL; cached->jsobject = NULL;
@ -219,7 +226,7 @@ static const JSClass cache_entry_class = {
"cache_entry", "cache_entry",
JSCLASS_HAS_PRIVATE, /* struct cache_entry *; a weak reference */ JSCLASS_HAS_PRIVATE, /* struct cache_entry *; a weak reference */
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
cache_entry_get_property, cache_entry_set_property, JS_PropertyStub, JS_StrictPropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, cache_entry_finalize JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, cache_entry_finalize
}; };
@ -252,9 +259,7 @@ smjs_get_cache_entry_object(struct cache_entry *cached)
/* Do this last, so that if any previous step fails, we can /* Do this last, so that if any previous step fails, we can
* just forget the object and its finalizer won't attempt to * just forget the object and its finalizer won't attempt to
* access @cached. */ * access @cached. */
if (JS_FALSE == JS_SetPrivate(smjs_ctx, cache_entry_object, cached)) /* to @cache_entry_class */ JS_SetPrivate(cache_entry_object, cached); /* to @cache_entry_class */
return NULL;
cached->jsobject = cache_entry_object; cached->jsobject = cache_entry_object;
return cache_entry_object; return cache_entry_object;
} }
@ -278,6 +283,136 @@ smjs_detach_cache_entry_object(struct cache_entry *cached)
== cached); == cached);
if_assert_failed {} if_assert_failed {}
JS_SetPrivate(smjs_ctx, cached->jsobject, NULL); JS_SetPrivate(cached->jsobject, NULL);
cached->jsobject = NULL; cached->jsobject = NULL;
} }
static JSBool
cache_entry_get_property_length(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{
ELINKS_CAST_PROP_PARAMS
struct cache_entry *cached;
/* 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 *) &cache_entry_class, NULL))
return JS_FALSE;
cached = JS_GetInstancePrivate(ctx, obj,
(JSClass *) &cache_entry_class, NULL);
if (!cached) return JS_FALSE; /* already detached */
assert(cache_entry_is_valid(cached));
if_assert_failed return JS_FALSE;
/* Get a strong reference to the cache entry to prevent it
* from being deleted if some function called below decides to
* collect garbage. After this, all code paths must
* eventually unlock the object. */
object_lock(cached);
*vp = INT_TO_JSVAL(cached->length);
object_unlock(cached);
return JS_TRUE;
}
static JSBool
cache_entry_get_property_head(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{
ELINKS_CAST_PROP_PARAMS
struct cache_entry *cached;
/* 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 *) &cache_entry_class, NULL))
return JS_FALSE;
cached = JS_GetInstancePrivate(ctx, obj,
(JSClass *) &cache_entry_class, NULL);
if (!cached) return JS_FALSE; /* already detached */
assert(cache_entry_is_valid(cached));
if_assert_failed return JS_FALSE;
/* Get a strong reference to the cache entry to prevent it
* from being deleted if some function called below decides to
* collect garbage. After this, all code paths must
* eventually unlock the object. */
object_lock(cached);
*vp = STRING_TO_JSVAL(JS_NewStringCopyZ(smjs_ctx, cached->head));
object_unlock(cached);
return JS_TRUE;
}
static JSBool
cache_entry_set_property_head(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSBool strict, JSMutableHandleValue hvp)
{
ELINKS_CAST_PROP_PARAMS
struct cache_entry *cached;
JSString *jsstr;
unsigned char *str;
/* 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 *) &cache_entry_class, NULL))
return JS_FALSE;
cached = JS_GetInstancePrivate(ctx, obj,
(JSClass *) &cache_entry_class, NULL);
if (!cached) return JS_FALSE; /* already detached */
assert(cache_entry_is_valid(cached));
if_assert_failed return JS_FALSE;
/* Get a strong reference to the cache entry to prevent it
* from being deleted if some function called below decides to
* collect garbage. After this, all code paths must
* eventually unlock the object. */
object_lock(cached);
jsstr = JS_ValueToString(smjs_ctx, *vp);
str = JS_EncodeString(smjs_ctx, jsstr);
mem_free_set(&cached->head, stracpy(str));
object_unlock(cached);
return JS_TRUE;
}
static JSBool
cache_entry_get_property_uri(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{
ELINKS_CAST_PROP_PARAMS
struct cache_entry *cached;
/* 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 *) &cache_entry_class, NULL))
return JS_FALSE;
cached = JS_GetInstancePrivate(ctx, obj,
(JSClass *) &cache_entry_class, NULL);
if (!cached) return JS_FALSE; /* already detached */
assert(cache_entry_is_valid(cached));
if_assert_failed return JS_FALSE;
/* Get a strong reference to the cache entry to prevent it
* from being deleted if some function called below decides to
* collect garbage. After this, all code paths must
* eventually unlock the object. */
object_lock(cached);
*vp = STRING_TO_JSVAL(JS_NewStringCopyZ(smjs_ctx, struri(cached->uri)));
object_unlock(cached);
return JS_TRUE;
}

View File

@ -94,7 +94,7 @@ smjs_do_file(unsigned char *path)
} }
static JSBool static JSBool
smjs_do_file_wrapper(JSContext *ctx, uintN argc, jsval *rval) smjs_do_file_wrapper(JSContext *ctx, unsigned int argc, jsval *rval)
{ {
jsval *argv = JS_ARGV(ctx, rval); jsval *argv = JS_ARGV(ctx, rval);
JSString *jsstr = JS_ValueToString(smjs_ctx, *argv); JSString *jsstr = JS_ValueToString(smjs_ctx, *argv);
@ -136,7 +136,7 @@ init_smjs(struct module *module)
return; return;
} }
JS_SetOptions(smjs_ctx, JSOPTION_VAROBJFIX | JSOPTION_JIT | JSOPTION_METHODJIT); JS_SetOptions(smjs_ctx, JSOPTION_VAROBJFIX | JSOPTION_METHODJIT);
JS_SetVersion(smjs_ctx, JSVERSION_LATEST); JS_SetVersion(smjs_ctx, JSVERSION_LATEST);
JS_SetErrorReporter(smjs_ctx, error_reporter); JS_SetErrorReporter(smjs_ctx, error_reporter);

View File

@ -33,7 +33,7 @@
/* @elinks_funcs{"alert"} */ /* @elinks_funcs{"alert"} */
static JSBool static JSBool
elinks_alert(JSContext *ctx, uintN argc, jsval *rval) elinks_alert(JSContext *ctx, unsigned int argc, jsval *rval)
{ {
jsval val; jsval val;
jsval *argv = JS_ARGV(ctx, rval); jsval *argv = JS_ARGV(ctx, rval);
@ -69,7 +69,7 @@ elinks_alert(JSContext *ctx, uintN argc, jsval *rval)
/* @elinks_funcs{"execute"} */ /* @elinks_funcs{"execute"} */
static JSBool static JSBool
elinks_execute(JSContext *ctx, uintN argc, jsval *rval) elinks_execute(JSContext *ctx, unsigned int argc, jsval *rval)
{ {
jsval val; jsval val;
jsval *argv = JS_ARGV(ctx, rval); jsval *argv = JS_ARGV(ctx, rval);
@ -95,10 +95,15 @@ enum elinks_prop {
ELINKS_SESSION, ELINKS_SESSION,
}; };
static JSBool elinks_get_property_home(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp);
static JSBool elinks_get_property_location(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp);
static JSBool elinks_set_property_location(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSBool strict, JSMutableHandleValue hvp);
static JSBool elinks_get_property_session(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp);
static const JSPropertySpec elinks_props[] = { static const JSPropertySpec elinks_props[] = {
{ "home", ELINKS_HOME, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY }, { "home", 0, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY, JSOP_WRAPPER(elinks_get_property_home), JSOP_NULLWRAPPER },
{ "location", ELINKS_LOCATION, JSPROP_ENUMERATE | JSPROP_PERMANENT }, { "location", 0, JSPROP_ENUMERATE | JSPROP_PERMANENT, JSOP_WRAPPER(elinks_get_property_location), JSOP_WRAPPER(elinks_set_property_location) },
{ "session", ELINKS_SESSION, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY }, { "session", 0, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY, JSOP_WRAPPER(elinks_get_property_session), JSOP_NULLWRAPPER},
{ NULL } { NULL }
}; };
@ -106,8 +111,11 @@ static const JSClass elinks_class;
/* @elinks_class.getProperty */ /* @elinks_class.getProperty */
static JSBool static JSBool
elinks_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp) elinks_get_property(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{ {
ELINKS_CAST_PROP_PARAMS
jsid id = *(hid._);
/* This can be called if @obj if not itself an instance of the /* This can be called if @obj if not itself an instance of the
* appropriate class but has one in its prototype chain. Fail * appropriate class but has one in its prototype chain. Fail
* such calls. */ * such calls. */
@ -161,8 +169,11 @@ elinks_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp)
} }
static JSBool static JSBool
elinks_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp) elinks_set_property(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSBool strict, JSMutableHandleValue hvp)
{ {
ELINKS_CAST_PROP_PARAMS
jsid id = *(hid._);
/* This can be called if @obj if not itself an instance of the /* This can be called if @obj if not itself an instance of the
* appropriate class but has one in its prototype chain. Fail * appropriate class but has one in its prototype chain. Fail
* such calls. */ * such calls. */
@ -205,7 +216,7 @@ static const JSClass elinks_class = {
0, 0,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
elinks_get_property, elinks_set_property, elinks_get_property, elinks_set_property,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, NULL
}; };
static const spidermonkeyFunctionSpec elinks_funcs[] = { static const spidermonkeyFunctionSpec elinks_funcs[] = {
@ -262,3 +273,87 @@ smjs_invoke_elinks_object_method(unsigned char *method, jsval argv[], int argc,
return JS_CallFunctionValue(smjs_ctx, smjs_elinks_object, return JS_CallFunctionValue(smjs_ctx, smjs_elinks_object,
*rval, argc, argv, rval); *rval, argc, argv, rval);
} }
static JSBool
elinks_get_property_home(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{
ELINKS_CAST_PROP_PARAMS
/* 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 *) &elinks_class, NULL))
return JS_FALSE;
*vp = STRING_TO_JSVAL(JS_NewStringCopyZ(smjs_ctx, elinks_home));
return JS_TRUE;
}
static JSBool
elinks_get_property_location(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{
ELINKS_CAST_PROP_PARAMS
struct uri *uri;
/* 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 *) &elinks_class, NULL))
return JS_FALSE;
if (!smjs_ses) return JS_FALSE;
uri = have_location(smjs_ses) ? cur_loc(smjs_ses)->vs.uri : smjs_ses->loading_uri;
*vp = STRING_TO_JSVAL(JS_NewStringCopyZ(smjs_ctx, uri ? (const char *) struri(uri) : ""));
return JS_TRUE;
}
static JSBool
elinks_set_property_location(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSBool strict, JSMutableHandleValue hvp)
{
ELINKS_CAST_PROP_PARAMS
JSString *jsstr;
unsigned char *url;
/* 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 *) &elinks_class, NULL))
return JS_FALSE;
if (!smjs_ses) return JS_FALSE;
jsstr = JS_ValueToString(smjs_ctx, *vp);
if (!jsstr) return JS_FALSE;
url = JS_EncodeString(smjs_ctx, jsstr);
if (!url) return JS_FALSE;
goto_url(smjs_ses, url);
return JS_TRUE;
}
static JSBool
elinks_get_property_session(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{
ELINKS_CAST_PROP_PARAMS
JSObject *jsobj;
/* 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 *) &elinks_class, NULL))
return JS_FALSE;
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;
}

View File

@ -19,7 +19,7 @@ static const JSClass global_class = {
"global", JSCLASS_GLOBAL_FLAGS, "global", JSCLASS_GLOBAL_FLAGS,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_PropertyStub, JS_StrictPropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, NULL
}; };
static JSObject * static JSObject *
@ -29,7 +29,7 @@ smjs_get_global_object(void)
assert(smjs_ctx); assert(smjs_ctx);
jsobj = JS_NewCompartmentAndGlobalObject(smjs_ctx, (JSClass *) &global_class, NULL); jsobj = JS_NewGlobalObject(smjs_ctx, (JSClass *) &global_class, NULL);
if (!jsobj) return NULL; if (!jsobj) return NULL;

View File

@ -18,16 +18,15 @@ static const JSClass smjs_globhist_item_class; /* defined below */
/* @smjs_globhist_item_class.finalize */ /* @smjs_globhist_item_class.finalize */
static void static void
smjs_globhist_item_finalize(JSContext *ctx, JSObject *obj) smjs_globhist_item_finalize(JSFreeOp *op, JSObject *obj)
{ {
struct global_history_item *history_item; struct global_history_item *history_item;
#if 0
assert(JS_InstanceOf(ctx, obj, (JSClass *) &smjs_globhist_item_class, NULL)); assert(JS_InstanceOf(ctx, obj, (JSClass *) &smjs_globhist_item_class, NULL));
if_assert_failed return; if_assert_failed return;
#endif
history_item = JS_GetInstancePrivate(ctx, obj, history_item = JS_GetPrivate(obj);
(JSClass *) &smjs_globhist_item_class,
NULL);
if (history_item) object_unlock(history_item); if (history_item) object_unlock(history_item);
} }
@ -42,18 +41,28 @@ enum smjs_globhist_item_prop {
GLOBHIST_LAST_VISIT = -3, GLOBHIST_LAST_VISIT = -3,
}; };
static JSBool smjs_globhist_item_get_property_title(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp);
static JSBool smjs_globhist_item_set_property_title(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSBool strict, JSMutableHandleValue hvp);
static JSBool smjs_globhist_item_get_property_url(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp);
static JSBool smjs_globhist_item_set_property_url(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSBool strict, JSMutableHandleValue hvp);
static JSBool smjs_globhist_item_get_property_last_visit(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp);
static JSBool smjs_globhist_item_set_property_last_visit(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSBool strict, JSMutableHandleValue hvp);
static const JSPropertySpec smjs_globhist_item_props[] = { static const JSPropertySpec smjs_globhist_item_props[] = {
{ "title", GLOBHIST_TITLE, JSPROP_ENUMERATE }, { "title", 0, JSPROP_ENUMERATE, JSOP_WRAPPER(smjs_globhist_item_get_property_title), JSOP_WRAPPER(smjs_globhist_item_set_property_title) },
{ "url", GLOBHIST_URL, JSPROP_ENUMERATE }, { "url", 0, JSPROP_ENUMERATE, JSOP_WRAPPER(smjs_globhist_item_get_property_url), JSOP_WRAPPER(smjs_globhist_item_set_property_url) },
{ "last_visit", GLOBHIST_LAST_VISIT, JSPROP_ENUMERATE }, { "last_visit", 0, JSPROP_ENUMERATE, JSOP_WRAPPER(smjs_globhist_item_get_property_last_visit), JSOP_WRAPPER(smjs_globhist_item_set_property_last_visit) },
{ NULL } { NULL }
}; };
/* @smjs_globhist_item_class.getProperty */ /* @smjs_globhist_item_class.getProperty */
static JSBool static JSBool
smjs_globhist_item_get_property(JSContext *ctx, JSObject *obj, jsid id, smjs_globhist_item_get_property(JSContext *ctx, JSHandleObject hobj, JSHandleId hid,
jsval *vp) JSMutableHandleValue hvp)
{ {
ELINKS_CAST_PROP_PARAMS
jsid id = *(hid._);
struct global_history_item *history_item; struct global_history_item *history_item;
/* This can be called if @obj if not itself an instance of the /* This can be called if @obj if not itself an instance of the
@ -101,7 +110,7 @@ smjs_globhist_item_get_property(JSContext *ctx, JSObject *obj, jsid id,
* Since the Date object uses milliseconds since the epoch, * Since the Date object uses milliseconds since the epoch,
* I'd rather export that, but SpiderMonkey doesn't provide * I'd rather export that, but SpiderMonkey doesn't provide
* a suitable type. -- Miciah */ * a suitable type. -- Miciah */
JS_NewNumberValue(smjs_ctx, history_item->last_visit, vp); *vp = JS_NumberValue(history_item->last_visit);
return JS_TRUE; return JS_TRUE;
default: default:
@ -117,8 +126,11 @@ smjs_globhist_item_get_property(JSContext *ctx, JSObject *obj, jsid id,
/* @smjs_globhist_item_class.setProperty */ /* @smjs_globhist_item_class.setProperty */
static JSBool static JSBool
smjs_globhist_item_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp) smjs_globhist_item_set_property(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSBool strict, JSMutableHandleValue hvp)
{ {
ELINKS_CAST_PROP_PARAMS
jsid id = *(hid._);
struct global_history_item *history_item; struct global_history_item *history_item;
/* This can be called if @obj if not itself an instance of the /* This can be called if @obj if not itself an instance of the
@ -154,7 +166,7 @@ smjs_globhist_item_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool s
return JS_TRUE; return JS_TRUE;
} }
case GLOBHIST_LAST_VISIT: { case GLOBHIST_LAST_VISIT: {
uint32 seconds; uint32_t seconds;
/* Bug 923: Assumes time_t values fit in uint32. */ /* Bug 923: Assumes time_t values fit in uint32. */
JS_ValueToECMAUint32(smjs_ctx, *vp, &seconds); JS_ValueToECMAUint32(smjs_ctx, *vp, &seconds);
@ -189,10 +201,10 @@ smjs_get_globhist_item_object(struct global_history_item *history_item)
NULL, NULL); NULL, NULL);
if (!jsobj if (!jsobj
|| JS_TRUE != JS_DefineProperties(smjs_ctx, jsobj, || JS_TRUE != JS_DefineProperties(smjs_ctx, jsobj,
(JSPropertySpec *) smjs_globhist_item_props) (JSPropertySpec *) smjs_globhist_item_props)) {
|| JS_TRUE != JS_SetPrivate(smjs_ctx, jsobj, history_item)) /* to @smjs_globhist_item_class */
return NULL; return NULL;
}
JS_SetPrivate(jsobj, history_item); /* to @smjs_globhist_item_class */
object_lock(history_item); object_lock(history_item);
return jsobj; return jsobj;
@ -201,8 +213,12 @@ smjs_get_globhist_item_object(struct global_history_item *history_item)
/* @smjs_globhist_class.getProperty */ /* @smjs_globhist_class.getProperty */
static JSBool static JSBool
smjs_globhist_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp) smjs_globhist_get_property(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{ {
ELINKS_CAST_PROP_PARAMS
jsid id = *(hid._);
(void)obj;
JSObject *jsobj; JSObject *jsobj;
unsigned char *uri_string; unsigned char *uri_string;
struct global_history_item *history_item; struct global_history_item *history_item;
@ -234,7 +250,7 @@ static const JSClass smjs_globhist_class = {
"global_history", 0, "global_history", 0,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
smjs_globhist_get_property, JS_StrictPropertyStub, smjs_globhist_get_property, JS_StrictPropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, NULL,
}; };
static JSObject * static JSObject *
@ -265,3 +281,178 @@ smjs_init_globhist_interface(void)
JS_SetProperty(smjs_ctx, smjs_elinks_object, "globhist", &val); JS_SetProperty(smjs_ctx, smjs_elinks_object, "globhist", &val);
} }
static JSBool
smjs_globhist_item_get_property_title(JSContext *ctx, JSHandleObject hobj, JSHandleId hid,
JSMutableHandleValue hvp)
{
ELINKS_CAST_PROP_PARAMS
struct global_history_item *history_item;
/* 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 *) &smjs_globhist_item_class, NULL))
return JS_FALSE;
history_item = JS_GetInstancePrivate(ctx, obj,
(JSClass *) &smjs_globhist_item_class,
NULL);
if (!history_item) return JS_FALSE;
*vp = STRING_TO_JSVAL(JS_NewStringCopyZ(smjs_ctx, history_item->title));
return JS_TRUE;
}
static JSBool
smjs_globhist_item_set_property_title(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSBool strict, JSMutableHandleValue hvp)
{
ELINKS_CAST_PROP_PARAMS
struct global_history_item *history_item;
JSString *jsstr;
unsigned char *str;
/* 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 *) &smjs_globhist_item_class, NULL))
return JS_FALSE;
history_item = JS_GetInstancePrivate(ctx, obj,
(JSClass *) &smjs_globhist_item_class,
NULL);
if (!history_item) return JS_FALSE;
jsstr = JS_ValueToString(smjs_ctx, *vp);
str = JS_EncodeString(smjs_ctx, jsstr);
mem_free_set(&history_item->title, stracpy(str));
return JS_TRUE;
}
static JSBool
smjs_globhist_item_get_property_url(JSContext *ctx, JSHandleObject hobj, JSHandleId hid,
JSMutableHandleValue hvp)
{
ELINKS_CAST_PROP_PARAMS
struct global_history_item *history_item;
/* 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 *) &smjs_globhist_item_class, NULL))
return JS_FALSE;
history_item = JS_GetInstancePrivate(ctx, obj,
(JSClass *) &smjs_globhist_item_class,
NULL);
if (!history_item) return JS_FALSE;
*vp = STRING_TO_JSVAL(JS_NewStringCopyZ(smjs_ctx, history_item->url));
return JS_TRUE;
}
static JSBool
smjs_globhist_item_set_property_url(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSBool strict, JSMutableHandleValue hvp)
{
ELINKS_CAST_PROP_PARAMS
struct global_history_item *history_item;
JSString *jsstr;
unsigned char *str;
/* 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 *) &smjs_globhist_item_class, NULL))
return JS_FALSE;
history_item = JS_GetInstancePrivate(ctx, obj,
(JSClass *) &smjs_globhist_item_class,
NULL);
if (!history_item) return JS_FALSE;
jsstr = JS_ValueToString(smjs_ctx, *vp);
str = JS_EncodeString(smjs_ctx, jsstr);
mem_free_set(&history_item->url, stracpy(str));
return JS_TRUE;
}
static JSBool
smjs_globhist_item_get_property_last_visit(JSContext *ctx, JSHandleObject hobj, JSHandleId hid,
JSMutableHandleValue hvp)
{
ELINKS_CAST_PROP_PARAMS
struct global_history_item *history_item;
/* 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 *) &smjs_globhist_item_class, NULL))
return JS_FALSE;
history_item = JS_GetInstancePrivate(ctx, obj,
(JSClass *) &smjs_globhist_item_class,
NULL);
if (!history_item) return JS_FALSE;
/* TODO: I'd rather return a date object, but that introduces
* synchronisation issues:
*
* - How do we cause a change to that date object to affect
* the actual global history item?
* - How do we get a change to that global history item
* to affect all date objects?
*
* The biggest obstacle is that we have no way to trigger code
* when one messes with the date object.
*
* -- Miciah */
/* XXX: Currently, ECMAScript gets seconds since the epoch.
* Since the Date object uses milliseconds since the epoch,
* I'd rather export that, but SpiderMonkey doesn't provide
* a suitable type. -- Miciah */
*vp = JS_NumberValue(history_item->last_visit);
return JS_TRUE;
}
/* @smjs_globhist_item_class.setProperty */
static JSBool
smjs_globhist_item_set_property_last_visit(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSBool strict, JSMutableHandleValue hvp)
{
ELINKS_CAST_PROP_PARAMS
struct global_history_item *history_item;
uint32_t seconds;
/* 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 *) &smjs_globhist_item_class, NULL))
return JS_FALSE;
history_item = JS_GetInstancePrivate(ctx, obj,
(JSClass *) &smjs_globhist_item_class,
NULL);
if (!history_item) return JS_FALSE;
/* Bug 923: Assumes time_t values fit in uint32. */
JS_ValueToECMAUint32(smjs_ctx, *vp, &seconds);
history_item->last_visit = seconds;
return JS_TRUE;
}

View File

@ -17,8 +17,11 @@ static const JSClass keymap_class; /* defined below */
/* @keymap_class.getProperty */ /* @keymap_class.getProperty */
static JSBool static JSBool
keymap_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp) keymap_get_property(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{ {
ELINKS_CAST_PROP_PARAMS
jsid id = *(hid._);
unsigned char *action_str; unsigned char *action_str;
const unsigned char *keystroke_str; const unsigned char *keystroke_str;
int *data; int *data;
@ -74,8 +77,11 @@ smjs_keybinding_action_callback(va_list ap, void *data)
/* @keymap_class.setProperty */ /* @keymap_class.setProperty */
static JSBool static JSBool
keymap_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp) keymap_set_property(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSBool strict, JSMutableHandleValue hvp)
{ {
ELINKS_CAST_PROP_PARAMS
jsid id = *(hid._);
int *data; int *data;
unsigned char *keymap_str; unsigned char *keymap_str;
jsval val; jsval val;
@ -116,7 +122,7 @@ keymap_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval
return JS_TRUE; return JS_TRUE;
} else if (JSVAL_IS_OBJECT(*vp)) { } else if (!JSVAL_IS_PRIMITIVE(*vp) || JSVAL_IS_NULL(*vp)) {
unsigned char *err = NULL; unsigned char *err = NULL;
int event_id; int event_id;
struct string event_name = NULL_STRING; struct string event_name = NULL_STRING;
@ -160,15 +166,15 @@ keymap_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval
/* @keymap_class.finalize */ /* @keymap_class.finalize */
static void static void
keymap_finalize(JSContext *ctx, JSObject *obj) keymap_finalize(JSFreeOp *op, JSObject *obj)
{ {
void *data; void *data;
#if 0
assert(JS_InstanceOf(ctx, obj, (JSClass *) &keymap_class, NULL)); assert(JS_InstanceOf(ctx, obj, (JSClass *) &keymap_class, NULL));
if_assert_failed return; if_assert_failed return;
#endif
data = JS_GetInstancePrivate(ctx, obj, data = JS_GetPrivate(obj);
(JSClass *) &keymap_class, NULL);
mem_free(data); mem_free(data);
} }
@ -197,12 +203,8 @@ smjs_get_keymap_object(enum keymap_id keymap_id)
data = intdup(keymap_id); data = intdup(keymap_id);
if (!data) return NULL; if (!data) return NULL;
if (JS_TRUE == JS_SetPrivate(smjs_ctx, keymap_object, data)) /* to @keymap_class */ JS_SetPrivate(keymap_object, data); /* to @keymap_class */
return keymap_object; return keymap_object;
mem_free(data);
return NULL;
} }
static const JSClass keymaps_hash_class = { static const JSClass keymaps_hash_class = {
@ -210,7 +212,7 @@ static const JSClass keymaps_hash_class = {
JSCLASS_HAS_PRIVATE, JSCLASS_HAS_PRIVATE,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_PropertyStub, JS_StrictPropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, NULL,
}; };
static JSObject * static JSObject *

View File

@ -65,7 +65,7 @@ end:
} }
static JSBool static JSBool
smjs_load_uri(JSContext *ctx, uintN argc, jsval *rval) smjs_load_uri(JSContext *ctx, unsigned int argc, jsval *rval)
{ {
jsval *argv = JS_ARGV(ctx, rval); jsval *argv = JS_ARGV(ctx, rval);
struct smjs_load_uri_hop *hop; struct smjs_load_uri_hop *hop;

View File

@ -42,8 +42,11 @@ static const JSClass location_array_class; /* Defined below. */
/* @location_array.getProperty */ /* @location_array.getProperty */
static JSBool static JSBool
smjs_location_array_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp) smjs_location_array_get_property(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{ {
ELINKS_CAST_PROP_PARAMS
jsid id = *(hid._);
struct session *ses; struct session *ses;
int index; int index;
struct location *loc; struct location *loc;
@ -90,19 +93,20 @@ smjs_location_array_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *
* finalizes all objects before it frees the JSRuntime, so * finalizes all objects before it frees the JSRuntime, so
* session.history_jsobject won't be left dangling. */ * session.history_jsobject won't be left dangling. */
static void static void
smjs_location_array_finalize(JSContext *ctx, JSObject *obj) smjs_location_array_finalize(JSFreeOp *op, JSObject *obj)
{ {
struct session *ses; struct session *ses;
#if 0
assert(JS_InstanceOf(ctx, obj, (JSClass *) &location_array_class, NULL)); assert(JS_InstanceOf(ctx, obj, (JSClass *) &location_array_class, NULL));
if_assert_failed return; if_assert_failed return;
#endif
ses = JS_GetInstancePrivate(ctx, obj, ses = JS_GetPrivate(obj);
(JSClass *) &location_array_class, NULL);
if (!ses) return; /* already detached */ if (!ses) return; /* already detached */
JS_SetPrivate(ctx, obj, NULL); /* perhaps not necessary */ JS_SetPrivate(obj, NULL); /* perhaps not necessary */
assert(ses->history_jsobject == obj); assert(ses->history_jsobject == obj);
if_assert_failed return; if_assert_failed return;
ses->history_jsobject = NULL; ses->history_jsobject = NULL;
@ -135,8 +139,7 @@ smjs_get_session_location_array_object(struct session *ses)
/* Do this last, so that if any previous step fails, we can /* Do this last, so that if any previous step fails, we can
* just forget the object and its finalizer won't attempt to * just forget the object and its finalizer won't attempt to
* access @ses. */ * access @ses. */
if (JS_FALSE == JS_SetPrivate(smjs_ctx, obj, ses)) JS_SetPrivate(obj, ses);
return NULL;
ses->history_jsobject = obj; ses->history_jsobject = obj;
return obj; return obj;
@ -188,8 +191,11 @@ static const JSPropertySpec session_props[] = {
/* @session_class.getProperty */ /* @session_class.getProperty */
static JSBool static JSBool
session_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp) session_get_property(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{ {
ELINKS_CAST_PROP_PARAMS
jsid id = *(hid._);
struct session *ses; struct session *ses;
/* This can be called if @obj if not itself an instance of the /* This can be called if @obj if not itself an instance of the
@ -294,8 +300,11 @@ session_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp)
} }
static JSBool static JSBool
session_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp) session_set_property(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSBool strict, JSMutableHandleValue hvp)
{ {
ELINKS_CAST_PROP_PARAMS
jsid id = *(hid._);
struct session *ses; struct session *ses;
/* This can be called if @obj if not itself an instance of the /* This can be called if @obj if not itself an instance of the
@ -450,7 +459,7 @@ session_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsva
/** Pointed to by session_class.construct. Create a new session (tab) /** Pointed to by session_class.construct. Create a new session (tab)
* and return the JSObject wrapper. */ * and return the JSObject wrapper. */
static JSBool static JSBool
session_construct(JSContext *ctx, uintN argc, jsval *rval) session_construct(JSContext *ctx, unsigned int argc, jsval *rval)
{ {
jsval val; jsval val;
jsval *argv = JS_ARGV(ctx, rval); jsval *argv = JS_ARGV(ctx, rval);
@ -484,19 +493,20 @@ session_construct(JSContext *ctx, uintN argc, jsval *rval)
* finalizes all objects before it frees the JSRuntime, so session.jsobject * finalizes all objects before it frees the JSRuntime, so session.jsobject
* won't be left dangling. */ * won't be left dangling. */
static void static void
session_finalize(JSContext *ctx, JSObject *obj) session_finalize(JSFreeOp *op, JSObject *obj)
{ {
struct session *ses; struct session *ses;
#if 0
assert(JS_InstanceOf(ctx, obj, (JSClass *) &session_class, NULL)); assert(JS_InstanceOf(ctx, obj, (JSClass *) &session_class, NULL));
if_assert_failed return; if_assert_failed return;
#endif
ses = JS_GetInstancePrivate(ctx, obj, ses = JS_GetPrivate(obj);
(JSClass *) &session_class, NULL);
if (!ses) return; /* already detached */ if (!ses) return; /* already detached */
JS_SetPrivate(ctx, obj, NULL); /* perhaps not necessary */ JS_SetPrivate(obj, NULL); /* perhaps not necessary */
assert(ses->jsobject == obj); assert(ses->jsobject == obj);
if_assert_failed return; if_assert_failed return;
ses->jsobject = NULL; ses->jsobject = NULL;
@ -508,7 +518,7 @@ static const JSClass session_class = {
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
session_get_property, session_set_property, session_get_property, session_set_property,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, session_finalize, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, session_finalize,
NULL, NULL, session_construct NULL, NULL, NULL, session_construct
}; };
/** Return an SMJS object through which scripts can access @a ses. /** Return an SMJS object through which scripts can access @a ses.
@ -534,8 +544,7 @@ smjs_get_session_object(struct session *ses)
/* Do this last, so that if any previous step fails, we can /* Do this last, so that if any previous step fails, we can
* just forget the object and its finalizer won't attempt to * just forget the object and its finalizer won't attempt to
* access @ses. */ * access @ses. */
if (JS_FALSE == JS_SetPrivate(smjs_ctx, obj, ses)) /* to @session_class */ JS_SetPrivate(obj, ses); /* to @session_class */
return NULL;
ses->jsobject = obj; ses->jsobject = obj;
return obj; return obj;
@ -558,7 +567,7 @@ smjs_detach_session_object(struct session *ses)
== ses); == ses);
if_assert_failed {} if_assert_failed {}
JS_SetPrivate(smjs_ctx, ses->jsobject, NULL); JS_SetPrivate(ses->jsobject, NULL);
ses->jsobject = NULL; ses->jsobject = NULL;
} }
@ -569,7 +578,7 @@ smjs_detach_session_object(struct session *ses)
== ses); == ses);
if_assert_failed {} if_assert_failed {}
JS_SetPrivate(smjs_ctx, ses->history_jsobject, NULL); JS_SetPrivate(ses->history_jsobject, NULL);
ses->history_jsobject = NULL; ses->history_jsobject = NULL;
} }
} }
@ -581,10 +590,13 @@ smjs_detach_session_object(struct session *ses)
* previously attached to the session object, the object will remain in * previously attached to the session object, the object will remain in
* memory but it will no longer be able to access the session object. */ * memory but it will no longer be able to access the session object. */
static JSBool static JSBool
session_array_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp) session_array_get_property(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{ {
ELINKS_CAST_PROP_PARAMS
jsid id = *(hid._);
JSObject *tabobj; JSObject *tabobj;
struct terminal *term = JS_GetPrivate(ctx, obj); struct terminal *term = JS_GetPrivate(obj);
int index; int index;
struct window *tab; struct window *tab;
@ -614,7 +626,7 @@ static const JSClass session_array_class = {
JSCLASS_HAS_PRIVATE, /* struct terminal *term; a weak reference */ JSCLASS_HAS_PRIVATE, /* struct terminal *term; a weak reference */
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
session_array_get_property, JS_StrictPropertyStub, session_array_get_property, JS_StrictPropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, NULL
}; };
JSObject * JSObject *
@ -629,8 +641,7 @@ smjs_get_session_array_object(struct terminal *term)
NULL, NULL); NULL, NULL);
if (!obj) return NULL; if (!obj) return NULL;
if (JS_FALSE == JS_SetPrivate(smjs_ctx, obj, term)) JS_SetPrivate(obj, term);
return NULL;
return obj; return obj;
} }
@ -653,12 +664,12 @@ smjs_detach_session_array_object(struct terminal *term)
== term); == term);
if_assert_failed {} if_assert_failed {}
JS_SetPrivate(smjs_ctx, term->session_array_jsobject, NULL); JS_SetPrivate(term->session_array_jsobject, NULL);
term->session_array_jsobject = NULL; term->session_array_jsobject = NULL;
} }
static JSBool static JSBool
smjs_session_goto_url(JSContext *ctx, uintN argc, jsval *rval) smjs_session_goto_url(JSContext *ctx, unsigned int argc, jsval *rval)
{ {
jsval val; jsval val;
struct delayed_open *deo; struct delayed_open *deo;

View File

@ -30,8 +30,11 @@ static const JSPropertySpec terminal_props[] = {
/* @terminal_class.getProperty */ /* @terminal_class.getProperty */
static JSBool static JSBool
terminal_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp) terminal_get_property(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{ {
ELINKS_CAST_PROP_PARAMS
jsid id = *(hid._);
struct terminal *term; struct terminal *term;
/* This can be called if @obj if not itself an instance of the /* This can be called if @obj if not itself an instance of the
@ -68,19 +71,18 @@ terminal_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp)
* finalizes all objects before it frees the JSRuntime, so terminal.jsobject * finalizes all objects before it frees the JSRuntime, so terminal.jsobject
* won't be left dangling. */ * won't be left dangling. */
static void static void
terminal_finalize(JSContext *ctx, JSObject *obj) terminal_finalize(JSFreeOp *op, JSObject *obj)
{ {
struct terminal *term; struct terminal *term;
#if 0
assert(JS_InstanceOf(ctx, obj, (JSClass *) &terminal_class, NULL)); assert(JS_InstanceOf(ctx, obj, (JSClass *) &terminal_class, NULL));
if_assert_failed return; if_assert_failed return;
#endif
term = JS_GetInstancePrivate(ctx, obj, term = JS_GetPrivate(obj);
(JSClass *) &terminal_class, NULL);
if (!term) return; /* already detached */ if (!term) return; /* already detached */
JS_SetPrivate(ctx, obj, NULL); /* perhaps not necessary */ JS_SetPrivate(obj, NULL); /* perhaps not necessary */
assert(term->jsobject == obj); assert(term->jsobject == obj);
if_assert_failed return; if_assert_failed return;
term->jsobject = NULL; term->jsobject = NULL;
@ -118,8 +120,7 @@ smjs_get_terminal_object(struct terminal *term)
/* Do this last, so that if any previous step fails, we can /* Do this last, so that if any previous step fails, we can
* just forget the object and its finalizer won't attempt to * just forget the object and its finalizer won't attempt to
* access @cached. */ * access @cached. */
if (JS_FALSE == JS_SetPrivate(smjs_ctx, obj, term)) /* to @terminal_class */ JS_SetPrivate(obj, term); /* to @terminal_class */
return NULL;
term->jsobject = obj; term->jsobject = obj;
return obj; return obj;
@ -145,15 +146,18 @@ smjs_detach_terminal_object(struct terminal *term)
== term); == term);
if_assert_failed {} if_assert_failed {}
JS_SetPrivate(smjs_ctx, term->jsobject, NULL); JS_SetPrivate(term->jsobject, NULL);
term->jsobject = NULL; term->jsobject = NULL;
} }
/* @terminal_array_class.getProperty */ /* @terminal_array_class.getProperty */
static JSBool static JSBool
terminal_array_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp) terminal_array_get_property(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{ {
ELINKS_CAST_PROP_PARAMS
jsid id = *(hid._);
int index; int index;
struct terminal *term; struct terminal *term;
@ -181,7 +185,7 @@ static const JSClass terminal_array_class = {
0, 0,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
terminal_array_get_property, JS_StrictPropertyStub, terminal_array_get_property, JS_StrictPropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, NULL
}; };
/** Return an SMJS object that scripts can use an array to get terminal /** Return an SMJS object that scripts can use an array to get terminal

View File

@ -39,8 +39,11 @@ static const JSPropertySpec view_state_props[] = {
/* @view_state_class.getProperty */ /* @view_state_class.getProperty */
static JSBool static JSBool
view_state_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp) view_state_get_property(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{ {
ELINKS_CAST_PROP_PARAMS
jsid id = *(hid._);
struct view_state *vs; struct view_state *vs;
/* This can be called if @obj if not itself an instance of the /* This can be called if @obj if not itself an instance of the
@ -81,8 +84,11 @@ view_state_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp)
/* @view_state_class.setProperty */ /* @view_state_class.setProperty */
static JSBool static JSBool
view_state_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp) view_state_set_property(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSBool strict, JSMutableHandleValue hvp)
{ {
ELINKS_CAST_PROP_PARAMS
jsid id = *(hid._);
struct view_state *vs; struct view_state *vs;
/* This can be called if @obj if not itself an instance of the /* This can be called if @obj if not itself an instance of the
@ -117,19 +123,22 @@ view_state_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, j
* finalizes all objects before it frees the JSRuntime, so view_state.jsobject * finalizes all objects before it frees the JSRuntime, so view_state.jsobject
* won't be left dangling. */ * won't be left dangling. */
static void static void
view_state_finalize(JSContext *ctx, JSObject *obj) view_state_finalize(JSFreeOp *op, JSObject *obj)
{ {
struct view_state *vs; struct view_state *vs;
#if 0
assert(JS_InstanceOf(ctx, obj, (JSClass *) &view_state_class, NULL)); assert(JS_InstanceOf(ctx, obj, (JSClass *) &view_state_class, NULL));
if_assert_failed return; if_assert_failed return;
vs = JS_GetInstancePrivate(ctx, obj, vs = JS_GetInstancePrivate(ctx, obj,
(JSClass *) &view_state_class, NULL); (JSClass *) &view_state_class, NULL);
#endif
vs = JS_GetPrivate(obj);
if (!vs) return; /* already detached */ if (!vs) return; /* already detached */
JS_SetPrivate(ctx, obj, NULL); /* perhaps not necessary */ JS_SetPrivate(obj, NULL); /* perhaps not necessary */
assert(vs->jsobject == obj); assert(vs->jsobject == obj);
if_assert_failed return; if_assert_failed return;
vs->jsobject = NULL; vs->jsobject = NULL;
@ -168,16 +177,18 @@ smjs_get_view_state_object(struct view_state *vs)
/* Do this last, so that if any previous step fails, we can /* Do this last, so that if any previous step fails, we can
* just forget the object and its finalizer won't attempt to * just forget the object and its finalizer won't attempt to
* access @vs. */ * access @vs. */
if (JS_FALSE == JS_SetPrivate(smjs_ctx, view_state_object, vs)) /* to @view_state_class */ JS_SetPrivate(view_state_object, vs); /* to @view_state_class */
return NULL;
vs->jsobject = view_state_object; vs->jsobject = view_state_object;
return view_state_object; return view_state_object;
} }
static JSBool static JSBool
smjs_elinks_get_view_state(JSContext *ctx, JSObject *obj, jsid id, jsval *vp) smjs_elinks_get_view_state(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{ {
ELINKS_CAST_PROP_PARAMS
(void)obj;
JSObject *vs_obj; JSObject *vs_obj;
struct view_state *vs; struct view_state *vs;
@ -214,7 +225,7 @@ smjs_detach_view_state_object(struct view_state *vs)
== vs); == vs);
if_assert_failed {} if_assert_failed {}
JS_SetPrivate(smjs_ctx, vs->jsobject, NULL); JS_SetPrivate(vs->jsobject, NULL);
vs->jsobject = NULL; vs->jsobject = NULL;
} }

View File

@ -1,5 +1,5 @@
<p><a href="javascript:document.title = 'This is a test'; document.title += ', this document URL is '+document.url;void(0);">Change the document.title while preventing going anywhere because returning <code>undefined</code>.</a></p> <p><a href="javascript:document.title = 'This is a test'; document.title += ', this document URL is '+document.url;void(0);">Change the document.title while preventing going anywhere because returning <code>undefined</code>.</a></p>
<p><a href="javascript:document.url='elinks.or.cz';">Change the document.url</a> (which is impossible because it's read-only, but the return value of the statement is used as the link target so it magically still works).</p> <p><a href="javascript:document.url='http://elinks.or.cz';">Change the document.url</a> (which is impossible because it's read-only, but the return value of the statement is used as the link target so it magically still works).</p>
<p><a href="javascript:{ document.title = 'This is a test'; document.title += ', this document URL is '+document.url; 'elinks.or.cz' }">Change the document.title and go to elinks.or.cz (return value of statement).</a></p> <p><a href="javascript:{ document.title = 'This is a test'; document.title += ', this document URL is '+document.url; 'http://elinks.or.cz' }">Change the document.title and go to elinks.or.cz (return value of statement).</a></p>