mirror of
https://github.com/netsurf-browser/netsurf
synced 2024-11-22 06:21:45 +03:00
JS: Split concept of JS context into heap and thread
In preparation for proper splitting of Javascript support into heaps and threads, this renames the types and corrects the no-js builds to still work. At this time no substantive change in semantics exists, and the duktape build won't work. Signed-off-by: Daniel Silverstone <dsilvers@digital-scurf.org>
This commit is contained in:
parent
313dc9b099
commit
17b28e85c1
@ -72,7 +72,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_GETTHREAD, /**< Javascript thread */
|
||||
CONTENT_MSG_GETDIMS, /**< Get viewport dimensions. */
|
||||
CONTENT_MSG_SCROLL, /**< Request to scroll content */
|
||||
CONTENT_MSG_DRAGSAVE, /**< Allow drag saving of content */
|
||||
@ -180,9 +180,9 @@ union content_msg_data {
|
||||
struct content_rfc5988_link *rfc5988_link;
|
||||
|
||||
/**
|
||||
* CONTENT_MSG_GETCTX - Javascript context
|
||||
* CONTENT_MSG_GETTHREAD - Javascript context (thread)
|
||||
*/
|
||||
struct jscontext **jscontext;
|
||||
struct jsthread **jsthread;
|
||||
|
||||
/**
|
||||
* CONTENT_MSG_GETDIMS - Get the viewport dimensions
|
||||
|
@ -757,8 +757,8 @@ void html_finish_conversion(html_content *htmlc)
|
||||
* object, but with its target set to the Document object (and
|
||||
* the currentTarget set to the Window object)
|
||||
*/
|
||||
if (htmlc->jscontext != NULL) {
|
||||
js_fire_event(htmlc->jscontext, "load", htmlc->document, NULL);
|
||||
if (htmlc->jsthread != NULL) {
|
||||
js_fire_event(htmlc->jsthread, "load", htmlc->document, NULL);
|
||||
}
|
||||
|
||||
/* convert dom tree to box tree */
|
||||
@ -896,20 +896,20 @@ dom_default_action_DOMNodeInserted_cb(struct dom_event *evt, void *pw)
|
||||
}
|
||||
if (htmlc->enable_scripting) {
|
||||
/* ensure javascript context is available */
|
||||
if (htmlc->jscontext == NULL) {
|
||||
if (htmlc->jsthread == NULL) {
|
||||
union content_msg_data msg_data;
|
||||
|
||||
msg_data.jscontext = &htmlc->jscontext;
|
||||
msg_data.jsthread = &htmlc->jsthread;
|
||||
content_broadcast(&htmlc->base,
|
||||
CONTENT_MSG_GETCTX,
|
||||
CONTENT_MSG_GETTHREAD,
|
||||
&msg_data);
|
||||
NSLOG(netsurf, INFO,
|
||||
"javascript context: %p (htmlc: %p)",
|
||||
htmlc->jscontext,
|
||||
htmlc->jsthread,
|
||||
htmlc);
|
||||
}
|
||||
if (htmlc->jscontext != NULL) {
|
||||
js_handle_new_element(htmlc->jscontext,
|
||||
if (htmlc->jsthread != NULL) {
|
||||
js_handle_new_element(htmlc->jsthread,
|
||||
(dom_element *) node);
|
||||
}
|
||||
}
|
||||
@ -1015,8 +1015,8 @@ dom_default_action_finished_cb(struct dom_event *evt, void *pw)
|
||||
{
|
||||
html_content *htmlc = pw;
|
||||
|
||||
if (htmlc->jscontext != NULL)
|
||||
js_event_cleanup(htmlc->jscontext, evt);
|
||||
if (htmlc->jsthread != NULL)
|
||||
js_event_cleanup(htmlc->jsthread, evt);
|
||||
}
|
||||
|
||||
/* callback function selector
|
||||
@ -1136,7 +1136,7 @@ html_create_html_data(html_content *c, const http_parameter *params)
|
||||
c->search_string = NULL;
|
||||
c->scripts_count = 0;
|
||||
c->scripts = NULL;
|
||||
c->jscontext = NULL;
|
||||
c->jsthread = NULL;
|
||||
|
||||
c->enable_scripting = nsoption_bool(enable_javascript);
|
||||
c->base.active = 1; /* The html content itself is active */
|
||||
|
@ -151,8 +151,8 @@ typedef struct html_content {
|
||||
unsigned int scripts_count;
|
||||
/** Scripts */
|
||||
struct html_script *scripts;
|
||||
/** javascript context */
|
||||
struct jscontext *jscontext;
|
||||
/** javascript thread in use */
|
||||
struct jsthread *jsthread;
|
||||
|
||||
/** Number of entries in stylesheet_content. */
|
||||
unsigned int stylesheet_count;
|
||||
|
@ -340,8 +340,9 @@ html_object_callback(hlcache_handle *object,
|
||||
/* Don't care about favicons that aren't on top level content */
|
||||
break;
|
||||
|
||||
case CONTENT_MSG_GETCTX:
|
||||
*(event->data.jscontext) = NULL;
|
||||
case CONTENT_MSG_GETTHREAD:
|
||||
/* Objects don't have JS threads */
|
||||
*(event->data.jsthread) = NULL;
|
||||
break;
|
||||
|
||||
case CONTENT_MSG_GETDIMS:
|
||||
|
@ -42,7 +42,7 @@
|
||||
#include "html/html.h"
|
||||
#include "html/html_internal.h"
|
||||
|
||||
typedef bool (script_handler_t)(struct jscontext *jscontext, const uint8_t *data, size_t size, const char *name);
|
||||
typedef bool (script_handler_t)(struct jsthread *jsthread, const uint8_t *data, size_t size, const char *name);
|
||||
|
||||
|
||||
static script_handler_t *select_script_handler(content_type ctype)
|
||||
@ -62,7 +62,7 @@ nserror html_script_exec(html_content *c, bool allow_defer)
|
||||
script_handler_t *script_handler;
|
||||
bool have_run_something = false;
|
||||
|
||||
if (c->jscontext == NULL) {
|
||||
if (c->jsthread == NULL) {
|
||||
return NSERROR_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
@ -95,7 +95,7 @@ nserror html_script_exec(html_content *c, bool allow_defer)
|
||||
size_t size;
|
||||
data = content_get_source_data(
|
||||
s->data.handle, &size );
|
||||
script_handler(c->jscontext, data, size,
|
||||
script_handler(c->jsthread, data, size,
|
||||
nsurl_access(hlcache_handle_get_url(s->data.handle)));
|
||||
have_run_something = true;
|
||||
/* We have to re-acquire this here since the
|
||||
@ -319,12 +319,12 @@ convert_script_sync_cb(hlcache_handle *script,
|
||||
|
||||
/* attempt to execute script */
|
||||
script_handler = select_script_handler(content_get_type(s->data.handle));
|
||||
if (script_handler != NULL && parent->jscontext != NULL) {
|
||||
if (script_handler != NULL && parent->jsthread != NULL) {
|
||||
/* script has a handler */
|
||||
const uint8_t *data;
|
||||
size_t size;
|
||||
data = content_get_source_data(s->data.handle, &size );
|
||||
script_handler(parent->jscontext, data, size,
|
||||
script_handler(parent->jsthread, data, size,
|
||||
nsurl_access(hlcache_handle_get_url(s->data.handle)));
|
||||
}
|
||||
|
||||
@ -549,7 +549,7 @@ exec_inline_script(html_content *c, dom_node *node, dom_string *mimetype)
|
||||
lwc_string_unref(lwcmimetype);
|
||||
|
||||
if (script_handler != NULL) {
|
||||
script_handler(c->jscontext,
|
||||
script_handler(c->jsthread,
|
||||
(const uint8_t *)dom_string_data(script),
|
||||
dom_string_byte_length(script),
|
||||
"?inline script?");
|
||||
@ -575,13 +575,13 @@ html_process_script(void *ctx, dom_node *node)
|
||||
/* We should only ever be here if scripting was enabled for this
|
||||
* content so it's correct to make a javascript context if there
|
||||
* isn't one already. */
|
||||
if (c->jscontext == NULL) {
|
||||
if (c->jsthread == NULL) {
|
||||
union content_msg_data msg_data;
|
||||
|
||||
msg_data.jscontext = &c->jscontext;
|
||||
content_broadcast(&c->base, CONTENT_MSG_GETCTX, &msg_data);
|
||||
NSLOG(netsurf, INFO, "javascript context %p ", c->jscontext);
|
||||
if (c->jscontext == NULL) {
|
||||
msg_data.jsthread = &c->jsthread;
|
||||
content_broadcast(&c->base, CONTENT_MSG_GETTHREAD, &msg_data);
|
||||
NSLOG(netsurf, INFO, "javascript context %p ", c->jsthread);
|
||||
if (c->jsthread == NULL) {
|
||||
/* no context and it could not be created, abort */
|
||||
return DOM_HUBBUB_OK;
|
||||
}
|
||||
@ -668,6 +668,6 @@ nserror html_script_free(html_content *html)
|
||||
/* exported internal interface documented in html/html_internal.h */
|
||||
nserror html_script_invalidate_ctx(html_content *htmlc)
|
||||
{
|
||||
htmlc->jscontext = NULL;
|
||||
htmlc->jsthread = NULL;
|
||||
return NSERROR_OK;
|
||||
}
|
||||
|
@ -25,15 +25,33 @@
|
||||
|
||||
#include "utils/errors.h"
|
||||
|
||||
typedef struct jscontext jscontext;
|
||||
typedef struct jsobject jsobject;
|
||||
|
||||
struct dom_event;
|
||||
struct dom_document;
|
||||
struct dom_node;
|
||||
struct dom_element;
|
||||
struct dom_string;
|
||||
|
||||
/**
|
||||
* JavaScript interpreter heap
|
||||
*
|
||||
* In order to try and be moderately performant, we create a heap
|
||||
* per browser window. This heap is shared by all browsing contexts
|
||||
* we end up creating in that window.
|
||||
*/
|
||||
typedef struct jsheap jsheap;
|
||||
|
||||
/**
|
||||
* JavaScript interpreter thread
|
||||
*
|
||||
* When we create a browsing context itself (window+content) we have
|
||||
* to create a JS thread to attach to the browsing context.
|
||||
*
|
||||
* JS threads are associated with heaps and will be destroyed when
|
||||
* the heap is destroyed. They can be shut down manually though
|
||||
* and should be for object lifetime safety reasons.
|
||||
*/
|
||||
typedef struct jsthread jsthread;
|
||||
|
||||
/**
|
||||
* Initialise javascript interpreter
|
||||
*/
|
||||
@ -45,41 +63,51 @@ void js_initialise(void);
|
||||
void js_finalise(void);
|
||||
|
||||
/**
|
||||
* Create a new javascript context.
|
||||
* Create a new javascript heap.
|
||||
*
|
||||
* There is usually one context per browsing context (browser window)
|
||||
* There is usually one heap per browser window.
|
||||
*
|
||||
* \param timeout elapsed wallclock time (in seconds) before \a callback is called
|
||||
* \param jsctx Updated to the created JS context
|
||||
* \param heap Updated to the created JS heap
|
||||
* \return NSERROR_OK on success, appropriate error otherwise.
|
||||
*/
|
||||
nserror js_newcontext(int timeout, jscontext **jsctx);
|
||||
nserror js_newheap(int timeout, jsheap **heap);
|
||||
|
||||
/**
|
||||
* Destroy a previously created context
|
||||
* Destroy a previously created heap.
|
||||
*
|
||||
* \param heap The heap to destroy
|
||||
*/
|
||||
void js_destroycontext(jscontext *ctx);
|
||||
void js_destroyheap(jsheap *heap);
|
||||
|
||||
/**
|
||||
* Create a new javascript compartment
|
||||
* Create a new javascript thread
|
||||
*
|
||||
* This is called once for a page with javascript script tags on
|
||||
* it. It constructs a fresh global window object.
|
||||
* it. It constructs a fresh global window object and prepares the JS
|
||||
* browsing context. It's important that threads are shut down cleanly
|
||||
* when the browsing context is going to be cleaned up.
|
||||
*
|
||||
* \param heap The heap to create the thread within
|
||||
* \param win_priv The value to give to the Window constructor as the window
|
||||
* \param doc_priv The value to give to the Document constructor as the document
|
||||
* \param thread Updated to the created thread
|
||||
* \return NSERROR_OK on success, appropriate error otherwise
|
||||
*/
|
||||
jsobject *js_newcompartment(jscontext *ctx, void *win_priv, void *doc_priv);
|
||||
nserror js_newthread(jsheap *heap, void *win_priv, void *doc_priv, jsthread **thread);
|
||||
|
||||
/**
|
||||
* execute some javascript in a context
|
||||
*/
|
||||
bool js_exec(jscontext *ctx, const uint8_t *txt, size_t txtlen, const char *name);
|
||||
bool js_exec(jsthread *thread, const uint8_t *txt, size_t txtlen, const char *name);
|
||||
|
||||
/**
|
||||
* fire an event at a dom node
|
||||
*/
|
||||
bool js_fire_event(jscontext *ctx, const char *type, struct dom_document *doc, struct dom_node *target);
|
||||
bool js_fire_event(jsthread *thread, const char *type, struct dom_document *doc, struct dom_node *target);
|
||||
|
||||
bool
|
||||
js_dom_event_add_listener(jscontext *ctx,
|
||||
js_dom_event_add_listener(jsthread *thread,
|
||||
struct dom_document *document,
|
||||
struct dom_node *node,
|
||||
struct dom_string *event_type_dom,
|
||||
@ -94,7 +122,7 @@ js_dom_event_add_listener(jscontext *ctx,
|
||||
* by the context provided. The JS implementation must then scan the element
|
||||
* for on* attributes and register appropriate listeners for those handlers.
|
||||
*/
|
||||
void js_handle_new_element(jscontext *ctx, struct dom_element *node);
|
||||
void js_handle_new_element(jsthread *thread, struct dom_element *node);
|
||||
|
||||
/**
|
||||
* Handle an event propagation finished callback.
|
||||
@ -104,6 +132,6 @@ void js_handle_new_element(jscontext *ctx, struct dom_element *node);
|
||||
* it may need to perform before the DOM finishes and the event may end up
|
||||
* freed.
|
||||
*/
|
||||
void js_event_cleanup(jscontext *ctx, struct dom_event *evt);
|
||||
void js_event_cleanup(jsthread *thread, struct dom_event *evt);
|
||||
|
||||
#endif /* NETSURF_JAVASCRIPT_JS_H_ */
|
||||
|
@ -35,35 +35,36 @@ void js_finalise(void)
|
||||
{
|
||||
}
|
||||
|
||||
nserror js_newcontext(int timeout, jscontext **jsctx)
|
||||
nserror js_newheap(int timeout, jsheap **heap)
|
||||
{
|
||||
*jsctx = NULL;
|
||||
*heap = NULL;
|
||||
return NSERROR_OK;
|
||||
}
|
||||
|
||||
void js_destroycontext(jscontext *ctx)
|
||||
void js_destroyheap(jsheap *heap)
|
||||
{
|
||||
}
|
||||
|
||||
jsobject *js_newcompartment(jscontext *ctx, void *win_priv, void *doc_priv)
|
||||
nserror js_newthread(jsheap *heap, void *win_priv, void *doc_priv, jsthread **thread)
|
||||
{
|
||||
return NULL;
|
||||
*thread = NULL;
|
||||
return NSERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
bool js_exec(jscontext *ctx, const uint8_t *txt, size_t txtlen, const char *name)
|
||||
bool js_exec(jsthread *thread, const uint8_t *txt, size_t txtlen, const char *name)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool js_fire_event(jscontext *ctx, const char *type, struct dom_document *doc, struct dom_node *target)
|
||||
bool js_fire_event(jsthread *thread, const char *type, struct dom_document *doc, struct dom_node *target)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void js_handle_new_element(jscontext *ctx, struct dom_element *node)
|
||||
void js_handle_new_element(jsthread *thread, struct dom_element *node)
|
||||
{
|
||||
}
|
||||
|
||||
void js_event_cleanup(jscontext *ctx, struct dom_event *evt)
|
||||
void js_event_cleanup(jsthread *thread, struct dom_event *evt)
|
||||
{
|
||||
}
|
||||
|
@ -263,7 +263,8 @@ struct browser_window {
|
||||
bool can_edit;
|
||||
|
||||
/** current javascript context */
|
||||
struct jscontext *jsctx;
|
||||
struct jsheap *jsheap;
|
||||
struct jsthread *jsthread;
|
||||
|
||||
/** cache of the currently displayed status text. */
|
||||
struct {
|
||||
|
@ -1485,15 +1485,19 @@ browser_window_callback(hlcache_handle *c, const hlcache_event *event, void *pw)
|
||||
}
|
||||
break;
|
||||
|
||||
case CONTENT_MSG_GETCTX:
|
||||
/* only the content object created by the browser
|
||||
* window requires a new global compartment object
|
||||
*/
|
||||
assert(bw->loading_content == c);
|
||||
if (js_newcompartment(bw->jsctx,
|
||||
bw,
|
||||
hlcache_handle_get_content(c)) != NULL) {
|
||||
*(event->data.jscontext) = bw->jsctx;
|
||||
case CONTENT_MSG_GETTHREAD:
|
||||
{
|
||||
/* only the content object created by the browser
|
||||
* window requires a new global compartment object
|
||||
*/
|
||||
jsthread *thread;
|
||||
assert(bw->loading_content == c);
|
||||
if (js_newthread(bw->jsheap,
|
||||
bw,
|
||||
hlcache_handle_get_content(c),
|
||||
&thread) == NSERROR_OK) {
|
||||
*(event->data.jsthread) = thread;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1760,8 +1764,8 @@ static void browser_window_destroy_internal(struct browser_window *bw)
|
||||
bw->box = NULL;
|
||||
}
|
||||
|
||||
if (bw->jsctx != NULL) {
|
||||
js_destroycontext(bw->jsctx);
|
||||
if (bw->jsheap != NULL) {
|
||||
js_destroyheap(bw->jsheap);
|
||||
}
|
||||
|
||||
/* These simply free memory, so are safe here */
|
||||
@ -3085,7 +3089,7 @@ browser_window_initialise_common(enum browser_window_create_flags flags,
|
||||
assert(bw);
|
||||
|
||||
/* new javascript context for each window/(i)frame */
|
||||
err = js_newcontext(nsoption_int(script_timeout), &bw->jsctx);
|
||||
err = js_newheap(nsoption_int(script_timeout), &bw->jsheap);
|
||||
if (err != NSERROR_OK)
|
||||
return err;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user