From 94137186a3e2270e9b96f243a82a77a590c17f01 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Fri, 16 May 2014 14:38:10 +0100 Subject: make property generation use map --- src/jsapi-libdom-function.c | 5 + src/jsapi-libdom-property.c | 412 ++++++++++++++++++++----------------- src/jsapi-libdom.h | 4 + test/data/bindings/htmlelement.bnd | 4 +- 4 files changed, 238 insertions(+), 187 deletions(-) diff --git a/src/jsapi-libdom-function.c b/src/jsapi-libdom-function.c index af9c215..4f62bcd 100644 --- a/src/jsapi-libdom-function.c +++ b/src/jsapi-libdom-function.c @@ -720,6 +720,11 @@ output_private_get(struct binding *binding, const char *argname) return ret; } +/** + * Generate operator (function) body + * + * + */ static int webidl_operator_body(struct binding *binding, struct binding_interface *inf, struct webidl_node *node) diff --git a/src/jsapi-libdom-property.c b/src/jsapi-libdom-property.c index 93ffcc5..1a6cc33 100644 --- a/src/jsapi-libdom-property.c +++ b/src/jsapi-libdom-property.c @@ -19,25 +19,38 @@ static int generate_property_tinyid(struct binding *binding, const char *interface); static int generate_property_spec(struct binding *binding, const char *interface); -static int generate_property_body(struct binding *binding, const char *interface); /* generate context data fetcher if the binding has private data */ static inline int -output_private_get(struct binding *binding, const char *argname) +output_private_get(struct binding *binding, + struct binding_interface *inf, + const char *argname) { int ret = 0; if (binding->has_private) { ret = fprintf(binding->outfile, - "\tstruct jsclass_private *%s;\n" - "\n" - "\t%s = JS_GetInstancePrivate(cx, obj, &JSClass_%s, NULL);\n" - "\tif (%s == NULL) {\n" - "\t\treturn JS_FALSE;\n" - "\t}\n\n", - argname, argname, binding->interface, argname); + "\tstruct jsclass_private *%s;\n\n", argname); + + if (inf->refcount == 0) { + /* leaf class so use safer getinstance private */ + ret += fprintf(binding->outfile, + "\t%s = JS_GetInstancePrivate(cx, obj, &JSClass_%s, NULL);\n", + argname, + inf->name); + } else { + ret += fprintf(binding->outfile, + "\t%s = JS_GetPrivate(obj);\n", + argname); + } + + ret += fprintf(binding->outfile, + "\tif (%s == NULL) {\n" + "\t\treturn JS_FALSE;\n" + "\t}\n\n", + argname); if (options->dbglog) { ret += fprintf(binding->outfile, @@ -321,14 +334,15 @@ static bool property_is_ro(struct webidl_node *node) return false; } -static int webidl_property_spec_cb(struct webidl_node *node, void *ctx) +static int webidl_property_spec(struct binding *binding, + struct binding_interface *inf, + struct webidl_node *node) { - struct binding *binding = ctx; - struct webidl_node *type_node; const char *type = NULL; struct webidl_node *ident_node; const char *ident; + bool ro = false; ident_node = webidl_node_find_type(webidl_node_getnode(node), NULL, @@ -356,11 +370,10 @@ static int webidl_property_spec_cb(struct webidl_node *node, void *ctx) /* if there is a putforwards the property requires a setter */ if ((property_is_ro(node)) && (get_keyval_extended_attribute(node, "PutForwards") == NULL)) { - fprintf(binding->outfile, "\tJSAPI_PS_RO(\"%s\",\n", ident); - } else { - fprintf(binding->outfile, "\tJSAPI_PS(\"%s\",\n", ident); + ro = true; } + /* generate property shared status */ switch (get_binding_shared_modifier(binding, type, ident)) { @@ -371,120 +384,110 @@ static int webidl_property_spec_cb(struct webidl_node *node, void *ctx) * js doesnt provide storage and setter/getter must * perform all GC management. */ - fprintf(binding->outfile, - "\t\t%s,\n" - "\t\tJSAPI_PROP_TINYID_%s,\n" - "\t\tJSPROP_SHARED | ", - ident, + fprintf(binding->outfile, + "\tJSAPI_PS_%s(%s, %s, JSPROP_SHARED),\n", + ro?"RO":"RW", + inf->name, ident); break; case GENBIND_TYPE_TYPE: /* shared property with a type handler */ - fprintf(binding->outfile, - "\t\t%s,\n" - "\t\tJSAPI_PROP_TINYID_%s,\n" - "\t\tJSPROP_SHARED | ", - type, - ident); + fprintf(binding->outfile, + "\tJSAPI_PS_ID_%s(%s, %s, JSPROP_SHARED, %s),\n", + ro?"RO":"RW", + inf->name, + ident, + type); break; case GENBIND_TYPE_UNSHARED: /* unshared property without type handler */ - fprintf(binding->outfile, - "\t\t%s,\n" - "\t\tJSAPI_PROP_TINYID_%s,\n" - "\t\t", - ident, ident); + fprintf(binding->outfile, + "\tJSAPI_PS_%s(%s, %s, 0),\n", + ro?"RO":"RW", + inf->name, + ident); break; case GENBIND_TYPE_TYPE_UNSHARED: /* unshared property with a type handler */ - fprintf(binding->outfile, - "\t\t%s,\n" - "\t\tJSAPI_PROP_TINYID_%s,\n" - "\t\t", - type, ident); + fprintf(binding->outfile, + "\tJSAPI_PS_ID_%s(%s, %s, 0, %s),\n", + ro?"RO":"RW", + inf->name, + ident, + type); break; } - fprintf(binding->outfile, "JSPROP_ENUMERATE),\n"); return 0; } - -static int -generate_property_spec(struct binding *binding, const char *interface) -{ - struct webidl_node *interface_node; - struct webidl_node *members_node; - struct webidl_node *inherit_node; - int res = 0; - - /* find interface in webidl with correct ident attached */ - interface_node = webidl_node_find_type_ident(binding->wi_ast, - WEBIDL_NODE_TYPE_INTERFACE, - interface); - - if (interface_node == NULL) { - fprintf(stderr, - "Unable to find interface %s in loaded WebIDL\n", - interface); - return -1; - } - - /* generate property entries for each list (partial interfaces) */ - members_node = webidl_node_find_type(webidl_node_getnode(interface_node), - NULL, - WEBIDL_NODE_TYPE_LIST); - - while (members_node != NULL) { - - fprintf(binding->outfile,"\t/**** %s ****/\n", interface); - - /* for each property emit a JSAPI_PS() */ - webidl_node_for_each_type(webidl_node_getnode(members_node), - WEBIDL_NODE_TYPE_ATTRIBUTE, - webidl_property_spec_cb, - binding); - - members_node = webidl_node_find_type(webidl_node_getnode(interface_node), - members_node, - WEBIDL_NODE_TYPE_LIST); - } - - /* check for inherited nodes and insert them too */ - inherit_node = webidl_node_find(webidl_node_getnode(interface_node), - NULL, - webidl_cmp_node_type, - (void *)WEBIDL_NODE_TYPE_INTERFACE_INHERITANCE); - - if (inherit_node != NULL) { - res = generate_property_spec(binding, - webidl_node_gettext(inherit_node)); - } - - return res; -} - - - /* exported interface documented in jsapi-libdom.h */ int output_property_spec(struct binding *binding) { + int inf; int res; + struct webidl_node *list_node; + struct webidl_node *op_node; /* operation on list node */ + + /* for each interface in the map */ + for (inf = 0; inf < binding->interfacec; inf++) { + if (binding->interfaces[inf].own_properties == 0) { + /* if the interface has no properties then + * there is nothing to generate. + */ + continue; + } - fprintf(binding->outfile, - "static JSPropertySpec jsclass_properties[] = {\n"); + /* generate property specifier */ + fprintf(binding->outfile, + "static JSPropertySpec JSClass_%s_properties[] = {\n", + binding->interfaces[inf].name); - res = generate_property_spec(binding, binding->interface); + /* iterate each list within an interface */ + list_node = webidl_node_find_type( + webidl_node_getnode(binding->interfaces[inf].widl_node), + NULL, + WEBIDL_NODE_TYPE_LIST); - fprintf(binding->outfile, "\tJSAPI_PS_END\n};\n\n"); + while (list_node != NULL) { + /* iterate through operations in a list */ + op_node = webidl_node_find_type( + webidl_node_getnode(list_node), + NULL, + WEBIDL_NODE_TYPE_ATTRIBUTE); + + while (op_node != NULL) { + res = webidl_property_spec( + binding, + &binding->interfaces[inf], + op_node); + if (res != 0) { + return res; + } + + op_node = webidl_node_find_type( + webidl_node_getnode(list_node), + op_node, + WEBIDL_NODE_TYPE_ATTRIBUTE); + } - return res; + + list_node = webidl_node_find_type( + webidl_node_getnode(binding->interfaces[inf].widl_node), + list_node, + WEBIDL_NODE_TYPE_LIST); + } + + fprintf(binding->outfile, "\tJSAPI_PS_END\n};\n\n"); + + } + return 0; } @@ -734,6 +737,7 @@ static int output_return_declaration(struct binding *binding, static int output_property_placeholder(struct binding *binding, + struct binding_interface *inf, struct webidl_node* oplist, const char *ident) { @@ -741,34 +745,36 @@ output_property_placeholder(struct binding *binding, WARN(WARNING_UNIMPLEMENTED, "property %s.%s has no implementation\n", - binding->interface, + inf->name, ident); if (options->dbglog) { fprintf(binding->outfile, "\tJSLOG(\"property %s.%s has no implementation\");\n", - binding->interface, + inf->name, ident); } return 0; } static int output_property_getter(struct binding *binding, + struct binding_interface *inf, struct webidl_node *node, const char *ident) { struct genbind_node *property_node; fprintf(binding->outfile, - "static JSBool JSAPI_PROP(%s_get, JSContext *cx, JSObject *obj, jsval *vp)\n" + "static JSBool JSAPI_PROP_GET(%s, %s, JSContext *cx, JSObject *obj, jsval *vp)\n" "{\n", + inf->name, ident); /* return value declaration */ output_return_declaration(binding, "jsret", node); - output_private_get(binding, "private"); + output_private_get(binding, inf, "private"); property_node = genbind_node_find_type_ident(binding->gb_ast, NULL, @@ -801,7 +807,7 @@ static int output_property_getter(struct binding *binding, "\tjsret = private->%s;\n", ident); } else { - output_property_placeholder(binding, node, ident); + output_property_placeholder(binding, inf, node, ident); } } @@ -816,8 +822,9 @@ static int output_property_getter(struct binding *binding, } static int output_property_setter(struct binding *binding, + struct binding_interface *inf, struct webidl_node *node, - const char *ident) + const char *property_ident) { struct genbind_node *property_node; char *putforwards; @@ -827,22 +834,23 @@ static int output_property_setter(struct binding *binding, /* generate a putforwards setter */ fprintf(binding->outfile, "/* PutForwards setter */\n" - "static JSBool JSAPI_STRICTPROP(%s_set, JSContext *cx, JSObject *obj, jsval *vp)\n" + "static JSBool JSAPI_PROP_SET(%s, %s, JSContext *cx, JSObject *obj, jsval *vp)\n" "{\n", - ident); + inf->name, + property_ident); fprintf(binding->outfile, "\tjsval propval;\n" "\tif (JS_GetProperty(cx, obj, \"%s\", &propval) == JS_TRUE) {\n" "\t\tJS_SetProperty(cx, JSVAL_TO_OBJECT(propval), \"%s\", vp);\n" "\t}\n", - ident, putforwards); + property_ident, + putforwards); fprintf(binding->outfile, "\treturn JS_FALSE; /* disallow the asignment */\n" "}\n\n"); - return 0; } @@ -854,20 +862,21 @@ static int output_property_setter(struct binding *binding, property_node = genbind_node_find_type_ident(binding->gb_ast, NULL, GENBIND_NODE_TYPE_SETTER, - ident); + property_ident); fprintf(binding->outfile, - "static JSBool JSAPI_STRICTPROP(%s_set, JSContext *cx, JSObject *obj, jsval *vp)\n" + "static JSBool JSAPI_PROP_SET(%s, %s, JSContext *cx, JSObject *obj, jsval *vp)\n" "{\n", - ident); + inf->name, + property_ident); - output_private_get(binding, "private"); + output_private_get(binding, inf, "private"); if (property_node != NULL) { /* binding source block */ output_code_block(binding, genbind_node_getnode(property_node)); } else { - output_property_placeholder(binding, node, ident); + output_property_placeholder(binding, inf, node, property_ident); } fprintf(binding->outfile, @@ -878,9 +887,13 @@ static int output_property_setter(struct binding *binding, return 0; } -static int webidl_property_body_cb(struct webidl_node *node, void *ctx) +/** + * generate atribute (property) body. + */ +static int webidl_property_body(struct binding *binding, + struct binding_interface *inf, + struct webidl_node *node) { - struct binding *binding = ctx; struct webidl_node *ident_node; const char *ident; struct webidl_node *type_node; @@ -915,76 +928,22 @@ static int webidl_property_body_cb(struct webidl_node *node, void *ctx) * type handler */ if ((shared_mod & GENBIND_TYPE_TYPE) == 0) { - ret = output_property_setter(binding, node, ident); + ret = output_property_setter(binding, inf, node, ident); if (ret == 0) { /* property getter */ - ret = output_property_getter(binding, node, ident); + ret = output_property_getter(binding, inf, node, ident); } } return ret; -} - - -static int -generate_property_body(struct binding *binding, const char *interface) -{ - struct webidl_node *interface_node; - struct webidl_node *members_node; - struct webidl_node *inherit_node; - int res = 0; - - /* find interface in webidl with correct ident attached */ - interface_node = webidl_node_find_type_ident(binding->wi_ast, - WEBIDL_NODE_TYPE_INTERFACE, - interface); - - if (interface_node == NULL) { - fprintf(stderr, - "Unable to find interface %s in loaded WebIDL\n", - interface); - return -1; - } - - /* generate property bodies */ - members_node = webidl_node_find_type( - webidl_node_getnode(interface_node), - NULL, - WEBIDL_NODE_TYPE_LIST); - while (members_node != NULL) { - - fprintf(binding->outfile,"/**** %s ****/\n", interface); - - /* emit property body */ - webidl_node_for_each_type(webidl_node_getnode(members_node), - WEBIDL_NODE_TYPE_ATTRIBUTE, - webidl_property_body_cb, - binding); - - - members_node = webidl_node_find_type( - webidl_node_getnode(interface_node), - members_node, - WEBIDL_NODE_TYPE_LIST); - - } - /* check for inherited nodes and insert them too */ - inherit_node = webidl_node_find_type(webidl_node_getnode(interface_node), - NULL, - WEBIDL_NODE_TYPE_INTERFACE_INHERITANCE); - - if (inherit_node != NULL) { - res = generate_property_body(binding, - webidl_node_gettext(inherit_node)); - } - - return res; } + /* setter for type handler */ static int output_property_type_setter(struct binding *binding, + struct binding_interface *inf, struct genbind_node *node, const char *type) { @@ -1000,7 +959,7 @@ output_property_type_setter(struct binding *binding, /* property name vars */ output_property_tinyid_get_vars(binding, "tinyid"); /* context data */ - output_private_get(binding, "private"); + output_private_get(binding, inf, "private"); /* property name */ output_property_tinyid_get(binding, "tinyid"); @@ -1024,7 +983,10 @@ output_property_type_setter(struct binding *binding, /* getter for type handlers */ -static int output_property_type_getter(struct binding *binding, struct genbind_node *node, const char *type) +static int output_property_type_getter(struct binding *binding, + struct binding_interface *inf, + struct genbind_node *node, + const char *type) { struct genbind_node *property_node; node = node;/* currently unused */ @@ -1037,7 +999,7 @@ static int output_property_type_getter(struct binding *binding, struct genbind_n /* property tinyid vars */ output_property_tinyid_get_vars(binding, "tinyid"); /* context data */ - output_private_get(binding, "private"); + output_private_get(binding, inf, "private"); /* property tinyid */ output_property_tinyid_get(binding, "tinyid"); @@ -1068,6 +1030,7 @@ static int typehandler_property_cb(struct genbind_node *node, void *ctx) struct genbind_node *mod_node; enum genbind_type_modifier *share_mod; int ret = 0; + struct binding_interface *inf; mod_node = genbind_node_find_type(genbind_node_getnode(node), NULL, @@ -1083,10 +1046,14 @@ static int typehandler_property_cb(struct genbind_node *node, void *ctx) GENBIND_NODE_TYPE_IDENT); type = genbind_node_gettext(ident_node); if (type != NULL) { - ret = output_property_type_setter(binding, node, type); + ret = output_property_type_setter(binding, + inf, + node, + type); if (ret == 0) { /* property getter */ ret = output_property_type_getter(binding, + inf, node, type); } @@ -1095,20 +1062,95 @@ static int typehandler_property_cb(struct genbind_node *node, void *ctx) return ret; } -/* exported interface documented in jsapi-libdom.h */ -int -output_property_body(struct binding *binding) + +/** + * generate atribute (property) type body. + * + * Output property handler for an entire type of property + */ +static int webidl_attribute_typehandler_body(struct binding *binding, + struct binding_interface *inf) { int res; - res = generate_property_body(binding, binding->interface); + /* check if the interface has any properties with type handlers */ + if (!inf->has_type_properties) { + return 0; + } - if (res == 0) { - res = genbind_node_foreach_type(binding->binding_list, + res = genbind_node_foreach_type(binding->binding_list, GENBIND_NODE_TYPE_BINDING_PROPERTY, typehandler_property_cb, binding); - } + return res; + +} + +/* exported interface documented in jsapi-libdom.h */ +int +output_property_body(struct binding *binding) +{ + int inf; + int res; + struct webidl_node *list_node; + struct webidl_node *op_node; /* operation on list node */ + + /* for each interface in the map */ + for (inf = 0; inf < binding->interfacec; inf++) { + if (binding->interfaces[inf].own_properties == 0) { + /* if the interface has no properties then + * there is nothing to generate. + */ + continue; + } + + /* generate property bodies */ + + /* iterate each list within an interface */ + list_node = webidl_node_find_type( + webidl_node_getnode(binding->interfaces[inf].widl_node), + NULL, + WEBIDL_NODE_TYPE_LIST); + + while (list_node != NULL) { + /* iterate through operations in a list */ + op_node = webidl_node_find_type( + webidl_node_getnode(list_node), + NULL, + WEBIDL_NODE_TYPE_ATTRIBUTE); + + while (op_node != NULL) { + res = webidl_property_body( + binding, + &binding->interfaces[inf], + op_node); + if (res != 0) { + return res; + } + + op_node = webidl_node_find_type( + webidl_node_getnode(list_node), + op_node, + WEBIDL_NODE_TYPE_ATTRIBUTE); + } + + + list_node = webidl_node_find_type( + webidl_node_getnode(binding->interfaces[inf].widl_node), + list_node, + WEBIDL_NODE_TYPE_LIST); + } + + /* generate type handler bodies */ + res = webidl_attribute_typehandler_body(binding, + &binding->interfaces[inf]); + + if (res != 0) { + return res; + } + + } + return 0; } diff --git a/src/jsapi-libdom.h b/src/jsapi-libdom.h index 2925866..e8d57c4 100644 --- a/src/jsapi-libdom.h +++ b/src/jsapi-libdom.h @@ -19,6 +19,10 @@ struct binding_interface { int own_properties; /**< the number of properties the interface has */ int own_functions; /**< the number of functions the interface has */ + bool has_type_properties; /**< some of the properties on the + * interface have a type handler + */ + int inherit_idx; /**< index into binding map of inherited * interface or -1 for not in map */ diff --git a/test/data/bindings/htmlelement.bnd b/test/data/bindings/htmlelement.bnd index 1457a32..999a16f 100644 --- a/test/data/bindings/htmlelement.bnd +++ b/test/data/bindings/htmlelement.bnd @@ -37,8 +37,6 @@ preamble %{ binding jsapi_libdom { - interface Text; - interface Comment; interface HTMLElement; interface HTMLAnchorElement; interface HTMLAnchorElement; @@ -110,6 +108,8 @@ binding jsapi_libdom { interface HTMLTrackElement; interface HTMLUListElement; interface HTMLUnknownElement; + interface Text; + interface Comment; private "dom_element *" node; private "struct html_content *" htmlc; -- cgit v1.2.3