summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Sanders <vince@netsurf-browser.org>2012-06-10 22:17:30 +0000
committerVincent Sanders <vince@netsurf-browser.org>2012-06-10 22:17:30 +0000
commit4c89c9d5df511852f2743d277cf39611b49ce7f2 (patch)
tree07185cff7b5ab26416efe12c243f0d8ee76abe4a
parentfeb37dd067e7dac56fd5076badc7f2428134ef76 (diff)
downloadnetsurf-4c89c9d5df511852f2743d277cf39611b49ce7f2.tar.gz
netsurf-4c89c9d5df511852f2743d277cf39611b49ce7f2.tar.bz2
improve javascript support
svn path=/trunk/netsurf/; revision=13962
-rw-r--r--Makefile.sources16
-rw-r--r--content/content.h19
-rw-r--r--desktop/browser.c46
-rw-r--r--desktop/browser.h2
-rw-r--r--desktop/js.h11
-rw-r--r--desktop/netsurf.c4
-rw-r--r--desktop/nojs.c24
-rw-r--r--gtk/Makefile.target2
-rw-r--r--javascript/global.c61
-rw-r--r--javascript/global.h28
-rw-r--r--javascript/js.c (renamed from desktop/js.c)65
-rw-r--r--javascript/js.h39
-rw-r--r--javascript/nojs.c51
-rw-r--r--render/html.c42
-rw-r--r--render/html_internal.h4
15 files changed, 339 insertions, 75 deletions
diff --git a/Makefile.sources b/Makefile.sources
index 39d01b6d9..8806071c1 100644
--- a/Makefile.sources
+++ b/Makefile.sources
@@ -27,6 +27,13 @@ S_DESKTOP := cookies.c history_global_core.c hotlist.c knockout.c \
scrollbar.c sslcert.c textarea.c thumbnail.c tree.c \
tree_url_node.c version.c
+# Javascript sources
+ifeq ($(NETSURF_USE_JS),YES)
+S_JAVASCRIPT += js.c global.c
+else
+S_JAVASCRIPT += nojs.c
+endif
+
# S_COMMON are sources common to all builds
S_COMMON := $(addprefix content/,$(S_CONTENT)) \
$(addprefix content/fetchers/,$(S_FETCHERS)) \
@@ -34,7 +41,8 @@ S_COMMON := $(addprefix content/,$(S_CONTENT)) \
$(addprefix render/,$(S_RENDER)) \
$(addprefix utils/,$(S_UTILS)) \
$(addprefix utils/http/,$(S_HTTP)) \
- $(addprefix desktop/,$(S_DESKTOP))
+ $(addprefix desktop/,$(S_DESKTOP)) \
+ $(addprefix javascript/,$(S_JAVASCRIPT))
# S_IMAGE are sources related to image management
S_IMAGE_YES := image.c image_cache.c
@@ -61,12 +69,6 @@ S_PDF := $(addprefix desktop/save_pdf/,$(S_PDF))
S_BROWSER := browser.c download.c frames.c history_core.c netsurf.c \
save_complete.c save_text.c selection.c textinput.c
-ifeq ($(NETSURF_USE_JS),YES)
-S_BROWSER += js.c
-else
-S_BROWSER += nojs.c
-endif
-
S_BROWSER := $(addprefix desktop/,$(S_BROWSER))
# The following files depend on the testament
diff --git a/content/content.h b/content/content.h
index bdeeae48b..98879f8a5 100644
--- a/content/content.h
+++ b/content/content.h
@@ -73,6 +73,7 @@ typedef enum {
CONTENT_MSG_REFRESH, /**< wants refresh */
CONTENT_MSG_DOWNLOAD, /**< download, not for display */
CONTENT_MSG_LINK, /**< RFC5988 link */
+ CONTENT_MSG_GETCTX, /**< Javascript context */
} content_msg;
/** RFC5988 metadata link */
@@ -80,7 +81,7 @@ struct content_rfc5988_link {
struct content_rfc5988_link *next; /**< next rfc5988_link in list */
lwc_string *rel; /**< the link relationship - must be present */
- nsurl *href; /* the link href - must be present */
+ nsurl *href; /**< the link href - must be present */
lwc_string *hreflang;
lwc_string *type;
lwc_string *media;
@@ -89,8 +90,9 @@ struct content_rfc5988_link {
/** Extra data for some content_msg messages. */
union content_msg_data {
- const char *error; /**< Error message, for CONTENT_MSG_ERROR. */
- /** Area of content which needs redrawing, for CONTENT_MSG_REDRAW. */
+ /** CONTENT_MSG_ERROR - Error message */
+ const char *error;
+ /** CONTENT_MSG_REDRAW - Area of content which needs redrawing */
struct {
int x, y, width, height;
/** Redraw the area fully. If false, object must be set,
@@ -103,13 +105,16 @@ union content_msg_data {
/** Dimensions to plot object with. */
int object_width, object_height;
} redraw;
- int delay; /**< Minimum delay, for CONTENT_MSG_REFRESH */
- /** Reformat should not cause a redraw, for CONTENT_MSG_REFORMAT */
+ /** CONTENT_MSG_REFRESH - Minimum delay */
+ int delay;
+ /** CONTENT_MSG_REFORMAT - Reformat should not cause a redraw */
bool background;
- /** Low-level cache handle, for CONTENT_MSG_DOWNLOAD */
+ /** CONTENT_MSG_DOWNLOAD - Low-level cache handle */
struct llcache_handle *download;
- /** rfc5988 link data CONTENT_MSG_RFC5988_LINK */
+ /** CONTENT_MSG_RFC5988_LINK - rfc5988 link data */
struct content_rfc5988_link *rfc5988_link;
+ /** CONTENT_MSG_GETCTX - Javascript context */
+ struct jscontext **jscontext;
};
/** parameters to content redraw */
diff --git a/desktop/browser.c b/desktop/browser.c
index 0f9ec2bc5..d43098003 100644
--- a/desktop/browser.c
+++ b/desktop/browser.c
@@ -54,7 +54,8 @@
#include "desktop/selection.h"
#include "desktop/textinput.h"
#include "desktop/plotters.h"
-#include "desktop/js.h"
+
+#include "javascript/js.h"
#include "render/form.h"
#include "render/textplain.h"
@@ -963,9 +964,6 @@ void browser_window_go_post(struct browser_window *bw, const char *url,
browser_window_set_status(bw, messages_get("Loading"));
bw->history_add = add_to_history;
- /* fresh javascript compartment */
- bw->jsglobal = js_newcompartment(bw->jsctx);
-
/* Verifiable fetches may trigger a download */
if (verifiable)
fetch_flags |= HLCACHE_RETRIEVE_MAY_DOWNLOAD;
@@ -977,28 +975,34 @@ void browser_window_go_post(struct browser_window *bw, const char *url,
browser_window_callback, bw,
parent != NULL ? &child : NULL,
CONTENT_ANY, &c);
- if (error == NSERROR_NO_FETCH_HANDLER) {
+
+ switch (error) {
+ case NSERROR_NO_FETCH_HANDLER: /* no handler for this type */
gui_launch_url(nsurl_access(nsurl));
nsurl_unref(nsurl);
if (nsref != NULL)
nsurl_unref(nsref);
- return;
- } else if (error != NSERROR_OK) {
+ break;
+
+ case NSERROR_OK:
+ bw->loading_content = c;
+ browser_window_start_throbber(bw);
+ browser_window_refresh_url_bar(bw, nsurl, NULL);
+
+ nsurl_unref(nsurl);
+ if (nsref != NULL)
+ nsurl_unref(nsref);
+ break;
+
+ default: /* assume out of memory */
+ /* TODO: fix all fetcher errors being reported as OOM? */
nsurl_unref(nsurl);
if (nsref != NULL)
nsurl_unref(nsref);
browser_window_set_status(bw, messages_get("NoMemory"));
warn_user("NoMemory", 0);
- return;
- }
- bw->loading_content = c;
- browser_window_start_throbber(bw);
- browser_window_refresh_url_bar(bw, nsurl, NULL);
-
- nsurl_unref(nsurl);
- if (nsref != NULL)
- nsurl_unref(nsref);
+ }
}
@@ -1391,6 +1395,16 @@ nserror browser_window_callback(hlcache_handle *c,
}
break;
+ case CONTENT_MSG_GETCTX:
+ /* only the content object created by the browser
+ * window requires a new global compartment object
+ */
+ if (js_newcompartment(bw->jsctx,
+ hlcache_handle_get_content(c)) != NULL) {
+ *(event->data.jscontext) = bw->jsctx;
+ }
+ break;
+
default:
assert(0);
}
diff --git a/desktop/browser.h b/desktop/browser.h
index e0d42265a..09107a3e6 100644
--- a/desktop/browser.h
+++ b/desktop/browser.h
@@ -199,8 +199,6 @@ struct browser_window {
/** current javascript context */
struct jscontext *jsctx;
- /** current global javascript object */
- struct jsobject *jsglobal;
/** cache of the currently displayed status text. */
char *status_text; /**< Current status bar text. */
diff --git a/desktop/js.h b/desktop/js.h
deleted file mode 100644
index b70845f16..000000000
--- a/desktop/js.h
+++ /dev/null
@@ -1,11 +0,0 @@
-
-typedef struct jscontext jscontext;
-typedef struct jsobject jsobject;
-
-void js_initialise(void);
-void js_finalise(void);
-
-jscontext *js_newcontext(void);
-void js_destroycontext(jscontext *ctx);
-
-jsobject *js_newcompartment(jscontext *ctx);
diff --git a/desktop/netsurf.c b/desktop/netsurf.c
index 606dfa649..2b6be861a 100644
--- a/desktop/netsurf.c
+++ b/desktop/netsurf.c
@@ -42,7 +42,9 @@
#include "desktop/gui.h"
#include "desktop/options.h"
#include "desktop/searchweb.h"
-#include "desktop/js.h"
+
+#include "javascript/js.h"
+
#include "render/html.h"
#include "render/textplain.h"
#include "utils/log.h"
diff --git a/desktop/nojs.c b/desktop/nojs.c
deleted file mode 100644
index 9a5c3c65e..000000000
--- a/desktop/nojs.c
+++ /dev/null
@@ -1,24 +0,0 @@
-#include "desktop/js.h"
-#include "utils/log.h"
-
-void js_initialise(void)
-{
-}
-
-void js_finalise(void)
-{
-}
-
-jscontext *js_newcontext(void)
-{
- return NULL;
-}
-
-void js_destroycontext(jscontext *ctx)
-{
-}
-
-jsobject *js_newcompartment(jscontext *ctx)
-{
- return NULL;
-}
diff --git a/gtk/Makefile.target b/gtk/Makefile.target
index 778093837..2e658e6b6 100644
--- a/gtk/Makefile.target
+++ b/gtk/Makefile.target
@@ -102,7 +102,7 @@ S_GTK := font_pango.c bitmap.c gui.c schedule.c thumbnail.c plotters.c \
treeview.c scaffolding.c gdk.c completion.c login.c throbber.c \
selection.c history.c window.c filetype.c download.c menu.c \
print.c save.c search.c tabs.c theme.c toolbar.c \
- compat.c cookies.c hotlist.c system_colour.c \
+ compat.c cookies.c hotlist.c system_colour.c \
$(addprefix dialogs/,options.c about.c source.c)
S_GTK := $(addprefix gtk/,$(S_GTK)) $(addprefix utils/,container.c)
diff --git a/javascript/global.c b/javascript/global.c
new file mode 100644
index 000000000..10355a910
--- /dev/null
+++ b/javascript/global.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2012 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "mozjs/jsapi.h"
+
+#include "content/content.h"
+#include "javascript/global.h"
+#include "utils/log.h"
+
+static JSBool jsalert(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString* u16_txt;
+ char *txt;
+
+ if (!JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "S", &u16_txt))
+ return JS_FALSE;
+
+
+#ifdef SPIDERMONKEY_400
+ unsigned int length;
+ length = JS_GetStringLength(u16_txt);
+ txt = alloca(sizeof(char)*(length+1));
+ JS_EncodeStringToBuffer(u16_txt, txt, length);
+ txt[length] = '\0';
+
+#else
+ txt = JS_GetStringBytes(u16_txt);
+#endif
+
+ warn_user(txt, NULL);
+
+ JS_SET_RVAL(cx, vp, JSVAL_VOID);
+
+ return JS_TRUE;
+}
+
+static JSFunctionSpec global_functions[] =
+{
+ JS_FN("alert", jsalert, 1, 0),
+ JS_FS_END
+};
+
+bool js_new_globalfunc(JSContext *cx, JSObject *global)
+{
+ return JS_DefineFunctions(cx, global, global_functions);
+}
diff --git a/javascript/global.h b/javascript/global.h
new file mode 100644
index 000000000..329c82c8d
--- /dev/null
+++ b/javascript/global.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2012 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * spidermonkey engine global functions.
+ */
+
+#ifndef _NETSURF_JAVASCRIPT_GLOBAL_H_
+#define _NETSURF_JAVASCRIPT_GLOBAL_H_
+
+bool js_new_globalfunc(JSContext *cx, JSObject *global);
+
+#endif
diff --git a/desktop/js.c b/javascript/js.c
index 540ff82a5..81dc96be6 100644
--- a/desktop/js.c
+++ b/javascript/js.c
@@ -1,6 +1,27 @@
+/*
+ * Copyright 2012 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
#include "mozjs/jsapi.h"
-#include "desktop/js.h"
+#include "content/content.h"
+#include "javascript/global.h"
+#include "javascript/js.h"
+
#include "utils/log.h"
static JSRuntime *rt; /* global runtime */
@@ -71,7 +92,7 @@ static JSClass global_class = {
};
-jsobject *js_newcompartment(jscontext *ctx)
+jsobject *js_newcompartment(jscontext *ctx, struct content* c)
{
JSContext *cx = (JSContext *)ctx;
JSObject *global;
@@ -79,7 +100,7 @@ jsobject *js_newcompartment(jscontext *ctx)
if (cx == NULL) {
return NULL;
}
-#ifdef HAVE_JS_NEWCOMPARTMENTANDGLOBALOBJECT
+#ifdef SPIDERMONKEY_400
global = JS_NewCompartmentAndGlobalObject(cx, &global_class, NULL);
if (global == NULL) {
return NULL;
@@ -92,13 +113,45 @@ jsobject *js_newcompartment(jscontext *ctx)
JS_SetGlobalObject(cx, global);
#endif
- /* Populate the global object with the standard globals,
- like Object and Array. */
+ JS_SetContextPrivate(cx, c); /* private pointer to content */
+
+ js_new_globalfunc(cx, global);
+
+ /* Populate the global object with the standard globals, like
+ Object and Array. */
if (!JS_InitStandardClasses(cx, global)) {
return NULL;
}
- LOG(("Creating new global object %p", global));
+ LOG(("Created new global object %p", global));
return (jsobject *)global;
}
+
+bool js_exec(jscontext *ctx, const char *txt, int txtlen)
+{
+ JSContext *cx = (JSContext *)ctx;
+
+ //LOG(("%p \"%s\"",cx ,txt));
+
+ if (ctx == NULL) {
+ return false;
+ }
+
+ if (txt == NULL) {
+ return false;
+ }
+
+ if (txtlen == 0) {
+ return false;
+ }
+
+ if (JS_EvaluateScript(cx,
+ JS_GetGlobalObject(cx),
+ txt, txtlen,
+ "<head>", 0, NULL) == JS_TRUE) {
+ return true;
+ }
+
+ return false;
+}
diff --git a/javascript/js.h b/javascript/js.h
new file mode 100644
index 000000000..d8e241564
--- /dev/null
+++ b/javascript/js.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2012 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Interface to javascript engine functions.
+ */
+
+#ifndef _NETSURF_JAVASCRIPT_JS_H_
+#define _NETSURF_JAVASCRIPT_JS_H_
+
+typedef struct jscontext jscontext;
+typedef struct jsobject jsobject;
+
+void js_initialise(void);
+void js_finalise(void);
+
+jscontext *js_newcontext(void);
+void js_destroycontext(jscontext *ctx);
+
+jsobject *js_newcompartment(jscontext *ctx, struct content* c);
+
+bool js_exec(jscontext *ctx, const char *txt, int txtlen);
+
+#endif /* _NETSURF_JAVASCRIPT_JS_H_ */
diff --git a/javascript/nojs.c b/javascript/nojs.c
new file mode 100644
index 000000000..fe1cd191a
--- /dev/null
+++ b/javascript/nojs.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2012 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Dummy implementation of javascript engine functions.
+ */
+
+#include "desktop/js.h"
+#include "utils/log.h"
+
+void js_initialise(void)
+{
+}
+
+void js_finalise(void)
+{
+}
+
+jscontext *js_newcontext(void)
+{
+ return NULL;
+}
+
+void js_destroycontext(jscontext *ctx)
+{
+}
+
+jsobject *js_newcompartment(jscontext *ctx, struct content* c)
+{
+ return NULL;
+}
+
+bool js_exec(jscontext *ctx, char *txt, int txtlen)
+{
+ return true;
+}
diff --git a/render/html.c b/render/html.c
index 7e74008b5..47e28d998 100644
--- a/render/html.c
+++ b/render/html.c
@@ -38,6 +38,7 @@
#include "desktop/options.h"
#include "desktop/selection.h"
#include "desktop/scrollbar.h"
+#include "javascript/js.h"
#include "image/bitmap.h"
#include "render/box.h"
#include "render/font.h"
@@ -104,6 +105,7 @@ static dom_string *html_dom_string_sizes;
static dom_string *html_dom_string_title;
static dom_string *html_dom_string_base;
static dom_string *html_dom_string_link;
+static dom_string *html_dom_string_script;
dom_string *html_dom_string_target;
static dom_string *html_dom_string__parent;
static dom_string *html_dom_string__self;
@@ -158,6 +160,7 @@ html_create_html_data(html_content *c, const http_parameter *params)
c->box = NULL;
c->font_func = &nsfont;
c->scrollbar = NULL;
+ c->jscontext = NULL;
if (lwc_intern_string("*", SLEN("*"), &c->universal) != lwc_error_ok) {
error = BINDING_NOMEM;
@@ -356,6 +359,40 @@ encoding_change:
}
}
+/** process script node */
+static bool html_process_script(html_content *c, dom_node *node)
+{
+ dom_exception exc; /* returned by libdom functions */
+ dom_string *script;
+
+ bool success;
+
+ /* ensure javascript context is available */
+ if (c->jscontext == NULL) {
+ union content_msg_data msg_data;
+
+ msg_data.jscontext = &c->jscontext;
+ content_broadcast(&c->base, CONTENT_MSG_GETCTX, msg_data);
+ LOG(("javascript context %p ", c->jscontext));
+ if (c->jscontext == NULL) {
+ return false;
+ }
+ }
+
+ exc = dom_node_get_text_content(node, &script);
+ if ((exc != DOM_NO_ERR) || (script == NULL)) {
+ return false;
+ }
+
+ js_exec(c->jscontext,
+ dom_string_data(script),
+ dom_string_byte_length(script)) ;
+
+ dom_string_unref(script);
+
+ return success;
+}
+
/** process link node */
static bool html_process_link(html_content *c, dom_node *node)
{
@@ -557,6 +594,9 @@ static bool html_head(html_content *c, dom_node *head)
} else if (dom_string_caseless_isequal(node_name,
html_dom_string_link)) {
html_process_link(c, node);
+ } else if (dom_string_caseless_isequal(node_name,
+ html_dom_string_script)) {
+ html_process_script(c, node);
}
}
}
@@ -3037,6 +3077,7 @@ static void html_fini(void)
HTML_DOM_STRING_UNREF(sizes);
HTML_DOM_STRING_UNREF(title);
HTML_DOM_STRING_UNREF(base);
+ HTML_DOM_STRING_UNREF(script);
HTML_DOM_STRING_UNREF(link);
HTML_DOM_STRING_UNREF(target);
HTML_DOM_STRING_UNREF(_blank);
@@ -3165,6 +3206,7 @@ nserror html_init(void)
HTML_DOM_STRING_INTERN(title);
HTML_DOM_STRING_INTERN(base);
HTML_DOM_STRING_INTERN(link);
+ HTML_DOM_STRING_INTERN(script);
HTML_DOM_STRING_INTERN(target);
HTML_DOM_STRING_INTERN(_blank);
HTML_DOM_STRING_INTERN(_self);
diff --git a/render/html_internal.h b/render/html_internal.h
index 0bb47275b..3d9dea389 100644
--- a/render/html_internal.h
+++ b/render/html_internal.h
@@ -104,6 +104,10 @@ typedef struct html_content {
/** Context for free text search, or NULL if none */
struct search_context *search;
+
+ /** javascript context */
+ struct jscontext *jscontext;
+
} html_content;