From 99c54f1d9d198fc6ea9477ff58aafb76e5c1f20a Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Fri, 26 Oct 2012 12:36:14 +0100 Subject: split class prototype initialisation from instantiation --- javascript/jsapi.c | 53 +++----- javascript/jsapi.h | 44 +------ javascript/jsapi/binding.h | 82 +++++++++++++ javascript/jsapi/console.c | 2 +- javascript/jsapi/window.c | 297 ++++++++++++++++++++------------------------- 5 files changed, 238 insertions(+), 240 deletions(-) create mode 100644 javascript/jsapi/binding.h (limited to 'javascript') diff --git a/javascript/jsapi.c b/javascript/jsapi.c index f7ac3eda1..4e980b5fd 100644 --- a/javascript/jsapi.c +++ b/javascript/jsapi.c @@ -17,6 +17,7 @@ */ #include "javascript/jsapi.h" +#include "javascript/jsapi/binding.h" #include "content/content.h" #include "javascript/content.h" @@ -90,46 +91,32 @@ void js_destroycontext(jscontext *ctx) } - +/** Create new compartment to run scripts within + * + * This performs the following actions + * 1. constructs a new global object by initialising a window class + * 2. Instantiate the global a window object + */ jsobject *js_newcompartment(jscontext *ctx, void *win_priv, void *doc_priv) { JSContext *cx = (JSContext *)ctx; - JSObject *window_obj = NULL; - JSObject *document_obj; - JSObject *navigator_obj; - JSObject *console_obj; - struct html_content *htmlc = doc_priv; - - if (cx == NULL) - goto js_newcompartment_fail; - - /* create the window object as the global */ - window_obj = jsapi_new_window(cx, NULL, win_priv); - if (window_obj == NULL) - goto js_newcompartment_fail; - - /* attach the subclasses off the window global */ - document_obj = jsapi_new_Document(cx, window_obj, htmlc->document, htmlc); - if (document_obj == NULL) - goto js_newcompartment_fail; - - navigator_obj = jsapi_new_navigator(cx, window_obj); - if (navigator_obj == NULL) - goto js_newcompartment_fail; + JSObject *window_proto; + JSObject *window; - /* @todo forms, history, location */ - - console_obj = jsapi_new_console(cx, window_obj); - if (console_obj == NULL) - goto js_newcompartment_fail; - - return (jsobject *)window_obj; + if (cx == NULL) { + return NULL; + } -js_newcompartment_fail: + window_proto = jsapi_InitClass_Window(cx, NULL); + if (window_proto == NULL) { + LOG(("Unable to initialise window class")); + return NULL; + } - LOG(("New compartment creation failed")); + window = jsapi_new_Window(cx, window_proto, NULL, win_priv, doc_priv); + + return (jsobject *)window; - return NULL; } bool js_exec(jscontext *ctx, const char *txt, size_t txtlen) diff --git a/javascript/jsapi.h b/javascript/jsapi.h index 91d9184b4..93c0effdd 100644 --- a/javascript/jsapi.h +++ b/javascript/jsapi.h @@ -17,7 +17,7 @@ */ /** \file - * spidermonkey jsapi bindings and compatability glue. + * spidermonkey jsapi compatability glue. */ #ifndef _NETSURF_JAVASCRIPT_JSAPI_H_ @@ -149,47 +149,5 @@ JS_NewCompartmentAndGlobalObject(JSContext *cx, #endif -/** Create a new javascript window object - * - * @param cx The javascript context. - * @param parent The parent object or NULL for new global - * @param win_priv The private context to set on the object - * @return new javascript object or NULL on error - */ -JSObject *jsapi_new_window(JSContext *cx, JSObject *parent, void *win_priv); - -/** Create a new javascript document object - * - * @param cx The javascript context. - * @param parent The parent object, usually a global window object - * @param doc_priv The private context to set on the object - * @return new javascript object or NULL on error - */ -JSObject *jsapi_new_Document(JSContext *cx, JSObject *parent, dom_document *node, struct html_content *htmlc); - -/** Create a new javascript console object - * - * @param cx The javascript context. - * @param parent The parent object, usually a global window object - * @return new javascript object or NULL on error - */ -JSObject *jsapi_new_console(JSContext *cx, JSObject *parent); - -/** Create a new javascript navigator object - * - * @param cx The javascript context. - * @param parent The parent object, usually a global window object - * @return new javascript object or NULL on error - */ -JSObject *jsapi_new_navigator(JSContext *cx, JSObject *parent); - -/** Create a new javascript element object - * - * @param cx The javascript context. - * @param parent The parent object, usually a global window object - * @param doc_priv The private context to set on the object - * @return new javascript object or NULL on error - */ -JSObject *jsapi_new_element(JSContext *cx, JSObject *parent, struct html_content *htmlc, struct dom_element *domelement); #endif diff --git a/javascript/jsapi/binding.h b/javascript/jsapi/binding.h new file mode 100644 index 000000000..b565136af --- /dev/null +++ b/javascript/jsapi/binding.h @@ -0,0 +1,82 @@ +/* + * 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 class bindings + */ + +#ifndef _NETSURF_JAVASCRIPT_JSAPI_BINDING_H_ +#define _NETSURF_JAVASCRIPT_JSAPI_BINDING_H_ + +JSObject *jsapi_InitClass_Window(JSContext *cx, JSObject *parent); + +/** Create a new javascript window object + * + * @param cx The javascript context. + * @param parent The parent object or NULL for new global + * @param win_priv The private context to set on the object + * @return new javascript object or NULL on error + */ +JSObject *jsapi_new_Window(JSContext *cx, + JSObject *window, + JSObject *parent, + struct browser_window *bw, + html_content *htmlc); + + +JSObject *jsapi_InitClass_Document(JSContext *cx, JSObject *parent); + +/** Create a new javascript document object + * + * @param cx The javascript context. + * @param parent The parent object, usually a global window object + * @param doc_priv The private context to set on the object + * @return new javascript object or NULL on error + */ +JSObject *jsapi_new_Document(JSContext *cx, + JSObject *proto, + JSObject *parent, + dom_document *node, + struct html_content *htmlc); + +/** Create a new javascript console object + * + * @param cx The javascript context. + * @param parent The parent object, usually a global window object + * @return new javascript object or NULL on error + */ +JSObject *jsapi_new_Console(JSContext *cx, JSObject *parent); + +/** Create a new javascript navigator object + * + * @param cx The javascript context. + * @param parent The parent object, usually a global window object + * @return new javascript object or NULL on error + */ +JSObject *jsapi_new_Navigator(JSContext *cx, JSObject *parent); + +/** Create a new javascript element object + * + * @param cx The javascript context. + * @param parent The parent object, usually a global window object + * @param doc_priv The private context to set on the object + * @return new javascript object or NULL on error + */ +JSObject *jsapi_new_element(JSContext *cx, JSObject *parent, struct html_content *htmlc, struct dom_element *domelement); + +#endif diff --git a/javascript/jsapi/console.c b/javascript/jsapi/console.c index 6a6d7d3c3..3cd51883d 100644 --- a/javascript/jsapi/console.c +++ b/javascript/jsapi/console.c @@ -137,7 +137,7 @@ static JSClass jsclass_console = }; -JSObject *jsapi_new_console(JSContext *cx, JSObject *parent) +JSObject *jsapi_new_Console(JSContext *cx, JSObject *parent) { return JS_InitClass(cx, parent, diff --git a/javascript/jsapi/window.c b/javascript/jsapi/window.c index 72d3837d9..476a38324 100644 --- a/javascript/jsapi/window.c +++ b/javascript/jsapi/window.c @@ -19,131 +19,33 @@ #include "utils/log.h" #include "javascript/jsapi.h" +#include "javascript/jsapi/binding.h" -/* IDL - -[NamedPropertiesObject] -interface Window : EventTarget { - // the current browsing context - [Unforgeable] readonly attribute WindowProxy window; - [Replaceable] readonly attribute WindowProxy self; - [Unforgeable] readonly attribute Document document; - attribute DOMString name; - [PutForwards=href, Unforgeable] readonly attribute Location location; - readonly attribute History history; - - boolean find(optional DOMString aString, optional boolean aCaseSensitive, optional boolean aBackwards, optional boolean aWrapAround, optional boolean aWholeWord, optional boolean aSearchInFrames, optional boolean aShowDialog); - - [Replaceable] readonly attribute BarProp locationbar; - [Replaceable] readonly attribute BarProp menubar; - [Replaceable] readonly attribute BarProp personalbar; - [Replaceable] readonly attribute BarProp scrollbars; - [Replaceable] readonly attribute BarProp statusbar; - [Replaceable] readonly attribute BarProp toolbar; - attribute DOMString status; - void close(); - void stop(); - void focus(); - void blur(); - - // other browsing contexts - [Replaceable] readonly attribute WindowProxy frames; - [Replaceable] readonly attribute unsigned long length; - [Unforgeable] readonly attribute WindowProxy top; - attribute WindowProxy? opener; - readonly attribute WindowProxy parent; - readonly attribute Element? frameElement; - WindowProxy open(optional DOMString url, optional DOMString target, optional DOMString features, optional boolean replace); - getter WindowProxy (unsigned long index); - getter object (DOMString name); - - // the user agent - readonly attribute Navigator navigator; - readonly attribute External external; - readonly attribute ApplicationCache applicationCache; - - // user prompts - void alert(DOMString message); - boolean confirm(DOMString message); - DOMString? prompt(DOMString message, optional DOMString default); - void print(); - any showModalDialog(DOMString url, optional any argument); - - // cross-document messaging - void postMessage(any message, DOMString targetOrigin, optional sequence transfer); - - // event handler IDL attributes - [TreatNonCallableAsNull] attribute Function? onabort; - [TreatNonCallableAsNull] attribute Function? onafterprint; - [TreatNonCallableAsNull] attribute Function? onbeforeprint; - [TreatNonCallableAsNull] attribute Function? onbeforeunload; - [TreatNonCallableAsNull] attribute Function? onblur; - [TreatNonCallableAsNull] attribute Function? oncancel; - [TreatNonCallableAsNull] attribute Function? oncanplay; - [TreatNonCallableAsNull] attribute Function? oncanplaythrough; - [TreatNonCallableAsNull] attribute Function? onchange; - [TreatNonCallableAsNull] attribute Function? onclick; - [TreatNonCallableAsNull] attribute Function? onclose; - [TreatNonCallableAsNull] attribute Function? oncontextmenu; - [TreatNonCallableAsNull] attribute Function? oncuechange; - [TreatNonCallableAsNull] attribute Function? ondblclick; - [TreatNonCallableAsNull] attribute Function? ondrag; - [TreatNonCallableAsNull] attribute Function? ondragend; - [TreatNonCallableAsNull] attribute Function? ondragenter; - [TreatNonCallableAsNull] attribute Function? ondragleave; - [TreatNonCallableAsNull] attribute Function? ondragover; - [TreatNonCallableAsNull] attribute Function? ondragstart; - [TreatNonCallableAsNull] attribute Function? ondrop; - [TreatNonCallableAsNull] attribute Function? ondurationchange; - [TreatNonCallableAsNull] attribute Function? onemptied; - [TreatNonCallableAsNull] attribute Function? onended; - [TreatNonCallableAsNull] attribute Function? onerror; - [TreatNonCallableAsNull] attribute Function? onfocus; - [TreatNonCallableAsNull] attribute Function? onhashchange; - [TreatNonCallableAsNull] attribute Function? oninput; - [TreatNonCallableAsNull] attribute Function? oninvalid; - [TreatNonCallableAsNull] attribute Function? onkeydown; - [TreatNonCallableAsNull] attribute Function? onkeypress; - [TreatNonCallableAsNull] attribute Function? onkeyup; - [TreatNonCallableAsNull] attribute Function? onload; - [TreatNonCallableAsNull] attribute Function? onloadeddata; - [TreatNonCallableAsNull] attribute Function? onloadedmetadata; - [TreatNonCallableAsNull] attribute Function? onloadstart; - [TreatNonCallableAsNull] attribute Function? onmessage; - [TreatNonCallableAsNull] attribute Function? onmousedown; - [TreatNonCallableAsNull] attribute Function? onmousemove; - [TreatNonCallableAsNull] attribute Function? onmouseout; - [TreatNonCallableAsNull] attribute Function? onmouseover; - [TreatNonCallableAsNull] attribute Function? onmouseup; - [TreatNonCallableAsNull] attribute Function? onmousewheel; - [TreatNonCallableAsNull] attribute Function? onoffline; - [TreatNonCallableAsNull] attribute Function? ononline; - [TreatNonCallableAsNull] attribute Function? onpause; - [TreatNonCallableAsNull] attribute Function? onplay; - [TreatNonCallableAsNull] attribute Function? onplaying; - [TreatNonCallableAsNull] attribute Function? onpagehide; - [TreatNonCallableAsNull] attribute Function? onpageshow; - [TreatNonCallableAsNull] attribute Function? onpopstate; - [TreatNonCallableAsNull] attribute Function? onprogress; - [TreatNonCallableAsNull] attribute Function? onratechange; - [TreatNonCallableAsNull] attribute Function? onreset; - [TreatNonCallableAsNull] attribute Function? onresize; - [TreatNonCallableAsNull] attribute Function? onscroll; - [TreatNonCallableAsNull] attribute Function? onseeked; - [TreatNonCallableAsNull] attribute Function? onseeking; - [TreatNonCallableAsNull] attribute Function? onselect; - [TreatNonCallableAsNull] attribute Function? onshow; - [TreatNonCallableAsNull] attribute Function? onstalled; - [TreatNonCallableAsNull] attribute Function? onstorage; - [TreatNonCallableAsNull] attribute Function? onsubmit; - [TreatNonCallableAsNull] attribute Function? onsuspend; - [TreatNonCallableAsNull] attribute Function? ontimeupdate; - [TreatNonCallableAsNull] attribute Function? onunload; - [TreatNonCallableAsNull] attribute Function? onvolumechange; - [TreatNonCallableAsNull] attribute Function? onwaiting; + +struct jsclass_private { + struct browser_window *bw; + struct html_content *htmlc; + JSObject *document_obj; + JSObject *navigator_obj; + JSObject *console_obj; }; -*/ +static void jsclass_finalize(JSContext *cx, JSObject *obj); +static JSBool jsclass_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags, JSObject **objp); + +JSClass JSClass_Window = { + "Window", + JSCLASS_NEW_RESOLVE | JSCLASS_HAS_PRIVATE | JSCLASS_GLOBAL_FLAGS, + JS_PropertyStub, + JS_PropertyStub, + JS_PropertyStub, + JS_StrictPropertyStub, + JS_EnumerateStub, + (JSResolveOp)jsclass_resolve, + JS_ConvertStub, + jsclass_finalize, + JSCLASS_NO_OPTIONAL_MEMBERS +}; static JSBool JSAPI_NATIVE(alert, JSContext *cx, uintN argc, jsval *vp) @@ -254,62 +156,130 @@ static JSBool JSAPI_PROPERTYGET(self, JSContext *cx, JSObject *obj, jsval *vp) return JS_TRUE; } +static JSBool JSAPI_PROPERTYGET(document, JSContext *cx, JSObject *obj, jsval *vp) +{ + struct jsclass_private *private; + + private = JS_GetInstancePrivate(cx, + obj, + &JSClass_Window, + NULL); + if (private == NULL) + return JS_FALSE; + + JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(private->document_obj)); + return JS_TRUE; +} + static JSPropertySpec jsproperties_window[] = { + JSAPI_PS_RO(document, 0, JSPROP_ENUMERATE | JSPROP_SHARED), JSAPI_PS_RO(window, 0, JSPROP_ENUMERATE | JSPROP_SHARED), JSAPI_PS_RO(self, 0, JSPROP_ENUMERATE | JSPROP_SHARED), JSAPI_PS_END }; -/* The class of the global object. */ -static JSClass jsclass_window = { - "window", - JSCLASS_HAS_PRIVATE | JSCLASS_GLOBAL_FLAGS, - JS_PropertyStub, - JS_PropertyStub, - JS_PropertyStub, - JS_StrictPropertyStub, - JS_EnumerateStub, - JS_ResolveStub, - JS_ConvertStub, - JS_FinalizeStub, - JSCLASS_NO_OPTIONAL_MEMBERS -}; +static JSBool jsclass_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags, JSObject **objp) +{ + *objp = NULL; + return JS_TRUE; +} +static void jsclass_finalize(JSContext *cx, JSObject *obj) +{ struct jsclass_private *private; -JSObject * jsapi_new_window(JSContext *cx, JSObject *parent, void *win_priv) + private = JS_GetInstancePrivate(cx, obj, &JSClass_Window, NULL); + if (private != NULL) { + free(private); + } +} + +JSObject *jsapi_InitClass_Window(JSContext *cx, JSObject *parent) { JSObject *window = NULL; + JSObject *proto; + + window = JS_NewCompartmentAndGlobalObject(cx, &JSClass_Window, NULL); + if (window == NULL) { + return NULL; + } + + /** @todo reconsider global object handling. future + * editions of spidermonkey appear to be removing the + * idea of a global so we probably need to handle + * global object references internally + */ + + /* set the contexts global */ + JS_SetGlobalObject(cx, window); + + /* Populate the global object with the standard globals, like + * Object and Array. + */ + if (!JS_InitStandardClasses(cx, window)) { + return NULL; + } + + /* Initialises all the user javascript classes to make their + * prototypes available. + */ + /** @todo should we be managing these prototype objects ourselves */ + proto = jsapi_InitClass_Document(cx, window); + if (proto == NULL) { + return NULL; + } + + return window; +} - if (parent == NULL) { - window = JS_NewCompartmentAndGlobalObject(cx, &jsclass_window, NULL); - if (window == NULL) { - return NULL; - } - - /** @todo reconsider global object handling. future - * editions of spidermonkey appear to be removing the - * idea of a global so we probably need to handle - * global object references internally - */ - - /* set the contexts global */ - JS_SetGlobalObject(cx, window); - - /* Populate the global object with the standard globals, like - * Object and Array. - */ - if (!JS_InitStandardClasses(cx, window)) { - return NULL; - } - - } else { - /* @todo sort out windows that are not globals */ - assert(false); +JSObject *jsapi_new_Window(JSContext *cx, + JSObject *window, + JSObject *parent, + struct browser_window *bw, + html_content *htmlc) +{ + struct jsclass_private *private; + + /* @todo sort out windows that are not globals */ + assert(parent == NULL); + + /* create private data */ + private = malloc(sizeof(struct jsclass_private)); + if (private == NULL) { + return NULL; + } + private->bw = bw; + private->htmlc = htmlc; + + + /* instantiate the subclasses off the window global */ + private->document_obj = jsapi_new_Document(cx, + NULL, + window, + htmlc->document, + htmlc); + if (private->document_obj == NULL) { + free(private); + return NULL; + } + +/* + private->navigator_obj = jsapi_new_Navigator(cx, window); + if (private->navigator_obj == NULL) { + free(private); + return NULL; + } +*/ + /** @todo forms, history, location */ + + private->console_obj = jsapi_new_Console(cx, window); + if (private->console_obj == NULL) { + free(private); + return NULL; } /* private pointer to browsing context */ - if (!JS_SetPrivate(cx, window, win_priv)) + if (!JS_SetPrivate(cx, window, private)) return NULL; /* functions */ @@ -321,6 +291,7 @@ JSObject * jsapi_new_window(JSContext *cx, JSObject *parent, void *win_priv) if (!JS_DefineProperties(cx, window, jsproperties_window)) return NULL; + LOG(("Created new window object %p", window)); return window; -- cgit v1.2.3