summaryrefslogtreecommitdiff
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
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.
-rw-r--r--src/duk-libdom.c118
-rw-r--r--src/webidl-ast.h1
-rw-r--r--src/webidl-parser.y24
3 files changed, 136 insertions, 7 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");
diff --git a/src/webidl-ast.h b/src/webidl-ast.h
index 5126de8..109159f 100644
--- a/src/webidl-ast.h
+++ b/src/webidl-ast.h
@@ -47,6 +47,7 @@ enum webidl_node_type {
};
enum webidl_type {
+ WEBIDL_TYPE_ANY, /**< The type is unconstrained */
WEBIDL_TYPE_USER,
WEBIDL_TYPE_BOOL,
WEBIDL_TYPE_BYTE,
diff --git a/src/webidl-parser.y b/src/webidl-parser.y
index 14385d6..42fed63 100644
--- a/src/webidl-parser.y
+++ b/src/webidl-parser.y
@@ -180,6 +180,8 @@ webidl_error(YYLTYPE *locp, struct webidl_node **winbind_ast, const char *str)
%type <node> ReturnType
%type <node> SingleType
%type <node> UnionType
+%type <node> UnionMemberType
+%type <node> UnionMemberTypes
%type <node> NonAnyType
%type <node> ConstType
%type <node> PrimitiveType
@@ -1462,7 +1464,9 @@ SingleType:
|
TOK_ANY TypeSuffixStartingWithArray
{
- $$ = NULL; /* todo implement */
+ /* todo deal with TypeSuffixStartingWithArray */
+ $$ = webidl_node_new(WEBIDL_NODE_TYPE_TYPE_BASE,
+ NULL, (void *)WEBIDL_TYPE_ANY);
}
;
@@ -1470,24 +1474,40 @@ SingleType:
UnionType:
'(' UnionMemberType TOK_OR UnionMemberType UnionMemberTypes ')'
{
- $$ = NULL;
+ $$ = webidl_node_prepend($2, webidl_node_prepend($4, $5));
}
;
/* [60] */
UnionMemberType:
NonAnyType
+ {
+ $$ = webidl_node_new(WEBIDL_NODE_TYPE_TYPE, NULL, $1);
+ }
|
UnionType TypeSuffix
+ {
+ /* todo handle suffix */
+ $$ = $1;
+ }
|
TOK_ANY '[' ']' TypeSuffix
+ {
+ $$ = NULL;
+ }
;
/* [61] */
UnionMemberTypes:
/* empty */
+ {
+ $$ = NULL;
+ }
|
TOK_OR UnionMemberType UnionMemberTypes
+ {
+ $$ = webidl_node_prepend($2, $3);
+ }
;
/* [62]