improve javascript support

svn path=/trunk/netsurf/; revision=13962
This commit is contained in:
Vincent Sanders 2012-06-10 22:17:30 +00:00
parent feb37dd067
commit 4c89c9d5df
15 changed files with 339 additions and 75 deletions

View File

@ -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

View File

@ -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 */

View File

@ -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);
}

View File

@ -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. */

View File

@ -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);

View File

@ -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"

View File

@ -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;
}

View File

@ -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)

61
javascript/global.c Normal file
View File

@ -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);
}

28
javascript/global.h Normal file
View File

@ -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

View File

@ -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;
}

39
javascript/js.h Normal file
View File

@ -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_ */

51
javascript/nojs.c Normal file
View File

@ -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;
}

View File

@ -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);

View File

@ -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;