--- trunk/instrument-js.c 2008/10/05 18:05:12 245 +++ trunk/instrument-js.c 2008/10/12 16:41:57 293 @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -88,6 +89,30 @@ JS_DestroyRuntime(runtime); } +static void print_javascript(const jschar * characters, size_t num_characters, Stream * f) { + for (size_t i = 0; i < num_characters; i++) { + jschar c = characters[i]; + /* + XXX does not handle no-break space, other unicode "space separator" + */ + switch (c) { + case 0x9: + case 0xB: + case 0xC: + Stream_write_char(f, c); + break; + default: + if (32 <= c && c <= 126) { + Stream_write_char(f, c); + } + else { + Stream_printf(f, "\\u%04x", c); + } + break; + } + } +} + static void print_string(JSString * s, Stream * f) { size_t length = JSSTRING_LENGTH(s); jschar * characters = JSSTRING_CHARS(s); @@ -515,13 +540,17 @@ /* check whether this is a getter or setter */ switch (p->pn_op) { case JSOP_GETTER: - Stream_write_string(f, "get "); - instrument_expression(p->pn_left, f); - instrument_function(p->pn_right, f, 0, FUNCTION_GETTER_OR_SETTER); - break; case JSOP_SETTER: - Stream_write_string(f, "set "); + if (p->pn_op == JSOP_GETTER) { + Stream_write_string(f, "get "); + } + else { + Stream_write_string(f, "set "); + } instrument_expression(p->pn_left, f); + if (p->pn_right->pn_type != TOK_FUNCTION) { + fatal("parse error: expected function"); + } instrument_function(p->pn_right, f, 0, FUNCTION_GETTER_OR_SETTER); break; default: @@ -966,6 +995,10 @@ return true; } +static void error_reporter(JSContext * context, const char * message, JSErrorReport * report) { + fprintf(stderr, "jscoverage: parse error: line %u: %s\n", report->lineno, message); +} + void jscoverage_instrument_js(const char * id, const uint16_t * characters, size_t num_characters, Stream * output) { file_id = id; @@ -976,10 +1009,13 @@ } /* parse the javascript */ + JSErrorReporter old_error_reporter = JS_SetErrorReporter(context, error_reporter); JSParseNode * node = js_ParseTokenStream(context, global, token_stream); if (node == NULL) { + js_ReportUncaughtException(context); fatal("parse error in file: %s", file_id); } + JS_SetErrorReporter(context, old_error_reporter); num_lines = node->pn_pos.end.lineno; lines = xmalloc(num_lines); for (unsigned int i = 0; i < num_lines; i++) { @@ -1090,15 +1126,7 @@ /* conditionals */ for (struct IfDirective * if_directive = if_directives; if_directive != NULL; if_directive = if_directive->next) { Stream_write_string(output, "if (!("); - for (const jschar * p = if_directive->condition_start; p < if_directive->condition_end; p++) { - jschar c = *p; - if (c == '\t' || (32 <= c && c <= 126)) { - Stream_write_char(output, c); - } - else { - Stream_printf(output, "\\u%04x", c); - } - } + print_javascript(if_directive->condition_start, if_directive->condition_end - if_directive->condition_start, output); Stream_write_string(output, ")) {\n"); Stream_printf(output, " _$jscoverage['%s'].conditionals[%d] = %d;\n", file_id, if_directive->start_line, if_directive->end_line); Stream_write_string(output, "}\n");