From d8592e4f99a5c088ec1ea459b41253f9832ac5bf Mon Sep 17 00:00:00 2001
From: witekfl <witekfl@pldmachine.(none)>
Date: Tue, 10 Jan 2006 19:17:29 +0100
Subject: [PATCH] Alternative experimental ECMAScript engine.

---
 Makefile.config.in             |   1 +
 configure.in                   |  51 +-
 src/ecmascript/Makefile        |   7 +-
 src/ecmascript/ecmascript.c    |  92 +---
 src/ecmascript/ecmascript.h    |   8 +
 src/ecmascript/see.c           | 243 +++++++++
 src/ecmascript/see.h           |  17 +
 src/ecmascript/see.o           | Bin 0 -> 85976 bytes
 src/ecmascript/see/Makefile    |   6 +
 src/ecmascript/see/document.c  | 257 +++++++++
 src/ecmascript/see/document.h  |  14 +
 src/ecmascript/see/form.c      | 964 +++++++++++++++++++++++++++++++++
 src/ecmascript/see/form.h      |  19 +
 src/ecmascript/see/input.c     | 100 ++++
 src/ecmascript/see/input.h     |  11 +
 src/ecmascript/see/location.c  | 363 +++++++++++++
 src/ecmascript/see/location.h  |   9 +
 src/ecmascript/see/navigator.c | 150 +++++
 src/ecmascript/see/navigator.h |   8 +
 src/ecmascript/see/strings.c   | 379 +++++++++++++
 src/ecmascript/see/strings.h   | 101 ++++
 src/ecmascript/see/unibar.c    | 206 +++++++
 src/ecmascript/see/unibar.h    |   9 +
 src/ecmascript/see/window.c    | 371 +++++++++++++
 src/ecmascript/see/window.h    |  27 +
 src/ecmascript/spidermonkey.c  |  79 ++-
 test/ecmascript/infinite2.html |   5 +
 27 files changed, 3408 insertions(+), 89 deletions(-)
 create mode 100644 src/ecmascript/see.c
 create mode 100644 src/ecmascript/see.h
 create mode 100644 src/ecmascript/see.o
 create mode 100644 src/ecmascript/see/Makefile
 create mode 100644 src/ecmascript/see/document.c
 create mode 100644 src/ecmascript/see/document.h
 create mode 100644 src/ecmascript/see/form.c
 create mode 100644 src/ecmascript/see/form.h
 create mode 100644 src/ecmascript/see/input.c
 create mode 100644 src/ecmascript/see/input.h
 create mode 100644 src/ecmascript/see/location.c
 create mode 100644 src/ecmascript/see/location.h
 create mode 100644 src/ecmascript/see/navigator.c
 create mode 100644 src/ecmascript/see/navigator.h
 create mode 100644 src/ecmascript/see/strings.c
 create mode 100644 src/ecmascript/see/strings.h
 create mode 100644 src/ecmascript/see/unibar.c
 create mode 100644 src/ecmascript/see/unibar.h
 create mode 100644 src/ecmascript/see/window.c
 create mode 100644 src/ecmascript/see/window.h
 create mode 100644 test/ecmascript/infinite2.html

diff --git a/Makefile.config.in b/Makefile.config.in
index d66f55434..3eaf09396 100644
--- a/Makefile.config.in
+++ b/Makefile.config.in
@@ -142,6 +142,7 @@ CONFIG_RISCOS = @CONFIG_RISCOS@
 CONFIG_RUBY = @CONFIG_RUBY@
 CONFIG_SCANNER = @CONFIG_SCANNER@
 CONFIG_SCRIPTING = @CONFIG_SCRIPTING@
+CONFIG_SEE = @CONFIG_SEE@
 CONFIG_SHA1 = @CONFIG_SHA1@
 CONFIG_SMALL = @CONFIG_SMALL@
 CONFIG_SMB = @CONFIG_SMB@
diff --git a/configure.in b/configure.in
index ca6d2d931..bb2684c70 100644
--- a/configure.in
+++ b/configure.in
@@ -496,6 +496,55 @@ if test "$CONFIG_WIN32" = yes; then
 	EL_CONFIG_WIN32
 fi
 
+dnl ===================================================================
+dnl Check for SEE (Simple Ecmascript Engine)
+dnl ===================================================================
+AC_ARG_WITH(see, [  --with-see              enable Simple Ecmascript Engine (SEE) support],
+            [ if test "x$withval" != xno; then enable_see=yes; fi ])
+
+# The following is probably bad, ugly and so on. Stolen from Guile's (1.4)
+# SEE_FLAGS but I really don't want to require people to have Guile in order
+# to compile CVS. Also, the macro seems to be really stupid regarding searching
+# for Guile in $PATH etc. --pasky
+
+AC_MSG_CHECKING([for SEE])
+
+if test "$enable_see" = "yes"; then
+	AC_MSG_RESULT(yes);
+	## Based on the SEE_FLAGS macro.
+
+	if test -d "$withval"; then
+		SEE_PATH="$withval:$PATH"
+	else
+		SEE_PATH="$PATH"
+	fi
+
+	AC_PATH_PROG(SEE_CONFIG, libsee-config, no, $SEE_PATH)
+
+	## First, let's just see if we can find Guile at all.
+	if test "$SEE_CONFIG" != no; then
+		cf_result="yes";
+
+		SEE_LIBS="`$SEE_CONFIG --libs`"
+		SEE_CFLAGS="`$SEE_CONFIG --cppflags`"
+		LIBS="$SEE_LIBS $LIBS"
+		CPPFLAGS="$CPPFLAGS $SEE_CFLAGS"
+		EL_CONFIG(CONFIG_SEE, [SEE])
+		AC_SUBST(SEE_CFLAGS)
+		AC_SUBST(CONFIG_SEE)
+		disable_spidermonkey=yes
+	else
+		if test -n "$withval" && test "x$withval" != xno; then
+			AC_MSG_ERROR([SEE not found])
+		else
+			AC_MSG_WARN([SEE support disabled])
+		fi
+	fi
+else
+	AC_MSG_RESULT(no);
+fi
+
+
 dnl ===================================================================
 dnl Check for SpiderMonkey, optional even if installed.
 dnl ===================================================================
@@ -550,7 +599,7 @@ fi
 
 AC_SUBST(CONFIG_SPIDERMONKEY)
 
-EL_CONFIG_DEPENDS(CONFIG_ECMASCRIPT, [CONFIG_SPIDERMONKEY], [ECMAScript (JavaScript)])
+EL_CONFIG_DEPENDS(CONFIG_ECMASCRIPT, [CONFIG_SEE CONFIG_SPIDERMONKEY], [ECMAScript (JavaScript)])
 
 
 dnl ===================================================================
diff --git a/src/ecmascript/Makefile b/src/ecmascript/Makefile
index 441d00733..894a276e4 100644
--- a/src/ecmascript/Makefile
+++ b/src/ecmascript/Makefile
@@ -2,7 +2,10 @@ top_builddir=../..
 include $(top_builddir)/Makefile.config
 INCLUDES += $(SPIDERMONKEY_CFLAGS)
 
-SUBDIRS = spidermonkey
-OBJS	= ecmascript.o spidermonkey.o
+SUBDIRS-$(CONFIG_SPIDERMONKEY) += spidermonkey
+SUBDIRS-$(CONFIG_SEE) += see
+OBJS-$(CONFIG_SPIDERMONKEY) += spidermonkey.o
+OBJS-$(CONFIG_SEE) += see.o
+OBJS	= ecmascript.o
 
 include $(top_srcdir)/Makefile.lib
diff --git a/src/ecmascript/ecmascript.c b/src/ecmascript/ecmascript.c
index 7b9fadf50..718786ff6 100644
--- a/src/ecmascript/ecmascript.c
+++ b/src/ecmascript/ecmascript.c
@@ -12,7 +12,6 @@
 #include "document/document.h"
 #include "document/view.h"
 #include "ecmascript/ecmascript.h"
-#include "ecmascript/spidermonkey.h"
 #include "intl/gettext/libintl.h"
 #include "main/module.h"
 #include "protocol/uri.h"
@@ -61,49 +60,6 @@ static struct option_info ecmascript_options[] = {
 	NULL_OPTION_INFO,
 };
 
-#define get_ecmascript_enable()		get_opt_bool("ecmascript.enable")
-
-
-static void
-ecmascript_init(struct module *module)
-{
-	spidermonkey_init();
-}
-
-static void
-ecmascript_done(struct module *module)
-{
-	spidermonkey_done();
-}
-
-
-struct ecmascript_interpreter *
-ecmascript_get_interpreter(struct view_state *vs)
-{
-	struct ecmascript_interpreter *interpreter;
-
-	assert(vs);
-
-	interpreter = mem_calloc(1, sizeof(*interpreter));
-	if (!interpreter)
-		return NULL;
-
-	interpreter->vs = vs;
-	init_list(interpreter->onload_snippets);
-	spidermonkey_get_interpreter(interpreter);
-
-	return interpreter;
-}
-
-void
-ecmascript_put_interpreter(struct ecmascript_interpreter *interpreter)
-{
-	assert(interpreter);
-	spidermonkey_put_interpreter(interpreter);
-	free_string_list(&interpreter->onload_snippets);
-	mem_free(interpreter);
-}
-
 void
 ecmascript_reset_state(struct view_state *vs)
 {
@@ -124,40 +80,6 @@ ecmascript_reset_state(struct view_state *vs)
 		vs->ecmascript_fragile = 1;
 }
 
-
-void
-ecmascript_eval(struct ecmascript_interpreter *interpreter,
-                struct string *code)
-{
-	if (!get_ecmascript_enable())
-		return;
-	assert(interpreter);
-	spidermonkey_eval(interpreter, code);
-}
-
-
-unsigned char *
-ecmascript_eval_stringback(struct ecmascript_interpreter *interpreter,
-			   struct string *code)
-{
-	if (!get_ecmascript_enable())
-		return NULL;
-	assert(interpreter);
-	return spidermonkey_eval_stringback(interpreter, code);
-}
-
-
-int
-ecmascript_eval_boolback(struct ecmascript_interpreter *interpreter,
-			 struct string *code)
-{
-	if (!get_ecmascript_enable())
-		return -1;
-	assert(interpreter);
-	return spidermonkey_eval_boolback(interpreter, code);
-}
-
-
 void
 ecmascript_protocol_handler(struct session *ses, struct uri *uri)
 {
@@ -197,6 +119,20 @@ ecmascript_protocol_handler(struct session *ses, struct uri *uri)
 }
 
 
+void
+ecmascript_timeout_dialog(struct terminal *term, int max_exec_time)
+{
+	info_box(term, MSGBOX_FREE_TEXT,
+		 N_("JavaScript Emergency"), ALIGN_LEFT,
+		 msg_text(term,
+		  N_("A script embedded in the current document was running\n"
+		  "for more than %d seconds. This probably means there is\n"
+		  "a bug in the script and it could have halted the whole\n"
+		  "ELinks, so the script execution was interrupted."),
+		  max_exec_time));
+
+}
+
 struct module ecmascript_module = struct_module(
 	/* name: */		N_("ECMAScript"),
 	/* options: */		ecmascript_options,
diff --git a/src/ecmascript/ecmascript.h b/src/ecmascript/ecmascript.h
index fd9f13cb4..58429e039 100644
--- a/src/ecmascript/ecmascript.h
+++ b/src/ecmascript/ecmascript.h
@@ -9,9 +9,12 @@
 #include "util/time.h"
 
 struct string;
+struct terminal;
 struct uri;
 struct view_state;
 
+#define get_ecmascript_enable()		get_opt_bool("ecmascript.enable")
+
 struct ecmascript_interpreter {
 	struct view_state *vs;
 	void *backend_data;
@@ -63,6 +66,11 @@ int ecmascript_eval_boolback(struct ecmascript_interpreter *interpreter, struct
  * follows a link with this synstax. */
 void ecmascript_protocol_handler(struct session *ses, struct uri *uri);
 
+void ecmascript_init(struct module *);
+void ecmascript_done(struct module *);
+void ecmascript_timeout_dialog(struct terminal *term, int max_exec_time);
+
+
 extern struct module ecmascript_module;
 
 #endif
diff --git a/src/ecmascript/see.c b/src/ecmascript/see.c
new file mode 100644
index 000000000..b9aa9b668
--- /dev/null
+++ b/src/ecmascript/see.c
@@ -0,0 +1,243 @@
+/* The SEE ECMAScript backend. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "elinks.h"
+
+#include <see/see.h>
+
+#include "bfu/dialog.h"
+#include "cache/cache.h"
+#include "cookies/cookies.h"
+#include "dialogs/menu.h"
+#include "dialogs/status.h"
+#include "document/html/frames.h"
+#include "document/document.h"
+#include "document/forms.h"
+#include "document/view.h"
+#include "ecmascript/ecmascript.h"
+#include "ecmascript/see.h"
+#include "ecmascript/see/document.h"
+#include "ecmascript/see/form.h"
+#include "ecmascript/see/input.h"
+#include "ecmascript/see/location.h"
+#include "ecmascript/see/navigator.h"
+#include "ecmascript/see/strings.h"
+#include "ecmascript/see/unibar.h"
+#include "ecmascript/see/window.h"
+#include "intl/gettext/libintl.h"
+#include "main/select.h"
+#include "osdep/newwin.h"
+#include "osdep/sysname.h"
+#include "protocol/http/http.h"
+#include "protocol/uri.h"
+#include "session/history.h"
+#include "session/location.h"
+#include "session/session.h"
+#include "session/task.h"
+#include "terminal/tab.h"
+#include "terminal/terminal.h"
+#include "util/conv.h"
+#include "util/string.h"
+#include "viewer/text/draw.h"
+#include "viewer/text/form.h"
+#include "viewer/text/link.h"
+#include "viewer/text/vs.h"
+
+
+/*** Global methods */
+
+
+/* TODO? Are there any which need to be implemented? */
+
+
+
+/*** The ELinks interface */
+
+void
+ecmascript_init(struct module *module)
+{
+	see_init();
+}
+
+void
+ecmascript_done(struct module *module)
+{
+	see_done();
+}
+
+struct ecmascript_interpreter *
+ecmascript_get_interpreter(struct view_state *vs)
+{
+	struct ecmascript_interpreter *interpreter;
+
+	assert(vs);
+
+	interpreter = mem_calloc(1, sizeof(*interpreter));
+	if (!interpreter)
+		return NULL;
+
+	interpreter->vs = vs;
+	init_list(interpreter->onload_snippets);
+	see_get_interpreter(interpreter);
+
+	return interpreter;
+}
+
+void
+ecmascript_put_interpreter(struct ecmascript_interpreter *interpreter)
+{
+	assert(interpreter);
+	see_put_interpreter(interpreter);
+	free_string_list(&interpreter->onload_snippets);
+	mem_free(interpreter);
+}
+
+void
+ecmascript_eval(struct ecmascript_interpreter *interpreter,
+                struct string *code)
+{
+	if (!get_ecmascript_enable())
+		return;
+	assert(interpreter);
+	see_eval(interpreter, code);
+}
+
+unsigned char *
+ecmascript_eval_stringback(struct ecmascript_interpreter *interpreter,
+			   struct string *code)
+{
+	if (!get_ecmascript_enable())
+		return NULL;
+	assert(interpreter);
+	return see_eval_stringback(interpreter, code);
+}
+
+int
+ecmascript_eval_boolback(struct ecmascript_interpreter *interpreter,
+			 struct string *code)
+{
+	if (!get_ecmascript_enable())
+		return -1;
+	assert(interpreter);
+	return see_eval_boolback(interpreter, code);
+}
+
+void
+see_init(void)
+{
+	init_intern_strings();
+}
+
+void
+see_done(void)
+{
+}
+
+void *
+see_get_interpreter(struct ecmascript_interpreter *interpreter)
+{
+	struct global_object *g = SEE_NEW(NULL, struct global_object);
+	struct SEE_interpreter *interp = &g->interp;
+
+	interpreter->backend_data = g;
+	g->max_exec_time = get_opt_int("ecmascript.max_exec_time");
+	g->exec_start = time(NULL);
+	SEE_interpreter_init(interp);
+	init_js_window_object(interpreter);
+	init_js_menubar_object(interpreter);
+	init_js_statusbar_object(interpreter);
+	init_js_navigator_object(interpreter);
+	init_js_history_object(interpreter);
+	init_js_location_object(interpreter);
+	init_js_document_object(interpreter);
+	init_js_forms_object(interpreter);
+	return interp;
+}
+
+void
+see_put_interpreter(struct ecmascript_interpreter *interpreter)
+{
+	interpreter->backend_data = NULL;
+}
+
+void
+see_eval(struct ecmascript_interpreter *interpreter,
+                  struct string *code)
+{
+
+	struct SEE_interpreter *interp = interpreter->backend_data;
+	struct global_object *g = (struct global_object *)interp;
+	struct SEE_input *input = SEE_input_elinks(interp, code->source);
+	SEE_try_context_t try_ctxt;
+	struct SEE_value result;
+	struct SEE_value v;
+
+	g->exec_start = time(NULL);
+	SEE_TRY(interp, try_ctxt) {
+		SEE_Global_eval(interp, input, &result);
+	}
+
+	SEE_INPUT_CLOSE(input);
+	SEE_CAUGHT(try_ctxt);
+}
+
+
+unsigned char *
+see_eval_stringback(struct ecmascript_interpreter *interpreter,
+			     struct string *code)
+{
+	struct SEE_interpreter *interp = interpreter->backend_data;
+	struct global_object *g = (struct global_object *)interp;
+	struct SEE_input *input = SEE_input_elinks(interp, code->source);
+	SEE_try_context_t try_ctxt;
+	struct SEE_value result;
+	unsigned char *string = NULL;
+
+	g->exec_start = time(NULL);
+	SEE_TRY(interp, try_ctxt) {
+		SEE_Global_eval(interp, input, &result);
+		if (SEE_VALUE_GET_TYPE(&result) != SEE_NULL)
+			string = SEE_value_to_unsigned_char(interp, &result);
+
+	}
+	SEE_INPUT_CLOSE(input);
+	if (SEE_CAUGHT(try_ctxt)) {
+		return NULL;
+	}
+	return string;
+}
+
+int
+see_eval_boolback(struct ecmascript_interpreter *interpreter,
+			   struct string *code)
+{
+	struct SEE_interpreter *interp = interpreter->backend_data;
+	struct global_object *g = (struct global_object *)interp;
+	struct SEE_input *input = SEE_input_elinks(interp, code->source);
+	SEE_try_context_t try_ctxt;
+	struct SEE_value result;
+	SEE_int32_t res = 0;
+
+	g->exec_start = time(NULL);
+	SEE_TRY(interp, try_ctxt) {
+		SEE_Global_eval(interp, input, &result);
+		/* history.back() returns SEE_NULL */
+		if (SEE_VALUE_GET_TYPE(&result) == SEE_NULL)
+			res = 0;
+		else
+			res = SEE_ToInt32(interp, &result);
+	}
+
+	SEE_INPUT_CLOSE(input);
+	if (SEE_CAUGHT(try_ctxt)) {
+		return -1;
+	}
+	return res;
+}
diff --git a/src/ecmascript/see.h b/src/ecmascript/see.h
new file mode 100644
index 000000000..206be2cb8
--- /dev/null
+++ b/src/ecmascript/see.h
@@ -0,0 +1,17 @@
+#ifndef EL__ECMASCRIPT_SEE_H
+#define EL__ECMASCRIPT_SEE_H
+
+struct ecmascript_interpreter;
+struct string;
+
+void see_init();
+void see_done();
+
+void *see_get_interpreter(struct ecmascript_interpreter *interpreter);
+void see_put_interpreter(struct ecmascript_interpreter *interpreter);
+
+void see_eval(struct ecmascript_interpreter *interpreter, struct string *code);
+unsigned char *see_eval_stringback(struct ecmascript_interpreter *interpreter, struct string *code);
+int see_eval_boolback(struct ecmascript_interpreter *interpreter, struct string *code);
+
+#endif
diff --git a/src/ecmascript/see.o b/src/ecmascript/see.o
new file mode 100644
index 0000000000000000000000000000000000000000..a62cbd352616bbc0b248d9f30c21fe13b81b7cda
GIT binary patch
literal 85976
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

literal 0
HcmV?d00001

diff --git a/src/ecmascript/see/Makefile b/src/ecmascript/see/Makefile
new file mode 100644
index 000000000..f1c4b9e81
--- /dev/null
+++ b/src/ecmascript/see/Makefile
@@ -0,0 +1,6 @@
+top_builddir=../../..
+include $(top_builddir)/Makefile.config
+
+OBJS = document.o form.o input.o location.o navigator.o strings.o unibar.o window.o
+
+include $(top_srcdir)/Makefile.lib
diff --git a/src/ecmascript/see/document.c b/src/ecmascript/see/document.c
new file mode 100644
index 000000000..888edaa00
--- /dev/null
+++ b/src/ecmascript/see/document.c
@@ -0,0 +1,257 @@
+/* The SEE document object implementation. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "elinks.h"
+
+#include <see/see.h>
+
+#include "bfu/dialog.h"
+#include "cache/cache.h"
+#include "cookies/cookies.h"
+#include "dialogs/menu.h"
+#include "dialogs/status.h"
+#include "document/html/frames.h"
+#include "document/document.h"
+#include "document/forms.h"
+#include "document/view.h"
+#include "ecmascript/ecmascript.h"
+#include "ecmascript/see/document.h"
+#include "ecmascript/see/form.h"
+#include "ecmascript/see/input.h"
+#include "ecmascript/see/strings.h"
+#include "ecmascript/see/window.h"
+#include "intl/gettext/libintl.h"
+#include "main/select.h"
+#include "osdep/newwin.h"
+#include "osdep/sysname.h"
+#include "protocol/http/http.h"
+#include "protocol/uri.h"
+#include "session/history.h"
+#include "session/location.h"
+#include "session/session.h"
+#include "session/task.h"
+#include "terminal/tab.h"
+#include "terminal/terminal.h"
+#include "util/conv.h"
+#include "util/memory.h"
+#include "util/string.h"
+#include "viewer/text/draw.h"
+#include "viewer/text/form.h"
+#include "viewer/text/link.h"
+#include "viewer/text/vs.h"
+
+static void document_get(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *, struct SEE_value *);
+static void document_put(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *, struct SEE_value *, int);
+static int document_canput(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *);
+static int document_hasproperty(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *);
+static void js_document_write(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
+
+void location_goto(struct document_view *, unsigned char *);
+
+struct SEE_objectclass js_document_object_class = {
+	NULL,
+	document_get,
+	document_put,
+	document_canput,
+	document_hasproperty,
+	SEE_no_delete,
+	SEE_no_defaultvalue,
+	NULL,
+	NULL,
+	NULL,
+	NULL
+};
+
+static void
+document_get(struct SEE_interpreter *interp, struct SEE_object *o,
+	   struct SEE_string *p, struct SEE_value *res)
+{
+	struct global_object *g = (struct global_object *)interp;
+	struct js_window_object *win = g->win;
+	struct view_state *vs = win->vs;
+	struct document_view *doc_view = vs->doc_view;
+	struct document *document = doc_view->document;
+	struct js_document_object *doc = (struct js_document_object *)o;
+	struct session *ses = doc_view->session;
+	struct SEE_string *str;
+	unsigned char *string;
+
+	checktime(interp);
+	SEE_SET_UNDEFINED(res);
+
+	if (p == s_cookie) {
+#ifdef CONFIG_COOKIES
+		struct string *cookies = send_cookies(vs->uri);
+
+		if (cookies) {
+			static unsigned char cookiestr[1024];
+			strncpy(cookiestr, cookies->source, 1024);
+			done_string(cookies);
+
+			str = string_to_SEE_string(interp, cookiestr);
+		} else {
+			str = string_to_SEE_string(interp, "");
+		}
+		SEE_SET_STRING(res, str);
+#endif
+	} else if (p == s_title) {
+		str = string_to_SEE_string(interp, document->title);
+		SEE_SET_STRING(res, str);
+	} else if (p == s_url) {
+		string = get_uri_string(document->uri, URI_ORIGINAL);
+		str = string_to_SEE_string(interp, string);
+		mem_free_if(string);
+		SEE_SET_STRING(res, str);
+	} else if (p == s_location) {
+		SEE_OBJECT_GET(interp, interp->Global, s_location, res);
+	} else if (p == s_referrer) {
+		switch (get_opt_int("protocol.http.referer.policy")) {
+			case REFERER_NONE:
+				SEE_SET_UNDEFINED(res);
+				break;
+			case REFERER_FAKE:
+				str = string_to_SEE_string(interp,
+				 get_opt_str("protocol.http.referer.fake"));
+				SEE_SET_STRING(res, str);
+				break;
+			case REFERER_TRUE:
+				if (ses->referrer) {
+					string = get_uri_string(ses->referrer, URI_HTTP_REFERRER);
+					str = string_to_SEE_string(interp, string);
+					mem_free_if(string);
+					SEE_SET_STRING(res, str);
+				}
+				break;
+			case REFERER_SAME_URL:
+				string = get_uri_string(document->uri, URI_HTTP_REFERRER);
+				str = string_to_SEE_string(interp, string);
+				mem_free_if(string);
+				SEE_SET_STRING(res, str);
+				break;
+
+		}
+	} else if (p == s_forms) {
+		SEE_SET_OBJECT(res, doc->forms);
+	} else {
+		struct form *form;
+		unsigned char *string = SEE_string_to_unsigned_char(p);
+		struct form_view *form_view;
+		struct js_form *form_object;
+
+		foreach (form, document->forms) {
+			if (!form->name || strcasecmp(string, form->name))
+				continue;
+			mem_free_if(string);
+			form_view = find_form_view(doc_view, form);
+			form_object = js_get_form_object(interp, doc, form_view);
+			SEE_SET_OBJECT(res, (struct SEE_object *)form_object);
+			break;
+		}
+	}
+}
+
+static void
+document_put(struct SEE_interpreter *interp, struct SEE_object *o,
+	   struct SEE_string *p, struct SEE_value *val, int attr)
+{
+	struct global_object *g = (struct global_object *)interp;
+	struct view_state *vs = g->win->vs;
+	struct document_view *doc_view = vs->doc_view;
+	struct document *document = doc_view->document;
+	struct js_document_object *doc = (struct js_document_object *)o;
+	struct SEE_value res;
+	unsigned char *string;
+
+	checktime(interp);
+	if (p == s_forms) {
+		SEE_ToObject(interp, val, &res);
+		doc->forms = res.u.object;
+	} else if (p == s_title) {
+		string = SEE_value_to_unsigned_char(interp, val);
+		mem_free_set(&document->title, string);
+		print_screen_status(doc_view->session);
+	} else if (p == s_location || p == s_url) {
+		/* According to the specs this should be readonly but some
+		 * broken sites still assign to it (i.e.
+		 * http://www.e-handelsfonden.dk/validering.asp?URL=www.polyteknisk.dk).
+		 * So emulate window.location. */
+		string = SEE_value_to_unsigned_char(interp, val);
+		location_goto(doc_view, string);
+		mem_free_if(string);
+	} else if (p == s_cookie) {
+#ifdef CONFIG_COOKIES
+		string = SEE_value_to_unsigned_char(interp, val);
+		set_cookie(vs->uri, string);
+		mem_free_if(string);
+#endif
+	}
+
+
+}
+
+static void
+js_document_write(struct SEE_interpreter *interp, struct SEE_object *self,
+	     struct SEE_object *thisobj, int argc, struct SEE_value **argv,
+	     struct SEE_value *res)
+{
+#ifdef CONFIG_LEDS
+	struct global_object *g = (struct global_object *)interp;
+	struct view_state *vs = g->win->vs;
+
+	/* XXX: I don't know about you, but I have *ENOUGH* of those 'Undefined
+	 * function' errors, I want to see just the useful ones. So just
+	 * lighting a led and going away, no muss, no fuss. --pasky */
+	/* TODO: Perhaps we can introduce ecmascript.error_report_unsupported
+	 * -> "Show information about the document using some valid,
+	 *  nevertheless unsupported methods/properties." --pasky too */
+
+	set_led_value(vs->doc_view->session->status.ecmascript_led, 'J');
+#endif
+	checktime(interp);
+	SEE_SET_BOOLEAN(res, 0);
+}
+
+static int
+document_canput(struct SEE_interpreter *interp, struct SEE_object *o,
+	      struct SEE_string *p)
+{
+	checktime(interp);
+	if (p == s_location || p == s_url || p == s_cookie)
+		return 1;
+	return 0;
+}
+
+static int
+document_hasproperty(struct SEE_interpreter *interp, struct SEE_object *o,
+	      struct SEE_string *p)
+{
+	checktime(interp);
+	/* all unknown properties return UNDEFINED value */
+	return 1;
+}
+
+
+void
+init_js_document_object(struct ecmascript_interpreter *interpreter)
+{
+	struct global_object *g = interpreter->backend_data;
+	struct SEE_interpreter *interp = &g->interp;
+	struct SEE_value v;
+	struct js_document_object *doc = SEE_NEW(interp,
+		struct js_document_object);
+
+	doc->object.objectclass = &js_document_object_class;
+	doc->object.objectclass->Class = s_document;
+	doc->object.Prototype = NULL;
+
+	SEE_SET_OBJECT(&v, (struct SEE_object *)doc);
+	SEE_OBJECT_PUT(interp, interp->Global, s_document, &v, 0);
+
+	doc->write = SEE_cfunction_make(interp, js_document_write, s_write, 1);
+}
diff --git a/src/ecmascript/see/document.h b/src/ecmascript/see/document.h
new file mode 100644
index 000000000..1fde46eba
--- /dev/null
+++ b/src/ecmascript/see/document.h
@@ -0,0 +1,14 @@
+#ifndef EL__ECMASCRIPT_SEE_DOCUMENT_H
+#define EL__ECMASCRIPT_SEE_DOCUMENT_H
+
+struct ecmascript_interpreter;
+
+struct js_document_object {
+	struct SEE_object object;
+	struct SEE_object *write;
+	struct SEE_object *forms;
+};
+
+void init_js_document_object(struct ecmascript_interpreter *);
+
+#endif
diff --git a/src/ecmascript/see/form.c b/src/ecmascript/see/form.c
new file mode 100644
index 000000000..db343d9f2
--- /dev/null
+++ b/src/ecmascript/see/form.c
@@ -0,0 +1,964 @@
+/* The SEE form object implementation. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "elinks.h"
+
+#include <see/see.h>
+
+#include "bfu/dialog.h"
+#include "cache/cache.h"
+#include "cookies/cookies.h"
+#include "dialogs/menu.h"
+#include "dialogs/status.h"
+#include "document/html/frames.h"
+#include "document/document.h"
+#include "document/forms.h"
+#include "document/view.h"
+#include "ecmascript/ecmascript.h"
+#include "ecmascript/see/document.h"
+#include "ecmascript/see/form.h"
+#include "ecmascript/see/input.h"
+#include "ecmascript/see/strings.h"
+#include "ecmascript/see/window.h"
+#include "intl/gettext/libintl.h"
+#include "main/select.h"
+#include "osdep/newwin.h"
+#include "osdep/sysname.h"
+#include "protocol/http/http.h"
+#include "protocol/uri.h"
+#include "session/history.h"
+#include "session/location.h"
+#include "session/session.h"
+#include "session/task.h"
+#include "terminal/tab.h"
+#include "terminal/terminal.h"
+#include "util/conv.h"
+#include "util/memory.h"
+#include "util/string.h"
+#include "viewer/text/draw.h"
+#include "viewer/text/form.h"
+#include "viewer/text/link.h"
+#include "viewer/text/vs.h"
+
+static void input_get(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *, struct SEE_value *);
+static void input_put(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *, struct SEE_value *, int);
+static void js_input_blur(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
+static void js_input_click(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
+static void js_input_focus(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
+static void js_input_select(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
+static int input_canput(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *);
+static int input_hasproperty(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *);
+static struct js_input *js_get_input_object(struct SEE_interpreter *, struct js_form *, struct form_state *);
+static struct js_input *js_get_form_control_object(struct SEE_interpreter *, struct js_form *, enum form_type,  struct form_state *);
+
+static void js_form_elems_item(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
+static void js_form_elems_namedItem(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
+static void form_elems_get(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *, struct SEE_value *);
+static int form_elems_hasproperty(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *);
+
+static void js_forms_item(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
+static void js_forms_namedItem(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
+static void forms_get(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *, struct SEE_value *);
+static int forms_hasproperty(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *);
+
+static void form_get(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *, struct SEE_value *);
+static void form_put(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *, struct SEE_value *, int);
+static int form_canput(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *);
+static int form_hasproperty(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *);
+static void js_form_reset(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
+static void js_form_submit(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
+
+
+struct SEE_objectclass js_input_object_class = {
+	NULL,
+	input_get,
+	input_put,
+	input_canput,
+	input_hasproperty,
+	SEE_no_delete,
+	SEE_no_defaultvalue,
+	NULL,
+	NULL,
+	NULL,
+	NULL
+};
+
+struct SEE_objectclass js_form_elems_class = {
+	NULL,
+	form_elems_get,
+	SEE_no_put,
+	SEE_no_canput,
+	form_elems_hasproperty,
+	SEE_no_delete,
+	SEE_no_defaultvalue,
+	NULL,
+	NULL,
+	NULL,
+	NULL
+};
+
+struct SEE_objectclass js_forms_object_class = {
+	NULL,
+	forms_get,
+	SEE_no_put,
+	SEE_no_canput,
+	forms_hasproperty,
+	SEE_no_delete,
+	SEE_no_defaultvalue,
+	NULL,
+	NULL,
+	NULL,
+	NULL
+};
+
+struct SEE_objectclass js_form_class = {
+	NULL,
+	form_get,
+	form_put,
+	form_canput,
+	form_hasproperty,
+	SEE_no_delete,
+	SEE_no_defaultvalue,
+	NULL,
+	NULL,
+	NULL,
+	NULL
+};
+
+struct js_input {
+	struct SEE_object object;
+	struct js_form *parent;
+	struct form_state *fs;
+	struct SEE_object *blur;
+	struct SEE_object *click;
+	struct SEE_object *focus;
+	struct SEE_object *select;
+};
+
+struct js_forms_object {
+	struct SEE_object object;
+	struct js_document_object *parent;
+	struct SEE_object *item;
+	struct SEE_object *namedItem;
+};
+
+struct js_form_elems {
+	struct SEE_object object;
+	struct js_form *parent;
+	struct SEE_object *item;
+	struct SEE_object *namedItem;
+};
+
+
+static void
+input_get(struct SEE_interpreter *interp, struct SEE_object *o,
+	   struct SEE_string *p, struct SEE_value *res)
+{
+	struct global_object *g = (struct global_object *)interp;
+	struct view_state *vs = g->win->vs;
+	struct document_view *doc_view = vs->doc_view;
+	struct document *document = doc_view->document;
+	struct js_input *input = (struct js_input *)o;
+	struct js_form *parent = input->parent;
+	struct form_state *fs = input->fs;
+	struct form_control *fc = find_form_control(document, fs);
+	int linknum;
+	struct link *link = NULL;
+	struct SEE_string *str;
+
+	assert(fc);
+	assert(fc->form && fs);
+
+	checktime(interp);
+	linknum = get_form_control_link(document, fc);
+	/* Hiddens have no link. */
+	if (linknum >= 0) link = &document->links[linknum];
+	SEE_SET_UNDEFINED(res);
+
+	if (p == s_accessKey) {
+		struct string keystr;
+		if (!link)
+			return;
+
+		init_string(&keystr);
+		add_accesskey_to_string(&keystr, link->accesskey);
+		str = string_to_SEE_string(interp, keystr.source);
+		SEE_SET_STRING(res, str);
+		done_string(&keystr);
+	} else if (p == s_alt) {
+		str = string_to_SEE_string(interp, fc->alt);
+		SEE_SET_STRING(res, str);
+	} else if (p == s_checked) {
+		SEE_SET_BOOLEAN(res, fs->state);
+	} else if (p == s_defaultChecked) {
+		SEE_SET_BOOLEAN(res, fc->default_state);
+	} else if (p == s_defaultValue) {
+		str = string_to_SEE_string(interp, fc->default_value);
+		SEE_SET_STRING(res, str);
+	} else if (p == s_disabled) {
+		/* FIXME: <input readonly disabled> --pasky */
+		SEE_SET_BOOLEAN(res, fc->mode == FORM_MODE_DISABLED);
+	} else if (p == s_form) {
+		SEE_SET_OBJECT(res, (struct SEE_object *)parent);
+	} else if (p == s_maxLength) {
+		SEE_SET_NUMBER(res, fc->maxlength);
+	} else if (p == s_name) {
+		str = string_to_SEE_string(interp, fc->name);
+		SEE_SET_STRING(res, str);
+	} else if (p == s_readonly) {
+		/* FIXME: <input readonly disabled> --pasky */
+		SEE_SET_BOOLEAN(res, fc->mode == FORM_MODE_READONLY);
+	} else if (p == s_size) {
+		SEE_SET_NUMBER(res, fc->size);
+	} else if (p == s_src) {
+		if (link && link->where_img) {
+			str = string_to_SEE_string(interp, link->where_img);
+			SEE_SET_STRING(res, str);
+		}
+	} else if (p == s_tabindex) {
+		if (link) {
+			/* FIXME: This is WRONG. --pasky */
+			SEE_SET_NUMBER(res, link->number);
+		}
+	} else if (p == s_type) {
+		switch (fc->type) {
+		case FC_TEXT: str = s_text; break;
+		case FC_PASSWORD: str = s_password; break;
+		case FC_FILE: str = s_file; break;
+		case FC_CHECKBOX: str = s_checkbox; break;
+		case FC_RADIO: str = s_radio; break;
+		case FC_SUBMIT: str = s_submit; break;
+		case FC_IMAGE: str = s_image; break;
+		case FC_RESET: str = s_reset; break;
+		case FC_BUTTON: str = s_button; break;
+		case FC_HIDDEN: str = s_hidden; break;
+		default: str = NULL;
+		}
+		if (str) {
+			SEE_SET_STRING(res, str);
+		}
+	} else if (p == s_value) {
+		str = string_to_SEE_string(interp, fs->value);
+		SEE_SET_STRING(res, str);
+	}
+}
+
+static void
+input_put(struct SEE_interpreter *interp, struct SEE_object *o,
+	   struct SEE_string *p, struct SEE_value *val, int attr)
+{
+	struct global_object *g = (struct global_object *)interp;
+	struct view_state *vs = g->win->vs;
+	struct document_view *doc_view = vs->doc_view;
+	struct document *document = doc_view->document;
+	struct js_input *input = (struct js_input *)o;
+	struct form_state *fs = input->fs;
+	struct form_control *fc = find_form_control(document, fs);
+	int linknum;
+	struct link *link = NULL;
+	unsigned char *string = NULL;
+
+	assert(fc);
+	assert(fc->form && fs);
+
+	checktime(interp);
+	linknum = get_form_control_link(document, fc);
+	/* Hiddens have no link. */
+	if (linknum >= 0) link = &document->links[linknum];
+
+	if (p == s_accessKey) {
+		if (link) {
+			string = SEE_value_to_unsigned_char(interp, val);
+			if (!string)
+				return;
+			link->accesskey = accesskey_string_to_unicode(string);
+			mem_free(string);
+		}
+	} else if (p == s_alt) {
+		string = SEE_value_to_unsigned_char(interp, val);
+		mem_free_set(&fc->alt, string);
+	} else if (p == s_checked) {
+		if (fc->type != FC_CHECKBOX && fc->type != FC_RADIO)
+			return;
+		fs->state = SEE_ToUint32(interp, val);
+	} else if (p == s_disabled) {
+		/* FIXME: <input readonly disabled> --pasky */
+		SEE_uint32_t boo = SEE_ToUint32(interp, val);
+		fc->mode = (boo ? FORM_MODE_DISABLED
+		: (fc->mode == FORM_MODE_READONLY ? FORM_MODE_READONLY
+		: FORM_MODE_NORMAL));
+	} else if (p == s_maxLength) {
+		string = SEE_value_to_unsigned_char(interp, val);
+		if (!string)
+			return;
+		fc->maxlength = atol(string);
+		mem_free(string);
+	} else if (p == s_name) {
+		string = SEE_value_to_unsigned_char(interp, val);
+		mem_free_set(&fc->name, string);
+	} else if (p == s_readonly) {
+		SEE_uint32_t boo = SEE_ToUint32(interp, val);
+		fc->mode = (boo ? FORM_MODE_READONLY
+		: fc->mode == FORM_MODE_DISABLED ? FORM_MODE_DISABLED
+	        : FORM_MODE_NORMAL);
+	} else if (p == s_src) {
+		if (link) {
+			string = SEE_value_to_unsigned_char(interp, val);
+			mem_free_set(&link->where_img, string);
+		}
+	} else if (p == s_value) {
+		if (fc->type == FC_FILE)
+			return;
+		string = SEE_value_to_unsigned_char(interp, val);
+		mem_free_set(&fs->value, string);
+		if (fc->type == FC_TEXT || fc->type == FC_PASSWORD)
+			fs->state = strlen(fs->value);
+	}
+}
+
+static void
+js_input_blur(struct SEE_interpreter *interp, struct SEE_object *self,
+	     struct SEE_object *thisobj, int argc, struct SEE_value **argv,
+	     struct SEE_value *res)
+{
+	/* We are a text-mode browser and there *always* has to be something
+	 * selected.  So we do nothing for now. (That was easy.) */
+}
+
+static void
+js_input_click(struct SEE_interpreter *interp, struct SEE_object *self,
+	     struct SEE_object *thisobj, int argc, struct SEE_value **argv,
+	     struct SEE_value *res)
+{
+	struct global_object *g = (struct global_object *)interp;
+	struct view_state *vs = g->win->vs;
+	struct document_view *doc_view = vs->doc_view;
+	struct document *document = doc_view->document;
+	struct session *ses = doc_view->session;
+	struct js_input *input = (struct js_input *)thisobj;
+	struct form_state *fs = input->fs;
+	struct form_control *fc;
+	int linknum;
+
+	checktime(interp);
+	SEE_SET_BOOLEAN(res, 0);
+	assert(fs);
+	fc = find_form_control(document, fs);
+	assert(fc);
+
+	linknum = get_form_control_link(document, fc);
+	/* Hiddens have no link. */
+	if (linknum < 0)
+		return;
+
+	/* Restore old current_link afterwards? */
+	jump_to_link_number(ses, doc_view, linknum);
+	if (enter(ses, doc_view, 0) == FRAME_EVENT_REFRESH)
+		refresh_view(ses, doc_view, 0);
+	else
+		print_screen_status(ses);
+}
+
+static void
+js_input_focus(struct SEE_interpreter *interp, struct SEE_object *self,
+	     struct SEE_object *thisobj, int argc, struct SEE_value **argv,
+	     struct SEE_value *res)
+{
+	struct global_object *g = (struct global_object *)interp;
+	struct view_state *vs = g->win->vs;
+	struct document_view *doc_view = vs->doc_view;
+	struct document *document = doc_view->document;
+	struct session *ses = doc_view->session;
+	struct js_input *input = (struct js_input *)thisobj;
+	struct form_state *fs = input->fs;
+	struct form_control *fc;
+	int linknum;
+
+	checktime(interp);
+	assert(fs);
+	fc = find_form_control(document, fs);
+	assert(fc);
+
+	linknum = get_form_control_link(document, fc);
+	/* Hiddens have no link. */
+	if (linknum < 0) 
+	 	return;
+
+	jump_to_link_number(ses, doc_view, linknum);
+
+}
+
+static void
+js_input_select(struct SEE_interpreter *interp, struct SEE_object *self,
+	     struct SEE_object *thisobj, int argc, struct SEE_value **argv,
+	     struct SEE_value *res)
+{
+	checktime(interp);
+	/* We support no text selecting yet.  So we do nothing for now.
+	 * (That was easy, too.) */
+}
+
+static int
+input_canput(struct SEE_interpreter *interp, struct SEE_object *o,
+	      struct SEE_string *p)
+{
+	checktime(interp);
+	return 1;
+}
+
+static int
+input_hasproperty(struct SEE_interpreter *interp, struct SEE_object *o,
+	      struct SEE_string *p)
+{
+	/* all unknown properties return UNDEFINED value */
+	checktime(interp);
+	return 1;
+}
+
+static struct js_input *
+js_get_input_object(struct SEE_interpreter *interp, struct js_form *jsform,
+	struct form_state *fs)
+{
+	struct js_input *jsinput;
+
+	checktime(interp);
+	if (fs->ecmascript_obj)
+		return fs->ecmascript_obj;
+
+	/* jsform ('form') is input's parent */
+	/* FIXME: That is NOT correct since the real containing element
+	 * should be its parent, but gimme DOM first. --pasky */
+	jsinput = SEE_NEW(interp, struct js_input);
+
+	jsinput->object.objectclass = &js_input_object_class;
+	jsinput->object.objectclass->Class = s_input;
+	jsinput->object.Prototype = NULL;
+
+	jsinput->blur = SEE_cfunction_make(interp, js_input_blur, s_blur, 0);
+	jsinput->click = SEE_cfunction_make(interp, js_input_click, s_click, 0);
+	jsinput->focus = SEE_cfunction_make(interp, js_input_focus, s_focus, 0);
+	jsinput->select = SEE_cfunction_make(interp, js_input_select, s_select, 0);
+
+	jsinput->fs = fs;
+	jsinput->parent = jsform;
+
+	fs->ecmascript_obj = jsinput;
+	return jsinput;
+}
+
+static struct js_input *
+js_get_form_control_object(struct SEE_interpreter *interp, struct js_form *jsform,
+	enum form_type type,  struct form_state *fs)
+{
+	checktime(interp);
+	switch (type) {
+		case FC_TEXT:
+		case FC_PASSWORD:
+		case FC_FILE:
+		case FC_CHECKBOX:
+		case FC_RADIO:
+		case FC_SUBMIT:
+		case FC_IMAGE:
+		case FC_RESET:
+		case FC_BUTTON:
+		case FC_HIDDEN:
+			return js_get_input_object(interp, jsform, fs);
+
+		case FC_TEXTAREA:
+		case FC_SELECT:
+			/* TODO */
+			return NULL;
+
+		default:
+			INTERNAL("Weird fc->type %d", type);
+			return NULL;
+	}
+}
+
+
+
+
+static void
+js_form_elems_item(struct SEE_interpreter *interp, struct SEE_object *self,
+	     struct SEE_object *thisobj, int argc, struct SEE_value **argv,
+	     struct SEE_value *res)
+{
+	struct global_object *g = (struct global_object *)interp;
+	struct view_state *vs = g->win->vs;
+	struct document_view *doc_view = vs->doc_view;
+	struct document *document = doc_view->document;
+	struct js_form_elems *jsfe = (struct js_form_elems *)thisobj;
+	struct js_form *parent_form = jsfe->parent;
+	struct form_view *fv = parent_form->fv;
+	struct form *form = find_form_by_form_view(document, fv);
+	struct form_control *fc;
+	unsigned char *string;
+	int counter = -1;
+	int index;
+
+	checktime(interp);
+	SEE_SET_UNDEFINED(res);
+	if (argc < 1)
+		return;
+	string = SEE_value_to_unsigned_char(interp, argv[0]);
+	if (!string)
+		return;
+	index = atol(string);
+	mem_free(string);
+
+	foreach (fc, form->items) {
+		counter++;
+		if (counter == index) {
+			struct js_input *fcobj = js_get_form_control_object(interp, parent_form, fc->type, find_form_state(doc_view, fc));
+
+			if (fcobj) {
+				SEE_SET_OBJECT(res, (struct SEE_object *)fcobj);
+			}
+			break;
+		}
+	}
+
+}
+
+static void
+js_form_elems_namedItem(struct SEE_interpreter *interp, struct SEE_object *self,
+	     struct SEE_object *thisobj, int argc, struct SEE_value **argv,
+	     struct SEE_value *res)
+{
+	struct global_object *g = (struct global_object *)interp;
+	struct view_state *vs = g->win->vs;
+	struct document_view *doc_view = vs->doc_view;
+	struct document *document = doc_view->document;
+	struct js_form_elems *jsfe = (struct js_form_elems *)thisobj;
+	struct js_form *parent_form = jsfe->parent;
+	struct form_view *fv = parent_form->fv;
+	struct form *form = find_form_by_form_view(document, fv);
+	struct form_control *fc;
+	unsigned char *string;
+
+	checktime(interp);
+	SEE_SET_UNDEFINED(res);
+	if (argc < 1)
+		return;
+	string = SEE_value_to_unsigned_char(interp, argv[0]);
+	if (!string)
+		return;
+
+	foreach (fc, form->items) {
+		if (fc->name && !strcasecmp(string, fc->name)) {
+			struct js_input *fcobj = js_get_form_control_object(interp, parent_form, fc->type, find_form_state(doc_view, fc));
+
+			if (fcobj) {
+				SEE_SET_OBJECT(res, (struct SEE_object *)fcobj);
+			}
+			break;
+		}
+	}
+	mem_free(string);
+}
+
+static void
+form_elems_get(struct SEE_interpreter *interp, struct SEE_object *o,
+	   struct SEE_string *p, struct SEE_value *res)
+{
+	struct global_object *g = (struct global_object *)interp;
+	struct view_state *vs = g->win->vs;
+	struct document_view *doc_view = vs->doc_view;
+	struct document *document = doc_view->document;
+	struct js_form_elems *jsfe = (struct js_form_elems *)o;
+	struct js_form *parent_form = jsfe->parent;
+	struct form_view *fv = parent_form->fv;
+	struct form *form = find_form_by_form_view(document, fv);
+
+	checktime(interp);
+	if (p == s_length) {
+		SEE_number_t length = list_size(&form->items);
+		SEE_SET_NUMBER(res, length);
+	} else {
+		unsigned char *string = SEE_string_to_unsigned_char(p);
+		struct SEE_value argv;
+
+		if (!string) {
+			SEE_SET_UNDEFINED(res);
+			return;
+		}
+		SEE_SET_STRING(&argv, p);
+		if (string[0] >= '0' && string[1] <= '9') {
+			js_form_elems_item(interp, o, NULL, 1,
+			 (struct SEE_value **)&argv, res); 
+		} else {
+			js_form_elems_namedItem(interp, o, NULL, 1,
+			 (struct SEE_value **)&argv, res);
+		}
+		mem_free(string);
+	}
+}
+
+static int
+form_elems_hasproperty(struct SEE_interpreter *interp, struct SEE_object *o,
+	      struct SEE_string *p)
+{
+	checktime(interp);
+	/* all unknown properties return UNDEFINED value */
+	return 1;
+}
+
+
+static void
+js_forms_item(struct SEE_interpreter *interp, struct SEE_object *self,
+	     struct SEE_object *thisobj, int argc, struct SEE_value **argv,
+	     struct SEE_value *res)
+{
+	struct global_object *g = (struct global_object *)interp;
+	struct view_state *vs = g->win->vs;
+	struct js_forms_object *fo = (struct js_forms_object *)thisobj;
+	struct js_document_object *doc = fo->parent;
+	struct form_view *fv;
+	unsigned char *string;
+	int counter = -1;
+	int index;
+
+	checktime(interp);
+	SEE_SET_UNDEFINED(res);
+	if (argc < 1)
+		return;
+
+	string = SEE_value_to_unsigned_char(interp, argv[0]);
+	if (!string)
+		return;
+	index = atol(string);
+	mem_free(string);
+
+	foreach (fv, vs->forms) {
+		counter++;
+		if (counter == index) {
+			struct js_form *obj = js_get_form_object(interp, doc, fv);
+
+			SEE_SET_OBJECT(res, (struct SEE_object *)obj);
+			break;
+		}
+	}
+}
+
+static void
+js_forms_namedItem(struct SEE_interpreter *interp, struct SEE_object *self,
+	     struct SEE_object *thisobj, int argc, struct SEE_value **argv,
+	     struct SEE_value *res)
+{
+	struct global_object *g = (struct global_object *)interp;
+	struct view_state *vs = g->win->vs;
+	struct document_view *doc_view = vs->doc_view;
+	struct document *document = doc_view->document;
+	struct js_forms_object *fo = (struct js_forms_object *)thisobj;
+	struct js_document_object *doc = fo->parent;
+	struct form *form;
+	unsigned char *string;
+
+	checktime(interp);
+	SEE_SET_UNDEFINED(res);
+	if (argc < 1)
+		return;
+
+	string = SEE_value_to_unsigned_char(interp, argv[0]);
+	if (!string)
+		return;
+	foreach (form, document->forms) {
+		if (form->name && !strcasecmp(string, form->name)) {
+			struct form_view *fv = find_form_view(doc_view, form);
+			struct js_form *obj = js_get_form_object(interp,
+			 doc, fv);
+
+			SEE_SET_OBJECT(res, (struct SEE_object *)obj);
+			break;
+			
+		}
+	}
+	mem_free(string);
+}
+
+static void
+forms_get(struct SEE_interpreter *interp, struct SEE_object *o,
+	   struct SEE_string *p, struct SEE_value *res)
+{
+	struct global_object *g = (struct global_object *)interp;
+	struct view_state *vs = g->win->vs;
+	struct document_view *doc_view = vs->doc_view;
+	struct document *document = doc_view->document;
+
+	checktime(interp);
+	if (p == s_length) {
+		SEE_number_t length = list_size(&document->forms);
+		SEE_SET_NUMBER(res, length);
+	} else {
+		unsigned char *string = SEE_string_to_unsigned_char(p);
+		struct SEE_value argv;
+
+		if (!string) {
+			SEE_SET_UNDEFINED(res);
+			return;
+		}
+		SEE_SET_STRING(&argv, p);
+		if (string[0] >= '0' && string[1] <= '9') {
+			js_forms_item(interp, o, NULL, 1,
+			 (struct SEE_value **)&argv, res); 
+		} else {
+			js_forms_namedItem(interp, o, NULL, 1,
+			 (struct SEE_value **)&argv, res);
+		}
+		mem_free(string);
+	}
+}
+
+static int
+forms_hasproperty(struct SEE_interpreter *interp, struct SEE_object *o,
+	      struct SEE_string *p)
+{
+	checktime(interp);
+	/* all unknown properties return UNDEFINED value */
+	return 1;
+}
+
+
+
+static void
+form_get(struct SEE_interpreter *interp, struct SEE_object *o,
+	   struct SEE_string *p, struct SEE_value *res)
+{
+	struct global_object *g = (struct global_object *)interp;
+	struct view_state *vs = g->win->vs;
+	struct document_view *doc_view = vs->doc_view;
+	struct js_form *js_form = (struct js_form *)o;
+	struct form_view *fv = js_form->fv;
+	struct form *form = find_form_by_form_view(doc_view->document, fv);
+	struct SEE_string *str;
+
+	checktime(interp);
+	SEE_SET_UNDEFINED(res);
+
+	if (p == s_action) {
+		str = string_to_SEE_string(interp, form->action);
+		SEE_SET_STRING(res, str);
+	} else if (p == s_encoding) {
+		switch (form->method) {
+		case FORM_METHOD_GET:
+		case FORM_METHOD_POST:
+			/* "application/x-www-form-urlencoded" */
+			SEE_SET_STRING(res, s_application_);
+			break;
+		case FORM_METHOD_POST_MP:
+			/* "multipart/form-data" */
+			SEE_SET_STRING(res, s_multipart_);
+			break;
+		case FORM_METHOD_POST_TEXT_PLAIN:
+			/* "text/plain") */
+			SEE_SET_STRING(res, s_textplain);
+			break;
+		}
+	} else if (p == s_length) {
+		SEE_number_t num = list_size(&form->items);
+		SEE_SET_NUMBER(res, num);
+	} else if (p == s_method) {
+		switch (form->method) {
+		case FORM_METHOD_GET:
+			SEE_SET_STRING(res, s_GET);
+			break;
+
+		case FORM_METHOD_POST:
+		case FORM_METHOD_POST_MP:
+		case FORM_METHOD_POST_TEXT_PLAIN:
+			SEE_SET_STRING(res, s_POST);
+			break;
+		}
+	} else if (p == s_name) {
+		str = string_to_SEE_string(interp, form->name);
+		SEE_SET_STRING(res, str);
+	} else if (p == s_target) {
+		str = string_to_SEE_string(interp, form->target);
+		SEE_SET_STRING(res, str);
+	} else if (p == s_elements) {
+		struct js_form_elems *jsfe = SEE_NEW(interp, struct js_form_elems);
+
+		jsfe->object.objectclass = &js_form_elems_class;
+		jsfe->object.objectclass->Class = s_elements;
+		jsfe->object.Prototype = NULL;
+		jsfe->parent = js_form;
+		jsfe->item = SEE_cfunction_make(interp, js_form_elems_item, s_item, 1);
+		jsfe->namedItem = SEE_cfunction_make(interp, js_form_elems_namedItem, s_namedItem, 1);
+		SEE_SET_OBJECT(res, (struct SEE_object *)jsfe);
+	} else if (p == s_submit) {
+		SEE_SET_OBJECT(res, js_form->submit);
+	} else if (p == s_reset) {
+		SEE_SET_OBJECT(res, js_form->reset);
+	} else {
+		unsigned char *string = SEE_string_to_unsigned_char(p);
+		struct form_control *fc;
+
+		if (!string)
+			return;
+		foreach(fc, form->items) {
+			struct js_input *fcobj = NULL;
+
+			if (!fc->name || strcasecmp(string, fc->name))
+				continue;
+			fcobj = js_get_form_control_object(interp, js_form, fc->type, find_form_state(doc_view, fc));
+
+			if (fcobj) {
+				SEE_SET_OBJECT(res, (struct SEE_object *)fcobj);
+			}
+			break;
+		}
+		mem_free(string);
+	}
+}
+
+static void
+form_put(struct SEE_interpreter *interp, struct SEE_object *o,
+	   struct SEE_string *p, struct SEE_value *val, int attr)
+{
+	struct global_object *g = (struct global_object *)interp;
+	struct view_state *vs = g->win->vs;
+	struct document_view *doc_view = vs->doc_view;
+	struct js_form *js_form = (struct js_form *)o;
+	struct form_view *fv = js_form->fv;
+	struct form *form = find_form_by_form_view(doc_view->document, fv);
+	unsigned char *string = SEE_value_to_unsigned_char(interp, val);
+
+	checktime(interp);
+	if (!string)
+		return;
+
+	if (p == s_action) {
+		mem_free_set(&form->action, string);
+	} else if (p == s_encoding) {
+		if (!strcasecmp(string, "application/x-www-form-urlencoded")) {
+			form->method = form->method == FORM_METHOD_GET ? FORM_METHOD_GET
+			                                               : FORM_METHOD_POST;
+		} else if (!strcasecmp(string, "multipart/form-data")) {
+			form->method = FORM_METHOD_POST_MP;
+		} else if (!strcasecmp(string, "text/plain")) {
+			form->method = FORM_METHOD_POST_TEXT_PLAIN;
+		}
+		mem_free(string);
+	} else if (p == s_method) {
+		if (!strcasecmp(string, "GET")) {
+			form->method = FORM_METHOD_GET;
+		} else if (!strcasecmp(string, "POST")) {
+			form->method = FORM_METHOD_POST;
+		}
+		mem_free(string);
+	} else if (p == s_name) {
+		mem_free_set(&form->name, string);
+	} else if (p == s_target) {
+		mem_free_set(&form->target, string);
+	}		
+}
+
+static int
+form_canput(struct SEE_interpreter *interp, struct SEE_object *o,
+	      struct SEE_string *p)
+{
+	checktime(interp);
+	return 1;
+}
+
+static int
+form_hasproperty(struct SEE_interpreter *interp, struct SEE_object *o,
+	      struct SEE_string *p)
+{
+	checktime(interp);
+	return 1;
+}
+
+static void
+js_form_reset(struct SEE_interpreter *interp, struct SEE_object *self,
+	     struct SEE_object *thisobj, int argc, struct SEE_value **argv,
+	     struct SEE_value *res)
+{
+	struct global_object *g = (struct global_object *)interp;
+	struct view_state *vs = g->win->vs;
+	struct document_view *doc_view = vs->doc_view;
+	struct js_form *js_form = (struct js_form *)thisobj;
+	struct form_view *fv = js_form->fv;
+	struct form *form = find_form_by_form_view(doc_view->document, fv);
+
+	assert(form);
+
+	checktime(interp);
+	do_reset_form(doc_view, form);
+	draw_forms(doc_view->session->tab->term, doc_view);
+	SEE_SET_BOOLEAN(res, 0);
+}
+
+static void
+js_form_submit(struct SEE_interpreter *interp, struct SEE_object *self,
+	     struct SEE_object *thisobj, int argc, struct SEE_value **argv,
+	     struct SEE_value *res)
+{
+	struct global_object *g = (struct global_object *)interp;
+	struct view_state *vs = g->win->vs;
+	struct document_view *doc_view = vs->doc_view;
+	struct session *ses = doc_view->session;
+	struct js_form *js_form = (struct js_form *)thisobj;
+	struct form_view *fv = js_form->fv;
+	struct form *form = find_form_by_form_view(doc_view->document, fv);
+
+	assert(form);
+	checktime(interp);
+	submit_given_form(ses, doc_view, form);
+	SEE_SET_BOOLEAN(res, 0);
+}
+
+struct js_form *js_get_form_object(struct SEE_interpreter *interp,
+	struct js_document_object *doc, struct form_view *fv)
+{
+	struct js_form *js_form;
+
+	checktime(interp);
+	if (fv->ecmascript_obj)
+		return fv->ecmascript_obj;
+
+	/* jsdoc ('document') is fv's parent */
+	/* FIXME: That is NOT correct since the real containing element
+	 * should be its parent, but gimme DOM first. --pasky */
+	js_form = SEE_NEW(interp, struct js_form);
+	js_form->object.objectclass = &js_form_class;
+	js_form->object.objectclass->Class = s_form;
+	js_form->object.Prototype = NULL; /* TODO: use prototype for form */
+	js_form->parent = doc;
+	js_form->reset = SEE_cfunction_make(interp, js_form_reset, s_reset, 0);
+	js_form->submit = SEE_cfunction_make(interp, js_form_submit, s_submit, 0);
+	js_form->fv = fv;
+		
+	fv->ecmascript_obj = js_form;
+	return js_form;
+}
+
+void
+init_js_forms_object(struct ecmascript_interpreter *interpreter)
+{
+	struct global_object *g = interpreter->backend_data;
+	struct SEE_interpreter *interp = &g->interp;
+	struct SEE_value v, document;
+	struct js_forms_object *forms = SEE_NEW(interp,
+	 struct js_forms_object);
+
+	forms->object.objectclass = &js_forms_object_class;
+	forms->object.objectclass->Class = s_forms;
+	forms->object.Prototype = NULL;
+
+	SEE_OBJECT_GET(interp, interp->Global, s_document, &document);
+	SEE_SET_OBJECT(&v, (struct SEE_object *)forms);
+	SEE_OBJECT_PUT(interp, document.u.object, s_forms, &v, 0);
+
+	forms->item = SEE_cfunction_make(interp, js_forms_item, s_item, 1);
+	forms->namedItem = SEE_cfunction_make(interp, js_forms_namedItem,
+	 s_namedItem, 1);
+	forms->parent = (struct js_document_object *)document.u.object;
+}
diff --git a/src/ecmascript/see/form.h b/src/ecmascript/see/form.h
new file mode 100644
index 000000000..707f0d3b3
--- /dev/null
+++ b/src/ecmascript/see/form.h
@@ -0,0 +1,19 @@
+#ifndef EL__ECMASCRIPT_SEE_FORM_H
+#define EL__ECMASCRIPT_SEE_FORM_H
+
+struct js_document_object;
+struct ecmascript_interpreter;
+struct form_view;
+
+struct js_form {
+	struct SEE_object object;
+	struct js_document_object *parent;
+	struct form_view *fv;
+	struct SEE_object *reset;
+	struct SEE_object *submit;
+};
+
+struct js_form *js_get_form_object(struct SEE_interpreter *, struct js_document_object*, struct form_view *);
+void init_js_forms_object(struct ecmascript_interpreter *);
+
+#endif
diff --git a/src/ecmascript/see/input.c b/src/ecmascript/see/input.c
new file mode 100644
index 000000000..ac9be61bc
--- /dev/null
+++ b/src/ecmascript/see/input.c
@@ -0,0 +1,100 @@
+/* Input for SEE */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <see/see.h>
+#include <string.h>
+#include "ecmascript/see/input.h"
+#include "util/memory.h"
+
+static SEE_unicode_t input_elinks_next(struct SEE_input *);
+static void input_elinks_close(struct SEE_input *);
+
+static struct SEE_inputclass input_elinks_class = {
+	input_elinks_next,
+	input_elinks_close
+};
+
+struct input_elinks {
+	struct SEE_input inp;
+	unsigned char *s;
+};
+
+static SEE_unicode_t
+input_elinks_next(struct SEE_input *inp)
+{
+	struct input_elinks *input = (struct input_elinks*)inp;
+	SEE_unicode_t next;
+
+	next = input->inp.lookahead;
+
+	if (*input->s == '\0') {
+		input->inp.eof = 1;
+	} else {
+		input->inp.lookahead = *input->s++;
+		input->inp.eof = 0;
+	}
+	return next;
+}
+
+static void
+input_elinks_close(struct SEE_input *inp)
+{
+	/* nothing */
+}
+
+struct SEE_input *
+SEE_input_elinks(struct SEE_interpreter *interp, unsigned char *s)
+{
+	struct input_elinks *input;
+
+	input = SEE_NEW(interp, struct input_elinks);
+	input->inp.interpreter = interp;
+	input->inp.inputclass = &input_elinks_class;
+	input->inp.filename = NULL;
+	input->inp.first_lineno = 1;
+	input->s = s;
+	SEE_INPUT_NEXT((struct SEE_input *)input);	/* prime */
+	return (struct SEE_input *)input;
+}
+
+unsigned char *
+SEE_string_to_unsigned_char(struct SEE_string *S)
+{
+	int i;
+	unsigned char *str = mem_alloc(S->length + 1);
+
+	if (!str)
+		return NULL;
+
+	for (i = 0; i < S->length; i++)
+		str[i] = (unsigned char)S->data[i];
+	str[S->length] = '\0';
+	return str;
+}
+
+unsigned char *
+SEE_value_to_unsigned_char(struct SEE_interpreter *interp, struct SEE_value *val)
+{
+	struct SEE_value result;
+
+	SEE_ToString(interp, val, &result);
+	return SEE_string_to_unsigned_char(result.u.string);
+}
+
+struct SEE_string *
+string_to_SEE_string(struct SEE_interpreter *interp, unsigned char *s)
+{
+	unsigned int len;
+	unsigned int i;
+	struct SEE_string *str;
+
+	len = s ? strlen(s) : 0;
+	str = SEE_string_new(interp, len);
+	str->length = len;
+	for (i = 0; i < len; i++)
+		str->data[i] = s[i];
+	return str;
+}
diff --git a/src/ecmascript/see/input.h b/src/ecmascript/see/input.h
new file mode 100644
index 000000000..d2d4755b4
--- /dev/null
+++ b/src/ecmascript/see/input.h
@@ -0,0 +1,11 @@
+#ifndef EL__ECMASCRIPT_SEE_INPUT_H
+#define EL__ECMASCRIPT_SEE_INPUT_H
+
+#include <see/see.h>
+
+struct SEE_input *SEE_input_elinks(struct SEE_interpreter *, unsigned char *);
+unsigned char *SEE_string_to_unsigned_char(struct SEE_string *);
+unsigned char *SEE_value_to_unsigned_char(struct SEE_interpreter *, struct SEE_value *);
+struct SEE_string *string_to_SEE_string(struct SEE_interpreter *, unsigned char *);
+
+#endif
diff --git a/src/ecmascript/see/location.c b/src/ecmascript/see/location.c
new file mode 100644
index 000000000..38beb9097
--- /dev/null
+++ b/src/ecmascript/see/location.c
@@ -0,0 +1,363 @@
+/* The SEE location and history objects implementation. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "elinks.h"
+
+#include <see/see.h>
+
+#include "bfu/dialog.h"
+#include "cache/cache.h"
+#include "cookies/cookies.h"
+#include "dialogs/menu.h"
+#include "dialogs/status.h"
+#include "document/html/frames.h"
+#include "document/document.h"
+#include "document/forms.h"
+#include "document/view.h"
+#include "ecmascript/ecmascript.h"
+#include "ecmascript/see/input.h"
+#include "ecmascript/see/location.h"
+#include "ecmascript/see/strings.h"
+#include "ecmascript/see/window.h"
+#include "intl/gettext/libintl.h"
+#include "main/select.h"
+#include "osdep/newwin.h"
+#include "osdep/sysname.h"
+#include "protocol/http/http.h"
+#include "protocol/uri.h"
+#include "session/history.h"
+#include "session/location.h"
+#include "session/session.h"
+#include "session/task.h"
+#include "terminal/tab.h"
+#include "terminal/terminal.h"
+#include "util/conv.h"
+#include "util/memory.h"
+#include "util/string.h"
+#include "viewer/text/draw.h"
+#include "viewer/text/form.h"
+#include "viewer/text/link.h"
+#include "viewer/text/vs.h"
+
+static void delayed_goto(void *);
+static void history_get(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *, struct SEE_value *);
+static int history_hasproperty(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *);
+static void js_history_back(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
+static void js_history_forward(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
+static void js_history_go(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
+static void js_location_toString(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
+static void location_get(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *, struct SEE_value *);
+static void location_put(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *, struct SEE_value *, int);
+static int location_hasproperty(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *);
+static int location_canput(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *);
+
+void location_goto(struct document_view *, unsigned char *);
+
+struct js_history_object {
+	struct SEE_object object;
+	struct SEE_object *back;
+	struct SEE_object *forward;
+	struct SEE_object *go;
+};
+
+struct js_location_object {
+	struct SEE_object object;
+	struct SEE_object *toString;
+};
+
+struct delayed_goto {
+	/* It might look more convenient to pass doc_view around but it could
+	 * disappear during wild dances inside of frames or so. */
+	struct view_state *vs;
+	struct uri *uri;
+};
+
+struct SEE_objectclass js_history_object_class = {
+	NULL,
+	history_get,
+	SEE_no_put,
+	SEE_no_canput,
+	history_hasproperty,
+	SEE_no_delete,
+	SEE_no_defaultvalue,
+	NULL,
+	NULL,
+	NULL,
+	NULL
+};
+
+struct SEE_objectclass js_location_object_class = {
+	NULL,
+	location_get,
+	location_put,
+	location_canput,
+	location_hasproperty,
+	SEE_no_delete,
+	SEE_no_defaultvalue,
+	NULL,
+	NULL,
+	NULL,
+	NULL
+};
+
+static void
+delayed_goto(void *data)
+{
+	struct delayed_goto *deg = data;
+
+	assert(deg);
+	if (deg->vs->doc_view
+	    && deg->vs->doc_view == deg->vs->doc_view->session->doc_view) {
+		goto_uri_frame(deg->vs->doc_view->session, deg->uri,
+		               deg->vs->doc_view->name,
+			       CACHE_MODE_NORMAL);
+	}
+	done_uri(deg->uri);
+	mem_free(deg);
+}
+
+void
+location_goto(struct document_view *doc_view, unsigned char *url)
+{
+	unsigned char *new_abs_url;
+	struct uri *new_uri;
+	struct delayed_goto *deg;
+
+	/* Workaround for bug 611. Does not crash, but may lead to infinite loop.*/
+	if (!doc_view) return;
+	new_abs_url = join_urls(doc_view->document->uri,
+	                        trim_chars(url, ' ', 0));
+	if (!new_abs_url)
+		return;
+	new_uri = get_uri(new_abs_url, 0);
+	mem_free(new_abs_url);
+	if (!new_uri)
+		return;
+	deg = mem_calloc(1, sizeof(*deg));
+	if (!deg) {
+		done_uri(new_uri);
+		return;
+	}
+	assert(doc_view->vs);
+	deg->vs = doc_view->vs;
+	deg->uri = new_uri;
+	/* It does not seem to be very safe inside of frames to
+	 * call goto_uri() right away. */
+	register_bottom_half(delayed_goto, deg);
+}
+
+
+static void
+history_get(struct SEE_interpreter *interp, struct SEE_object *o,
+	   struct SEE_string *p, struct SEE_value *res)
+{
+	struct js_history_object *history = (struct js_history_object *)o;
+
+	checktime(interp);
+	if (p == s_back) {
+		SEE_SET_OBJECT(res, history->back);
+	} else if (p == s_forward) {
+		SEE_SET_OBJECT(res, history->forward);
+	} else if (p == s_go) {
+		SEE_SET_OBJECT(res, history->go);
+	} else {
+		SEE_SET_UNDEFINED(res);
+	}
+}
+
+static int
+history_hasproperty(struct SEE_interpreter *interp, struct SEE_object *o,
+	      struct SEE_string *p)
+{
+	checktime(interp);
+	if (p == s_back || p == s_forward || p == s_go)
+		return 1;
+	return 0;
+}
+
+static void
+js_history_back(struct SEE_interpreter *interp, struct SEE_object *self,
+	     struct SEE_object *thisobj, int argc, struct SEE_value **argv,
+	     struct SEE_value *res)
+{
+	struct global_object *g = (struct global_object *)interp;
+	struct view_state *vs = g->win->vs;
+	struct document_view *doc_view = vs->doc_view;
+	struct session *ses = doc_view->session;
+
+	SEE_SET_NULL(res);
+	go_back(ses);
+}
+
+static void
+js_history_forward(struct SEE_interpreter *interp, struct SEE_object *self,
+	     struct SEE_object *thisobj, int argc, struct SEE_value **argv,
+	     struct SEE_value *res)
+{
+	struct global_object *g = (struct global_object *)interp;
+	struct view_state *vs = g->win->vs;
+	struct document_view *doc_view = vs->doc_view;
+	struct session *ses = doc_view->session;
+
+	checktime(interp);
+	SEE_SET_NULL(res);
+	go_unback(ses);
+}
+
+static void
+js_history_go(struct SEE_interpreter *interp, struct SEE_object *self,
+	     struct SEE_object *thisobj, int argc, struct SEE_value **argv,
+	     struct SEE_value *res)
+{
+	struct global_object *g = (struct global_object *)interp;
+	struct view_state *vs = g->win->vs;
+	struct document_view *doc_view = vs->doc_view;
+	struct session *ses = doc_view->session;
+	unsigned char *str;
+	int index;
+	struct location *loc;
+
+	checktime(interp);
+	SEE_SET_NULL(res);
+	if (argc < 1)
+		return;
+
+	str = SEE_value_to_unsigned_char(interp, argv[0]);
+	if (!str)
+		return;
+
+	index  = atol(str);
+	mem_free(str);
+
+	for (loc = cur_loc(ses);
+	     loc != (struct location *) &ses->history.history;
+	     loc = index > 0 ? loc->next : loc->prev) {
+		if (!index) {
+			go_history(ses, loc);
+			break;
+		}
+
+		index += index > 0 ? -1 : 1;
+	}
+}
+
+static void
+js_location_toString(struct SEE_interpreter *interp, struct SEE_object *self,
+	     struct SEE_object *thisobj, int argc, struct SEE_value **argv,
+	     struct SEE_value *res)
+{
+	struct global_object *g = (struct global_object *)interp;
+	struct view_state *vs = g->win->vs;
+	unsigned char *string = get_uri_string(vs->uri, URI_ORIGINAL);
+	struct SEE_string *str = string_to_SEE_string(interp, string);
+
+	mem_free_if(string);	
+	checktime(interp);
+
+	SEE_SET_STRING(res, str);
+}
+
+static void
+location_get(struct SEE_interpreter *interp, struct SEE_object *o,
+	   struct SEE_string *p, struct SEE_value *res)
+{
+	struct js_location_object *loc = (struct js_location_object *)o;
+
+	checktime(interp);
+	if (p == s_toString || p == s_toLocaleString) {
+		SEE_SET_OBJECT(res, loc->toString);
+	} else if (p == s_href) {
+		struct global_object *g = (struct global_object *)interp;
+		struct view_state *vs = g->win->vs;
+		unsigned char *string = get_uri_string(vs->uri, URI_ORIGINAL);
+		struct SEE_string *str = string_to_SEE_string(interp, string);
+
+		mem_free_if(string);
+		SEE_SET_STRING(res, str);
+	} else {
+		SEE_SET_UNDEFINED(res);
+	}
+}
+
+static void
+location_put(struct SEE_interpreter *interp, struct SEE_object *o,
+	   struct SEE_string *p, struct SEE_value *val, int attr)
+{
+	checktime(interp);
+	if (p == s_href) {
+		struct global_object *g = (struct global_object *)interp;
+		struct view_state *vs = g->win->vs;
+		struct document_view *doc_view = vs->doc_view;
+		unsigned char *url = SEE_value_to_unsigned_char(interp, val);
+
+		location_goto(doc_view, url);
+		mem_free(url);
+	}
+}
+
+static int
+location_hasproperty(struct SEE_interpreter *interp, struct SEE_object *o,
+	      struct SEE_string *p)
+{
+	checktime(interp);
+	if (p == s_toString || p == s_toLocaleString || p == s_href)
+		return 1;
+	return 0;
+}
+
+static int
+location_canput(struct SEE_interpreter *interp, struct SEE_object *o,
+	      struct SEE_string *p)
+{
+	checktime(interp);
+	if (p == s_href)
+		return 1;
+	return 0;
+}
+
+void
+init_js_history_object(struct ecmascript_interpreter *interpreter)
+{
+	struct global_object *g = interpreter->backend_data;
+	struct SEE_interpreter *interp = &g->interp;
+	struct SEE_value v;
+	struct js_history_object *history = SEE_NEW(interp,
+	 struct js_history_object);
+
+	history->object.objectclass = &js_history_object_class;
+	history->object.objectclass->Class = s_history;
+	history->object.Prototype = NULL;
+
+	SEE_SET_OBJECT(&v, (struct SEE_object *)history);
+	SEE_OBJECT_PUT(interp, interp->Global, s_history, &v, 0);
+
+	history->back = SEE_cfunction_make(interp, js_history_back, s_back, 0);
+	history->forward = SEE_cfunction_make(interp, js_history_forward, s_forward, 0);
+	history->go = SEE_cfunction_make(interp, js_history_go, s_go, 1);
+}
+
+void
+init_js_location_object(struct ecmascript_interpreter *interpreter)
+{
+	struct global_object *g = interpreter->backend_data;
+	struct SEE_interpreter *interp = &g->interp;
+	struct SEE_value v;
+	struct js_location_object *loc = SEE_NEW(interp,
+		struct js_location_object);
+
+	loc->object.objectclass = &js_location_object_class;
+	loc->object.objectclass->Class = s_location;
+	loc->object.Prototype = NULL;
+
+	SEE_SET_OBJECT(&v, (struct SEE_object *)loc);
+	SEE_OBJECT_PUT(interp, interp->Global, s_location, &v, 0);
+
+	loc->toString = SEE_cfunction_make(interp, js_location_toString, s_toString, 0);
+}
diff --git a/src/ecmascript/see/location.h b/src/ecmascript/see/location.h
new file mode 100644
index 000000000..9a4c096e4
--- /dev/null
+++ b/src/ecmascript/see/location.h
@@ -0,0 +1,9 @@
+#ifndef EL__ECMASCRIPT_SEE_LOCATION_H
+#define EL__ECMASCRIPT_SEE_LOCATION_H
+
+struct ecmascript_interpreter;
+
+void init_js_history_object(struct ecmascript_interpreter *);
+void init_js_location_object(struct ecmascript_interpreter *);
+
+#endif
diff --git a/src/ecmascript/see/navigator.c b/src/ecmascript/see/navigator.c
new file mode 100644
index 000000000..52b600e9d
--- /dev/null
+++ b/src/ecmascript/see/navigator.c
@@ -0,0 +1,150 @@
+/* The SEE navigator objects implementation. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "elinks.h"
+
+#include <see/see.h>
+
+#include "bfu/dialog.h"
+#include "cache/cache.h"
+#include "cookies/cookies.h"
+#include "dialogs/menu.h"
+#include "dialogs/status.h"
+#include "document/html/frames.h"
+#include "document/document.h"
+#include "document/forms.h"
+#include "document/view.h"
+#include "ecmascript/ecmascript.h"
+#include "ecmascript/see/input.h"
+#include "ecmascript/see/navigator.h"
+#include "ecmascript/see/strings.h"
+#include "ecmascript/see/window.h"
+#include "intl/gettext/libintl.h"
+#include "main/select.h"
+#include "osdep/newwin.h"
+#include "osdep/sysname.h"
+#include "protocol/http/http.h"
+#include "protocol/uri.h"
+#include "session/history.h"
+#include "session/location.h"
+#include "session/session.h"
+#include "session/task.h"
+#include "terminal/tab.h"
+#include "terminal/terminal.h"
+#include "util/conv.h"
+#include "util/memory.h"
+#include "util/string.h"
+#include "viewer/text/draw.h"
+#include "viewer/text/form.h"
+#include "viewer/text/link.h"
+#include "viewer/text/vs.h"
+
+static void navigator_get(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *, struct SEE_value *);
+static int navigator_hasproperty(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *);
+
+struct SEE_objectclass js_navigator_object_class = {
+	NULL,
+	navigator_get,
+	SEE_no_put,
+	SEE_no_canput,
+	navigator_hasproperty,
+	SEE_no_delete,
+	SEE_no_defaultvalue,
+	NULL,
+	NULL,
+	NULL,
+	NULL
+};
+
+static void
+navigator_get(struct SEE_interpreter *interp, struct SEE_object *o,
+	   struct SEE_string *p, struct SEE_value *res)
+{
+	struct SEE_string *str;
+
+	checktime(interp);
+	SEE_SET_UNDEFINED(res);
+	if (p == s_appCodeName) {
+		SEE_SET_STRING(res, s_Mozilla);
+	} else if (p == s_appName) {
+		SEE_SET_STRING(res, s_ELinks_);
+	} else if (p == s_appVersion) {
+		str = string_to_SEE_string(interp, VERSION);
+		SEE_SET_STRING(res, str);
+	} else if (p == s_language) {
+#ifdef CONFIG_NLS
+		if (get_opt_bool("protocol.http.accept_ui_language")) {
+			str = string_to_SEE_string(interp,
+			 language_to_iso639(current_language));
+			SEE_SET_STRING(res, str);
+		}
+#endif
+	} else if (p == s_platform) {
+		str = string_to_SEE_string(interp, system_name);
+		SEE_SET_STRING(res, str);
+	} else if (p == s_userAgent) {
+		/* FIXME: Code duplication. */
+		unsigned char *optstr = get_opt_str("protocol.http.user_agent");
+
+		if (*optstr && strcmp(optstr, " ")) {
+			unsigned char *ustr, ts[64] = "";
+			static unsigned char custr[256];
+
+			if (!list_empty(terminals)) {
+				unsigned int tslen = 0;
+				struct terminal *term = terminals.prev;
+
+				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);
+				str = string_to_SEE_string(interp, custr);
+				SEE_SET_STRING(res, str);
+			}
+		}
+	}
+}
+
+
+static int
+navigator_hasproperty(struct SEE_interpreter *interp, struct SEE_object *o,
+	      struct SEE_string *p)
+{
+	checktime(interp);
+	if (p == s_appCodeName || p == s_appName || p == s_appVersion
+	    || p == s_language || p == s_platform || p == s_userAgent)
+		return 1;
+	return 0;
+}
+
+
+
+void
+init_js_navigator_object(struct ecmascript_interpreter *interpreter)
+{
+	struct global_object *g = interpreter->backend_data;
+	struct SEE_interpreter *interp = &g->interp;
+	struct SEE_value v;
+	struct SEE_object *navigator;
+
+	navigator = SEE_NEW(interp, struct SEE_object);
+
+	navigator->objectclass = &js_navigator_object_class;
+	navigator->objectclass->Class = s_navigator;
+	navigator->Prototype = NULL;
+
+	SEE_SET_OBJECT(&v, navigator);
+	SEE_OBJECT_PUT(interp, interp->Global, s_navigator, &v, 0);
+}
diff --git a/src/ecmascript/see/navigator.h b/src/ecmascript/see/navigator.h
new file mode 100644
index 000000000..d5411acaa
--- /dev/null
+++ b/src/ecmascript/see/navigator.h
@@ -0,0 +1,8 @@
+#ifndef EL__ECMASCRIPT_SEE_NAVIGATOR_H
+#define EL__ECMASCRIPT_SEE_NAVIGATOR_H
+
+struct ecmascript_interpreter;
+
+void init_js_navigator_object(struct ecmascript_interpreter *);
+
+#endif
diff --git a/src/ecmascript/see/strings.c b/src/ecmascript/see/strings.c
new file mode 100644
index 000000000..a42d34ea7
--- /dev/null
+++ b/src/ecmascript/see/strings.c
@@ -0,0 +1,379 @@
+#include <see/see.h>
+
+struct SEE_string *s_window;
+struct SEE_string *s_closed;
+struct SEE_string *s_parent;
+struct SEE_string *s_self;
+struct SEE_string *s_top;
+struct SEE_string *s_alert;
+struct SEE_string *s_open;
+
+struct SEE_string *s_menubar;
+
+struct SEE_string *s_statusbar;
+struct SEE_string *s_visible;
+
+struct SEE_string *s_navigator;
+struct SEE_string *s_appCodeName;
+struct SEE_string *s_appName;
+struct SEE_string *s_appVersion;
+struct SEE_string *s_language;
+struct SEE_string *s_platform;
+struct SEE_string *s_userAgent;
+
+struct SEE_string *s_history;
+struct SEE_string *s_back;
+struct SEE_string *s_forward;
+struct SEE_string *s_go;
+
+struct SEE_string *s_location;
+struct SEE_string *s_href;
+struct SEE_string *s_toString;
+struct SEE_string *s_toLocaleString;
+
+struct SEE_string *s_input;
+struct SEE_string *s_accessKey;
+struct SEE_string *s_alt;
+struct SEE_string *s_checked;
+struct SEE_string *s_defaultChecked;
+struct SEE_string *s_defaultValue;
+struct SEE_string *s_disabled;
+struct SEE_string *s_form;
+struct SEE_string *s_maxLength;
+struct SEE_string *s_name;
+struct SEE_string *s_readonly;
+struct SEE_string *s_size;
+struct SEE_string *s_src;
+struct SEE_string *s_tabindex;
+struct SEE_string *s_type;
+struct SEE_string *s_value;
+struct SEE_string *s_blur;
+struct SEE_string *s_click;
+struct SEE_string *s_focus;
+struct SEE_string *s_select;
+
+struct SEE_string *s_elements;
+struct SEE_string *s_item;
+struct SEE_string *s_namedItem;
+struct SEE_string *s_length;
+
+struct SEE_string *s_action;
+struct SEE_string *s_encoding;
+struct SEE_string *s_method;
+struct SEE_string *s_target;
+struct SEE_string *s_reset;
+struct SEE_string *s_submit;
+
+struct SEE_string *s_forms;
+
+struct SEE_string *s_document;
+struct SEE_string *s_referrer;
+struct SEE_string *s_title;
+struct SEE_string *s_url;
+struct SEE_string *s_write;
+
+struct SEE_string *s_Mozilla;
+struct SEE_string *s_ELinks_;
+struct SEE_string *s_cookie;
+
+struct SEE_string *s_GET;
+struct SEE_string *s_POST;
+struct SEE_string *s_application_;
+struct SEE_string *s_multipart_;
+struct SEE_string *s_textplain;
+
+struct SEE_string *s_text;
+struct SEE_string *s_password;
+struct SEE_string *s_file;
+struct SEE_string *s_checkbox;
+struct SEE_string *s_radio;
+struct SEE_string *s_image;
+struct SEE_string *s_button;
+struct SEE_string *s_hidden;
+
+struct SEE_string *s_timeout;
+
+void
+init_intern_strings(void)
+{
+	static SEE_char_t SA_window[] =    {'w','i','n','d','o','w'};
+	static struct SEE_string S_window = SEE_STRING_DECL(SA_window);
+	static SEE_char_t SA_closed[] =  {'c','l','o','s','e','d'};
+	static struct SEE_string S_closed = SEE_STRING_DECL(SA_closed);
+	static SEE_char_t SA_parent[] =  {'p','a','r','e','n','t'};
+	static struct SEE_string S_parent = SEE_STRING_DECL(SA_parent);
+	static SEE_char_t SA_self[] =  {'s','e','l','f'};
+	static struct SEE_string S_self = SEE_STRING_DECL(SA_self);
+	static SEE_char_t SA_top[] =  {'t','o','p'};
+	static struct SEE_string S_top = SEE_STRING_DECL(SA_top);
+	static SEE_char_t SA_alert[] ={'a','l','e','r','t'};
+	static struct SEE_string S_alert = SEE_STRING_DECL(SA_alert);
+	static SEE_char_t SA_open[] ={'o','p','e','n'};
+	static struct SEE_string S_open = SEE_STRING_DECL(SA_open);
+
+	static SEE_char_t SA_menubar[] =  {'m','e','n','u','b','a','r'};
+	static struct SEE_string S_menubar = SEE_STRING_DECL(SA_menubar);
+
+	static SEE_char_t SA_statusbar[] =  {'s','t','a','t','u','s','b','a','r'};
+	static struct SEE_string S_statusbar = SEE_STRING_DECL(SA_statusbar);
+	static SEE_char_t SA_visible[] =  {'v','i','s','i','b','l','e'};
+	static struct SEE_string S_visible = SEE_STRING_DECL(SA_visible);
+
+	static SEE_char_t SA_navigator[] ={'n','a','v','i','g','a','t','o','r'};
+	static struct SEE_string S_navigator = SEE_STRING_DECL(SA_navigator);
+	static SEE_char_t SA_appCodeName[] ={'a','p','p','C','o','d','e','N','a','m','e'};
+	static struct SEE_string S_appCodeName = SEE_STRING_DECL(SA_appCodeName);
+	static SEE_char_t SA_appName[] ={'a','p','p','N','a','m','e'};
+	static struct SEE_string S_appName = SEE_STRING_DECL(SA_appName);
+	static SEE_char_t SA_appVersion[] ={'a','p','p','V','e','r','s','i','o','n'};
+	static struct SEE_string S_appVersion = SEE_STRING_DECL(SA_appVersion);
+	static SEE_char_t SA_language[] ={'l','a','n','g','u','a','g','e'};
+	static struct SEE_string S_language = SEE_STRING_DECL(SA_language);
+	static SEE_char_t SA_platform[] ={'p','l','a','t','f','o','r','m'};
+	static struct SEE_string S_platform = SEE_STRING_DECL(SA_platform);
+	static SEE_char_t SA_userAgent[] ={'u','s','e','r','A','g','e','n','t'};
+	static struct SEE_string S_userAgent = SEE_STRING_DECL(SA_userAgent);
+
+	static SEE_char_t SA_history[] ={'h','i','s','t','o','r','y'};
+	static struct SEE_string S_history = SEE_STRING_DECL(SA_history);
+	static SEE_char_t SA_back[] ={'b','a','c','k'};
+	static struct SEE_string S_back = SEE_STRING_DECL(SA_back);
+	static SEE_char_t SA_forward[] ={'f','o','r','w','a','r','d'};
+	static struct SEE_string S_forward = SEE_STRING_DECL(SA_forward);
+	static SEE_char_t SA_go[] ={'g','o'};
+	static struct SEE_string S_go = SEE_STRING_DECL(SA_go);
+
+	static SEE_char_t SA_location[] ={'l','o','c','a','t','i','o','n'};
+	static struct SEE_string S_location = SEE_STRING_DECL(SA_location);
+	static SEE_char_t SA_href[] ={'h','r','e','f'};
+	static struct SEE_string S_href = SEE_STRING_DECL(SA_href);
+	static SEE_char_t SA_toString[] ={'t','o','S','t','r','i','n','g'};
+	static struct SEE_string S_toString = SEE_STRING_DECL(SA_toString);
+	static SEE_char_t SA_toLocaleString[] ={'t','o','L','o','c','a','l','e','S','t','r','i','n','g'};
+	static struct SEE_string S_toLocaleString = SEE_STRING_DECL(SA_toLocaleString);
+
+	static SEE_char_t SA_input[] ={'i','n','p','u','t'};
+	static struct SEE_string S_input = SEE_STRING_DECL(SA_input);
+	static SEE_char_t SA_accessKey[] ={'a','c','c','e','s','s','K','e','y'};
+	static struct SEE_string S_accessKey = SEE_STRING_DECL(SA_accessKey);
+	static SEE_char_t SA_alt[] ={'a','l','t'};
+	static struct SEE_string S_alt = SEE_STRING_DECL(SA_alt);
+	static SEE_char_t SA_checked[] ={'c','h','e','c','k','e','d'};
+	static struct SEE_string S_checked = SEE_STRING_DECL(SA_checked);
+	static SEE_char_t SA_defaultChecked[] ={'d','e','f','a','u','l','t','C','h','e','c','k','e','d'};
+	static struct SEE_string S_defaultChecked = SEE_STRING_DECL(SA_defaultChecked);
+	static SEE_char_t SA_defaultValue[] ={'d','e','f','a','u','l','t','V','a','l','u','e'};
+	static struct SEE_string S_defaultValue = SEE_STRING_DECL(SA_defaultValue);
+	static SEE_char_t SA_disabled[] ={'d','i','s','a','b','l','e','d'};
+	static struct SEE_string S_disabled = SEE_STRING_DECL(SA_disabled);
+	static SEE_char_t SA_form[] ={'f','o','r','m'};
+	static struct SEE_string S_form = SEE_STRING_DECL(SA_form);
+	static SEE_char_t SA_maxLength[] ={'m','a','x','L','e','n','g','t','h'};
+	static struct SEE_string S_maxLength = SEE_STRING_DECL(SA_maxLength);
+	static SEE_char_t SA_name[] ={'n','a','m','e'};
+	static struct SEE_string S_name = SEE_STRING_DECL(SA_name);
+	static SEE_char_t SA_readonly[] ={'r','e','a','d','o','n','l','y'};
+	static struct SEE_string S_readonly = SEE_STRING_DECL(SA_readonly);
+	static SEE_char_t SA_size[] ={'s','i','z','e'};
+	static struct SEE_string S_size = SEE_STRING_DECL(SA_size);
+	static SEE_char_t SA_src[] ={'s','r','c'};
+	static struct SEE_string S_src = SEE_STRING_DECL(SA_src);
+	static SEE_char_t SA_tabindex[] ={'t','a','b','i','n','d','e','x'};
+	static struct SEE_string S_tabindex = SEE_STRING_DECL(SA_tabindex);
+	static SEE_char_t SA_type[] ={'t','y','p','e'};
+	static struct SEE_string S_type = SEE_STRING_DECL(SA_type);
+	static SEE_char_t SA_value[] ={'v','a','l','u','e'};
+	static struct SEE_string S_value = SEE_STRING_DECL(SA_value);
+	static SEE_char_t SA_blur[] ={'b','l','u','r'};
+	static struct SEE_string S_blur = SEE_STRING_DECL(SA_blur);
+	static SEE_char_t SA_click[] ={'c','l','i','c','k'};
+	static struct SEE_string S_click = SEE_STRING_DECL(SA_click);
+	static SEE_char_t SA_focus[] ={'f','o','c','u','s'};
+	static struct SEE_string S_focus = SEE_STRING_DECL(SA_focus);
+	static SEE_char_t SA_select[] ={'s','e','l','e','c','t'};
+	static struct SEE_string S_select = SEE_STRING_DECL(SA_select);
+
+	static SEE_char_t SA_elements[] ={'e','l','e','m','e','n','t','s'};
+	static struct SEE_string S_elements = SEE_STRING_DECL(SA_elements);
+	static SEE_char_t SA_item[] ={'i','t','e','m'};
+	static struct SEE_string S_item = SEE_STRING_DECL(SA_item);
+	static SEE_char_t SA_namedItem[] ={'n','a','m','e','d','I','t','e','m'};
+	static struct SEE_string S_namedItem = SEE_STRING_DECL(SA_namedItem);
+	static SEE_char_t SA_length[] ={'l','e','n','g','t','h'};
+	static struct SEE_string S_length = SEE_STRING_DECL(SA_length);
+
+	static SEE_char_t SA_action[] ={'a','c','t','i','o','n'};
+	static struct SEE_string S_action = SEE_STRING_DECL(SA_action);
+	static SEE_char_t SA_encoding[] ={'e','n','c','o','d','i','g'};
+	static struct SEE_string S_encoding = SEE_STRING_DECL(SA_encoding);
+	static SEE_char_t SA_method[] ={'m','e','t','h','o','d'};
+	static struct SEE_string S_method = SEE_STRING_DECL(SA_method);
+	static SEE_char_t SA_target[] ={'t','a','r','g','e','t'};
+	static struct SEE_string S_target = SEE_STRING_DECL(SA_target);
+	static SEE_char_t SA_reset[] ={'r','e','s','e','t'};
+	static struct SEE_string S_reset = SEE_STRING_DECL(SA_reset);
+	static SEE_char_t SA_submit[] ={'s','u','b','m','i','t'};
+	static struct SEE_string S_submit = SEE_STRING_DECL(SA_submit);
+
+	static SEE_char_t SA_forms[] ={'f','o','r','m','s'};
+	static struct SEE_string S_forms = SEE_STRING_DECL(SA_forms);
+
+	static SEE_char_t SA_document[] = {'d','o','c','u','m','e','n','t'};
+	static struct SEE_string S_document = SEE_STRING_DECL(SA_document);
+	static SEE_char_t SA_referrer[] ={'r','e','f','e','r','r','e','r'};
+	static struct SEE_string S_referrer = SEE_STRING_DECL(SA_referrer);
+	static SEE_char_t SA_title[] ={'t','i','t','l','e'};
+	static struct SEE_string S_title = SEE_STRING_DECL(SA_title);
+	static SEE_char_t SA_url[] ={'u','r','l'};
+	static struct SEE_string S_url = SEE_STRING_DECL(SA_url);
+	static SEE_char_t SA_write[] = {'w','r','i','t','e'};
+	static struct SEE_string S_write = SEE_STRING_DECL(SA_write);
+
+	static SEE_char_t SA_Mozilla[] = {'M','o','z','i','l','l','a'};
+	static struct SEE_string S_Mozilla = SEE_STRING_DECL(SA_Mozilla);
+	static SEE_char_t SA_ELinks_[] = {'E','L','i','n','k','s',' ','(',
+	 'r','o','u','g','h','l','y',' ','c','o','m','p','a','t','i','b','l','e',
+	 ' ','w','i','t','h',' ','N','e','t','s','c','a','p','e',' ',
+	 'N','a','v','i','g','a','t','o','r',',',' ','M','o','z','i','l','l','a',
+	 ' ','a','n','d',' ','M','i','c','r','o','s','o','f','t',' ',
+	 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r',')'};
+	static struct SEE_string S_ELinks_ = SEE_STRING_DECL(SA_ELinks_);
+
+	static SEE_char_t SA_cookie[] = {'c','o','o','k','i','e'};
+	static struct SEE_string S_cookie = SEE_STRING_DECL(SA_cookie);
+
+	static SEE_char_t SA_GET[] = {'G','E','T'};
+	static struct SEE_string S_GET = SEE_STRING_DECL(SA_GET);
+	static SEE_char_t SA_POST[] = {'P','O','S','T'};
+	static struct SEE_string S_POST = SEE_STRING_DECL(SA_POST);
+
+	static SEE_char_t SA_application_[] = {'a','p','p','l','i','c','a','t',
+	'i','o','n','/','x','-','w','w','w','-','f','o','r','m','-','u','r','l',
+	'e','n','c','o','d','e','d'};
+	static struct SEE_string S_application_ = SEE_STRING_DECL(SA_application_);
+	static SEE_char_t SA_multipart_[] = {'m','u','l','t','i','p','a','r','t','/',
+	'f','o','r','m','-','d','a','t','a'};
+	static struct SEE_string S_multipart_ = SEE_STRING_DECL(SA_multipart_);
+	static SEE_char_t SA_textplain[] = {'t','e','x','t','/','p','l','a','i','n'};
+	static struct SEE_string S_textplain = SEE_STRING_DECL(SA_textplain);
+
+	static SEE_char_t SA_text[] = {'t','e','x','t'};
+	static struct SEE_string S_text = SEE_STRING_DECL(SA_text);
+
+	static SEE_char_t SA_password[] = {'p','a','s','s','w','o','r','d'};
+	static struct SEE_string S_password = SEE_STRING_DECL(SA_password);
+
+	static SEE_char_t SA_file[] = {'f','i','l','e'};
+	static struct SEE_string S_file = SEE_STRING_DECL(SA_file);
+
+	static SEE_char_t SA_checkbox[] = {'c','h','e','c','k','b','o','x'};
+	static struct SEE_string S_checkbox = SEE_STRING_DECL(SA_checkbox);
+
+	static SEE_char_t SA_radio[] = {'r','a','d','i','o'};
+	static struct SEE_string S_radio = SEE_STRING_DECL(SA_radio);
+
+	static SEE_char_t SA_image[] = {'i','m','a','g','e'};
+	static struct SEE_string S_image = SEE_STRING_DECL(SA_image);
+
+	static SEE_char_t SA_button[] = {'b','u','t','t','o','n'};
+	static struct SEE_string S_button = SEE_STRING_DECL(SA_button);
+
+	static SEE_char_t SA_hidden[] = {'h','i','d','d','e','n'};
+	static struct SEE_string S_hidden = SEE_STRING_DECL(SA_hidden);
+
+	static SEE_char_t SA_timeout[] = {'t','i','m','e','o','u','t'};
+	static struct SEE_string S_timeout = SEE_STRING_DECL(SA_timeout);
+
+	SEE_intern_global(s_window = &S_window);
+	SEE_intern_global(s_closed = &S_closed);
+	SEE_intern_global(s_parent = &S_parent);
+	SEE_intern_global(s_self = &S_self);
+	SEE_intern_global(s_top = &S_top);
+	SEE_intern_global(s_alert = &S_alert);
+	SEE_intern_global(s_open = &S_open);
+
+	SEE_intern_global(s_menubar = &S_menubar);
+	SEE_intern_global(s_statusbar = &S_statusbar);
+	SEE_intern_global(s_visible = &S_visible);
+
+	SEE_intern_global(s_navigator = &S_navigator);
+	SEE_intern_global(s_appCodeName = &S_appCodeName);
+	SEE_intern_global(s_appName = &S_appName);
+	SEE_intern_global(s_appVersion = &S_appVersion);
+	SEE_intern_global(s_language = &S_language);
+	SEE_intern_global(s_platform = &S_platform);
+	SEE_intern_global(s_userAgent = &S_userAgent);
+
+	SEE_intern_global(s_history = &S_history);
+	SEE_intern_global(s_back = &S_back);
+	SEE_intern_global(s_forward = &S_forward);
+	SEE_intern_global(s_go = &S_go);
+
+	SEE_intern_global(s_location = &S_location);
+	SEE_intern_global(s_href = &S_href);
+	SEE_intern_global(s_toString = &S_toString);
+	SEE_intern_global(s_toLocaleString = &S_toLocaleString);
+
+	SEE_intern_global(s_input = &S_input);
+	SEE_intern_global(s_accessKey = &S_accessKey);
+	SEE_intern_global(s_alt = &S_alt);
+	SEE_intern_global(s_checked = &S_checked);
+	SEE_intern_global(s_defaultChecked = &S_defaultChecked);
+	SEE_intern_global(s_defaultValue = &S_defaultValue);
+	SEE_intern_global(s_disabled = &S_disabled);
+	SEE_intern_global(s_form = &S_form);
+	SEE_intern_global(s_maxLength = &S_maxLength);
+	SEE_intern_global(s_name = &S_name);
+	SEE_intern_global(s_readonly = &S_readonly);
+	SEE_intern_global(s_size = &S_size);
+	SEE_intern_global(s_src = &S_src);
+	SEE_intern_global(s_tabindex = &S_tabindex);
+	SEE_intern_global(s_type = &S_type);
+	SEE_intern_global(s_value = &S_value);
+	SEE_intern_global(s_blur = &S_blur);
+	SEE_intern_global(s_click = &S_click);
+	SEE_intern_global(s_focus = &S_focus);
+	SEE_intern_global(s_select = &S_select);
+
+	SEE_intern_global(s_elements = &S_elements);
+	SEE_intern_global(s_item = &S_item);
+	SEE_intern_global(s_namedItem = &S_namedItem);
+	SEE_intern_global(s_length = &S_length);
+
+	SEE_intern_global(s_action = &S_action);
+	SEE_intern_global(s_encoding = &S_encoding);
+	SEE_intern_global(s_method = &S_method);
+	SEE_intern_global(s_target = &S_target);
+	SEE_intern_global(s_reset = &S_reset);
+	SEE_intern_global(s_submit = &S_submit);
+
+	SEE_intern_global(s_forms = &S_forms);
+
+	SEE_intern_global(s_document = &S_document);
+	SEE_intern_global(s_referrer = &S_referrer);
+	SEE_intern_global(s_title = &S_title);
+	SEE_intern_global(s_url = &S_url);
+	SEE_intern_global(s_write = &S_write);
+
+	SEE_intern_global(s_Mozilla = &S_Mozilla);
+	SEE_intern_global(s_ELinks_ = &S_ELinks_);
+	SEE_intern_global(s_cookie = &S_cookie);
+
+	SEE_intern_global(s_GET = &S_GET);
+	SEE_intern_global(s_POST = &S_POST);
+
+	SEE_intern_global(s_application_ = &S_application_);
+	SEE_intern_global(s_multipart_ = &S_multipart_);
+	SEE_intern_global(s_textplain = &S_textplain);
+
+	SEE_intern_global(s_text = &S_text);
+	SEE_intern_global(s_password = &S_password);
+	SEE_intern_global(s_file = &S_file);
+	SEE_intern_global(s_checkbox = &S_checkbox);
+	SEE_intern_global(s_radio = &S_radio);
+	SEE_intern_global(s_image = &S_image);
+	SEE_intern_global(s_button = &S_button);
+	SEE_intern_global(s_hidden = &S_hidden);
+
+	SEE_intern_global(s_timeout = &S_timeout);
+}
diff --git a/src/ecmascript/see/strings.h b/src/ecmascript/see/strings.h
new file mode 100644
index 000000000..75f254a92
--- /dev/null
+++ b/src/ecmascript/see/strings.h
@@ -0,0 +1,101 @@
+
+#ifndef EL__ECMASCRIPT_SEE_STRINGS_H
+#define EL__ECMASCRIPT_SEE_STRINGS_H
+
+#include <see/see.h>
+
+void init_intern_strings(void);
+
+extern struct SEE_string *s_window;
+extern struct SEE_string *s_closed;
+extern struct SEE_string *s_parent;
+extern struct SEE_string *s_self;
+extern struct SEE_string *s_top;
+extern struct SEE_string *s_alert;
+extern struct SEE_string *s_open;
+
+extern struct SEE_string *s_menubar;
+
+extern struct SEE_string *s_statusbar;
+extern struct SEE_string *s_visible;
+
+extern struct SEE_string *s_navigator;
+extern struct SEE_string *s_appCodeName;
+extern struct SEE_string *s_appName;
+extern struct SEE_string *s_appVersion;
+extern struct SEE_string *s_language;
+extern struct SEE_string *s_platform;
+extern struct SEE_string *s_userAgent;
+
+extern struct SEE_string *s_history;
+extern struct SEE_string *s_back;
+extern struct SEE_string *s_forward;
+extern struct SEE_string *s_go;
+
+extern struct SEE_string *s_location;
+extern struct SEE_string *s_href;
+extern struct SEE_string *s_toString;
+extern struct SEE_string *s_toLocaleString;
+
+extern struct SEE_string *s_input;
+extern struct SEE_string *s_accessKey;
+extern struct SEE_string *s_alt;
+extern struct SEE_string *s_checked;
+extern struct SEE_string *s_defaultChecked;
+extern struct SEE_string *s_defaultValue;
+extern struct SEE_string *s_disabled;
+extern struct SEE_string *s_form;
+extern struct SEE_string *s_maxLength;
+extern struct SEE_string *s_name;
+extern struct SEE_string *s_readonly;
+extern struct SEE_string *s_size;
+extern struct SEE_string *s_src;
+extern struct SEE_string *s_tabindex;
+extern struct SEE_string *s_type;
+extern struct SEE_string *s_value;
+extern struct SEE_string *s_blur;
+extern struct SEE_string *s_click;
+extern struct SEE_string *s_focus;
+extern struct SEE_string *s_select;
+
+extern struct SEE_string *s_elements;
+extern struct SEE_string *s_item;
+extern struct SEE_string *s_namedItem;
+extern struct SEE_string *s_length;
+
+extern struct SEE_string *s_action;
+extern struct SEE_string *s_encoding;
+extern struct SEE_string *s_method;
+extern struct SEE_string *s_target;
+extern struct SEE_string *s_reset;
+extern struct SEE_string *s_submit;
+
+extern struct SEE_string *s_forms;
+
+extern struct SEE_string *s_document;
+extern struct SEE_string *s_referrer;
+extern struct SEE_string *s_title;
+extern struct SEE_string *s_url;
+extern struct SEE_string *s_write;
+
+extern struct SEE_string *s_Mozilla;
+extern struct SEE_string *s_ELinks_;
+extern struct SEE_string *s_cookie;
+
+extern struct SEE_string *s_GET;
+extern struct SEE_string *s_POST;
+extern struct SEE_string *s_application_;
+extern struct SEE_string *s_multipart_;
+extern struct SEE_string *s_textplain;
+
+extern struct SEE_string *s_text;
+extern struct SEE_string *s_password;
+extern struct SEE_string *s_file;
+extern struct SEE_string *s_checkbox;
+extern struct SEE_string *s_radio;
+extern struct SEE_string *s_image;
+extern struct SEE_string *s_button;
+extern struct SEE_string *s_hidden;
+
+extern struct SEE_string *s_timeout;
+#endif
diff --git a/src/ecmascript/see/unibar.c b/src/ecmascript/see/unibar.c
new file mode 100644
index 000000000..ecbfb5074
--- /dev/null
+++ b/src/ecmascript/see/unibar.c
@@ -0,0 +1,206 @@
+/* The SEE location and history objects implementation. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "elinks.h"
+
+#include <see/see.h>
+
+#include "bfu/dialog.h"
+#include "cache/cache.h"
+#include "cookies/cookies.h"
+#include "dialogs/menu.h"
+#include "dialogs/status.h"
+#include "document/html/frames.h"
+#include "document/document.h"
+#include "document/forms.h"
+#include "document/view.h"
+#include "ecmascript/ecmascript.h"
+#include "ecmascript/see/input.h"
+#include "ecmascript/see/strings.h"
+#include "ecmascript/see/unibar.h"
+#include "ecmascript/see/window.h"
+#include "intl/gettext/libintl.h"
+#include "main/select.h"
+#include "osdep/newwin.h"
+#include "osdep/sysname.h"
+#include "protocol/http/http.h"
+#include "protocol/uri.h"
+#include "session/history.h"
+#include "session/location.h"
+#include "session/session.h"
+#include "session/task.h"
+#include "terminal/tab.h"
+#include "terminal/terminal.h"
+#include "util/conv.h"
+#include "util/memory.h"
+#include "util/string.h"
+#include "viewer/text/draw.h"
+#include "viewer/text/form.h"
+#include "viewer/text/link.h"
+#include "viewer/text/vs.h"
+
+static void unibar_get(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *, struct SEE_value *);
+static void unibar_put(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *, struct SEE_value *, int);
+static int unibar_canput(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *);
+static int unibar_hasproperty(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *);
+
+struct js_unibar_object {
+	struct SEE_object object;
+	unsigned char bar;
+};
+
+struct SEE_objectclass js_menubar_object_class = {
+	NULL,
+	unibar_get,
+	unibar_put,
+	unibar_canput,
+	unibar_hasproperty,
+	SEE_no_delete,
+	SEE_no_defaultvalue,
+	NULL,
+	NULL,
+	NULL,
+	NULL
+};
+
+struct SEE_objectclass js_statusbar_object_class = {
+	NULL,
+	unibar_get,
+	unibar_put,
+	unibar_canput,
+	unibar_hasproperty,
+	SEE_no_delete,
+	SEE_no_defaultvalue,
+	NULL,
+	NULL,
+	NULL,
+	NULL
+};
+
+static void
+unibar_get(struct SEE_interpreter *interp, struct SEE_object *o,
+	   struct SEE_string *p, struct SEE_value *res)
+{
+	struct global_object *g = (struct global_object *)interp;
+	struct view_state *vs = g->win->vs;
+	struct document_view *doc_view = vs->doc_view;
+	struct session_status *status = &doc_view->session->status;
+	struct js_unibar_object *obj = (struct js_unibar_object *)o;
+	unsigned char bar = obj->bar;
+	
+	checktime(interp);
+	if (p == s_visible) {
+#define unibar_fetch(bar) \
+	SEE_SET_BOOLEAN(res, status->force_show_##bar##_bar >= 0 \
+	          ? status->force_show_##bar##_bar \
+	          : status->show_##bar##_bar)
+		switch (bar) {
+			case 's':
+				unibar_fetch(status);
+				break;
+			case 't':
+				unibar_fetch(title);
+				break;
+			default:
+				SEE_SET_BOOLEAN(res, 0);
+				break;
+		}
+#undef unibar_fetch
+		return;
+	}
+	SEE_SET_UNDEFINED(res);
+}
+
+static void
+unibar_put(struct SEE_interpreter *interp, struct SEE_object *o,
+	   struct SEE_string *p, struct SEE_value *val, int attr)
+{
+	checktime(interp);
+	if (p == s_location) {
+		struct global_object *g = (struct global_object *)interp;
+		struct view_state *vs = g->win->vs;
+		struct document_view *doc_view = vs->doc_view;
+		struct session_status *status = &doc_view->session->status;
+		struct js_unibar_object *obj = (struct js_unibar_object *)o;
+		unsigned char bar = obj->bar;
+
+		switch (bar) {
+			case 's':
+				status->force_show_status_bar =
+				 SEE_ToUint32(interp, val);
+				break;
+			case 't':
+				status->force_show_title_bar =
+				 SEE_ToUint32(interp, val);
+				break;
+			default:
+				break;
+
+		}
+	}
+}
+
+static int
+unibar_canput(struct SEE_interpreter *interp, struct SEE_object *o,
+	      struct SEE_string *p)
+{
+	checktime(interp);
+	if (p == s_visible)
+		return 1;
+	return 0;
+}
+
+static int
+unibar_hasproperty(struct SEE_interpreter *interp, struct SEE_object *o,
+	      struct SEE_string *p)
+{
+	checktime(interp);
+	if (p == s_visible)
+		return 1;
+	return 0;
+}
+
+void
+init_js_menubar_object(struct ecmascript_interpreter *interpreter)
+{
+	struct global_object *g = interpreter->backend_data;
+	struct SEE_interpreter *interp = &g->interp;
+	struct SEE_value v;
+	struct js_unibar_object *menu;
+
+	menu = SEE_NEW(interp, struct js_unibar_object);
+
+	menu->object.objectclass = &js_menubar_object_class;
+	menu->object.objectclass->Class = s_menubar;
+	menu->object.Prototype = NULL;
+	menu->bar = 't';
+
+	SEE_SET_OBJECT(&v, (struct SEE_object *)menu);
+	SEE_OBJECT_PUT(interp, interp->Global, s_menubar, &v, 0);
+}
+
+void
+init_js_statusbar_object(struct ecmascript_interpreter *interpreter)
+{
+	struct global_object *g = interpreter->backend_data;
+	struct SEE_interpreter *interp = &g->interp;
+	struct SEE_value v;
+	struct js_unibar_object *status;
+
+	status = SEE_NEW(interp, struct js_unibar_object);
+
+	status->object.objectclass = &js_statusbar_object_class;
+	status->object.objectclass->Class = s_statusbar;
+	status->object.Prototype = NULL;
+	status->bar = 's';
+
+	SEE_SET_OBJECT(&v, (struct SEE_object *)status);
+	SEE_OBJECT_PUT(interp, interp->Global, s_statusbar, &v, 0);
+}
diff --git a/src/ecmascript/see/unibar.h b/src/ecmascript/see/unibar.h
new file mode 100644
index 000000000..7eaf6e763
--- /dev/null
+++ b/src/ecmascript/see/unibar.h
@@ -0,0 +1,9 @@
+#ifndef EL__ECMASCRIPT_SEE_UNIBAR_H
+#define EL__ECMASCRIPT_SEE_UNIBAR_H
+
+struct emascript_interpreter;
+
+void init_js_menubar_object(struct ecmascript_interpreter *);
+void init_js_statusbar_object(struct ecmascript_interpreter *);
+
+#endif
diff --git a/src/ecmascript/see/window.c b/src/ecmascript/see/window.c
new file mode 100644
index 000000000..b8e8b420b
--- /dev/null
+++ b/src/ecmascript/see/window.c
@@ -0,0 +1,371 @@
+/* The SEE window object implementation. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "elinks.h"
+
+#include <see/see.h>
+
+#include "bfu/dialog.h"
+#include "cache/cache.h"
+#include "cookies/cookies.h"
+#include "dialogs/menu.h"
+#include "dialogs/status.h"
+#include "document/html/frames.h"
+#include "document/document.h"
+#include "document/forms.h"
+#include "document/view.h"
+#include "ecmascript/ecmascript.h"
+#include "ecmascript/see/input.h"
+#include "ecmascript/see/strings.h"
+#include "ecmascript/see/window.h"
+#include "intl/gettext/libintl.h"
+#include "main/select.h"
+#include "osdep/newwin.h"
+#include "osdep/sysname.h"
+#include "protocol/http/http.h"
+#include "protocol/uri.h"
+#include "session/history.h"
+#include "session/location.h"
+#include "session/session.h"
+#include "session/task.h"
+#include "terminal/tab.h"
+#include "terminal/terminal.h"
+#include "util/conv.h"
+#include "util/memory.h"
+#include "util/string.h"
+#include "viewer/text/draw.h"
+#include "viewer/text/form.h"
+#include "viewer/text/link.h"
+#include "viewer/text/vs.h"
+
+static struct js_window_object *js_get_global_object(void *);
+static struct js_window_object *js_try_resolve_frame(struct document_view *, unsigned char *);
+static void delayed_open(void *);
+static void delayed_goto_uri_frame(void *);
+static void window_get(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *, struct SEE_value *);
+static void window_put(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *, struct SEE_value *, int);
+static int window_canput(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *);
+static int window_hasproperty(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *);
+static void js_window_alert(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
+static void js_window_open(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
+
+void location_goto(struct document_view *, unsigned char *);
+
+struct delayed_open {
+	struct session *ses;
+	struct uri *uri;
+	unsigned char *target;
+};
+
+struct SEE_objectclass js_window_object_class = {
+	NULL,
+	window_get,
+	window_put,
+	window_canput,
+	window_hasproperty,
+	SEE_no_delete,
+	SEE_no_defaultvalue,
+	NULL,
+	NULL,
+	NULL,
+	NULL
+};
+
+static struct js_window_object *
+js_get_global_object(void *data)
+{
+	struct global_object *g = (struct global_object *)data;
+	return g->win;
+}
+
+static struct js_window_object *
+js_try_resolve_frame(struct document_view *doc_view, unsigned char *id)
+{
+	struct session *ses = doc_view->session;
+	struct frame *target;
+
+	assert(ses);
+	target = ses_find_frame(ses, id);
+	if (!target) return NULL;
+	if (target->vs.ecmascript_fragile)
+		ecmascript_reset_state(&target->vs);
+	if (!target->vs.ecmascript) return NULL;
+	return js_get_global_object(target->vs.ecmascript->backend_data);
+}
+
+
+static void
+delayed_open(void *data)
+{
+	struct delayed_open *deo = data;
+
+	assert(deo);
+	open_uri_in_new_tab(deo->ses, deo->uri, 0, 0);
+	done_uri(deo->uri);
+	mem_free(deo);
+}
+
+static void
+delayed_goto_uri_frame(void *data)
+{
+	struct delayed_open *deo = data;
+
+	assert(deo);
+	goto_uri_frame(deo->ses, deo->uri, deo->target, CACHE_MODE_NORMAL);
+	done_uri(deo->uri);
+	mem_free(deo);
+}
+
+
+
+static void
+window_get(struct SEE_interpreter *interp, struct SEE_object *o,
+	   struct SEE_string *p, struct SEE_value *res)
+{
+	struct js_window_object *win = (struct js_window_object *)o;
+	struct view_state *vs = win->vs;
+
+	checktime(interp);
+	if (p == s_closed) {
+		SEE_SET_BOOLEAN(res, 0);
+	} else if (p == s_self) {
+		SEE_SET_OBJECT(res, o);
+	} else if (p == s_top || p == s_parent) {
+		struct document_view *doc_view = vs->doc_view;
+		struct document_view *top_view = doc_view->session->doc_view;
+		struct js_window_object *newjsframe;
+
+		assert(top_view && top_view->vs);
+		if (top_view->vs->ecmascript_fragile)
+			ecmascript_reset_state(top_view->vs);
+		if (!top_view->vs->ecmascript) {
+			SEE_SET_UNDEFINED(res);
+			return;
+		}
+		newjsframe = js_get_global_object(
+			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)) {
+			SEE_SET_OBJECT(res, (struct SEE_object *)newjsframe);
+		}
+
+	} else if (p == s_alert) {
+		SEE_SET_OBJECT(res, win->alert);
+	} else if (p == s_open) {
+		SEE_SET_OBJECT(res, win->open);
+	} else {
+		unsigned char *frame = SEE_string_to_unsigned_char(p);
+		struct document_view *doc_view = vs->doc_view;
+		struct js_window_object *obj =
+		 js_try_resolve_frame(doc_view, frame);
+
+		mem_free_if(frame);
+		if (obj) {
+			SEE_SET_OBJECT(res, (struct SEE_object *)obj);
+		} else {
+			SEE_SET_UNDEFINED(res);
+		}
+	}
+}
+
+static void
+window_put(struct SEE_interpreter *interp, struct SEE_object *o,
+	   struct SEE_string *p, struct SEE_value *val, int attr)
+{
+	checktime(interp);
+	if (p == s_location) {
+		struct js_window_object *win = (struct js_window_object *)o;
+		struct view_state *vs = win->vs;
+		struct document_view *doc_view = vs->doc_view;
+		unsigned char *str = SEE_value_to_unsigned_char(interp, val);
+
+		if (str) {
+			location_goto(doc_view, str);
+			mem_free(str);
+		}
+	}
+}
+
+static int
+window_canput(struct SEE_interpreter *interp, struct SEE_object *o,
+	      struct SEE_string *p)
+{
+	checktime(interp);
+	if (p == s_location)
+		return 1;
+	return 0;
+}
+
+static int
+window_hasproperty(struct SEE_interpreter *interp, struct SEE_object *o,
+	      struct SEE_string *p)
+{
+	checktime(interp);
+	/* all unknown properties return UNDEFINED value */
+	return 1;
+}
+
+
+static void
+js_window_alert(struct SEE_interpreter *interp, struct SEE_object *self,
+	     struct SEE_object *thisobj, int argc, struct SEE_value **argv,
+	     struct SEE_value *res)
+{
+	struct js_window_object *win = (struct js_window_object *)thisobj;
+	struct view_state *vs = win->vs;
+	unsigned char *string;
+
+	checktime(interp);
+	SEE_SET_BOOLEAN(res, 1);
+	if (argc < 1)
+		return;
+
+	string = SEE_value_to_unsigned_char(interp, argv[0]);
+	if (!string || !*string)
+		return;
+
+	info_box(vs->doc_view->session->tab->term, MSGBOX_FREE_TEXT,
+		N_("JavaScript Alert"), ALIGN_CENTER, string);
+
+
+}
+
+static void
+js_window_open(struct SEE_interpreter *interp, struct SEE_object *self,
+	     struct SEE_object *thisobj, int argc, struct SEE_value **argv,
+	     struct SEE_value *res)
+{
+	struct js_window_object *win = (struct js_window_object*)thisobj;
+	struct view_state *vs = win->vs;
+	struct document_view *doc_view = vs->doc_view;
+	struct session *ses = doc_view->session;
+	unsigned char *target = "";
+	unsigned char *url, *url2;
+	struct uri *uri;
+#if 0
+	static time_t ratelimit_start;
+	static int ratelimit_count;
+#endif
+	checktime(interp);
+	SEE_SET_UNDEFINED(res);
+	if (get_opt_bool("ecmascript.block_window_opening")) {
+#ifdef CONFIG_LEDS
+		set_led_value(ses->status.popup_led, 'P');
+#endif
+		return;
+	}
+
+	if (argc < 1) return;
+#if 0
+	/* Ratelimit window opening. Recursive window.open() is very nice.
+	 * We permit at most 20 tabs in 2 seconds. The ratelimiter is very
+	 * rough but shall suffice against the usual cases. */
+
+	if (!ratelimit_start || time(NULL) - ratelimit_start > 2) {
+		ratelimit_start = time(NULL);
+		ratelimit_count = 0;
+	} else {
+		ratelimit_count++;
+		if (ratelimit_count > 20)
+			return;
+	}
+#endif
+	url = SEE_value_to_unsigned_char(interp, argv[0]);
+	if (!url) return;
+
+	/* TODO: Support for window naming and perhaps some window features? */
+
+	url2 = join_urls(doc_view->document->uri,
+	                trim_chars(url, ' ', 0));
+	mem_free(url);
+	if (!url2) return;
+	uri = get_uri(url2, 0);
+	mem_free(url2);
+	if (!uri) return;
+
+	if (argc > 1)
+		target = SEE_value_to_unsigned_char(interp, argv[1]);
+
+	if (target && *target && strcasecmp(target, "_blank")) {
+		struct delayed_open *deo = mem_calloc(1, sizeof(*deo));
+
+		if (deo) {
+			deo->ses = ses;
+			deo->uri = get_uri_reference(uri);
+			deo->target = target;
+			register_bottom_half(delayed_goto_uri_frame, deo);
+			goto end;
+		}
+	}
+
+	if (!get_cmd_opt_bool("no-connect")
+	    && !get_cmd_opt_bool("no-home")
+	    && !get_cmd_opt_bool("anonymous")
+	    && can_open_in_new(ses->tab->term)) {
+		open_uri_in_new_window(ses, uri, NULL, ENV_ANY,
+				       CACHE_MODE_NORMAL, TASK_NONE);
+	} else {
+		/* When opening a new tab, we might get rerendered, losing our
+		 * context and triggerring a disaster, so postpone that. */
+		struct delayed_open *deo = mem_calloc(1, sizeof(*deo));
+
+		if (deo) {
+			deo->ses = ses;
+			deo->uri = get_uri_reference(uri);
+			register_bottom_half(delayed_open, deo);
+		}
+	}
+
+end:
+	done_uri(uri);
+
+}
+
+
+void
+init_js_window_object(struct ecmascript_interpreter *interpreter)
+{
+	struct global_object *g = interpreter->backend_data;
+	struct SEE_interpreter *interp = &g->interp;
+	struct SEE_value v;
+
+	g->win = SEE_NEW(interp, struct js_window_object);
+
+	g->win->object.objectclass = &js_window_object_class;
+	g->win->object.objectclass->Class = s_window;
+	g->win->object.Prototype = NULL;
+	g->win->vs = interpreter->vs;
+
+	SEE_SET_OBJECT(&v, (struct SEE_object *)g->win);
+	SEE_OBJECT_PUT(interp, interp->Global, s_window, &v, 0);
+
+	g->win->alert = SEE_cfunction_make(interp, js_window_alert, s_alert, 1);
+	g->win->open = SEE_cfunction_make(interp, js_window_open, s_open, 3);
+}
+
+void
+checktime(struct SEE_interpreter *interp)
+{
+	struct global_object *g = (struct global_object *)interp;
+
+	if (time(NULL) - g->exec_start > g->max_exec_time) {
+		struct terminal *term = g->win->vs->doc_view->session->tab->term;
+		/* A killer script! Alert! */
+		ecmascript_timeout_dialog(term, g->max_exec_time);
+		SEE_error_throw_string(interp, interp->Error, s_timeout);
+	}
+}
diff --git a/src/ecmascript/see/window.h b/src/ecmascript/see/window.h
new file mode 100644
index 000000000..0e52e6518
--- /dev/null
+++ b/src/ecmascript/see/window.h
@@ -0,0 +1,27 @@
+#ifndef EL__ECMASCRIPT_SEE_WINDOW_H
+#define EL__ECMASCRIPT_SEE_WINDOW_H
+
+struct SEE_object;
+struct SEE_interpreter;
+struct string;
+struct view_state;
+
+
+struct js_window_object {
+	struct SEE_object object;
+	struct view_state *vs;
+	struct SEE_object *alert;
+	struct SEE_object *open;
+};
+
+struct global_object {
+	struct SEE_interpreter interp;
+	struct js_window_object *win;
+	int exec_start;
+	int max_exec_time;
+};
+
+void init_js_window_object(struct ecmascript_interpreter *);
+void checktime(struct SEE_interpreter *interp);
+
+#endif
diff --git a/src/ecmascript/spidermonkey.c b/src/ecmascript/spidermonkey.c
index 1fa14e63a..0f21054fe 100644
--- a/src/ecmascript/spidermonkey.c
+++ b/src/ecmascript/spidermonkey.c
@@ -61,6 +61,76 @@
 
 static JSRuntime *jsrt;
 
+void
+ecmascript_init(struct module *module)
+{
+	spidermonkey_init();
+}
+
+void
+ecmascript_done(struct module *module)
+{
+	spidermonkey_done();
+}
+
+struct ecmascript_interpreter *
+ecmascript_get_interpreter(struct view_state *vs)
+{
+	struct ecmascript_interpreter *interpreter;
+
+	assert(vs);
+
+	interpreter = mem_calloc(1, sizeof(*interpreter));
+	if (!interpreter)
+		return NULL;
+
+	interpreter->vs = vs;
+	init_list(interpreter->onload_snippets);
+	spidermonkey_get_interpreter(interpreter);
+
+	return interpreter;
+}
+
+void
+ecmascript_put_interpreter(struct ecmascript_interpreter *interpreter)
+{
+	assert(interpreter);
+	spidermonkey_put_interpreter(interpreter);
+	free_string_list(&interpreter->onload_snippets);
+	mem_free(interpreter);
+}
+
+void
+ecmascript_eval(struct ecmascript_interpreter *interpreter,
+                struct string *code)
+{
+	if (!get_ecmascript_enable())
+		return;
+	assert(interpreter);
+	spidermonkey_eval(interpreter, code);
+}
+
+unsigned char *
+ecmascript_eval_stringback(struct ecmascript_interpreter *interpreter,
+			   struct string *code)
+{
+	if (!get_ecmascript_enable())
+		return NULL;
+	assert(interpreter);
+	return spidermonkey_eval_stringback(interpreter, code);
+}
+
+int
+ecmascript_eval_boolback(struct ecmascript_interpreter *interpreter,
+			 struct string *code)
+{
+	if (!get_ecmascript_enable())
+		return -1;
+	assert(interpreter);
+	return spidermonkey_eval_boolback(interpreter, code);
+}
+
+
 static void
 error_reporter(JSContext *ctx, const char *message, JSErrorReport *report)
 {
@@ -123,14 +193,7 @@ safeguard(JSContext *ctx, JSScript *script)
 		struct terminal *term = interpreter->vs->doc_view->session->tab->term;
 
 		/* A killer script! Alert! */
-		info_box(term, MSGBOX_FREE_TEXT,
-			 N_("JavaScript Emergency"), ALIGN_LEFT,
-			 msg_text(term,
-				  N_("A script embedded in the current document was running\n"
-				  "for more than %d seconds. This probably means there is\n"
-				  "a bug in the script and it could have halted the whole\n"
-				  "ELinks, so the script execution was interrupted."),
-				  max_exec_time));
+		ecmascript_timeout_dialog(term, max_exec_time);
 		return JS_FALSE;
 	}
 	return JS_TRUE;
diff --git a/test/ecmascript/infinite2.html b/test/ecmascript/infinite2.html
new file mode 100644
index 000000000..8a9e24c49
--- /dev/null
+++ b/test/ecmascript/infinite2.html
@@ -0,0 +1,5 @@
+<script>
+	while (true) {
+		var a = location.href;
+	}
+</script>