diff options
-rw-r--r-- | src/duk-libdom-dictionary.c | 2 | ||||
-rw-r--r-- | src/duk-libdom-interface.c | 102 | ||||
-rw-r--r-- | src/ir.c | 68 | ||||
-rw-r--r-- | src/ir.h | 2 | ||||
-rw-r--r-- | src/options.h | 3 |
5 files changed, 155 insertions, 22 deletions
diff --git a/src/duk-libdom-dictionary.c b/src/duk-libdom-dictionary.c index 65a140a..09e4379 100644 --- a/src/duk-libdom-dictionary.c +++ b/src/duk-libdom-dictionary.c @@ -267,7 +267,7 @@ output_member_acessor(FILE* outf, default: WARN(WARNING_UNIMPLEMENTED, - "Dictionary %s:%s unhandled type (%d)\n", + "Dictionary %s:%s unhandled type (%d)", dictionarye->name, membere->name, *argument_type); diff --git a/src/duk-libdom-interface.c b/src/duk-libdom-interface.c index 0fef35b..96e41ad 100644 --- a/src/duk-libdom-interface.c +++ b/src/duk-libdom-interface.c @@ -619,7 +619,8 @@ output_prototype_attribute(FILE *outf, struct ir_entry *interfacee, struct ir_attribute_entry *attributee) { - if (attributee->modifier == WEBIDL_TYPE_MODIFIER_READONLY) { + if ((attributee->putforwards == NULL) && + (attributee->modifier == WEBIDL_TYPE_MODIFIER_READONLY)) { return output_populate_ro_property(outf, interfacee->class_name, attributee->name); @@ -1193,28 +1194,29 @@ output_interface_operations(FILE* outf, struct ir_entry *ife) return res; } + /** - * Generate class property getter/setter for a single attribute + * Generate class property setter for a single attribute */ static int -output_interface_attribute(FILE* outf, - struct ir_entry *interfacee, - struct ir_attribute_entry *atributee) +output_attribute_setter(FILE* outf, + struct ir_entry *interfacee, + struct ir_attribute_entry *atributee) { int cdatac; - /* getter definition */ + /* setter definition */ fprintf(outf, - "static duk_ret_t %s_%s_%s_getter(duk_context *ctx)\n", + "static duk_ret_t %s_%s_%s_setter(duk_context *ctx)\n", DLPFX, interfacee->class_name, atributee->name); fprintf(outf,"{\n"); output_get_method_private(outf, interfacee->class_name); - cdatac = output_ccode(outf, atributee->getter); + cdatac = output_ccode(outf, atributee->setter); if (cdatac == 0) { WARN(WARNING_UNIMPLEMENTED, - "Unimplemented: getter %s::%s();", + "Unimplemented: setter %s::%s();", interfacee->name, atributee->name); /* no implementation so generate default */ @@ -1223,23 +1225,80 @@ output_interface_attribute(FILE* outf, fprintf(outf, "}\n\n"); - /* readonly attributes have no setter */ - if (atributee->modifier == WEBIDL_TYPE_MODIFIER_READONLY) { - return 0; + return 0; +} + +/** + * Generate class property setter for a putforwards attribute + */ +static int +output_putforwards_setter(FILE* outf, + struct ir_entry *interfacee, + struct ir_attribute_entry *atributee) +{ + /* use explicit implementation in bindings if present */ + if (atributee->setter != NULL) { + return output_attribute_setter(outf, interfacee, atributee); } - /* setter definition */ + /* generate autogenerated putforwards */ + fprintf(outf, "static duk_ret_t %s_%s_%s_setter(duk_context *ctx)\n", DLPFX, interfacee->class_name, atributee->name); fprintf(outf,"{\n"); + fprintf(outf,"\tduk_ret_t get_ret;\n\n"); + + fprintf(outf, + "\tget_ret = %s_%s_%s_getter(ctx);\n", + DLPFX, interfacee->class_name, atributee->name); + + fprintf(outf, + "\tif (get_ret != 1) {\n" + "\t\treturn 0;\n" + "\t}\n\n" + "\t/* parameter attribute */\n\n" + "\tduk_swap(ctx, 0, 1);\n" + "\t/* attribute parameter */\n\n" + "\t/* call the putforward */\n"); + + fprintf(outf, + "\tduk_put_prop_string(ctx, 0, \"%s\");\n\n", + atributee->putforwards); + + fprintf(outf, + "\tduk_pop(ctx);\n\n" + "\treturn 0;\n"); + + fprintf(outf, "}\n\n"); + + return 0; +} + +/** + * Generate class property getter/setter for a single attribute + */ +static int +output_interface_attribute(FILE* outf, + struct ir_entry *interfacee, + struct ir_attribute_entry *atributee) +{ + int cdatac; + int res = 0; + + /* getter definition */ + fprintf(outf, + "static duk_ret_t %s_%s_%s_getter(duk_context *ctx)\n", + DLPFX, interfacee->class_name, atributee->name); + fprintf(outf,"{\n"); + output_get_method_private(outf, interfacee->class_name); - cdatac = output_ccode(outf, atributee->setter); + cdatac = output_ccode(outf, atributee->getter); if (cdatac == 0) { WARN(WARNING_UNIMPLEMENTED, - "Unimplemented: setter %s::%s();", + "Unimplemented: getter %s::%s();", interfacee->name, atributee->name); /* no implementation so generate default */ @@ -1248,7 +1307,18 @@ output_interface_attribute(FILE* outf, fprintf(outf, "}\n\n"); - return 0; + if (atributee->putforwards != NULL) { + res = output_putforwards_setter(outf, interfacee, atributee); + } else { + /* readonly attributes have no setter */ + if (atributee->modifier != WEBIDL_TYPE_MODIFIER_READONLY) { + res = output_attribute_setter(outf, + interfacee, + atributee); + } + } + + return res; } /** @@ -377,6 +377,56 @@ operation_map_new(struct webidl_node *interface, return 0; } +/** + * get the value of an extended attribute key/value item + */ +static char * +get_extended_value(struct webidl_node *node, const char *key) +{ + char *ident; + struct webidl_node *ext_attr; + struct webidl_node *elem; + + /* walk each extended attribute */ + ext_attr = webidl_node_find_type( + webidl_node_getnode(node), + NULL, + WEBIDL_NODE_TYPE_EXTENDED_ATTRIBUTE); + while (ext_attr != NULL) { + + elem = webidl_node_find_type( + webidl_node_getnode(ext_attr), + NULL, + WEBIDL_NODE_TYPE_IDENT); + ident = webidl_node_gettext(elem); + + if ((ident != NULL) && (strcmp(ident, key) == 0)) { + /* first identifier matches */ + + elem = webidl_node_find_type( + webidl_node_getnode(ext_attr), + elem, + WEBIDL_NODE_TYPE_IDENT); + ident = webidl_node_gettext(elem); + + if ((ident != NULL) && (*ident == '=')) { + return webidl_node_gettext( + webidl_node_find_type( + webidl_node_getnode(ext_attr), + elem, + WEBIDL_NODE_TYPE_IDENT)); + } + } + + ext_attr = webidl_node_find_type( + webidl_node_getnode(node), + ext_attr, + WEBIDL_NODE_TYPE_EXTENDED_ATTRIBUTE); + } + + return NULL; +} + static int attribute_map_new(struct webidl_node *interface, struct genbind_node *class, @@ -399,8 +449,7 @@ attribute_map_new(struct webidl_node *interface, return 0; } - attributev = calloc(attributec, - sizeof(struct ir_attribute_entry)); + attributev = calloc(attributec, sizeof(struct ir_attribute_entry)); if (attributev == NULL) { return -1; }; @@ -436,7 +485,7 @@ attribute_map_new(struct webidl_node *interface, GENBIND_METHOD_TYPE_GETTER, cure->name); - /* check fo readonly attributes */ + /* check for readonly attributes */ modifier = (enum webidl_type_modifier *)webidl_node_getint( webidl_node_find_type( webidl_node_getnode(at_node), @@ -454,9 +503,20 @@ attribute_map_new(struct webidl_node *interface, cure->name); } - cure++; + /* check for putforwards extended attribute */ + cure->putforwards = get_extended_value(at_node, + "PutForwards"); + + if ((cure->putforwards != NULL) && + (cure->modifier != WEBIDL_TYPE_MODIFIER_READONLY)) { + WARN(WARNING_WEBIDL, + "putforwards on a writable attribute (%s) is prohibited", + cure->name); + } /* move to next attribute */ + cure++; + at_node = webidl_node_find_type( webidl_node_getnode(list_node), at_node, @@ -53,6 +53,8 @@ struct ir_attribute_entry { struct webidl_node *node; /**< AST attribute node */ enum webidl_type_modifier modifier; + const char *putforwards; + struct genbind_node *getter; /**< getter from binding */ struct genbind_node *setter; /**< getter from binding */ }; diff --git a/src/options.h b/src/options.h index 5b7d73d..d452c17 100644 --- a/src/options.h +++ b/src/options.h @@ -28,9 +28,10 @@ extern struct options *options; enum opt_warnings { WARNING_UNIMPLEMENTED = 1, WARNING_DUPLICATED = 2, + WARNING_WEBIDL = 4, }; -#define WARNING_ALL (WARNING_UNIMPLEMENTED | WARNING_DUPLICATED) +#define WARNING_ALL (WARNING_UNIMPLEMENTED | WARNING_DUPLICATED | WARNING_WEBIDL) #define WARN(flags, msg, args...) do { \ if ((options->warnings & flags) != 0) { \ |