From 49effe103a260a60949d3c95494ae81b031799d9 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Tue, 19 Jun 2012 09:35:51 +0000 Subject: restructure javascript binding layout to be more explicit fix html content so it correctly loads all the script tags svn path=/trunk/netsurf/; revision=13968 --- Makefile.sources | 4 +- desktop/options_main.h | 8 +- javascript/global.c | 60 ---- javascript/global.h | 28 -- javascript/js.c | 173 ----------- javascript/jsapi.c | 173 +++++++++++ javascript/jsapi.h | 28 ++ javascript/jsapi/global.c | 60 ++++ javascript/nojs.c | 53 ---- javascript/none.c | 53 ++++ render/html.c | 765 +++++++++++++++++++++++++++++++++------------- render/html.h | 20 ++ render/html_internal.h | 10 +- 13 files changed, 894 insertions(+), 541 deletions(-) delete mode 100644 javascript/global.c delete mode 100644 javascript/global.h delete mode 100644 javascript/js.c create mode 100644 javascript/jsapi.c create mode 100644 javascript/jsapi.h create mode 100644 javascript/jsapi/global.c delete mode 100644 javascript/nojs.c create mode 100644 javascript/none.c diff --git a/Makefile.sources b/Makefile.sources index 8806071c1..50c8a9b50 100644 --- a/Makefile.sources +++ b/Makefile.sources @@ -29,9 +29,9 @@ S_DESKTOP := cookies.c history_global_core.c hotlist.c knockout.c \ # Javascript sources ifeq ($(NETSURF_USE_JS),YES) -S_JAVASCRIPT += js.c global.c +S_JAVASCRIPT += jsapi.c jsapi/global.c else -S_JAVASCRIPT += nojs.c +S_JAVASCRIPT += none.c endif # S_COMMON are sources common to all builds diff --git a/desktop/options_main.h b/desktop/options_main.h index d56d3a446..d44c26505 100644 --- a/desktop/options_main.h +++ b/desktop/options_main.h @@ -70,7 +70,7 @@ int disc_cache_age; \ /** Whether to block advertisements */ \ bool block_ads; \ - /** Disable website tracking, see \ + /** Disable website tracking, see \ * http://www.w3.org/Submission/2011/SUBM-web-tracking-protection-20110224/#dnt-uas */ \ bool do_not_track; \ /** Minimum GIF animation delay */ \ @@ -83,6 +83,8 @@ bool background_images; \ /** Whether to animate images */ \ bool animate_images; \ + /** Whether to execute javascript */ \ + bool enable_javascript; \ /** How many days to retain URL data for */ \ int expire_url; \ /** Default font family */ \ @@ -262,7 +264,8 @@ .max_cached_fetch_handles = 6, \ .suppress_curl_debug = true, \ .target_blank = true, \ - .button_2_tab = true + .button_2_tab = true, \ + .enable_javascript = true #define NSOPTION_MAIN_SYS_COLOUR_DEFAULTS \ .sys_colour_ActiveBorder = 0x00000000, \ @@ -320,6 +323,7 @@ { "foreground_images", OPTION_BOOL, &nsoptions.foreground_images }, \ { "background_images", OPTION_BOOL, &nsoptions.background_images }, \ { "animate_images", OPTION_BOOL, &nsoptions.animate_images }, \ + { "enable_javasctipt", OPTION_BOOL, &nsoptions.enable_javascript}, \ { "expire_url", OPTION_INTEGER, &nsoptions.expire_url }, \ { "font_default", OPTION_INTEGER, &nsoptions.font_default }, \ { "ca_bundle", OPTION_STRING, &nsoptions.ca_bundle }, \ diff --git a/javascript/global.c b/javascript/global.c deleted file mode 100644 index c2033d4fc..000000000 --- a/javascript/global.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2012 Vincent Sanders - * - * 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 . - */ - -#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; - - -#if JS_VERSION <= 180 - txt = JS_GetStringBytes(u16_txt); -#else - unsigned int length; - length = JS_GetStringLength(u16_txt); - txt = alloca(sizeof(char)*(length+1)); - JS_EncodeStringToBuffer(u16_txt, txt, length); - txt[length] = '\0'; -#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 deleted file mode 100644 index 329c82c8d..000000000 --- a/javascript/global.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2012 Vincent Sanders - * - * 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 . - */ - -/** \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/javascript/js.c b/javascript/js.c deleted file mode 100644 index 833e01785..000000000 --- a/javascript/js.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright 2012 Vincent Sanders - * - * 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 . - */ - -#include "mozjs/jsapi.h" - -#include "content/content.h" -#include "javascript/global.h" -#include "javascript/js.h" - -#include "utils/log.h" - -static JSRuntime *rt; /* global runtime */ - -void js_initialise(void) -{ - /* Create a JS runtime. */ - -#if JS_VERSION >= 180 - JS_SetCStringsAreUTF8(); /* we prefer our runtime to be utf-8 */ -#endif - - rt = JS_NewRuntime(8L * 1024L * 1024L); - LOG(("New runtime handle %p", rt)); -} - -void js_finalise(void) -{ - if (rt != NULL) { - LOG(("destroying runtime handle %p", rt)); - JS_DestroyRuntime(rt); - } - JS_ShutDown(); -} - -/* The error reporter callback. */ -static void js_reportError(JSContext *cx, const char *message, JSErrorReport *report) -{ - LOG(("%s:%u:%s\n", - report->filename ? report->filename : "", - (unsigned int) report->lineno, - message)); -} - -jscontext *js_newcontext(void) -{ - JSContext *cx; - - if (rt == NULL) { - return NULL; - } - - cx = JS_NewContext(rt, 8192); - if (cx == NULL) { - return NULL; - } - JS_SetOptions(cx, JSOPTION_VAROBJFIX | JSOPTION_JIT ); - JS_SetVersion(cx, JSVERSION_LATEST); - JS_SetErrorReporter(cx, js_reportError); - - LOG(("New Context %p", cx)); - - return (jscontext *)cx; -} - -void js_destroycontext(jscontext *ctx) -{ - JSContext *cx = (JSContext *)ctx; - if (cx != NULL) { - LOG(("Destroying Context %p", cx)); - JS_DestroyContext(cx); - } -} - - - -/* The class of the global object. */ -static JSClass global_class = { - "global", - JSCLASS_GLOBAL_FLAGS, - JS_PropertyStub, - JS_PropertyStub, - JS_PropertyStub, -#if JS_VERSION <= 180 - JS_PropertyStub, -#else - JS_StrictPropertyStub, -#endif - JS_EnumerateStub, - JS_ResolveStub, - JS_ConvertStub, - JS_FinalizeStub, - JSCLASS_NO_OPTIONAL_MEMBERS -}; - -jsobject *js_newcompartment(jscontext *ctx, struct content* c) -{ - JSContext *cx = (JSContext *)ctx; - JSObject *global; - - if (cx == NULL) { - return NULL; - } - -#if JS_VERSION <= 180 - global = JS_NewObject(cx, &global_class, NULL, NULL); - if (global == NULL) { - return NULL; - } - JS_SetGlobalObject(cx, global); -#else - global = JS_NewCompartmentAndGlobalObject(cx, &global_class, NULL); - if (global == NULL) { - return NULL; - } -#endif - - 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(("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, - "", 0, NULL) == JS_TRUE) { - return true; - } - - return false; -} diff --git a/javascript/jsapi.c b/javascript/jsapi.c new file mode 100644 index 000000000..6f5b510ef --- /dev/null +++ b/javascript/jsapi.c @@ -0,0 +1,173 @@ +/* + * Copyright 2012 Vincent Sanders + * + * 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 . + */ + +#include "mozjs/jsapi.h" + +#include "content/content.h" +#include "javascript/jsapi.h" +#include "javascript/js.h" + +#include "utils/log.h" + +static JSRuntime *rt; /* global runtime */ + +void js_initialise(void) +{ + /* Create a JS runtime. */ + +#if JS_VERSION >= 180 + JS_SetCStringsAreUTF8(); /* we prefer our runtime to be utf-8 */ +#endif + + rt = JS_NewRuntime(8L * 1024L * 1024L); + LOG(("New runtime handle %p", rt)); +} + +void js_finalise(void) +{ + if (rt != NULL) { + LOG(("destroying runtime handle %p", rt)); + JS_DestroyRuntime(rt); + } + JS_ShutDown(); +} + +/* The error reporter callback. */ +static void js_reportError(JSContext *cx, const char *message, JSErrorReport *report) +{ + LOG(("%s:%u:%s", + report->filename ? report->filename : "", + (unsigned int) report->lineno, + message)); +} + +jscontext *js_newcontext(void) +{ + JSContext *cx; + + if (rt == NULL) { + return NULL; + } + + cx = JS_NewContext(rt, 8192); + if (cx == NULL) { + return NULL; + } + JS_SetOptions(cx, JSOPTION_VAROBJFIX | JSOPTION_JIT ); + JS_SetVersion(cx, JSVERSION_LATEST); + JS_SetErrorReporter(cx, js_reportError); + + LOG(("New Context %p", cx)); + + return (jscontext *)cx; +} + +void js_destroycontext(jscontext *ctx) +{ + JSContext *cx = (JSContext *)ctx; + if (cx != NULL) { + LOG(("Destroying Context %p", cx)); + JS_DestroyContext(cx); + } +} + + + +/* The class of the global object. */ +static JSClass global_class = { + "global", + JSCLASS_GLOBAL_FLAGS, + JS_PropertyStub, + JS_PropertyStub, + JS_PropertyStub, +#if JS_VERSION <= 180 + JS_PropertyStub, +#else + JS_StrictPropertyStub, +#endif + JS_EnumerateStub, + JS_ResolveStub, + JS_ConvertStub, + JS_FinalizeStub, + JSCLASS_NO_OPTIONAL_MEMBERS +}; + +jsobject *js_newcompartment(jscontext *ctx, struct content* c) +{ + JSContext *cx = (JSContext *)ctx; + JSObject *global; + + if (cx == NULL) { + return NULL; + } + +#if JS_VERSION <= 180 + global = JS_NewObject(cx, &global_class, NULL, NULL); + if (global == NULL) { + return NULL; + } + JS_SetGlobalObject(cx, global); +#else + global = JS_NewCompartmentAndGlobalObject(cx, &global_class, NULL); + if (global == NULL) { + return NULL; + } +#endif + + JS_SetContextPrivate(cx, c); /* private pointer to content */ + + jsapi_new_globalfunc(cx, global); + + /* Populate the global object with the standard globals, like + Object and Array. */ + if (!JS_InitStandardClasses(cx, global)) { + return NULL; + } + + 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, + "", 0, NULL) == JS_TRUE) { + return true; + } + + return false; +} diff --git a/javascript/jsapi.h b/javascript/jsapi.h new file mode 100644 index 000000000..ce2051148 --- /dev/null +++ b/javascript/jsapi.h @@ -0,0 +1,28 @@ +/* + * Copyright 2012 Vincent Sanders + * + * 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 . + */ + +/** \file + * spidermonkey jsapi bindings. + */ + +#ifndef _NETSURF_JAVASCRIPT_JSAPI_H_ +#define _NETSURF_JAVASCRIPT_JSAPI_H_ + +bool jsapi_new_globalfunc(JSContext *cx, JSObject *global); + +#endif diff --git a/javascript/jsapi/global.c b/javascript/jsapi/global.c new file mode 100644 index 000000000..b86400428 --- /dev/null +++ b/javascript/jsapi/global.c @@ -0,0 +1,60 @@ +/* + * Copyright 2012 Vincent Sanders + * + * 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 . + */ + +#include "mozjs/jsapi.h" + +#include "content/content.h" +#include "javascript/jsapi.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; + + +#if JS_VERSION <= 180 + txt = JS_GetStringBytes(u16_txt); +#else + unsigned int length; + length = JS_GetStringLength(u16_txt); + txt = alloca(sizeof(char)*(length+1)); + JS_EncodeStringToBuffer(u16_txt, txt, length); + txt[length] = '\0'; +#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 jsapi_new_globalfunc(JSContext *cx, JSObject *global) +{ + return JS_DefineFunctions(cx, global, global_functions); +} diff --git a/javascript/nojs.c b/javascript/nojs.c deleted file mode 100644 index ec0ccc0f8..000000000 --- a/javascript/nojs.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2012 Vincent Sanders - * - * 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 . - */ - -/** \file - * Dummy implementation of javascript engine functions. - */ - -#include "content/content.h" - -#include "javascript/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, const char *txt, int txtlen) -{ - return true; -} diff --git a/javascript/none.c b/javascript/none.c new file mode 100644 index 000000000..ec0ccc0f8 --- /dev/null +++ b/javascript/none.c @@ -0,0 +1,53 @@ +/* + * Copyright 2012 Vincent Sanders + * + * 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 . + */ + +/** \file + * Dummy implementation of javascript engine functions. + */ + +#include "content/content.h" + +#include "javascript/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, const char *txt, int txtlen) +{ + return true; +} diff --git a/render/html.c b/render/html.c index e7ebbd54c..a3b5e01a2 100644 --- a/render/html.c +++ b/render/html.c @@ -93,6 +93,7 @@ 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; +static dom_string *html_dom_string_src; dom_string *html_dom_string_target; static dom_string *html_dom_string__parent; static dom_string *html_dom_string__self; @@ -147,6 +148,8 @@ html_create_html_data(html_content *c, const http_parameter *params) c->box = NULL; c->font_func = &nsfont; c->scrollbar = NULL; + c->scripts_count = 0; + c->scripts = NULL; c->jscontext = NULL; if (lwc_intern_string("*", SLEN("*"), &c->universal) != lwc_error_ok) { @@ -346,39 +349,6 @@ 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 = true; - - /* 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) @@ -581,10 +551,7 @@ 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); - } + } } } @@ -958,6 +925,8 @@ html_object_callback(hlcache_handle *object, case CONTENT_MSG_DONE: c->base.active--; + LOG(("%d fetches active", c->base.active)); + html_object_done(box, object, o->background); if (c->base.status != CONTENT_STATUS_LOADING && @@ -985,6 +954,7 @@ html_object_callback(hlcache_handle *object, o->content = NULL; c->base.active--; + LOG(("%d fetches active", c->base.active)); content_add_error(&c->base, "?", 0); html_set_status(c, event->data.error); @@ -1107,8 +1077,10 @@ static bool html_replace_object(struct content_html_object *object, nsurl *url) if (object->content != NULL) { /* remove existing object */ - if (content_get_status(object->content) != CONTENT_STATUS_DONE) + if (content_get_status(object->content) != CONTENT_STATUS_DONE) { c->base.active--; + LOG(("%d fetches active", c->base.active)); + } hlcache_handle_release(object->content); object->content = NULL; @@ -1128,6 +1100,8 @@ static bool html_replace_object(struct content_html_object *object, nsurl *url) for (page = c; page != NULL; page = page->page) { page->base.active++; + LOG(("%d fetches active", c->base.active)); + page->base.status = CONTENT_STATUS_READY; } @@ -1375,9 +1349,10 @@ html_convert_css_callback(hlcache_handle *css, break; case CONTENT_MSG_DONE: - LOG(("got stylesheet '%s'", + LOG(("done stylesheet slot %d '%s'", i, nsurl_access(hlcache_handle_get_url(css)))); parent->base.active--; + LOG(("%d fetches active", parent->base.active)); break; case CONTENT_MSG_ERROR: @@ -1387,6 +1362,7 @@ html_convert_css_callback(hlcache_handle *css, hlcache_handle_release(css); s->data.external = NULL; parent->base.active--; + LOG(("%d fetches active", parent->base.active)); content_add_error(&parent->base, "?", 0); break; @@ -1542,11 +1518,13 @@ html_process_style_element(html_content *c, } c->base.active++; + LOG(("%d fetches active", c->base.active)); /* Convert the content -- manually, as we want the result */ if (nscss_convert_css_data(sheet) != CSS_OK) { /* conversion failed */ c->base.active--; + LOG(("%d fetches active", c->base.active)); nscss_destroy_css_data(sheet); talloc_free(sheet); sheet = NULL; @@ -1564,95 +1542,22 @@ no_memory: return false; } -/** - * Process inline stylesheets and fetch linked stylesheets. - * - * Uses STYLE and LINK elements inside and outside HEAD + +/* depth-first walk the dom calling callback for each element * - * \param c content structure - * \param html xml node of html element - * \return true on success, false if an error occurred + * @param root the dom node to use as the root of the tree walk + * @return true if all nodes were examined, false if the callback terminated + * the walk early. */ - -static bool html_find_stylesheets(html_content *c, dom_node *html) +static bool +html_treewalk_dom(dom_node *root, + bool (*callback)(dom_node *node, dom_string *name, void *ctx), + void *ctx) { - content_type accept = CONTENT_CSS; dom_node *node; - unsigned int i = STYLESHEET_START; - union content_msg_data msg_data; - struct html_stylesheet *stylesheets; - hlcache_child_context child; - nserror ns_error; - nsurl *joined; - - child.charset = c->encoding; - child.quirks = c->base.quirks; - - /* stylesheet 0 is the base style sheet, - * stylesheet 1 is the quirks mode style sheet, - * stylesheet 2 is the adblocking stylesheet, - * stylesheet 3 is the user stylesheet */ - c->stylesheets = talloc_array(c, struct html_stylesheet, - STYLESHEET_START); - if (c->stylesheets == NULL) - goto no_memory; - c->stylesheets[STYLESHEET_BASE].type = HTML_STYLESHEET_EXTERNAL; - c->stylesheets[STYLESHEET_BASE].data.external = NULL; - c->stylesheets[STYLESHEET_QUIRKS].type = HTML_STYLESHEET_EXTERNAL; - c->stylesheets[STYLESHEET_QUIRKS].data.external = NULL; - c->stylesheets[STYLESHEET_ADBLOCK].type = HTML_STYLESHEET_EXTERNAL; - c->stylesheets[STYLESHEET_ADBLOCK].data.external = NULL; - c->stylesheets[STYLESHEET_USER].type = HTML_STYLESHEET_EXTERNAL; - c->stylesheets[STYLESHEET_USER].data.external = NULL; - c->stylesheet_count = STYLESHEET_START; - - c->base.active = 0; - - ns_error = hlcache_handle_retrieve(html_default_stylesheet_url, 0, - content_get_url(&c->base), NULL, - html_convert_css_callback, c, &child, accept, - &c->stylesheets[STYLESHEET_BASE].data.external); - if (ns_error != NSERROR_OK) - goto no_memory; - - c->base.active++; - - if (c->quirks == BINDING_QUIRKS_MODE_FULL) { - ns_error = hlcache_handle_retrieve(html_quirks_stylesheet_url, - 0, content_get_url(&c->base), NULL, - html_convert_css_callback, c, &child, accept, - &c->stylesheets[STYLESHEET_QUIRKS]. - data.external); - if (ns_error != NSERROR_OK) - goto no_memory; - - c->base.active++; - } + bool result = true;; - if (nsoption_bool(block_ads)) { - ns_error = hlcache_handle_retrieve(html_adblock_stylesheet_url, - 0, content_get_url(&c->base), NULL, - html_convert_css_callback, c, &child, accept, - &c->stylesheets[STYLESHEET_ADBLOCK]. - data.external); - if (ns_error != NSERROR_OK) - goto no_memory; - - c->base.active++; - } - - ns_error = hlcache_handle_retrieve(html_user_stylesheet_url, 0, - content_get_url(&c->base), NULL, - html_convert_css_callback, c, &child, accept, - &c->stylesheets[STYLESHEET_USER].data.external); - if (ns_error != NSERROR_OK) - goto no_memory; - - c->base.active++; - - /* depth-first search the tree for link elements */ - - node = dom_node_ref(html); /* tree root */ + node = dom_node_ref(root); /* tree root */ while (node != NULL) { dom_node *next = NULL; @@ -1723,125 +1628,524 @@ static bool html_find_stylesheets(html_content *c, dom_node *html) assert(node != NULL); exc = dom_node_get_node_type(node, &type); - if (exc != DOM_NO_ERR || type != DOM_ELEMENT_NODE) + if ((exc != DOM_NO_ERR) || (type != DOM_ELEMENT_NODE)) continue; exc = dom_node_get_node_name(node, &name); if (exc != DOM_NO_ERR) continue; - if (strcmp(dom_string_data(name), "link") == 0) { - dom_string *rel, *type_attr, *media, *href; + result = callback(node, name, ctx); - dom_string_unref(name); + dom_string_unref(name); - /* rel= */ - exc = dom_element_get_attribute(node, - html_dom_string_rel, &rel); - if (exc != DOM_NO_ERR || rel == NULL) - continue; + if (result == false) { + break; /* callback caused early termination */ + } + + } + return result; +} - if (strcasestr(dom_string_data(rel), - "stylesheet") == 0) { - dom_string_unref(rel); - continue; - } else if (strcasestr(dom_string_data(rel), - "alternate") != 0) { - /* Ignore alternate stylesheets */ - dom_string_unref(rel); - continue; - } - dom_string_unref(rel); - - /* type='text/css' or not present */ - exc = dom_element_get_attribute(node, - html_dom_string_type, &type_attr); - if (exc == DOM_NO_ERR && type_attr != NULL) { - if (strcmp(dom_string_data(type_attr), - "text/css") != 0) { - dom_string_unref(type_attr); - continue; - } - dom_string_unref(type_attr); - } +/* attempt to progress script execution + * + * execute scripts using algorithm found in: + * http://www.whatwg.org/specs/web-apps/current-work/multipage/scripting-1.html#the-script-element + * + */ +static bool html_scripts_exec(html_content *c) +{ + unsigned int i; + struct html_script *s; - /* media contains 'screen' or 'all' or not present */ - exc = dom_element_get_attribute(node, - html_dom_string_media, &media); - if (exc == DOM_NO_ERR && media != NULL) { - if (strcasestr(dom_string_data(media), - "screen") == NULL && - strcasestr( - dom_string_data(media), - "all") == NULL) { - dom_string_unref(media); - continue; + if (c->jscontext == NULL) + return false; + + for (i = 0, s = c->scripts; i != c->scripts_count; i++, s++) { + if (s->already_started) { + continue; + } + + assert((s->type == HTML_SCRIPT_EXTERNAL) || + (s->type == HTML_SCRIPT_INTERNAL)); + + if (s->type == HTML_SCRIPT_EXTERNAL) { + if (s->data.external == NULL) + continue; /* script not present - skip */ + + if (content_get_status(s->data.external) == CONTENT_STATUS_ERROR) + continue; /* script content errored - skip */ + + if (content_get_status(s->data.external) == CONTENT_STATUS_DONE) { + /* external script is now available + * execute it and continue + */ + const char *data; + unsigned long size; + data = content_get_source_data(s->data.external, &size ); + js_exec(c->jscontext, data, size); + s->already_started = true; + + } else { + /* script not yet available */ + if (!s->defer && !s->async) { + break; /* not deferable or async */ } - dom_string_unref(media); } + } else { + js_exec(c->jscontext, + dom_string_data(s->data.internal), + dom_string_byte_length(s->data.internal)); + s->already_started = true; + } + } - /* href='...' */ - exc = dom_element_get_attribute(node, - html_dom_string_href, &href); - if (exc != DOM_NO_ERR || href == NULL) - continue; + return true; +} - /* TODO: only the first preferred stylesheets (ie. - * those with a title attribute) should be loaded - * (see HTML4 14.3) */ +/* create new html script entry */ +static struct html_script *html_process_new_script(html_content *c, enum html_script_type type) +{ + struct html_script *nscript; + /* add space for new script entry */ + nscript = realloc(c->scripts, + sizeof(struct html_script) * (c->scripts_count + 1)); + if (nscript == NULL) { + return NULL; + } - ns_error = nsurl_join(c->base_url, - dom_string_data(href), &joined); - if (ns_error != NSERROR_OK) { - dom_string_unref(href); - goto no_memory; - } - dom_string_unref(href); - - LOG(("linked stylesheet %i '%s'", i, - nsurl_access(joined))); - - /* start fetch */ - stylesheets = talloc_realloc(c, - c->stylesheets, - struct html_stylesheet, i + 1); - if (stylesheets == NULL) { - nsurl_unref(joined); - goto no_memory; - } + c->scripts = nscript; - c->stylesheets = stylesheets; - c->stylesheet_count++; - c->stylesheets[i].type = HTML_STYLESHEET_EXTERNAL; - ns_error = hlcache_handle_retrieve(joined, 0, - content_get_url(&c->base), NULL, - html_convert_css_callback, c, &child, - accept, - &c->stylesheets[i].data.external); + /* increment script entry count */ + nscript = &c->scripts[c->scripts_count]; + c->scripts_count++; - nsurl_unref(joined); + nscript->already_started = false; + nscript->parser_inserted = false; + nscript->force_async = true; + nscript->ready_exec = false; + nscript->async = false; + nscript->defer = false; - if (ns_error != NSERROR_OK) - goto no_memory; + nscript->type = type; - c->base.active++; + return nscript; +} - i++; - } else if (strcmp(dom_string_data(name), "style") == 0) { - dom_string_unref(name); +/** + * Callback for fetchcache() for linked stylesheets. + */ - if (!html_process_style_element(c, &i, node)) - return false; - } else { - dom_string_unref(name); +static nserror +html_convert_script_callback(hlcache_handle *script, + const hlcache_event *event, + void *pw) +{ + html_content *parent = pw; + unsigned int i; + struct html_script *s; + + /* Find sheet */ + for (i = 0, s = parent->scripts; i != parent->scripts_count; i++, s++) { + if (s->type == HTML_SCRIPT_EXTERNAL && + s->data.external == script) + break; + } + + assert(i != parent->scripts_count); + + switch (event->type) { + case CONTENT_MSG_LOADING: + break; + + case CONTENT_MSG_READY: + break; + + case CONTENT_MSG_DONE: + LOG(("script %d done '%s'", i, + nsurl_access(hlcache_handle_get_url(script)))); + parent->base.active--; + LOG(("%d fetches active", parent->base.active)); + + /* script finished loading so try and continue execution */ + html_scripts_exec(parent); + break; + + case CONTENT_MSG_ERROR: + LOG(("script %s failed: %s", + nsurl_access(hlcache_handle_get_url(script)), + event->data.error)); + hlcache_handle_release(script); + s->data.external = NULL; + parent->base.active--; + LOG(("%d fetches active", parent->base.active)); + content_add_error(&parent->base, "?", 0); + + /* script failed loading so try and continue execution */ + html_scripts_exec(parent); + + break; + + case CONTENT_MSG_STATUS: + html_set_status(parent, content_get_status_message(script)); + content_broadcast(&parent->base, CONTENT_MSG_STATUS, + event->data); + break; + + default: + assert(0); + } + + if (parent->base.active == 0) + html_finish_conversion(parent); + + return NSERROR_OK; +} + +/** process script node + * + * + */ +static bool +html_process_script(dom_node *node, dom_string *name, void *ctx) +{ + html_content *c = (html_content *)ctx; + dom_exception exc; /* returned by libdom functions */ + dom_string *src, *script; + struct html_script *nscript; + union content_msg_data msg_data; + + if (!dom_string_isequal(name, html_dom_string_script)) + return true; /* was not a script tag, carry on the walk */ + + /* 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) { + /* no context and it could not be created, abort */ + return false; } } - assert(c->stylesheet_count == i); + exc = dom_element_get_attribute(node, html_dom_string_src, &src); + if (exc != DOM_NO_ERR || src == NULL) { + /* does not appear to be a src so script is inline content */ + exc = dom_node_get_text_content(node, &script); + if ((exc != DOM_NO_ERR) || (script == NULL)) { + return true; /* no contents, skip */ + } + + nscript = html_process_new_script(c, HTML_STYLESHEET_INTERNAL); + if (nscript == NULL) { + dom_string_unref(script); + goto html_process_script_no_memory; + } + + nscript->data.internal = script; + + /* type */ + /* charset (encoding) */ + } else { + /* script with a src tag */ + nserror ns_error; + nsurl *joined; + hlcache_child_context child; + + child.charset = c->encoding; + child.quirks = c->base.quirks; + + nscript = html_process_new_script(c, HTML_STYLESHEET_EXTERNAL); + if (nscript == NULL) { + dom_string_unref(src); + goto html_process_script_no_memory; + } + + /* type */ + /* charset (encoding) */ + + ns_error = nsurl_join(c->base_url, dom_string_data(src), &joined); + dom_string_unref(src); + if (ns_error != NSERROR_OK) { + goto html_process_script_no_memory; + } + + LOG(("script %i '%s'", c->scripts_count, nsurl_access(joined))); + + ns_error = hlcache_handle_retrieve(joined, + 0, + content_get_url(&c->base), + NULL, + html_convert_script_callback, + c, + &child, + CONTENT_ANY, + &nscript->data.external); + + nsurl_unref(joined); + + if (ns_error != NSERROR_OK) + goto html_process_script_no_memory; + + c->base.active++; /* ensure base content knows the fetch is active */ + LOG(("%d fetches active", c->base.active)); + + } + + return true; + +html_process_script_no_memory: + msg_data.error = messages_get("NoMemory"); + content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data); + return false; /* out of memory, abort walk */ +} + +/** + * Process inline script and fetch linked scripts. + * + * + * + * \param c content structure + * \param html dom node of html element + * \return true on success, false if an error occurred + */ +static bool html_find_scripts(html_content *c, dom_node *html) +{ + return html_treewalk_dom(html, html_process_script, c); +} + +struct find_stylesheet_ctx { + unsigned int count; + hlcache_child_context child; + html_content *c; +}; + +/** callback to process stylesheet elements + */ +static bool +html_process_stylesheet(dom_node *node, dom_string *name, void *vctx) +{ + struct find_stylesheet_ctx *ctx = (struct find_stylesheet_ctx *)vctx; + dom_string *rel, *type_attr, *media, *href; + struct html_stylesheet *stylesheets; + nsurl *joined; + union content_msg_data msg_data; + dom_exception exc; + nserror ns_error; + + /* deal with style nodes */ + if (strcmp(dom_string_data(name), "style") == 0) { + if (!html_process_style_element(ctx->c, &ctx->count, node)) + return false; + return true; + } + + /* if it is not a link node skip it */ + if (strcmp(dom_string_data(name), "link") != 0) { + return true; + } + + /* rel= */ + exc = dom_element_get_attribute(node, + html_dom_string_rel, &rel); + if (exc != DOM_NO_ERR || rel == NULL) + return true; + + if (strcasestr(dom_string_data(rel), "stylesheet") == 0) { + dom_string_unref(rel); + return true; + } else if (strcasestr(dom_string_data(rel), "alternate") != 0) { + /* Ignore alternate stylesheets */ + dom_string_unref(rel); + return true; + } + dom_string_unref(rel); + + /* type='text/css' or not present */ + exc = dom_element_get_attribute(node, html_dom_string_type, &type_attr); + if (exc == DOM_NO_ERR && type_attr != NULL) { + if (strcmp(dom_string_data(type_attr), "text/css") != 0) { + dom_string_unref(type_attr); + return true; + } + dom_string_unref(type_attr); + } + + /* media contains 'screen' or 'all' or not present */ + exc = dom_element_get_attribute(node, html_dom_string_media, &media); + if (exc == DOM_NO_ERR && media != NULL) { + if (strcasestr(dom_string_data(media), "screen") == NULL && + strcasestr(dom_string_data(media), "all") == NULL) { + dom_string_unref(media); + return true; + } + dom_string_unref(media); + } + + /* href='...' */ + exc = dom_element_get_attribute(node, html_dom_string_href, &href); + if (exc != DOM_NO_ERR || href == NULL) + return true; + + /* TODO: only the first preferred stylesheets (ie. + * those with a title attribute) should be loaded + * (see HTML4 14.3) */ + + ns_error = nsurl_join(ctx->c->base_url, dom_string_data(href), &joined); + if (ns_error != NSERROR_OK) { + dom_string_unref(href); + goto no_memory; + } + dom_string_unref(href); + + LOG(("linked stylesheet %i '%s'", ctx->count, nsurl_access(joined))); + + /* start fetch */ + stylesheets = talloc_realloc(ctx->c, + ctx->c->stylesheets, + struct html_stylesheet, + ctx->count + 1); + if (stylesheets == NULL) { + nsurl_unref(joined); + goto no_memory; + } + + ctx->c->stylesheets = stylesheets; + ctx->c->stylesheet_count++; + ctx->c->stylesheets[ctx->count].type = HTML_STYLESHEET_EXTERNAL; + ns_error = hlcache_handle_retrieve(joined, + 0, + content_get_url(&ctx->c->base), + NULL, + html_convert_css_callback, + ctx->c, + &ctx->child, + CONTENT_CSS, + &ctx->c->stylesheets[ctx->count].data.external); + + nsurl_unref(joined); + + if (ns_error != NSERROR_OK) + goto no_memory; + + ctx->c->base.active++; + LOG(("%d fetches active", ctx->c->base.active)); + + ctx->count++; return true; no_memory: + msg_data.error = messages_get("NoMemory"); + content_broadcast(&ctx->c->base, CONTENT_MSG_ERROR, msg_data); + return false; + +} + + +/** + * Process inline stylesheets and fetch linked stylesheets. + * + * Uses STYLE and LINK elements inside and outside HEAD + * + * \param c content structure + * \param html dom node of html element + * \return true on success, false if an error occurred + */ + +static bool html_find_stylesheets(html_content *c, dom_node *html) +{ + content_type accept = CONTENT_CSS; + union content_msg_data msg_data; + nserror ns_error; + bool result; + struct find_stylesheet_ctx ctx; + + /* setup context */ + ctx.c = c; + ctx.count = STYLESHEET_START; + + ctx.child.charset = c->encoding; + ctx.child.quirks = c->base.quirks; + + /* stylesheet 0 is the base style sheet, + * stylesheet 1 is the quirks mode style sheet, + * stylesheet 2 is the adblocking stylesheet, + * stylesheet 3 is the user stylesheet */ + c->stylesheets = talloc_array(c, struct html_stylesheet, + STYLESHEET_START); + if (c->stylesheets == NULL) + goto html_find_stylesheets_no_memory; + + c->stylesheets[STYLESHEET_BASE].type = HTML_STYLESHEET_EXTERNAL; + c->stylesheets[STYLESHEET_BASE].data.external = NULL; + c->stylesheets[STYLESHEET_QUIRKS].type = HTML_STYLESHEET_EXTERNAL; + c->stylesheets[STYLESHEET_QUIRKS].data.external = NULL; + c->stylesheets[STYLESHEET_ADBLOCK].type = HTML_STYLESHEET_EXTERNAL; + c->stylesheets[STYLESHEET_ADBLOCK].data.external = NULL; + c->stylesheets[STYLESHEET_USER].type = HTML_STYLESHEET_EXTERNAL; + c->stylesheets[STYLESHEET_USER].data.external = NULL; + c->stylesheet_count = STYLESHEET_START; + + ns_error = hlcache_handle_retrieve(html_default_stylesheet_url, 0, + content_get_url(&c->base), NULL, + html_convert_css_callback, c, &ctx.child, accept, + &c->stylesheets[STYLESHEET_BASE].data.external); + if (ns_error != NSERROR_OK) + goto html_find_stylesheets_no_memory; + + c->base.active++; + LOG(("%d fetches active", c->base.active)); + + if (c->quirks == BINDING_QUIRKS_MODE_FULL) { + ns_error = hlcache_handle_retrieve(html_quirks_stylesheet_url, + 0, content_get_url(&c->base), NULL, + html_convert_css_callback, c, &ctx.child, accept, + &c->stylesheets[STYLESHEET_QUIRKS]. + data.external); + if (ns_error != NSERROR_OK) + goto html_find_stylesheets_no_memory; + + c->base.active++; + LOG(("%d fetches active", c->base.active)); + + } + + if (nsoption_bool(block_ads)) { + ns_error = hlcache_handle_retrieve(html_adblock_stylesheet_url, + 0, content_get_url(&c->base), NULL, + html_convert_css_callback, c, &ctx.child, accept, + &c->stylesheets[STYLESHEET_ADBLOCK]. + data.external); + if (ns_error != NSERROR_OK) + goto html_find_stylesheets_no_memory; + + c->base.active++; + LOG(("%d fetches active", c->base.active)); + + } + + ns_error = hlcache_handle_retrieve(html_user_stylesheet_url, 0, + content_get_url(&c->base), NULL, + html_convert_css_callback, c, &ctx.child, accept, + &c->stylesheets[STYLESHEET_USER].data.external); + if (ns_error != NSERROR_OK) + goto html_find_stylesheets_no_memory; + + c->base.active++; + LOG(("%d fetches active", c->base.active)); + + + result = html_treewalk_dom(html, html_process_stylesheet, &ctx); + + assert(c->stylesheet_count == ctx.count); + + return result; + +html_find_stylesheets_no_memory: msg_data.error = messages_get("NoMemory"); content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data); return false; @@ -2024,6 +2328,14 @@ static bool html_convert(struct content *c) } } + /* find script tags */ + if (nsoption_bool(enable_javascript)) { + /* @todo this ought to be done during parse */ + html_find_scripts(htmlc, html); + /* run as far as we can */ + html_scripts_run(htmlc); + } + /* get stylesheets */ if (html_find_stylesheets(htmlc, html) == false) return false; @@ -2091,6 +2403,7 @@ bool html_fetch_object(html_content *c, nsurl *url, struct box *box, c->num_objects++; c->base.active++; + LOG(("%d fetches active", c->base.active)); return true; } @@ -2099,12 +2412,6 @@ bool html_fetch_object(html_content *c, nsurl *url, struct box *box, - - - - - - /** * Stop loading a CONTENT_HTML. */ @@ -2141,6 +2448,8 @@ static void html_stop(struct content *c) object->content = NULL; c->active--; + LOG(("%d fetches active", c->active)); + } } @@ -2360,6 +2669,20 @@ static void html_destroy(struct content *c) } } + /* Free scripts */ + for (i = 0; i != html->scripts_count; i++) { + if (html->scripts[i].type == HTML_SCRIPT_EXTERNAL && + html->scripts[i].data.external != NULL) { + hlcache_handle_release( + html->scripts[i].data.external); + } else if (html->scripts[i].type == + HTML_SCRIPT_INTERNAL && + html->scripts[i].data.internal != NULL) { + dom_string_unref(html->scripts[i].data.internal); + } + } + free(html->scripts); + /* Free objects */ html_destroy_objects(html); } @@ -3034,6 +3357,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(src); HTML_DOM_STRING_UNREF(script); HTML_DOM_STRING_UNREF(link); HTML_DOM_STRING_UNREF(target); @@ -3164,6 +3488,7 @@ nserror html_init(void) HTML_DOM_STRING_INTERN(base); HTML_DOM_STRING_INTERN(link); HTML_DOM_STRING_INTERN(script); + HTML_DOM_STRING_INTERN(src); HTML_DOM_STRING_INTERN(target); HTML_DOM_STRING_INTERN(_blank); HTML_DOM_STRING_INTERN(_self); diff --git a/render/html.h b/render/html.h index 7d2ef82cf..f0ab47d51 100644 --- a/render/html.h +++ b/render/html.h @@ -58,6 +58,26 @@ struct html_stylesheet { } data; /**< Sheet data */ }; +/** + * Container for scripts used by an HTML document + */ +struct html_script { + /** Type of script */ + enum html_script_type { HTML_SCRIPT_EXTERNAL, HTML_SCRIPT_INTERNAL } type; + union { + struct hlcache_handle *external; + struct dom_string *internal; + } data; /**< Script data */ + struct dom_string *script_type; + struct dom_string *encoding; + bool already_started; + bool parser_inserted; + bool force_async; + bool ready_exec; + bool async; + bool defer; +}; + /** An object (, , etc.) in a CONTENT_HTML document. */ struct content_html_object { diff --git a/render/html_internal.h b/render/html_internal.h index 3d9dea389..da3d686bd 100644 --- a/render/html_internal.h +++ b/render/html_internal.h @@ -58,6 +58,13 @@ typedef struct html_content { /** Font callback table */ const struct font_functions *font_func; + /** Number of entries in scripts */ + unsigned int scripts_count; + /** Scripts */ + struct html_script *scripts; + /** javascript context */ + struct jscontext *jscontext; + /** Number of entries in stylesheet_content. */ unsigned int stylesheet_count; /** Stylesheets. Each may be NULL. */ @@ -105,9 +112,6 @@ typedef struct html_content { /** Context for free text search, or NULL if none */ struct search_context *search; - /** javascript context */ - struct jscontext *jscontext; - } html_content; -- cgit v1.2.3