885 |
output_statement(node, f, indent); |
output_statement(node, f, indent); |
886 |
} |
} |
887 |
|
|
888 |
|
static bool characters_start_with(const jschar * characters, size_t line_start, size_t line_end, const char * prefix) { |
889 |
|
const jschar * characters_end = characters + line_end; |
890 |
|
const jschar * cp = characters + line_start; |
891 |
|
const char * bp = prefix; |
892 |
|
for (;;) { |
893 |
|
if (*bp == '\0') { |
894 |
|
return true; |
895 |
|
} |
896 |
|
else if (cp == characters_end) { |
897 |
|
return false; |
898 |
|
} |
899 |
|
else if (*cp != *bp) { |
900 |
|
return false; |
901 |
|
} |
902 |
|
bp++; |
903 |
|
cp++; |
904 |
|
} |
905 |
|
} |
906 |
|
|
907 |
void jscoverage_instrument_js(const char * id, const uint16_t * characters, size_t num_characters, Stream * output) { |
void jscoverage_instrument_js(const char * id, const uint16_t * characters, size_t num_characters, Stream * output) { |
908 |
file_id = id; |
file_id = id; |
909 |
|
|
959 |
while (i < num_characters) { |
while (i < num_characters) { |
960 |
line_number++; |
line_number++; |
961 |
size_t line_start = i; |
size_t line_start = i; |
962 |
/* FIXME */ |
jschar c; |
963 |
while (i < num_characters && characters[i] != '\r' && characters[i] != '\n') { |
bool done = false; |
964 |
i++; |
while (! done && i < num_characters) { |
965 |
|
c = characters[i]; |
966 |
|
switch (c) { |
967 |
|
case '\r': |
968 |
|
case '\n': |
969 |
|
case 0x2028: |
970 |
|
case 0x2029: |
971 |
|
done = true; |
972 |
|
break; |
973 |
|
default: |
974 |
|
i++; |
975 |
|
break; |
976 |
|
} |
977 |
} |
} |
978 |
size_t line_end = i; |
size_t line_end = i; |
979 |
if (i < num_characters) { |
if (i < num_characters) { |
980 |
if (characters[i] == '\r') { |
i++; |
981 |
line_end = i; |
if (c == '\r' && i < num_characters && characters[i] == '\n') { |
|
i++; |
|
|
if (i < num_characters && characters[i] == '\n') { |
|
|
i++; |
|
|
} |
|
|
} |
|
|
else if (characters[i] == '\n') { |
|
|
line_end = i; |
|
982 |
i++; |
i++; |
983 |
} |
} |
|
else { |
|
|
abort(); |
|
|
} |
|
984 |
} |
} |
985 |
char * line = js_DeflateString(context, characters + line_start, line_end - line_start); |
if (characters_start_with(characters, line_start, line_end, "//#JSCOVERAGE_IF")) { |
|
if (str_starts_with(line, "//#JSCOVERAGE_IF")) { |
|
986 |
if (! has_conditionals) { |
if (! has_conditionals) { |
987 |
has_conditionals = true; |
has_conditionals = true; |
988 |
Stream_printf(output, "_$jscoverage['%s'].conditionals = [];\n", file_id); |
Stream_printf(output, "_$jscoverage['%s'].conditionals = [];\n", file_id); |
989 |
} |
} |
990 |
Stream_printf(output, "if (!%s) {\n", line + 16); |
Stream_write_string(output, "if (!("); |
991 |
|
for (size_t j = line_start + 16; j < line_end; j++) { |
992 |
|
jschar c = characters[j]; |
993 |
|
if (c == '\t' || (32 <= c && c <= 126)) { |
994 |
|
Stream_write_char(output, c); |
995 |
|
} |
996 |
|
else { |
997 |
|
Stream_printf(output, "\\u%04x", c); |
998 |
|
} |
999 |
|
} |
1000 |
|
Stream_write_string(output, ")) {\n"); |
1001 |
Stream_printf(output, " _$jscoverage['%s'].conditionals[%d] = ", file_id, line_number); |
Stream_printf(output, " _$jscoverage['%s'].conditionals[%d] = ", file_id, line_number); |
1002 |
} |
} |
1003 |
else if (str_starts_with(line, "//#JSCOVERAGE_ENDIF")) { |
else if (characters_start_with(characters, line_start, line_end, "//#JSCOVERAGE_ENDIF")) { |
1004 |
Stream_printf(output, "%d;\n", line_number); |
Stream_printf(output, "%d;\n", line_number); |
1005 |
Stream_printf(output, "}\n"); |
Stream_printf(output, "}\n"); |
1006 |
} |
} |
|
JS_free(context, line); |
|
1007 |
} |
} |
1008 |
|
|
1009 |
/* copy the original source to the output */ |
/* copy the original source to the output */ |