summaryrefslogtreecommitdiff
path: root/src/duk-libdom.c
diff options
context:
space:
mode:
authorVincent Sanders <vince@kyllikki.org>2015-08-13 23:07:23 +0100
committerVincent Sanders <vince@kyllikki.org>2015-08-13 23:07:23 +0100
commitee69169f841542c6d5d8a8c7d4b011e294d73bd8 (patch)
treeabde7636384cfc792668287545d066d962706bf0 /src/duk-libdom.c
parentb86883a7cce7d982c3f0d0069332dd490331e630 (diff)
downloadnsgenbind-ee69169f841542c6d5d8a8c7d4b011e294d73bd8.tar.gz
nsgenbind-ee69169f841542c6d5d8a8c7d4b011e294d73bd8.tar.bz2
Basic type checking for operation arguments
Arguments passed to basic operations are checked for type if they are strings, bolleans or numbers. Operations that are overloaded, special or have elipsis are not checked.
Diffstat (limited to 'src/duk-libdom.c')
-rw-r--r--src/duk-libdom.c118
1 files changed, 113 insertions, 5 deletions
diff --git a/src/duk-libdom.c b/src/duk-libdom.c
index 5f82bd1..aad7bb6 100644
--- a/src/duk-libdom.c
+++ b/src/duk-libdom.c
@@ -1074,6 +1074,95 @@ output_operation_optional_defaults(FILE* outf,
return 0;
}
+static int
+output_operation_argument_type_check(
+ FILE* outf,
+ struct interface_map_entry *interfacee,
+ struct interface_map_operation_entry *operatione,
+ struct interface_map_operation_overload_entry *overloade,
+ int argidx)
+{
+ struct interface_map_operation_argument_entry *argumente;
+ struct webidl_node *type_node;
+ enum webidl_type *argument_type;
+
+ argumente = overloade->argumentv + argidx;
+
+ type_node = webidl_node_find_type(
+ webidl_node_getnode(argumente->node),
+ NULL,
+ WEBIDL_NODE_TYPE_TYPE);
+
+ if (type_node == NULL) {
+ fprintf(stderr, "%s:%s %dth argument %s has no type\n",
+ interfacee->name,
+ operatione->name,
+ argidx,
+ argumente->name);
+ return -1;
+ }
+
+ argument_type = (enum webidl_type *)webidl_node_getint(
+ webidl_node_find_type(
+ webidl_node_getnode(type_node),
+ NULL,
+ WEBIDL_NODE_TYPE_TYPE_BASE));
+
+ if (argument_type == NULL) {
+ fprintf(stderr,
+ "%s:%s %dth argument %s has no type base\n",
+ interfacee->name,
+ operatione->name,
+ argidx,
+ argumente->name);
+ return -1;
+ }
+
+ if (*argument_type == WEBIDL_TYPE_ANY) {
+ /* allowing any type needs no check */
+ return 0;
+ }
+
+ fprintf(outf, "\tif (%s_argc > %d) {\n", DLPFX, argidx);
+
+ switch (*argument_type) {
+ case WEBIDL_TYPE_STRING:
+ fprintf(outf,
+ "\t\tif (!duk_is_string(ctx, %d)) {\n"
+ "\t\t\tduk_error(ctx, DUK_ERR_ERROR, %s_error_fmt_string_type, %d, \"%s\");\n"
+ "\t\t}\n", argidx, DLPFX, argidx, argumente->name);
+ break;
+
+ case WEBIDL_TYPE_BOOL:
+ fprintf(outf,
+ "\t\tif (!duk_is_boolean(ctx, %d)) {\n"
+ "\t\t\tduk_error(ctx, DUK_ERR_ERROR, %s_error_fmt_bool_type, %d, \"%s\");\n"
+ "\t\t}\n", argidx, DLPFX, argidx, argumente->name);
+ break;
+
+ case WEBIDL_TYPE_FLOAT:
+ case WEBIDL_TYPE_DOUBLE:
+ case WEBIDL_TYPE_SHORT:
+ case WEBIDL_TYPE_LONG:
+ case WEBIDL_TYPE_LONGLONG:
+ fprintf(outf,
+ "\t\tif (!duk_is_number(ctx, %d)) {\n"
+ "\t\t\tduk_error(ctx, DUK_ERR_ERROR, %s_error_fmt_number_type, %d, \"%s\");\n"
+ "\t\t}\n", argidx, DLPFX, argidx, argumente->name);
+ break;
+
+
+ default:
+ fprintf(outf,
+ "\t\t/* unhandled type check */\n");
+ }
+
+ fprintf(outf, "\t}\n");
+
+ return 0;
+}
+
+
/**
* generate a single class method for an interface operation
*/
@@ -1085,6 +1174,7 @@ output_interface_operation(FILE* outf,
int cdatac; /* cdata blocks output */
struct interface_map_operation_overload_entry *overloade;
int fixedargc; /* number of non optional arguments */
+ int argidx; /* loop counter for arguments */
int optargc; /* loop counter for optional arguments */
if (operatione->name == NULL) {
@@ -1155,12 +1245,24 @@ output_interface_operation(FILE* outf,
fprintf(outf,
"if (%s_argc > %d) {\n"
"\t\t/* remove extraneous parameters */\n"
- "\t\tduk_set_top(ctx, %d);\n",
+ "\t\tduk_set_top(ctx, %d);\n"
+ "\t}\n",
DLPFX,
overloade->argumentc,
overloade->argumentc);
- fprintf(outf, "\t}\n");
+ fprintf(outf, "\n");
+
+ /* generate argument type checks */
+ fprintf(outf, "\t/* check types of passed arguments are correct */\n");
+
+ for (argidx = 0; argidx < overloade->argumentc; argidx++) {
+ output_operation_argument_type_check(outf,
+ interfacee,
+ operatione,
+ overloade,
+ argidx);
+ }
output_get_method_private(outf, interfacee->class_name);
@@ -1618,10 +1720,13 @@ output_binding_header(struct interface_map *interface_map)
fprintf(bindf,
"/* Constant strings */\n"
"extern const char *%s_error_fmt_argument;\n"
+ "extern const char *%s_error_fmt_string_type;\n"
+ "extern const char *%s_error_fmt_bool_type;\n"
+ "extern const char *%s_error_fmt_number_type;\n"
"extern const char *%s_magic_string_private;\n"
"extern const char *%s_magic_string_prototypes;\n"
"\n",
- DLPFX, DLPFX, DLPFX);
+ DLPFX, DLPFX, DLPFX, DLPFX, DLPFX, DLPFX);
fprintf(bindf,
"duk_bool_t %s_instanceof(duk_context *ctx, const char *klass);\n",
@@ -1676,8 +1781,11 @@ output_binding_src(struct interface_map *interface_map)
fprintf(bindf,
"/* Error format strings */\n"
- "const char *%s_error_fmt_argument =\"%%d argument required, but ony %%d present.\";\n",
- DLPFX);
+ "const char *%s_error_fmt_argument =\"%%d argument required, but ony %%d present.\";\n"
+ "const char *%s_error_fmt_string_type =\"argument %%d (%%s) requires a string\";\n"
+ "const char *%s_error_fmt_bool_type =\"argument %%d (%%s) requires a bool\";\n"
+ "const char *%s_error_fmt_number_type =\"argument %%d (%%s) requires a number\";\n",
+ DLPFX, DLPFX, DLPFX, DLPFX);
fprintf(bindf, "\n");