[elinks] port to js-1.8.5 API (upstream commits f31cf6f and 2844f8b)
Kamil Dudka
kdudka at fedoraproject.org
Thu Apr 21 14:15:08 UTC 2011
commit 78e83f9df0a43a7ac4eff36bf4e71d079f6bd72d
Author: Kamil Dudka <kdudka at redhat.com>
Date: Thu Apr 21 16:08:02 2011 +0200
port to js-1.8.5 API (upstream commits f31cf6f and 2844f8b)
elinks-0.12pre5-js185.patch | 2267 +++++++++++++++++++++++++++++++++++++++++++
elinks.spec | 9 +-
2 files changed, 2275 insertions(+), 1 deletions(-)
---
diff --git a/elinks-0.12pre5-js185.patch b/elinks-0.12pre5-js185.patch
new file mode 100644
index 0000000..733ff8a
--- /dev/null
+++ b/elinks-0.12pre5-js185.patch
@@ -0,0 +1,2267 @@
+From a3f59264b9504e8bf3d0ac70b99a237bc964089d Mon Sep 17 00:00:00 2001
+From: Miciah Dashiel Butler Masters <miciah.masters at gmail.com>
+Date: Sat, 18 Jul 2009 23:41:01 +0000
+Subject: [PATCH 1/2] Heartbeat code using JS_TriggerOperationCallback
+
+Implement new heartbeat code to catch runaway execution of document
+ECMAScript code. The old code uses JS_SetBranchCallback which is
+deprecated in new versions of SpiderMonkey. The new code uses setitimer(2)
+and the JS_SetOperationCallback and JS_TriggerOperationCallback interfaces,
+introduced in SpiderMonkey 1.8.1. Compatibility with both the old
+JS_SetBranchCallback and the new interfaces is maintained.
+
+Signed-off-by: Kamil Dudka <kdudka at redhat.com>
+---
+ Makefile.config.in | 1 +
+ configure.in | 12 +++
+ src/ecmascript/ecmascript.h | 4 +
+ src/ecmascript/spidermonkey.c | 38 ++++++++-
+ src/ecmascript/spidermonkey/Makefile | 2 +
+ src/ecmascript/spidermonkey/heartbeat.c | 125 +++++++++++++++++++++++++++++++
+ src/ecmascript/spidermonkey/heartbeat.h | 24 ++++++
+ 7 files changed, 201 insertions(+), 5 deletions(-)
+ create mode 100644 src/ecmascript/spidermonkey/heartbeat.c
+ create mode 100644 src/ecmascript/spidermonkey/heartbeat.h
+
+diff --git a/Makefile.config.in b/Makefile.config.in
+index c463868..40a8cd7 100644
+--- a/Makefile.config.in
++++ b/Makefile.config.in
+@@ -117,6 +117,7 @@ CONFIG_DOM = @CONFIG_DOM@
+ CONFIG_ECMASCRIPT = @CONFIG_ECMASCRIPT@
+ CONFIG_ECMASCRIPT_SEE = @CONFIG_ECMASCRIPT_SEE@
+ CONFIG_ECMASCRIPT_SMJS = @CONFIG_ECMASCRIPT_SMJS@
++CONFIG_ECMASCRIPT_SMJS_HEARTBEAT = @CONFIG_ECMASCRIPT_SMJS@
+ CONFIG_EXMODE = @CONFIG_EXMODE@
+ CONFIG_FASTMEM = @CONFIG_FASTMEM@
+ CONFIG_FINGER = @CONFIG_FINGER@
+diff --git a/configure.in b/configure.in
+index f3e3d77..f79ca78 100644
+--- a/configure.in
++++ b/configure.in
+@@ -283,6 +283,7 @@ AC_CHECK_FUNCS(snprintf vsnprintf asprintf vasprintf)
+ AC_CHECK_FUNCS(getifaddrs getpwnam inet_pton inet_ntop)
+ AC_CHECK_FUNCS(fflush fsync fseeko ftello sigaction)
+ AC_CHECK_FUNCS(gettimeofday clock_gettime)
++AC_CHECK_FUNCS(setitimer, HAVE_SETITIMER=yes)
+
+ AC_CHECK_FUNCS([cygwin_conv_to_full_win32_path])
+
+@@ -651,6 +652,8 @@ AC_MSG_RESULT($cf_result)
+ CONFIG_SPIDERMONKEY="$cf_result"
+ if test "$cf_result" = "yes"; then
+ AC_CHECK_FUNCS([[JS_ReportAllocationOverflow]])
++ AC_CHECK_FUNCS(JS_SetBranchCallback)
++ AC_CHECK_FUNCS(JS_TriggerOperationCallback, HAVE_JS_TRIGGEROPERATIONCALLBACK=yes)
+ fi
+ EL_RESTORE_FLAGS
+
+@@ -665,6 +668,15 @@ EL_CONFIG_DEPENDS(CONFIG_ECMASCRIPT, [CONFIG_ECMASCRIPT_SEE CONFIG_ECMASCRIPT_SM
+ AC_SUBST(CONFIG_ECMASCRIPT_SEE)
+ AC_SUBST(CONFIG_ECMASCRIPT_SMJS)
+
++if test "x$CONFIG_ECMASCRIPT_SMJS" = xyes &&
++ test "x$HAVE_JS_TRIGGEROPERATIONCALLBACK" = xyes &&
++ test "x$HAVE_SETITIMER" = xyes; then
++ EL_CONFIG(CONFIG_ECMASCRIPT_SMJS_HEARTBEAT, [ECMAScript heartbeat support])
++else
++ CONFIG_ECMASCRIPT_SMJS_HEARTBEAT=no
++fi
++AC_SUBST(CONFIG_ECMASCRIPT_SMJS_HEARTBEAT)
++
+
+ # ===================================================================
+ # Optional Spidermonkey-based ECMAScript browser scripting
+diff --git a/src/ecmascript/ecmascript.h b/src/ecmascript/ecmascript.h
+index e8d84b5..8613b34 100644
+--- a/src/ecmascript/ecmascript.h
++++ b/src/ecmascript/ecmascript.h
+@@ -32,7 +32,11 @@ struct ecmascript_interpreter {
+ /* The code evaluated by setTimeout() */
+ struct string code;
+
++#if defined(CONFIG_ECMASCRIPT_SMJS_HEARTBEAT)
++ struct heartbeat *heartbeat;
++#elif defined(HAVE_JS_SETBRANCHCALLBACK)
+ time_t exec_start;
++#endif
+
+ /* This is a cross-rerenderings accumulator of
+ * @document.onload_snippets (see its description for juicy details).
+diff --git a/src/ecmascript/spidermonkey.c b/src/ecmascript/spidermonkey.c
+index 78c3bca..16fb0a4 100644
+--- a/src/ecmascript/spidermonkey.c
++++ b/src/ecmascript/spidermonkey.c
+@@ -25,6 +25,7 @@
+ #include "ecmascript/spidermonkey.h"
+ #include "ecmascript/spidermonkey/document.h"
+ #include "ecmascript/spidermonkey/form.h"
++#include "ecmascript/spidermonkey/heartbeat.h"
+ #include "ecmascript/spidermonkey/location.h"
+ #include "ecmascript/spidermonkey/navigator.h"
+ #include "ecmascript/spidermonkey/unibar.h"
+@@ -109,6 +110,7 @@ reported:
+ JS_ClearPendingException(ctx);
+ }
+
++#if !defined(CONFIG_ECMASCRIPT_SMJS_HEARTBEAT) && defined(HAVE_JS_SETBRANCHCALLBACK)
+ static JSBool
+ safeguard(JSContext *ctx, JSScript *script)
+ {
+@@ -132,6 +134,7 @@ setup_safeguard(struct ecmascript_interpreter *interpreter,
+ interpreter->exec_start = time(NULL);
+ JS_SetBranchCallback(ctx, safeguard);
+ }
++#endif
+
+
+ static void
+@@ -172,6 +175,9 @@ spidermonkey_get_interpreter(struct ecmascript_interpreter *interpreter)
+ * some kind of bytecode cache. (If we will ever do that.) */
+ JS_SetOptions(ctx, JSOPTION_VAROBJFIX | JSOPTION_COMPILE_N_GO);
+ JS_SetErrorReporter(ctx, error_reporter);
++#if defined(CONFIG_ECMASCRIPT_SMJS_HEARTBEAT)
++ JS_SetOperationCallback(ctx, heartbeat_callback);
++#endif
+
+ window_obj = JS_NewObject(ctx, (JSClass *) &window_class, NULL, NULL);
+ if (!window_obj) goto release_and_fail;
+@@ -263,10 +269,17 @@ spidermonkey_eval(struct ecmascript_interpreter *interpreter,
+ assert(interpreter);
+ if (!js_module_init_ok) return;
+ ctx = interpreter->backend_data;
++#if defined(CONFIG_ECMASCRIPT_SMJS_HEARTBEAT)
++ interpreter->heartbeat = add_heartbeat(interpreter);
++#elif defined(HAVE_JS_SETBRANCHCALLBACK)
+ setup_safeguard(interpreter, ctx);
++#endif
+ interpreter->ret = ret;
+ JS_EvaluateScript(ctx, JS_GetGlobalObject(ctx),
+ code->source, code->length, "", 0, &rval);
++#if defined(CONFIG_ECMASCRIPT_SMJS_HEARTBEAT)
++ done_heartbeat(interpreter->heartbeat);
++#endif
+ }
+
+
+@@ -274,17 +287,25 @@ unsigned char *
+ spidermonkey_eval_stringback(struct ecmascript_interpreter *interpreter,
+ struct string *code)
+ {
++ JSBool ret;
+ JSContext *ctx;
+ jsval rval;
+
+ assert(interpreter);
+ if (!js_module_init_ok) return NULL;
+ ctx = interpreter->backend_data;
+- setup_safeguard(interpreter, ctx);
+ interpreter->ret = NULL;
+- if (JS_EvaluateScript(ctx, JS_GetGlobalObject(ctx),
+- code->source, code->length, "", 0, &rval)
+- == JS_FALSE) {
++#if defined(CONFIG_ECMASCRIPT_SMJS_HEARTBEAT)
++ interpreter->heartbeat = add_heartbeat(interpreter);
++#elif defined(HAVE_JS_SETBRANCHCALLBACK)
++ setup_safeguard(interpreter, ctx);
++#endif
++ ret = JS_EvaluateScript(ctx, JS_GetGlobalObject(ctx),
++ code->source, code->length, "", 0, &rval);
++#if defined(CONFIG_ECMASCRIPT_SMJS_HEARTBEAT)
++ done_heartbeat(interpreter->heartbeat);
++#endif
++ if (ret == JS_FALSE) {
+ return NULL;
+ }
+ if (JSVAL_IS_VOID(rval)) {
+@@ -308,14 +329,21 @@ spidermonkey_eval_boolback(struct ecmascript_interpreter *interpreter,
+ assert(interpreter);
+ if (!js_module_init_ok) return 0;
+ ctx = interpreter->backend_data;
+- setup_safeguard(interpreter, ctx);
+ interpreter->ret = NULL;
+ fun = JS_CompileFunction(ctx, NULL, "", 0, NULL, code->source,
+ code->length, "", 0);
+ if (!fun)
+ return -1;
+
++#if defined(CONFIG_ECMASCRIPT_SMJS_HEARTBEAT)
++ interpreter->heartbeat = add_heartbeat(interpreter);
++#elif defined(HAVE_JS_SETBRANCHCALLBACK)
++ setup_safeguard(interpreter, ctx);
++#endif
+ ret = JS_CallFunction(ctx, NULL, fun, 0, NULL, &rval);
++#if defined(CONFIG_ECMASCRIPT_SMJS_HEARTBEAT)
++ done_heartbeat(interpreter->heartbeat);
++#endif
+ if (ret == 2) { /* onClick="history.back()" */
+ return 0;
+ }
+diff --git a/src/ecmascript/spidermonkey/Makefile b/src/ecmascript/spidermonkey/Makefile
+index f1c0fef..377ca80 100644
+--- a/src/ecmascript/spidermonkey/Makefile
++++ b/src/ecmascript/spidermonkey/Makefile
+@@ -2,6 +2,8 @@ top_builddir=../../..
+ include $(top_builddir)/Makefile.config
+ INCLUDES += $(SPIDERMONKEY_CFLAGS)
+
++OBJS-$(CONFIG_ECMASCRIPT_SMJS_HEARTBEAT) += heartbeat.o
++
+ OBJS = document.o form.o location.o navigator.o unibar.o window.o
+
+ include $(top_srcdir)/Makefile.lib
+diff --git a/src/ecmascript/spidermonkey/heartbeat.c b/src/ecmascript/spidermonkey/heartbeat.c
+new file mode 100644
+index 0000000..bf95d92
+--- /dev/null
++++ b/src/ecmascript/spidermonkey/heartbeat.c
+@@ -0,0 +1,125 @@
++/* The SpiderMonkey ECMAScript backend heartbeat fuctionality. */
++
++#ifdef HAVE_CONFIG_H
++#include "config.h"
++#endif
++
++#include <sys/time.h> /* setitimer(2) */
++
++#include "elinks.h"
++
++#include "ecmascript/spidermonkey/util.h"
++
++#include "config/options.h"
++#include "document/view.h"
++#include "ecmascript/ecmascript.h"
++#include "ecmascript/spidermonkey.h"
++#include "ecmascript/spidermonkey/heartbeat.h"
++#include "osdep/signals.h"
++#include "session/session.h"
++#include "util/lists.h"
++#include "util/math.h" /* int_upper_bound */
++#include "util/memory.h"
++#include "viewer/text/vs.h"
++
++
++
++static INIT_LIST_OF(struct heartbeat, heartbeats);
++
++static struct itimerval heartbeat_timer = { { 1, 0 }, { 1, 0 } };
++
++
++/* This callback is installed by JS_SetOperationCallback and triggered
++ * by JS_TriggerOperationCallback in the heartbeat code below. Returning
++ * JS_FALSE terminates script execution immediately. */
++JSBool
++heartbeat_callback(JSContext *ctx)
++{
++ return JS_FALSE;
++}
++
++/* Callback for SIGVTALRM. Go through all heartbeats, decrease each
++ * one's TTL, and call JS_TriggerOperationCallback if a heartbeat's TTL
++ * goes to 0. */
++static void
++check_heartbeats(void *data)
++{
++ struct heartbeat *hb;
++
++ foreach (hb, heartbeats) {
++ assert(hb->interpreter);
++
++ --hb->ttl;
++
++ if (hb->ttl <= 0) {
++ if (hb->interpreter->vs
++ && hb->interpreter->vs->doc_view
++ && hb->interpreter->vs->doc_view->session
++ && hb->interpreter->vs->doc_view->session->tab
++ && hb->interpreter->vs->doc_view->session->tab->term) {
++ struct session *ses = hb->interpreter->vs->doc_view->session;
++ struct terminal *term = ses->tab->term;
++ int max_exec_time = get_opt_int("ecmascript.max_exec_time");
++
++ ecmascript_timeout_dialog(term, max_exec_time);
++ }
++
++ JS_TriggerOperationCallback(hb->interpreter->backend_data);
++ }
++ }
++
++ install_signal_handler(SIGVTALRM, check_heartbeats, NULL, 1);
++}
++
++/* Create a new heartbeat for the given interpreter. */
++struct heartbeat *
++add_heartbeat(struct ecmascript_interpreter *interpreter)
++{
++ struct session *ses;
++ struct heartbeat *hb;
++
++ assert(interpreter);
++
++ if (!interpreter->vs || !interpreter->vs->doc_view)
++ ses = NULL;
++ else
++ ses = interpreter->vs->doc_view->session;
++
++ hb = mem_alloc(sizeof(struct heartbeat));
++ if (!hb) return NULL;
++
++ hb->ttl = get_opt_int("ecmascript.max_exec_time");
++ hb->interpreter = interpreter;
++
++ 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);
++ }
++
++ /* We install the handler every call to add_heartbeat instead of only on
++ * 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. */
++void
++done_heartbeat(struct heartbeat *hb)
++{
++ assert(hb->interpreter);
++
++ /* Stop the heartbeat timer if this heartbeat is the only one. */
++ if (list_is_singleton(*hb)) {
++ heartbeat_timer.it_value.tv_sec = 0;
++ setitimer(ITIMER_VIRTUAL, &heartbeat_timer, NULL);
++ }
++
++ del_from_list(hb);
++ hb->interpreter->heartbeat = NULL;
++ mem_free(hb);
++}
+diff --git a/src/ecmascript/spidermonkey/heartbeat.h b/src/ecmascript/spidermonkey/heartbeat.h
+new file mode 100644
+index 0000000..f7c8b12
+--- /dev/null
++++ b/src/ecmascript/spidermonkey/heartbeat.h
+@@ -0,0 +1,24 @@
++#ifndef EL__ECMASCRIPT_SPIDERMONKEY_HEARTBEAT_H
++#define EL__ECMASCRIPT_SPIDERMONKEY_HEARTBEAT_H
++
++#include "ecmascript/spidermonkey/util.h"
++
++#include "ecmascript/spidermonkey.h"
++
++struct heartbeat {
++ LIST_HEAD(struct heartbeat);
++
++ int ttl; /* Time to live. This value is assigned when the
++ * script begins execution and is decremented every
++ * second. When it reaches 0, script execution is
++ * terminated. */
++
++ struct ecmascript_interpreter *interpreter;
++};
++
++struct heartbeat *add_heartbeat(struct ecmascript_interpreter *interpreter);
++void done_heartbeat(struct heartbeat *hb);
++
++JSBool heartbeat_callback(JSContext *ctx);
++
++#endif
+--
+1.7.4.2
+
+
+From dcaff5d937d63888c560727dda5f5348fa59a366 Mon Sep 17 00:00:00 2001
+From: witekfl <witekfl at poczta.onet.pl>
+Date: Tue, 19 Apr 2011 22:41:05 +0200
+Subject: [PATCH 2/2] JS_VERSION at least 185 is required for ECMASCript (xulrunner-2.0 or later)
+
+The code wasn't tested. It compiles
+
+Signed-off-by: Kamil Dudka <kdudka at redhat.com>
+---
+ configure.in | 10 ++-
+ src/ecmascript/spidermonkey-shared.h | 13 ++-
+ src/ecmascript/spidermonkey.c | 11 +--
+ src/ecmascript/spidermonkey/document.c | 44 ++++----
+ src/ecmascript/spidermonkey/form.c | 192 +++++++++++++++++++++----------
+ src/ecmascript/spidermonkey/location.c | 42 ++++---
+ src/ecmascript/spidermonkey/navigator.c | 10 +-
+ src/ecmascript/spidermonkey/unibar.c | 16 ++--
+ src/ecmascript/spidermonkey/window.c | 57 ++++++----
+ src/scripting/smjs/action_object.c | 29 +++--
+ src/scripting/smjs/bookmarks.c | 24 ++--
+ src/scripting/smjs/cache_object.c | 18 ++--
+ src/scripting/smjs/core.c | 11 +-
+ src/scripting/smjs/elinks_object.c | 26 +++--
+ src/scripting/smjs/global_object.c | 6 +-
+ src/scripting/smjs/globhist.c | 22 ++--
+ src/scripting/smjs/hooks.c | 4 +-
+ src/scripting/smjs/keybinding.c | 12 +-
+ src/scripting/smjs/load_uri.c | 10 +-
+ src/scripting/smjs/view_state_object.c | 16 ++--
+ 20 files changed, 344 insertions(+), 229 deletions(-)
+
+diff --git a/configure.in b/configure.in
+index f79ca78..64faf85 100644
+--- a/configure.in
++++ b/configure.in
+@@ -641,7 +641,15 @@ if test -z "$disable_spidermonkey"; then
+ CPPFLAGS="$CPPFLAGS_X $SPIDERMONKEY_CFLAGS"
+
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#define XP_UNIX
+- #include <jsapi.h>]], [[JS_GetReservedSlot(NULL, NULL, 0, NULL)]])],[cf_result=yes],[cf_result=no])
++ #define XP_UNIX
++ #include <jsapi.h>]], [[
++ #ifndef JS_VERSION
++ #error JS_VERSION
++ #endif
++ #if JS_VERSION < 185
++ #error too old
++ #endif]])],
++ [cf_result=yes],[cf_result=no])
+ fi
+ done
+ done
+diff --git a/src/ecmascript/spidermonkey-shared.h b/src/ecmascript/spidermonkey-shared.h
+index 4cc0eeb..98bfe31 100644
+--- a/src/ecmascript/spidermonkey-shared.h
++++ b/src/ecmascript/spidermonkey-shared.h
+@@ -50,6 +50,7 @@ JSObject *spidermonkey_InitClass(JSContext *cx, JSObject *obj,
+
+ static void undef_to_jsval(JSContext *ctx, jsval *vp);
+ static unsigned char *jsval_to_string(JSContext *ctx, jsval *vp);
++static unsigned char *jsid_to_string(JSContext *ctx, jsid *id);
+
+ /* Inline functions */
+
+@@ -68,7 +69,17 @@ jsval_to_string(JSContext *ctx, jsval *vp)
+ return "";
+ }
+
+- return empty_string_or_(JS_GetStringBytes(JS_ValueToString(ctx, val)));
++ return empty_string_or_(JS_EncodeString(ctx, JS_ValueToString(ctx, val)));
++}
++
++static inline unsigned char *
++jsid_to_string(JSContext *ctx, jsid *id)
++{
++ jsval v;
++
++ /* TODO: check returned value */
++ JS_IdToValue(ctx, *id, &v);
++ return jsval_to_string(ctx, &v);
+ }
+
+ #endif
+diff --git a/src/ecmascript/spidermonkey.c b/src/ecmascript/spidermonkey.c
+index 16fb0a4..021e6bd 100644
+--- a/src/ecmascript/spidermonkey.c
++++ b/src/ecmascript/spidermonkey.c
+@@ -167,19 +167,14 @@ spidermonkey_get_interpreter(struct ecmascript_interpreter *interpreter)
+ return NULL;
+ interpreter->backend_data = ctx;
+ JS_SetContextPrivate(ctx, interpreter);
+- /* TODO: Make JSOPTION_STRICT and JSOPTION_WERROR configurable. */
+-#ifndef JSOPTION_COMPILE_N_GO
+-#define JSOPTION_COMPILE_N_GO 0 /* Older SM versions don't have it. */
+-#endif
+- /* XXX: JSOPTION_COMPILE_N_GO will go (will it?) when we implement
+- * some kind of bytecode cache. (If we will ever do that.) */
+- JS_SetOptions(ctx, JSOPTION_VAROBJFIX | JSOPTION_COMPILE_N_GO);
++ JS_SetOptions(ctx, JSOPTION_VAROBJFIX | JSOPTION_JIT | JSOPTION_METHODJIT);
++ JS_SetVersion(ctx, JSVERSION_LATEST);
+ JS_SetErrorReporter(ctx, error_reporter);
+ #if defined(CONFIG_ECMASCRIPT_SMJS_HEARTBEAT)
+ JS_SetOperationCallback(ctx, heartbeat_callback);
+ #endif
+
+- window_obj = JS_NewObject(ctx, (JSClass *) &window_class, NULL, NULL);
++ window_obj = JS_NewCompartmentAndGlobalObject(ctx, (JSClass *) &window_class, NULL);
+ 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))
+diff --git a/src/ecmascript/spidermonkey/document.c b/src/ecmascript/spidermonkey/document.c
+index 8f7bb92..dd72aae 100644
+--- a/src/ecmascript/spidermonkey/document.c
++++ b/src/ecmascript/spidermonkey/document.c
+@@ -47,8 +47,8 @@
+ #include "viewer/text/vs.h"
+
+
+-static JSBool document_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp);
+-static JSBool document_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp);
++static JSBool document_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp);
++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. */
+ const JSClass document_class = {
+@@ -81,7 +81,7 @@ const JSPropertySpec document_props[] = {
+
+ /* @document_class.getProperty */
+ static JSBool
+-document_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
++document_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp)
+ {
+ JSObject *parent_win; /* instance of @window_class */
+ struct view_state *vs;
+@@ -104,9 +104,9 @@ document_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+ document = doc_view->document;
+ ses = doc_view->session;
+
+- if (JSVAL_IS_STRING(id)) {
++ if (JSID_IS_STRING(id)) {
+ struct form *form;
+- unsigned char *string = jsval_to_string(ctx, &id);
++ unsigned char *string = jsid_to_string(ctx, &id);
+
+ #ifdef CONFIG_COOKIES
+ if (!strcmp(string, "cookie")) {
+@@ -135,12 +135,12 @@ document_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+ return JS_TRUE;
+ }
+
+- if (!JSVAL_IS_INT(id))
++ if (!JSID_IS_INT(id))
+ return JS_TRUE;
+
+ undef_to_jsval(ctx, vp);
+
+- switch (JSVAL_TO_INT(id)) {
++ switch (JSID_TO_INT(id)) {
+ case JSP_DOC_LOC:
+ JS_GetProperty(ctx, parent_win, "location", vp);
+ break;
+@@ -188,7 +188,7 @@ document_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+
+ /* @document_class.setProperty */
+ static JSBool
+-document_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
++document_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
+ {
+ JSObject *parent_win; /* instance of @window_class */
+ struct view_state *vs;
+@@ -209,9 +209,9 @@ document_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+ doc_view = vs->doc_view;
+ document = doc_view->document;
+
+- if (JSVAL_IS_STRING(id)) {
++ if (JSID_IS_STRING(id)) {
+ #ifdef CONFIG_COOKIES
+- if (!strcmp(jsval_to_string(ctx, &id), "cookie")) {
++ if (!strcmp(jsid_to_string(ctx, &id), "cookie")) {
+ set_cookie(vs->uri, jsval_to_string(ctx, vp));
+ /* Do NOT touch our .cookie property, evil
+ * SpiderMonkey!! */
+@@ -221,10 +221,10 @@ document_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+ return JS_TRUE;
+ }
+
+- if (!JSVAL_IS_INT(id))
++ if (!JSID_IS_INT(id))
+ return JS_TRUE;
+
+- switch (JSVAL_TO_INT(id)) {
++ switch (JSID_TO_INT(id)) {
+ case JSP_DOC_TITLE:
+ mem_free_set(&document->title, stracpy(jsval_to_string(ctx, vp)));
+ print_screen_status(doc_view->session);
+@@ -242,8 +242,8 @@ document_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+ return JS_TRUE;
+ }
+
+-static JSBool document_write(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+-static JSBool document_writeln(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
++static JSBool document_write(JSContext *ctx, uintN argc, jsval *rval);
++static JSBool document_writeln(JSContext *ctx, uintN argc, jsval *rval);
+
+ const spidermonkeyFunctionSpec document_funcs[] = {
+ { "write", document_write, 1 },
+@@ -252,11 +252,12 @@ const spidermonkeyFunctionSpec document_funcs[] = {
+ };
+
+ static JSBool
+-document_write_do(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv,
+- jsval *rval, int newline)
++document_write_do(JSContext *ctx, uintN argc, jsval *rval, int newline)
+ {
++ jsval val;
+ struct ecmascript_interpreter *interpreter = JS_GetContextPrivate(ctx);
+ struct string *ret = interpreter->ret;
++ jsval *argv = JS_ARGV(ctx, rval);
+
+ if (argc >= 1 && ret) {
+ int i = 0;
+@@ -281,22 +282,23 @@ document_write_do(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv,
+ set_led_value(interpreter->vs->doc_view->session->status.ecmascript_led, 'J');
+ #endif
+
+- boolean_to_jsval(ctx, rval, 0);
++ boolean_to_jsval(ctx, &val, 0);
++ JS_SET_RVAL(ctx, rval, val);
+
+ return JS_TRUE;
+ }
+
+ /* @document_funcs{"write"} */
+ static JSBool
+-document_write(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
++document_write(JSContext *ctx, uintN argc, jsval *rval)
+ {
+
+- return document_write_do(ctx, obj, argc, argv, rval, 0);
++ return document_write_do(ctx, argc, rval, 0);
+ }
+
+ /* @document_funcs{"writeln"} */
+ static JSBool
+-document_writeln(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
++document_writeln(JSContext *ctx, uintN argc, jsval *rval)
+ {
+- return document_write_do(ctx, obj, argc, argv, rval, 1);
++ return document_write_do(ctx, argc, rval, 1);
+ }
+diff --git a/src/ecmascript/spidermonkey/form.c b/src/ecmascript/spidermonkey/form.c
+index ff436a1..824b170 100644
+--- a/src/ecmascript/spidermonkey/form.c
++++ b/src/ecmascript/spidermonkey/form.c
+@@ -55,8 +55,8 @@ static const JSClass form_class; /* defined below */
+ * HTMLInputElement. The difference could be spotted only by some clever tricky
+ * JS code, but I hope it doesn't matter anywhere. --pasky */
+
+-static JSBool input_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp);
+-static JSBool input_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp);
++static JSBool input_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp);
++static JSBool input_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp);
+ static void input_finalize(JSContext *ctx, JSObject *obj);
+
+ /* Each @input_class object must have a @form_class parent. */
+@@ -116,10 +116,10 @@ static const JSPropertySpec input_props[] = {
+ { NULL }
+ };
+
+-static JSBool input_blur(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+-static JSBool input_click(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+-static JSBool input_focus(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+-static JSBool input_select(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
++static JSBool input_blur(JSContext *ctx, uintN argc, jsval *rval);
++static JSBool input_click(JSContext *ctx, uintN argc, jsval *rval);
++static JSBool input_focus(JSContext *ctx, uintN argc, jsval *rval);
++static JSBool input_select(JSContext *ctx, uintN argc, jsval *rval);
+
+ static const spidermonkeyFunctionSpec input_funcs[] = {
+ { "blur", input_blur, 0 },
+@@ -150,7 +150,7 @@ input_get_form_state(JSContext *ctx, JSObject *jsinput)
+
+ /* @input_class.getProperty */
+ static JSBool
+-input_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
++input_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp)
+ {
+ JSObject *parent_form; /* instance of @form_class */
+ JSObject *parent_doc; /* instance of @document_class */
+@@ -189,7 +189,7 @@ input_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+ assert(fc);
+ assert(fc->form && fs);
+
+- if (!JSVAL_IS_INT(id))
++ if (!JSID_IS_INT(id))
+ return JS_TRUE;
+
+ linknum = get_form_control_link(document, fc);
+@@ -198,7 +198,7 @@ input_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+
+ undef_to_jsval(ctx, vp);
+
+- switch (JSVAL_TO_INT(id)) {
++ switch (JSID_TO_INT(id)) {
+ case JSP_INPUT_ACCESSKEY:
+ {
+ JSString *keystr;
+@@ -301,7 +301,7 @@ input_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+
+ /* @input_class.setProperty */
+ static JSBool
+-input_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
++input_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
+ {
+ JSObject *parent_form; /* instance of @form_class */
+ JSObject *parent_doc; /* instance of @document_class */
+@@ -341,14 +341,14 @@ input_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+ assert(fc);
+ assert(fc->form && fs);
+
+- if (!JSVAL_IS_INT(id))
++ if (!JSID_IS_INT(id))
+ return JS_TRUE;
+
+ linknum = get_form_control_link(document, fc);
+ /* Hiddens have no link. */
+ if (linknum >= 0) link = &document->links[linknum];
+
+- switch (JSVAL_TO_INT(id)) {
++ switch (JSID_TO_INT(id)) {
+ case JSP_INPUT_ACCESSKEY:
+ accesskey = jsval_to_accesskey(ctx, vp);
+ if (accesskey == UCS_NO_CHAR)
+@@ -422,7 +422,7 @@ input_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+
+ /* @input_funcs{"blur"} */
+ static JSBool
+-input_blur(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
++input_blur(JSContext *ctx, uintN argc, jsval *rval)
+ {
+ /* We are a text-mode browser and there *always* has to be something
+ * selected. So we do nothing for now. (That was easy.) */
+@@ -431,11 +431,14 @@ input_blur(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+
+ /* @input_funcs{"click"} */
+ static JSBool
+-input_click(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
++input_click(JSContext *ctx, uintN argc, jsval *rval)
+ {
++ jsval val;
+ JSObject *parent_form; /* instance of @form_class */
+ JSObject *parent_doc; /* instance of @document_class */
+ JSObject *parent_win; /* instance of @window_class */
++ JSObject *obj = JS_THIS_OBJECT(ctx, rval);
++ jsval *argv = JS_ARGV(ctx, rval);
+ struct view_state *vs;
+ struct document_view *doc_view;
+ struct document *document;
+@@ -479,17 +482,21 @@ input_click(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+ else
+ print_screen_status(ses);
+
+- boolean_to_jsval(ctx, rval, 0);
++ boolean_to_jsval(ctx, &val, 0);
++ JS_SET_RVAL(ctx, rval, val);
+ return JS_TRUE;
+ }
+
+ /* @input_funcs{"focus"} */
+ static JSBool
+-input_focus(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
++input_focus(JSContext *ctx, uintN argc, jsval *rval)
+ {
++ jsval val;
+ JSObject *parent_form; /* instance of @form_class */
+ JSObject *parent_doc; /* instance of @document_class */
+ JSObject *parent_win; /* instance of @window_class */
++ JSObject *obj = JS_THIS_OBJECT(ctx, rval);
++ jsval *argv = JS_ARGV(ctx, rval);
+ struct view_state *vs;
+ struct document_view *doc_view;
+ struct document *document;
+@@ -528,13 +535,14 @@ input_focus(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+
+ jump_to_link_number(ses, doc_view, linknum);
+
+- boolean_to_jsval(ctx, rval, 0);
++ boolean_to_jsval(ctx, &val, 0);
++ JS_SET_RVAL(ctx, rval, val);
+ return JS_TRUE;
+ }
+
+ /* @input_funcs{"select"} */
+ static JSBool
+-input_select(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
++input_select(JSContext *ctx, uintN argc, jsval *rval)
+ {
+ /* We support no text selecting yet. So we do nothing for now.
+ * (That was easy, too.) */
+@@ -662,19 +670,22 @@ get_form_control_object(JSContext *ctx, JSObject *jsform,
+
+
+ static struct form_view *form_get_form_view(JSContext *ctx, JSObject *jsform, jsval *argv);
+-static JSBool form_elements_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp);
++static JSBool form_elements_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp);
+
+ /* Each @form_elements_class object must have a @form_class parent. */
+ static const JSClass form_elements_class = {
+ "elements",
+ JSCLASS_HAS_PRIVATE,
+ JS_PropertyStub, JS_PropertyStub,
+- form_elements_get_property, JS_PropertyStub,
++ form_elements_get_property, JS_StrictPropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
+ };
+
+-static JSBool form_elements_item(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+-static JSBool form_elements_namedItem(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
++static JSBool form_elements_item2(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
++static JSBool form_elements_namedItem2(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
++static JSBool form_elements_item(JSContext *ctx, uintN argc, jsval *rval);
++static JSBool form_elements_namedItem(JSContext *ctx, uintN argc, jsval *rval);
++
+
+ static const spidermonkeyFunctionSpec form_elements_funcs[] = {
+ { "item", form_elements_item, 1 },
+@@ -696,8 +707,9 @@ static const JSPropertySpec form_elements_props[] = {
+
+ /* @form_elements_class.getProperty */
+ static JSBool
+-form_elements_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
++form_elements_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp)
+ {
++ jsval idval;
+ JSObject *parent_form; /* instance of @form_class */
+ JSObject *parent_doc; /* instance of @document_class */
+ JSObject *parent_win; /* instance of @window_class */
+@@ -730,32 +742,46 @@ form_elements_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+ if (!form_view) return JS_FALSE; /* detached */
+ form = find_form_by_form_view(document, form_view);
+
+- if (JSVAL_IS_STRING(id)) {
+- form_elements_namedItem(ctx, obj, 1, &id, vp);
++ if (JSID_IS_STRING(id)) {
++ JS_IdToValue(ctx, id, &idval);
++ form_elements_namedItem2(ctx, obj, 1, &idval, vp);
+ return JS_TRUE;
+ }
+
+- if (!JSVAL_IS_INT(id))
++ if (!JSID_IS_INT(id))
+ return JS_TRUE;
+
+ undef_to_jsval(ctx, vp);
+
+- switch (JSVAL_TO_INT(id)) {
++ switch (JSID_TO_INT(id)) {
+ case JSP_FORM_ELEMENTS_LENGTH:
+ int_to_jsval(ctx, vp, list_size(&form->items));
+ break;
+ default:
+ /* Array index. */
+- form_elements_item(ctx, obj, 1, &id, vp);
++ JS_IdToValue(ctx, id, &idval);
++ form_elements_item2(ctx, obj, 1, &idval, vp);
+ break;
+ }
+
+ return JS_TRUE;
+ }
+
++static JSBool
++form_elements_item(JSContext *ctx, uintN argc, jsval *rval)
++{
++ jsval val;
++ JSObject *obj = JS_THIS_OBJECT(ctx, rval);
++ jsval *argv = JS_ARGV(ctx, rval);
++ JSBool ret = form_elements_item2(ctx, obj, argc, argv, &val);
++
++ JS_SET_RVAL(ctx, rval, val);
++ return ret;
++}
++
+ /* @form_elements_funcs{"item"} */
+ static JSBool
+-form_elements_item(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
++form_elements_item2(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+ {
+ JSObject *parent_form; /* instance of @form_class */
+ JSObject *parent_doc; /* instance of @document_class */
+@@ -813,9 +839,21 @@ form_elements_item(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval
+ return JS_TRUE;
+ }
+
++static JSBool
++form_elements_namedItem(JSContext *ctx, uintN argc, jsval *rval)
++{
++ jsval val;
++ JSObject *obj = JS_THIS_OBJECT(ctx, rval);
++ jsval *argv = JS_ARGV(ctx, rval);
++ JSBool ret = form_elements_namedItem2(ctx, obj, argc, argv, &val);
++
++ JS_SET_RVAL(ctx, rval, val);
++ return ret;
++}
++
+ /* @form_elements_funcs{"namedItem"} */
+ static JSBool
+-form_elements_namedItem(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
++form_elements_namedItem2(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+ {
+ JSObject *parent_form; /* instance of @form_class */
+ JSObject *parent_doc; /* instance of @document_class */
+@@ -876,8 +914,8 @@ form_elements_namedItem(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv,
+
+
+
+-static JSBool form_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp);
+-static JSBool form_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp);
++static JSBool form_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp);
++static JSBool form_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp);
+ static void form_finalize(JSContext *ctx, JSObject *obj);
+
+ /* Each @form_class object must have a @document_class parent. */
+@@ -914,8 +952,8 @@ static const JSPropertySpec form_props[] = {
+ { NULL }
+ };
+
+-static JSBool form_reset(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+-static JSBool form_submit(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
++static JSBool form_reset(JSContext *ctx, uintN argc, jsval *rval);
++static JSBool form_submit(JSContext *ctx, uintN argc, jsval *rval);
+
+ static const spidermonkeyFunctionSpec form_funcs[] = {
+ { "reset", form_reset, 0 },
+@@ -940,7 +978,7 @@ form_get_form_view(JSContext *ctx, JSObject *jsform, jsval *argv)
+
+ /* @form_class.getProperty */
+ static JSBool
+-form_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
++form_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp)
+ {
+ /* DBG("doc %p %s\n", parent_doc, JS_GetStringBytes(JS_ValueToString(ctx, OBJECT_TO_JSVAL(parent_doc)))); */
+ JSObject *parent_doc; /* instance of @document_class */
+@@ -971,11 +1009,11 @@ form_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+
+ assert(form);
+
+- if (JSVAL_IS_STRING(id)) {
++ if (JSID_IS_STRING(id)) {
+ struct form_control *fc;
+ unsigned char *string;
+
+- string = jsval_to_string(ctx, &id);
++ string = jsid_to_string(ctx, &id);
+ foreach (fc, form->items) {
+ JSObject *fcobj = NULL;
+ struct form_state *fs;
+@@ -996,12 +1034,12 @@ form_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+ return JS_TRUE;
+ }
+
+- if (!JSVAL_IS_INT(id))
++ if (!JSID_IS_INT(id))
+ return JS_TRUE;
+
+ undef_to_jsval(ctx, vp);
+
+- switch (JSVAL_TO_INT(id)) {
++ switch (JSID_TO_INT(id)) {
+ case JSP_FORM_ACTION:
+ string_to_jsval(ctx, vp, form->action);
+ break;
+@@ -1076,7 +1114,7 @@ form_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+
+ /* @form_class.setProperty */
+ static JSBool
+-form_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
++form_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
+ {
+ JSObject *parent_doc; /* instance of @document_class */
+ JSObject *parent_win; /* instance of @window_class */
+@@ -1107,10 +1145,10 @@ form_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+
+ assert(form);
+
+- if (!JSVAL_IS_INT(id))
++ if (!JSID_IS_INT(id))
+ return JS_TRUE;
+
+- switch (JSVAL_TO_INT(id)) {
++ switch (JSID_TO_INT(id)) {
+ case JSP_FORM_ACTION:
+ string = stracpy(jsval_to_string(ctx, vp));
+ if (form->action) {
+@@ -1162,10 +1200,13 @@ form_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+
+ /* @form_funcs{"reset"} */
+ static JSBool
+-form_reset(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
++form_reset(JSContext *ctx, uintN argc, jsval *rval)
+ {
++ jsval val;
+ JSObject *parent_doc; /* instance of @document_class */
+ JSObject *parent_win; /* instance of @window_class */
++ JSObject *obj = JS_THIS_OBJECT(ctx, rval);
++ jsval *argv = JS_ARGV(ctx, rval);
+ struct view_state *vs;
+ struct document_view *doc_view;
+ struct form_view *fv;
+@@ -1191,17 +1232,21 @@ form_reset(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+ do_reset_form(doc_view, form);
+ draw_forms(doc_view->session->tab->term, doc_view);
+
+- boolean_to_jsval(ctx, rval, 0);
++ boolean_to_jsval(ctx, &val, 0);
++ JS_SET_RVAL(ctx, rval, val);
+
+ return JS_TRUE;
+ }
+
+ /* @form_funcs{"submit"} */
+ static JSBool
+-form_submit(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
++form_submit(JSContext *ctx, uintN argc, jsval *rval)
+ {
++ jsval val;
+ JSObject *parent_doc; /* instance of @document_class */
+ JSObject *parent_win; /* instance of @window_class */
++ JSObject *obj = JS_THIS_OBJECT(ctx, rval);
++ jsval *argv = JS_ARGV(ctx, rval);
+ struct view_state *vs;
+ struct document_view *doc_view;
+ struct session *ses;
+@@ -1227,7 +1272,8 @@ form_submit(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+ assert(form);
+ submit_given_form(ses, doc_view, form, 0);
+
+- boolean_to_jsval(ctx, rval, 0);
++ boolean_to_jsval(ctx, &val, 0);
++ JS_SET_RVAL(ctx, rval, val);
+
+ return JS_TRUE;
+ }
+@@ -1308,19 +1354,20 @@ spidermonkey_detach_form_view(struct form_view *fv)
+ }
+
+
+-static JSBool forms_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp);
++static JSBool forms_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp);
+
+ /* Each @forms_class object must have a @document_class parent. */
+ const JSClass forms_class = {
+ "forms",
+ JSCLASS_HAS_PRIVATE,
+ JS_PropertyStub, JS_PropertyStub,
+- forms_get_property, JS_PropertyStub,
++ forms_get_property, JS_StrictPropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
+ };
+
+-static JSBool forms_item(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+-static JSBool forms_namedItem(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
++static JSBool forms_item(JSContext *ctx, uintN argc, jsval *rval);
++static JSBool forms_item2(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
++static JSBool forms_namedItem(JSContext *ctx, uintN argc, jsval *rval);
+
+ const spidermonkeyFunctionSpec forms_funcs[] = {
+ { "item", forms_item, 1 },
+@@ -1365,8 +1412,9 @@ find_form_by_name(JSContext *ctx, JSObject *jsdoc,
+
+ /* @forms_class.getProperty */
+ static JSBool
+-forms_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
++forms_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp)
+ {
++ jsval idval;
+ JSObject *parent_doc; /* instance of @document_class */
+ JSObject *parent_win; /* instance of @window_class */
+ struct view_state *vs;
+@@ -1390,36 +1438,50 @@ forms_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+ doc_view = vs->doc_view;
+ document = doc_view->document;
+
+- if (JSVAL_IS_STRING(id)) {
++ if (JSID_IS_STRING(id)) {
+ /* When SMJS evaluates forms.namedItem("foo"), it first
+ * calls forms_get_property with id = JSString "namedItem"
+ * and *vp = JSObject JSFunction forms_namedItem.
+ * If we don't find a form whose name is id,
+ * we must leave *vp unchanged here, to avoid
+ * "TypeError: forms.namedItem is not a function". */
+- find_form_by_name(ctx, parent_doc, doc_view, id, vp);
++ JS_IdToValue(ctx, id, &idval);
++ find_form_by_name(ctx, parent_doc, doc_view, idval, vp);
+ return JS_TRUE;
+ }
+
+- if (!JSVAL_IS_INT(id))
++ if (!JSID_IS_INT(id))
+ return JS_TRUE;
+
+- switch (JSVAL_TO_INT(id)) {
++ switch (JSID_TO_INT(id)) {
+ case JSP_FORMS_LENGTH:
+ int_to_jsval(ctx, vp, list_size(&document->forms));
+ break;
+ default:
+ /* Array index. */
+- forms_item(ctx, obj, 1, &id, vp);
++ JS_IdToValue(ctx, id, &idval);
++ forms_item2(ctx, obj, 1, &idval, vp);
+ break;
+ }
+
+ return JS_TRUE;
+ }
+
++static JSBool
++forms_item(JSContext *ctx, uintN argc, jsval *rval)
++{
++ jsval val;
++ JSObject *obj = JS_THIS_OBJECT(ctx, rval);
++ jsval *argv = JS_ARGV(ctx, rval);
++ JSBool ret = forms_item2(ctx, obj, argc, argv, &val);
++
++ JS_SET_RVAL(ctx, rval, val);
++ return ret;
++}
++
+ /* @forms_funcs{"item"} */
+ static JSBool
+-forms_item(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
++forms_item2(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+ {
+ JSObject *parent_doc; /* instance of @document_class */
+ JSObject *parent_win; /* instance of @window_class */
+@@ -1459,10 +1521,13 @@ forms_item(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+
+ /* @forms_funcs{"namedItem"} */
+ static JSBool
+-forms_namedItem(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
++forms_namedItem(JSContext *ctx, uintN argc, jsval *rval)
+ {
++ jsval val;
+ JSObject *parent_doc; /* instance of @document_class */
+ JSObject *parent_win; /* instance of @window_class */
++ JSObject *obj = JS_THIS_OBJECT(ctx, rval);
++ jsval *argv = JS_ARGV(ctx, rval);
+ struct view_state *vs;
+ struct document_view *doc_view;
+
+@@ -1481,8 +1546,9 @@ forms_namedItem(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *r
+ if (argc != 1)
+ return JS_TRUE;
+
+- undef_to_jsval(ctx, rval);
+- find_form_by_name(ctx, parent_doc, doc_view, argv[0], rval);
++ undef_to_jsval(ctx, &val);
++ find_form_by_name(ctx, parent_doc, doc_view, argv[0], &val);
++ JS_SET_RVAL(ctx, rval, val);
+ return JS_TRUE;
+ }
+
+@@ -1519,13 +1585,13 @@ static unicode_val_T
+ jsval_to_accesskey(JSContext *ctx, jsval *vp)
+ {
+ size_t len;
+- const jschar *chr;
++ const char *chr;
+
+ /* Convert the value in place, to protect the result from GC. */
+ if (JS_ConvertValue(ctx, *vp, JSTYPE_STRING, vp) == JS_FALSE)
+ return UCS_NO_CHAR;
+- len = JS_GetStringLength(JSVAL_TO_STRING(*vp));
+- chr = JS_GetStringChars(JSVAL_TO_STRING(*vp));
++ len = JS_GetStringEncodingLength(ctx, JSVAL_TO_STRING(*vp));
++ chr = JS_EncodeString(ctx, JSVAL_TO_STRING(*vp));
+
+ /* This implementation ignores extra characters in the string. */
+ if (len < 1)
+diff --git a/src/ecmascript/spidermonkey/location.c b/src/ecmascript/spidermonkey/location.c
+index dd5b40b..752a890 100644
+--- a/src/ecmascript/spidermonkey/location.c
++++ b/src/ecmascript/spidermonkey/location.c
+@@ -45,15 +45,15 @@
+ #include "viewer/text/vs.h"
+
+
+-static JSBool history_back(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+-static JSBool history_forward(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+-static JSBool history_go(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
++static JSBool history_back(JSContext *ctx, uintN argc, jsval *rval);
++static JSBool history_forward(JSContext *ctx, uintN argc, jsval *rval);
++static JSBool history_go(JSContext *ctx, uintN argc, jsval *rval);
+
+ const JSClass history_class = {
+ "history",
+ JSCLASS_HAS_PRIVATE,
+ JS_PropertyStub, JS_PropertyStub,
+- JS_PropertyStub, JS_PropertyStub,
++ JS_PropertyStub, JS_StrictPropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
+ };
+
+@@ -66,7 +66,7 @@ const spidermonkeyFunctionSpec history_funcs[] = {
+
+ /* @history_funcs{"back"} */
+ static JSBool
+-history_back(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
++history_back(JSContext *ctx, uintN argc, jsval *rval)
+ {
+ struct ecmascript_interpreter *interpreter = JS_GetContextPrivate(ctx);
+ struct document_view *doc_view = interpreter->vs->doc_view;
+@@ -83,7 +83,7 @@ history_back(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval
+
+ /* @history_funcs{"forward"} */
+ static JSBool
+-history_forward(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
++history_forward(JSContext *ctx, uintN argc, jsval *rval)
+ {
+ struct ecmascript_interpreter *interpreter = JS_GetContextPrivate(ctx);
+ struct document_view *doc_view = interpreter->vs->doc_view;
+@@ -96,11 +96,12 @@ history_forward(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *r
+
+ /* @history_funcs{"go"} */
+ static JSBool
+-history_go(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
++history_go(JSContext *ctx, uintN argc, jsval *rval)
+ {
+ struct ecmascript_interpreter *interpreter = JS_GetContextPrivate(ctx);
+ struct document_view *doc_view = interpreter->vs->doc_view;
+ struct session *ses = doc_view->session;
++ jsval *argv = JS_ARGV(ctx, rval);
+ int index;
+ struct location *loc;
+
+@@ -124,8 +125,8 @@ history_go(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+ }
+
+
+-static JSBool location_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp);
+-static JSBool location_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp);
++static JSBool location_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp);
++static JSBool location_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp);
+
+ /* Each @location_class object must have a @window_class parent. */
+ const JSClass location_class = {
+@@ -150,7 +151,7 @@ const JSPropertySpec location_props[] = {
+
+ /* @location_class.getProperty */
+ static JSBool
+-location_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
++location_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp)
+ {
+ JSObject *parent_win; /* instance of @window_class */
+ struct view_state *vs;
+@@ -167,12 +168,12 @@ location_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+ vs = JS_GetInstancePrivate(ctx, parent_win,
+ (JSClass *) &window_class, NULL);
+
+- if (!JSVAL_IS_INT(id))
++ if (!JSID_IS_INT(id))
+ return JS_TRUE;
+
+ undef_to_jsval(ctx, vp);
+
+- switch (JSVAL_TO_INT(id)) {
++ switch (JSID_TO_INT(id)) {
+ case JSP_LOC_HREF:
+ astring_to_jsval(ctx, vp, get_uri_string(vs->uri, URI_ORIGINAL));
+ break;
+@@ -191,7 +192,7 @@ location_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+
+ /* @location_class.setProperty */
+ static JSBool
+-location_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
++location_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
+ {
+ JSObject *parent_win; /* instance of @window_class */
+ struct view_state *vs;
+@@ -210,10 +211,10 @@ location_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+ (JSClass *) &window_class, NULL);
+ doc_view = vs->doc_view;
+
+- if (!JSVAL_IS_INT(id))
++ if (!JSID_IS_INT(id))
+ return JS_TRUE;
+
+- switch (JSVAL_TO_INT(id)) {
++ switch (JSID_TO_INT(id)) {
+ case JSP_LOC_HREF:
+ location_goto(doc_view, jsval_to_string(ctx, vp));
+ break;
+@@ -222,7 +223,7 @@ location_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+ return JS_TRUE;
+ }
+
+-static JSBool location_toString(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
++static JSBool location_toString(JSContext *ctx, uintN argc, jsval *rval);
+
+ const spidermonkeyFunctionSpec location_funcs[] = {
+ { "toString", location_toString, 0 },
+@@ -232,9 +233,14 @@ const spidermonkeyFunctionSpec location_funcs[] = {
+
+ /* @location_funcs{"toString"}, @location_funcs{"toLocaleString"} */
+ static JSBool
+-location_toString(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
++location_toString(JSContext *ctx, uintN argc, jsval *rval)
+ {
+- return JS_GetProperty(ctx, obj, "href", rval);
++ jsval val;
++ JSObject *obj = JS_THIS_OBJECT(ctx, rval);
++ JSBool ret = JS_GetProperty(ctx, obj, "href", &val);
++
++ JS_SET_RVAL(ctx, rval, val);
++ return ret;
+ }
+
+ struct delayed_goto {
+diff --git a/src/ecmascript/spidermonkey/navigator.c b/src/ecmascript/spidermonkey/navigator.c
+index a009d62..e08a224 100644
+--- a/src/ecmascript/spidermonkey/navigator.c
++++ b/src/ecmascript/spidermonkey/navigator.c
+@@ -44,13 +44,13 @@
+ #include "viewer/text/vs.h"
+
+
+-static JSBool navigator_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp);
++static JSBool navigator_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp);
+
+ const JSClass navigator_class = {
+ "navigator",
+ JSCLASS_HAS_PRIVATE,
+ JS_PropertyStub, JS_PropertyStub,
+- navigator_get_property, JS_PropertyStub,
++ navigator_get_property, JS_StrictPropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
+ };
+
+@@ -81,14 +81,14 @@ const JSPropertySpec navigator_props[] = {
+
+ /* @navigator_class.getProperty */
+ static JSBool
+-navigator_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
++navigator_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp)
+ {
+- if (!JSVAL_IS_INT(id))
++ if (!JSID_IS_INT(id))
+ return JS_TRUE;
+
+ undef_to_jsval(ctx, vp);
+
+- switch (JSVAL_TO_INT(id)) {
++ switch (JSID_TO_INT(id)) {
+ case JSP_NAVIGATOR_APP_CODENAME:
+ string_to_jsval(ctx, vp, "Mozilla"); /* More like a constant nowadays. */
+ break;
+diff --git a/src/ecmascript/spidermonkey/unibar.c b/src/ecmascript/spidermonkey/unibar.c
+index 3c290a3..576c0a7 100644
+--- a/src/ecmascript/spidermonkey/unibar.c
++++ b/src/ecmascript/spidermonkey/unibar.c
+@@ -45,8 +45,8 @@
+ #include "viewer/text/vs.h"
+
+
+-static JSBool unibar_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp);
+-static JSBool unibar_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp);
++static JSBool unibar_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp);
++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. */
+ const JSClass menubar_class = {
+@@ -80,7 +80,7 @@ const JSPropertySpec unibar_props[] = {
+
+ /* @menubar_class.getProperty, @statusbar_class.getProperty */
+ static JSBool
+-unibar_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
++unibar_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp)
+ {
+ JSObject *parent_win; /* instance of @window_class */
+ struct view_state *vs;
+@@ -104,10 +104,10 @@ unibar_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+ status = &doc_view->session->status;
+ bar = JS_GetPrivate(ctx, obj); /* from @menubar_class or @statusbar_class */
+
+- if (!JSVAL_IS_INT(id))
++ if (!JSID_IS_INT(id))
+ return JS_TRUE;
+
+- switch (JSVAL_TO_INT(id)) {
++ switch (JSID_TO_INT(id)) {
+ case JSP_UNIBAR_VISIBLE:
+ #define unibar_fetch(bar) \
+ boolean_to_jsval(ctx, vp, status->force_show_##bar##_bar >= 0 \
+@@ -139,7 +139,7 @@ unibar_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+
+ /* @menubar_class.setProperty, @statusbar_class.setProperty */
+ static JSBool
+-unibar_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
++unibar_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
+ {
+ JSObject *parent_win; /* instance of @window_class */
+ struct view_state *vs;
+@@ -163,10 +163,10 @@ unibar_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+ status = &doc_view->session->status;
+ bar = JS_GetPrivate(ctx, obj); /* from @menubar_class or @statusbar_class */
+
+- if (!JSVAL_IS_INT(id))
++ if (!JSID_IS_INT(id))
+ return JS_TRUE;
+
+- switch (JSVAL_TO_INT(id)) {
++ switch (JSID_TO_INT(id)) {
+ case JSP_UNIBAR_VISIBLE:
+ switch (*bar) {
+ case 's':
+diff --git a/src/ecmascript/spidermonkey/window.c b/src/ecmascript/spidermonkey/window.c
+index 5e93a6f..9bc8dd9 100644
+--- a/src/ecmascript/spidermonkey/window.c
++++ b/src/ecmascript/spidermonkey/window.c
+@@ -44,12 +44,12 @@
+ #include "viewer/text/vs.h"
+
+
+-static JSBool window_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp);
+-static JSBool window_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp);
++static JSBool window_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp);
++static JSBool window_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp);
+
+ const JSClass window_class = {
+ "window",
+- JSCLASS_HAS_PRIVATE, /* struct view_state * */
++ JSCLASS_HAS_PRIVATE | JSCLASS_GLOBAL_FLAGS, /* struct view_state * */
+ JS_PropertyStub, JS_PropertyStub,
+ window_get_property, window_set_property,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
+@@ -122,7 +122,7 @@ find_child_frame(struct document_view *doc_view, struct frame_desc *tframe)
+
+ /* @window_class.getProperty */
+ static JSBool
+-window_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
++window_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp)
+ {
+ struct view_state *vs;
+
+@@ -138,11 +138,11 @@ window_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+ * location is then evaluated in string context, toString()
+ * is called which we overrode for that class below, so
+ * everything's fine. */
+- if (JSVAL_IS_STRING(id)) {
++ if (JSID_IS_STRING(id)) {
+ struct document_view *doc_view = vs->doc_view;
+ JSObject *obj;
+
+- obj = try_resolve_frame(doc_view, jsval_to_string(ctx, &id));
++ obj = try_resolve_frame(doc_view, jsid_to_string(ctx, &id));
+ /* TODO: Try other lookups (mainly element lookup) until
+ * something yields data. */
+ if (obj) {
+@@ -151,12 +151,12 @@ window_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+ return JS_TRUE;
+ }
+
+- if (!JSVAL_IS_INT(id))
++ if (!JSID_IS_INT(id))
+ return JS_TRUE;
+
+ undef_to_jsval(ctx, vp);
+
+- switch (JSVAL_TO_INT(id)) {
++ switch (JSID_TO_INT(id)) {
+ case JSP_WIN_CLOSED:
+ /* TODO: It will be a major PITA to implement this properly.
+ * Well, perhaps not so much if we introduce reference tracking
+@@ -254,7 +254,7 @@ void location_goto(struct document_view *doc_view, unsigned char *url);
+
+ /* @window_class.setProperty */
+ static JSBool
+-window_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
++window_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
+ {
+ struct view_state *vs;
+
+@@ -266,8 +266,8 @@ window_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+
+ vs = JS_GetInstancePrivate(ctx, obj, (JSClass *) &window_class, NULL);
+
+- if (JSVAL_IS_STRING(id)) {
+- if (!strcmp(jsval_to_string(ctx, &id), "location")) {
++ 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));
+@@ -278,10 +278,10 @@ window_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+ return JS_TRUE;
+ }
+
+- if (!JSVAL_IS_INT(id))
++ if (!JSID_IS_INT(id))
+ return JS_TRUE;
+
+- switch (JSVAL_TO_INT(id)) {
++ 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);
+@@ -298,9 +298,9 @@ window_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+ }
+
+
+-static JSBool window_alert(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+-static JSBool window_open(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+-static JSBool window_setTimeout(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
++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[] = {
+ { "alert", window_alert, 1 },
+@@ -311,8 +311,11 @@ const spidermonkeyFunctionSpec window_funcs[] = {
+
+ /* @window_funcs{"alert"} */
+ static JSBool
+-window_alert(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
++window_alert(JSContext *ctx, uintN argc, jsval *rval)
+ {
++ jsval val;
++ JSObject *obj = JS_THIS_OBJECT(ctx, rval);
++ jsval *argv = JS_ARGV(ctx, rval);
+ struct view_state *vs;
+ unsigned char *string;
+
+@@ -330,14 +333,18 @@ window_alert(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval
+ info_box(vs->doc_view->session->tab->term, MSGBOX_FREE_TEXT,
+ N_("JavaScript Alert"), ALIGN_CENTER, stracpy(string));
+
+- undef_to_jsval(ctx, rval);
++ undef_to_jsval(ctx, &val);
++ JS_SET_RVAL(ctx, rval, val);
+ return JS_TRUE;
+ }
+
+ /* @window_funcs{"open"} */
+ static JSBool
+-window_open(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
++window_open(JSContext *ctx, uintN argc, jsval *rval)
+ {
++ jsval val;
++ JSObject *obj = JS_THIS_OBJECT(ctx, rval);
++ jsval *argv = JS_ARGV(ctx, rval);
+ struct view_state *vs;
+ struct document_view *doc_view;
+ struct session *ses;
+@@ -407,7 +414,7 @@ window_open(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+ deo->uri = get_uri_reference(uri);
+ deo->target = stracpy(frame);
+ register_bottom_half(delayed_goto_uri_frame, deo);
+- boolean_to_jsval(ctx, rval, 1);
++ boolean_to_jsval(ctx, &val, 1);
+ goto end;
+ }
+ }
+@@ -418,7 +425,7 @@ window_open(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+ && can_open_in_new(ses->tab->term)) {
+ open_uri_in_new_window(ses, uri, NULL, ENV_ANY,
+ CACHE_MODE_NORMAL, TASK_NONE);
+- boolean_to_jsval(ctx, rval, 1);
++ boolean_to_jsval(ctx, &val, 1);
+ } else {
+ /* When opening a new tab, we might get rerendered, losing our
+ * context and triggerring a disaster, so postpone that. */
+@@ -428,9 +435,9 @@ window_open(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+ deo->ses = ses;
+ deo->uri = get_uri_reference(uri);
+ register_bottom_half(delayed_open, deo);
+- boolean_to_jsval(ctx, rval, 1);
++ boolean_to_jsval(ctx, &val, 1);
+ } else {
+- undef_to_jsval(ctx, rval);
++ undef_to_jsval(ctx, &val);
+ }
+ }
+
+@@ -438,13 +445,15 @@ end:
+ done_uri(uri);
+ mem_free_if(frame);
+
++ JS_SET_RVAL(ctx, rval, val);
+ return JS_TRUE;
+ }
+
+ /* @window_funcs{"setTimeout"} */
+ static JSBool
+-window_setTimeout(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
++window_setTimeout(JSContext *ctx, uintN argc, jsval *rval)
+ {
++ jsval *argv = JS_ARGV(ctx, rval);
+ struct ecmascript_interpreter *interpreter = JS_GetContextPrivate(ctx);
+ unsigned char *code;
+ int timeout;
+diff --git a/src/scripting/smjs/action_object.c b/src/scripting/smjs/action_object.c
+index d95564d..d0379e0 100644
+--- a/src/scripting/smjs/action_object.c
++++ b/src/scripting/smjs/action_object.c
+@@ -40,25 +40,31 @@ smjs_action_fn_finalize(JSContext *ctx, JSObject *obj)
+
+ /* @action_fn_class.call */
+ static JSBool
+-smjs_action_fn_callback(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv,
+- jsval *rval)
++smjs_action_fn_callback(JSContext *ctx, uintN argc, jsval *rval)
+ {
++ jsval value;
++ jsval *argv = JS_ARGV(ctx, rval);
+ struct smjs_action_fn_callback_hop *hop;
+ JSObject *fn_obj;
+
+ assert(smjs_ctx);
+ if_assert_failed return JS_FALSE;
+
+- *rval = JS_FALSE;
++ value = JS_FALSE;
+
+- if (JS_TRUE != JS_ValueToObject(ctx, argv[-2], &fn_obj))
++ if (JS_TRUE != JS_ValueToObject(ctx, argv[-2], &fn_obj)) {
++ JS_SET_RVAL(ctx, rval, value);
+ return JS_TRUE;
++ }
+ assert(JS_InstanceOf(ctx, fn_obj, (JSClass *) &action_fn_class, NULL));
+ if_assert_failed return JS_FALSE;
+
+ hop = JS_GetInstancePrivate(ctx, fn_obj,
+ (JSClass *) &action_fn_class, NULL);
+- if (!hop) return JS_TRUE;
++ if (!hop) {
++ JS_SET_RVAL(ctx, rval, value);
++ return JS_TRUE;
++ }
+
+ if (argc >= 1) {
+ int32 val;
+@@ -70,7 +76,8 @@ smjs_action_fn_callback(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv,
+
+ do_action(hop->ses, hop->action_id, 1);
+
+- *rval = JS_TRUE;
++ value = JS_TRUE;
++ JS_SET_RVAL(ctx, rval, value);
+
+ return JS_TRUE;
+ }
+@@ -79,7 +86,7 @@ static const JSClass action_fn_class = {
+ "action_fn",
+ JSCLASS_HAS_PRIVATE, /* struct smjs_action_fn_callback_hop * */
+ JS_PropertyStub, JS_PropertyStub,
+- JS_PropertyStub, JS_PropertyStub,
++ JS_PropertyStub, JS_StrictPropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub,
+ smjs_action_fn_finalize,
+ NULL, NULL,
+@@ -124,14 +131,16 @@ smjs_get_action_fn_object(unsigned char *action_str)
+
+ /* @action_class.getProperty */
+ static JSBool
+-action_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
++action_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp)
+ {
++ jsval val;
+ JSObject *action_fn;
+ unsigned char *action_str;
+
+ *vp = JSVAL_NULL;
+
+- action_str = JS_GetStringBytes(JS_ValueToString(ctx, id));
++ JS_IdToValue(ctx, id, &val);
++ action_str = JS_EncodeString(ctx, JS_ValueToString(ctx, val));
+ if (!action_str) return JS_TRUE;
+
+ action_fn = smjs_get_action_fn_object(action_str);
+@@ -146,7 +155,7 @@ static const JSClass action_class = {
+ "action",
+ 0,
+ JS_PropertyStub, JS_PropertyStub,
+- action_get_property, JS_PropertyStub,
++ action_get_property, JS_StrictPropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
+ };
+
+diff --git a/src/scripting/smjs/bookmarks.c b/src/scripting/smjs/bookmarks.c
+index f12f84b..6c8b7fa 100644
+--- a/src/scripting/smjs/bookmarks.c
++++ b/src/scripting/smjs/bookmarks.c
+@@ -113,29 +113,29 @@ jsval_to_bookmark_string(JSContext *ctx, jsval val, unsigned char **result)
+ unsigned char *str;
+
+ /* jsstring_to_utf8() might GC; protect the string to come. */
+- if (!JS_AddNamedRoot(ctx, &jsstr, "jsval_to_bookmark_string"))
++ if (!JS_AddNamedStringRoot(ctx, &jsstr, "jsval_to_bookmark_string"))
+ return JS_FALSE;
+
+ jsstr = JS_ValueToString(ctx, val);
+ if (jsstr == NULL) {
+- JS_RemoveRoot(ctx, &jsstr);
++ JS_RemoveStringRoot(ctx, &jsstr);
+ return JS_FALSE;
+ }
+
+ str = jsstring_to_utf8(ctx, jsstr, NULL);
+ if (str == NULL) {
+- JS_RemoveRoot(ctx, &jsstr);
++ JS_RemoveStringRoot(ctx, &jsstr);
+ return JS_FALSE;
+ }
+
+- JS_RemoveRoot(ctx, &jsstr);
++ JS_RemoveStringRoot(ctx, &jsstr);
+ mem_free_set(result, str);
+ return JS_TRUE;
+ }
+
+ /* @bookmark_class.getProperty */
+ static JSBool
+-bookmark_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
++bookmark_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp)
+ {
+ struct bookmark *bookmark;
+
+@@ -152,10 +152,10 @@ bookmark_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+
+ undef_to_jsval(ctx, vp);
+
+- if (!JSVAL_IS_INT(id))
++ if (!JSID_IS_INT(id))
+ return JS_FALSE;
+
+- switch (JSVAL_TO_INT(id)) {
++ switch (JSID_TO_INT(id)) {
+ case BOOKMARK_TITLE:
+ return bookmark_string_to_jsval(ctx, bookmark->title, vp);
+ case BOOKMARK_URL:
+@@ -177,7 +177,7 @@ bookmark_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+
+ /* @bookmark_class.setProperty */
+ static JSBool
+-bookmark_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
++bookmark_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
+ {
+ struct bookmark *bookmark;
+ unsigned char *title = NULL;
+@@ -195,10 +195,10 @@ bookmark_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+
+ if (!bookmark) return JS_FALSE;
+
+- if (!JSVAL_IS_INT(id))
++ if (!JSID_IS_INT(id))
+ return JS_FALSE;
+
+- switch (JSVAL_TO_INT(id)) {
++ switch (JSID_TO_INT(id)) {
+ case BOOKMARK_TITLE:
+ if (!jsval_to_bookmark_string(ctx, *vp, &title))
+ return JS_FALSE;
+@@ -250,7 +250,7 @@ smjs_get_bookmark_object(struct bookmark *bookmark)
+
+ /* @bookmark_folder_class.getProperty */
+ static JSBool
+-bookmark_folder_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
++bookmark_folder_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp)
+ {
+ struct bookmark *bookmark;
+ struct bookmark *folder;
+@@ -283,7 +283,7 @@ static const JSClass bookmark_folder_class = {
+ "bookmark_folder",
+ JSCLASS_HAS_PRIVATE, /* struct bookmark * */
+ JS_PropertyStub, JS_PropertyStub,
+- bookmark_folder_get_property, JS_PropertyStub,
++ bookmark_folder_get_property, JS_StrictPropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, bookmark_finalize,
+ };
+
+diff --git a/src/scripting/smjs/cache_object.c b/src/scripting/smjs/cache_object.c
+index cd23842..0bdb563 100644
+--- a/src/scripting/smjs/cache_object.c
++++ b/src/scripting/smjs/cache_object.c
+@@ -40,7 +40,7 @@ static const JSPropertySpec cache_entry_props[] = {
+
+ /* @cache_entry_class.getProperty */
+ static JSBool
+-cache_entry_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
++cache_entry_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp)
+ {
+ struct cache_entry *cached;
+ JSBool ret;
+@@ -66,9 +66,9 @@ cache_entry_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+
+ undef_to_jsval(ctx, vp);
+
+- if (!JSVAL_IS_INT(id))
++ if (!JSID_IS_INT(id))
+ ret = JS_FALSE;
+- else switch (JSVAL_TO_INT(id)) {
++ else switch (JSID_TO_INT(id)) {
+ case CACHE_ENTRY_CONTENT: {
+ struct fragment *fragment = get_cache_fragment(cached);
+
+@@ -121,7 +121,7 @@ cache_entry_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+
+ /* @cache_entry_class.setProperty */
+ static JSBool
+-cache_entry_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
++cache_entry_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
+ {
+ struct cache_entry *cached;
+ JSBool ret;
+@@ -145,12 +145,12 @@ cache_entry_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+ * eventually unlock the object. */
+ object_lock(cached);
+
+- if (!JSVAL_IS_INT(id))
++ if (!JSID_IS_INT(id))
+ ret = JS_FALSE;
+- else switch (JSVAL_TO_INT(id)) {
++ else switch (JSID_TO_INT(id)) {
+ case CACHE_ENTRY_CONTENT: {
+ JSString *jsstr = JS_ValueToString(smjs_ctx, *vp);
+- unsigned char *str = JS_GetStringBytes(jsstr);
++ unsigned char *str = JS_EncodeString(smjs_ctx, jsstr);
+ size_t len = JS_GetStringLength(jsstr);
+
+ add_fragment(cached, 0, str, len);
+@@ -161,7 +161,7 @@ cache_entry_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+ }
+ case CACHE_ENTRY_TYPE: {
+ JSString *jsstr = JS_ValueToString(smjs_ctx, *vp);
+- unsigned char *str = JS_GetStringBytes(jsstr);
++ unsigned char *str = JS_EncodeString(smjs_ctx, jsstr);
+
+ mem_free_set(&cached->content_type, stracpy(str));
+
+@@ -170,7 +170,7 @@ cache_entry_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+ }
+ case CACHE_ENTRY_HEAD: {
+ JSString *jsstr = JS_ValueToString(smjs_ctx, *vp);
+- unsigned char *str = JS_GetStringBytes(jsstr);
++ unsigned char *str = JS_EncodeString(smjs_ctx, jsstr);
+
+ mem_free_set(&cached->head, stracpy(str));
+
+diff --git a/src/scripting/smjs/core.c b/src/scripting/smjs/core.c
+index 2493904..ced28b0 100644
+--- a/src/scripting/smjs/core.c
++++ b/src/scripting/smjs/core.c
+@@ -94,11 +94,11 @@ smjs_do_file(unsigned char *path)
+ }
+
+ static JSBool
+-smjs_do_file_wrapper(JSContext *ctx, JSObject *obj, uintN argc,
+- jsval *argv, jsval *rval)
++smjs_do_file_wrapper(JSContext *ctx, uintN argc, jsval *rval)
+ {
++ jsval *argv = JS_ARGV(ctx, rval);
+ JSString *jsstr = JS_ValueToString(smjs_ctx, *argv);
+- unsigned char *path = JS_GetStringBytes(jsstr);
++ unsigned char *path = JS_EncodeString(smjs_ctx, jsstr);
+
+ if (smjs_do_file(path))
+ return JS_TRUE;
+@@ -136,6 +136,9 @@ init_smjs(struct module *module)
+ return;
+ }
+
++ JS_SetOptions(smjs_ctx, JSOPTION_VAROBJFIX | JSOPTION_JIT | JSOPTION_METHODJIT);
++ JS_SetVersion(smjs_ctx, JSVERSION_LATEST);
++
+ JS_SetErrorReporter(smjs_ctx, error_reporter);
+
+ smjs_init_global_object();
+@@ -308,7 +311,7 @@ jsstring_to_utf8(JSContext *ctx, JSString *jsstr, int *length)
+ struct string utf8;
+
+ utf16_len = JS_GetStringLength(jsstr);
+- utf16 = JS_GetStringChars(jsstr); /* stays owned by jsstr */
++ utf16 = JS_GetStringCharsZ(ctx, jsstr); /* stays owned by jsstr */
+ if (utf16 == NULL) {
+ /* JS_GetStringChars doesn't have a JSContext *
+ * parameter so it can't report the error
+diff --git a/src/scripting/smjs/elinks_object.c b/src/scripting/smjs/elinks_object.c
+index 5a9b394..3c51ec9 100644
+--- a/src/scripting/smjs/elinks_object.c
++++ b/src/scripting/smjs/elinks_object.c
+@@ -27,7 +27,7 @@
+
+
+ static JSBool
+-elinks_get_home(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
++elinks_get_home(JSContext *ctx, JSObject *obj, jsid id, jsval *vp)
+ {
+ *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(smjs_ctx, elinks_home));
+
+@@ -35,7 +35,7 @@ elinks_get_home(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+ }
+
+ static JSBool
+-elinks_get_location(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
++elinks_get_location(JSContext *ctx, JSObject *obj, jsid id, jsval *vp)
+ {
+ struct uri *uri;
+
+@@ -51,7 +51,7 @@ elinks_get_location(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+ }
+
+ static JSBool
+-elinks_set_location(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
++elinks_set_location(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
+ {
+ JSString *jsstr;
+ unsigned char *url;
+@@ -61,7 +61,7 @@ elinks_set_location(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+ jsstr = JS_ValueToString(smjs_ctx, *vp);
+ if (!jsstr) return JS_FALSE;
+
+- url = JS_GetStringBytes(jsstr);
++ url = JS_EncodeString(smjs_ctx, jsstr);
+ if (!url) return JS_FALSE;
+
+ goto_url(smjs_ses, url);
+@@ -71,8 +71,10 @@ elinks_set_location(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+
+ /* @elinks_funcs{"alert"} */
+ static JSBool
+-elinks_alert(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
++elinks_alert(JSContext *ctx, uintN argc, jsval *rval)
+ {
++ jsval val;
++ jsval *argv = JS_ARGV(ctx, rval);
+ unsigned char *string;
+
+ if (argc != 1)
+@@ -85,15 +87,18 @@ elinks_alert(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval
+ info_box(smjs_ses->tab->term, MSGBOX_NO_TEXT_INTL,
+ N_("User script alert"), ALIGN_LEFT, string);
+
+- undef_to_jsval(ctx, rval);
++ undef_to_jsval(ctx, &val);
++ JS_SET_RVAL(ctx, rval, val);
+
+ return JS_TRUE;
+ }
+
+ /* @elinks_funcs{"execute"} */
+ static JSBool
+-elinks_execute(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
++elinks_execute(JSContext *ctx, uintN argc, jsval *rval)
+ {
++ jsval val;
++ jsval *argv = JS_ARGV(ctx, rval);
+ unsigned char *string;
+
+ if (argc != 1)
+@@ -104,8 +109,9 @@ elinks_execute(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rv
+ return JS_TRUE;
+
+ exec_on_terminal(smjs_ses->tab->term, string, "", TERM_EXEC_BG);
+- undef_to_jsval(ctx, rval);
+
++ undef_to_jsval(ctx, &val);
++ JS_SET_RVAL(ctx, rval, val);
+ return JS_TRUE;
+ }
+
+@@ -113,7 +119,7 @@ static const JSClass elinks_class = {
+ "elinks",
+ 0,
+ JS_PropertyStub, JS_PropertyStub,
+- JS_PropertyStub, JS_PropertyStub,
++ JS_PropertyStub, JS_StrictPropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
+ };
+
+@@ -142,7 +148,7 @@ smjs_get_elinks_object(void)
+ return NULL;
+
+ if (!JS_DefineProperty(smjs_ctx, jsobj, "home", JSVAL_NULL,
+- elinks_get_home, JS_PropertyStub,
++ elinks_get_home, JS_StrictPropertyStub,
+ JSPROP_ENUMERATE
+ | JSPROP_PERMANENT
+ | JSPROP_READONLY))
+diff --git a/src/scripting/smjs/global_object.c b/src/scripting/smjs/global_object.c
+index 3a59782..0976f8a 100644
+--- a/src/scripting/smjs/global_object.c
++++ b/src/scripting/smjs/global_object.c
+@@ -16,9 +16,9 @@ JSObject *smjs_global_object;
+
+
+ static const JSClass global_class = {
+- "global", 0,
+- JS_PropertyStub, JS_PropertyStub,
++ "global", JSCLASS_GLOBAL_FLAGS,
+ JS_PropertyStub, JS_PropertyStub,
++ JS_PropertyStub, JS_StrictPropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
+ };
+
+@@ -29,7 +29,7 @@ smjs_get_global_object(void)
+
+ assert(smjs_ctx);
+
+- jsobj = JS_NewObject(smjs_ctx, (JSClass *) &global_class, NULL, NULL);
++ jsobj = JS_NewCompartmentAndGlobalObject(smjs_ctx, (JSClass *) &global_class, NULL);
+
+ if (!jsobj) return NULL;
+
+diff --git a/src/scripting/smjs/globhist.c b/src/scripting/smjs/globhist.c
+index 0ab6938..376c44e 100644
+--- a/src/scripting/smjs/globhist.c
++++ b/src/scripting/smjs/globhist.c
+@@ -51,7 +51,7 @@ static const JSPropertySpec smjs_globhist_item_props[] = {
+
+ /* @smjs_globhist_item_class.getProperty */
+ static JSBool
+-smjs_globhist_item_get_property(JSContext *ctx, JSObject *obj, jsval id,
++smjs_globhist_item_get_property(JSContext *ctx, JSObject *obj, jsid id,
+ jsval *vp)
+ {
+ struct global_history_item *history_item;
+@@ -70,10 +70,10 @@ smjs_globhist_item_get_property(JSContext *ctx, JSObject *obj, jsval id,
+
+ undef_to_jsval(ctx, vp);
+
+- if (!JSVAL_IS_INT(id))
++ if (!JSID_IS_INT(id))
+ return JS_FALSE;
+
+- switch (JSVAL_TO_INT(id)) {
++ switch (JSID_TO_INT(id)) {
+ case GLOBHIST_TITLE:
+ *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(smjs_ctx,
+ history_item->title));
+@@ -117,7 +117,7 @@ smjs_globhist_item_get_property(JSContext *ctx, JSObject *obj, jsval id,
+
+ /* @smjs_globhist_item_class.setProperty */
+ static JSBool
+-smjs_globhist_item_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
++smjs_globhist_item_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
+ {
+ struct global_history_item *history_item;
+
+@@ -133,13 +133,13 @@ smjs_globhist_item_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *
+
+ if (!history_item) return JS_FALSE;
+
+- if (!JSVAL_IS_INT(id))
++ if (!JSID_IS_INT(id))
+ return JS_FALSE;
+
+- switch (JSVAL_TO_INT(id)) {
++ switch (JSID_TO_INT(id)) {
+ case GLOBHIST_TITLE: {
+ JSString *jsstr = JS_ValueToString(smjs_ctx, *vp);
+- unsigned char *str = JS_GetStringBytes(jsstr);
++ unsigned char *str = JS_EncodeString(smjs_ctx, jsstr);
+
+ mem_free_set(&history_item->title, stracpy(str));
+
+@@ -147,7 +147,7 @@ smjs_globhist_item_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *
+ }
+ case GLOBHIST_URL: {
+ JSString *jsstr = JS_ValueToString(smjs_ctx, *vp);
+- unsigned char *str = JS_GetStringBytes(jsstr);
++ unsigned char *str = JS_EncodeString(smjs_ctx, jsstr);
+
+ mem_free_set(&history_item->url, stracpy(str));
+
+@@ -201,13 +201,13 @@ smjs_get_globhist_item_object(struct global_history_item *history_item)
+
+ /* @smjs_globhist_class.getProperty */
+ static JSBool
+-smjs_globhist_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
++smjs_globhist_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp)
+ {
+ JSObject *jsobj;
+ unsigned char *uri_string;
+ struct global_history_item *history_item;
+
+- uri_string = JS_GetStringBytes(JS_ValueToString(ctx, id));
++ uri_string = JS_EncodeString(ctx, JS_ValueToString(ctx, id));
+ if (!uri_string) goto ret_null;
+
+ history_item = get_global_history_item(uri_string);
+@@ -229,7 +229,7 @@ ret_null:
+ static const JSClass smjs_globhist_class = {
+ "global_history", 0,
+ JS_PropertyStub, JS_PropertyStub,
+- smjs_globhist_get_property, JS_PropertyStub,
++ smjs_globhist_get_property, JS_StrictPropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
+ };
+
+diff --git a/src/scripting/smjs/hooks.c b/src/scripting/smjs/hooks.c
+index 291039c..d69daf6 100644
+--- a/src/scripting/smjs/hooks.c
++++ b/src/scripting/smjs/hooks.c
+@@ -41,7 +41,7 @@ script_hook_url(va_list ap, void *data)
+ ret = EVENT_HOOK_STATUS_LAST;
+ } else {
+ JSString *jsstr = JS_ValueToString(smjs_ctx, rval);
+- unsigned char *str = JS_GetStringBytes(jsstr);
++ unsigned char *str = JS_EncodeString(smjs_ctx, jsstr);
+
+ mem_free_set(url, stracpy(str));
+ }
+@@ -58,7 +58,7 @@ script_hook_pre_format_html(va_list ap, void *data)
+ struct session *ses = va_arg(ap, struct session *);
+ struct cache_entry *cached = va_arg(ap, struct cache_entry *);
+ enum evhook_status ret = EVENT_HOOK_STATUS_NEXT;
+- JSObject *cache_entry_object, *view_state_object = JSVAL_NULL;
++ JSObject *cache_entry_object, *view_state_object = NULL;
+ jsval args[2], rval;
+
+ evhook_use_params(ses && cached);
+diff --git a/src/scripting/smjs/keybinding.c b/src/scripting/smjs/keybinding.c
+index 2b35477..b452298 100644
+--- a/src/scripting/smjs/keybinding.c
++++ b/src/scripting/smjs/keybinding.c
+@@ -17,7 +17,7 @@ static const JSClass keymap_class; /* defined below */
+
+ /* @keymap_class.getProperty */
+ static JSBool
+-keymap_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
++keymap_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp)
+ {
+ unsigned char *action_str;
+ const unsigned char *keystroke_str;
+@@ -32,7 +32,7 @@ keymap_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+ data = JS_GetInstancePrivate(ctx, obj,
+ (JSClass *) &keymap_class, NULL);
+
+- keystroke_str = JS_GetStringBytes(JS_ValueToString(ctx, id));
++ keystroke_str = JS_EncodeString(ctx, JS_ValueToString(ctx, id));
+ if (!keystroke_str) goto ret_null;
+
+ action_str = get_action_name_from_keystroke((enum keymap_id) *data,
+@@ -70,7 +70,7 @@ smjs_keybinding_action_callback(va_list ap, void *data)
+
+ /* @keymap_class.setProperty */
+ static JSBool
+-keymap_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
++keymap_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
+ {
+ int *data;
+ unsigned char *keymap_str;
+@@ -90,13 +90,13 @@ keymap_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+ keymap_str = get_keymap_name((enum keymap_id) *data);
+ if (!keymap_str) return JS_FALSE;
+
+- keystroke_str = JS_GetStringBytes(JS_ValueToString(ctx, id));
++ keystroke_str = JS_EncodeString(ctx, JS_ValueToString(ctx, id));
+ if (!keystroke_str) return JS_FALSE;
+
+ if (JSVAL_IS_STRING(*vp)) {
+ unsigned char *action_str;
+
+- action_str = JS_GetStringBytes(JS_ValueToString(ctx, *vp));
++ action_str = JS_EncodeString(ctx, JS_ValueToString(ctx, *vp));
+ if (!action_str) return JS_FALSE;
+
+ if (bind_do(keymap_str, keystroke_str, action_str, 0))
+@@ -203,7 +203,7 @@ static const JSClass keymaps_hash_class = {
+ "keymaps_hash",
+ JSCLASS_HAS_PRIVATE,
+ JS_PropertyStub, JS_PropertyStub,
+- JS_PropertyStub, JS_PropertyStub,
++ JS_PropertyStub, JS_StrictPropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
+ };
+
+diff --git a/src/scripting/smjs/load_uri.c b/src/scripting/smjs/load_uri.c
+index 4f2dcf2..7e3881c 100644
+--- a/src/scripting/smjs/load_uri.c
++++ b/src/scripting/smjs/load_uri.c
+@@ -56,7 +56,7 @@ smjs_loading_callback(struct download *download, void *data)
+ end:
+ if (download->cached)
+ object_unlock(download->cached);
+- JS_RemoveRoot(smjs_ctx, &hop->callback);
++ JS_RemoveValueRoot(smjs_ctx, &hop->callback);
+ mem_free(download->data);
+ mem_free(download);
+
+@@ -64,9 +64,9 @@ end:
+ }
+
+ static JSBool
+-smjs_load_uri(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv,
+- jsval *rval)
++smjs_load_uri(JSContext *ctx, uintN argc, jsval *rval)
+ {
++ jsval *argv = JS_ARGV(ctx, rval);
+ struct smjs_load_uri_hop *hop;
+ struct download *download;
+ JSString *jsstr;
+@@ -76,7 +76,7 @@ smjs_load_uri(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv,
+ if (argc < 2) return JS_FALSE;
+
+ jsstr = JS_ValueToString(smjs_ctx, argv[0]);
+- uri_string = JS_GetStringBytes(jsstr);
++ uri_string = JS_EncodeString(smjs_ctx, jsstr);
+
+ uri = get_uri(uri_string, 0);
+ if (!uri) return JS_FALSE;
+@@ -96,7 +96,7 @@ smjs_load_uri(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv,
+
+ hop->callback = argv[1];
+ hop->ses = smjs_ses;
+- if (!JS_AddNamedRoot(smjs_ctx, &hop->callback,
++ if (!JS_AddNamedValueRoot(smjs_ctx, &hop->callback,
+ "smjs_load_uri_hop.callback")) {
+ mem_free(hop);
+ mem_free(download);
+diff --git a/src/scripting/smjs/view_state_object.c b/src/scripting/smjs/view_state_object.c
+index 64f43ca..636b37b 100644
+--- a/src/scripting/smjs/view_state_object.c
++++ b/src/scripting/smjs/view_state_object.c
+@@ -39,7 +39,7 @@ static const JSPropertySpec view_state_props[] = {
+
+ /* @view_state_class.getProperty */
+ static JSBool
+-view_state_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
++view_state_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp)
+ {
+ struct view_state *vs;
+
+@@ -54,10 +54,10 @@ view_state_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+
+ undef_to_jsval(ctx, vp);
+
+- if (!JSVAL_IS_INT(id))
++ if (!JSID_IS_INT(id))
+ return JS_FALSE;
+
+- switch (JSVAL_TO_INT(id)) {
++ switch (JSID_TO_INT(id)) {
+ case VIEW_STATE_PLAIN:
+ *vp = INT_TO_JSVAL(vs->plain);
+
+@@ -80,7 +80,7 @@ view_state_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+
+ /* @view_state_class.setProperty */
+ static JSBool
+-view_state_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
++view_state_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
+ {
+ struct view_state *vs;
+
+@@ -93,10 +93,10 @@ view_state_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
+ vs = JS_GetInstancePrivate(ctx, obj,
+ (JSClass *) &view_state_class, NULL);
+
+- if (!JSVAL_IS_INT(id))
++ if (!JSID_IS_INT(id))
+ return JS_FALSE;
+
+- switch (JSVAL_TO_INT(id)) {
++ switch (JSID_TO_INT(id)) {
+ case VIEW_STATE_PLAIN: {
+ vs->plain = atol(jsval_to_string(ctx, vp));
+
+@@ -143,7 +143,7 @@ smjs_get_view_state_object(struct view_state *vs)
+ }
+
+ static JSBool
+-smjs_elinks_get_view_state(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
++smjs_elinks_get_view_state(JSContext *ctx, JSObject *obj, jsid id, jsval *vp)
+ {
+ JSObject *vs_obj;
+ struct view_state *vs;
+@@ -170,6 +170,6 @@ smjs_init_view_state_interface(void)
+ return;
+
+ JS_DefineProperty(smjs_ctx, smjs_elinks_object, "vs", JSVAL_NULL,
+- smjs_elinks_get_view_state, JS_PropertyStub,
++ smjs_elinks_get_view_state, JS_StrictPropertyStub,
+ JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY);
+ }
+--
+1.7.4.2
+
diff --git a/elinks.spec b/elinks.spec
index f8780b1..d64eb99 100644
--- a/elinks.spec
+++ b/elinks.spec
@@ -1,7 +1,7 @@
Name: elinks
Summary: A text-mode Web browser
Version: 0.12
-Release: 0.24.pre5%{?dist}
+Release: 0.25.pre5%{?dist}
License: GPLv2
URL: http://elinks.or.cz
Group: Applications/Internet
@@ -39,6 +39,7 @@ Patch7: elinks-0.11.3-macropen.patch
Patch8: elinks-scroll.patch
Patch9: elinks-nss.patch
Patch10: elinks-nss-inc.patch
+Patch11: elinks-0.12pre5-js185.patch
%description
Elinks is a text-based Web browser. Elinks does not display any images,
@@ -79,6 +80,9 @@ quickly and swiftly displays Web pages.
# Port elinks to use NSS library for cryptography (#346861) - incremental patch
%patch10 -p1
+# backported upstream commits f31cf6f and 2844f8b
+%patch11 -p1
+
# remove bogus serial numbers
sed -i 's/^# *serial [AM0-9]*$//' acinclude.m4 config/m4/*.m4
@@ -151,6 +155,9 @@ rm -rf $RPM_BUILD_ROOT
%{_mandir}/man5/*
%changelog
+* Thu Apr 21 2011 Kamil Dudka <kdudka at redhat.com> - 0.12-0.25.pre5
+- port to js-1.8.5 API (upstream commits f31cf6f and 2844f8b)
+
* Tue Feb 08 2011 Fedora Release Engineering <rel-eng at lists.fedoraproject.org> - 0.12-0.24.pre5
- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild
More information about the scm-commits
mailing list