/[jscoverage]/trunk/instrument-js.c
ViewVC logotype

Diff of /trunk/instrument-js.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 116 by siliconforks, Sat May 31 21:42:36 2008 UTC revision 167 by siliconforks, Mon Sep 15 15:54:26 2008 UTC
# Line 148  Line 148 
148  static void instrument_expression(JSParseNode * node, Stream * f);  static void instrument_expression(JSParseNode * node, Stream * f);
149  static void instrument_statement(JSParseNode * node, Stream * f, int indent);  static void instrument_statement(JSParseNode * node, Stream * f, int indent);
150    
151  static void instrument_function(JSParseNode * node, Stream * f, int indent) {  enum FunctionType {
152      assert(node->pn_arity == PN_FUNC);    FUNCTION_NORMAL,
153      assert(ATOM_IS_OBJECT(node->pn_funAtom));    FUNCTION_GETTER_OR_SETTER
154      JSObject * object = ATOM_TO_OBJECT(node->pn_funAtom);  };
155      assert(JS_ObjectIsFunction(context, object));  
156      JSFunction * function = (JSFunction *) JS_GetPrivate(context, object);  static void instrument_function(JSParseNode * node, Stream * f, int indent, enum FunctionType type) {
157      assert(function);    assert(node->pn_arity == PN_FUNC);
158      assert(object == function->object);    assert(ATOM_IS_OBJECT(node->pn_funAtom));
159      Stream_printf(f, "%*s", indent, "");    JSObject * object = ATOM_TO_OBJECT(node->pn_funAtom);
160      assert(JS_ObjectIsFunction(context, object));
161      JSFunction * function = (JSFunction *) JS_GetPrivate(context, object);
162      assert(function);
163      assert(object == function->object);
164      Stream_printf(f, "%*s", indent, "");
165      if (type == FUNCTION_NORMAL) {
166      Stream_write_string(f, "function");      Stream_write_string(f, "function");
167      }
168    
169      /* function name */    /* function name */
170      if (function->atom) {    if (function->atom) {
171        Stream_write_char(f, ' ');      Stream_write_char(f, ' ');
172        print_string_atom(function->atom, f);      print_string_atom(function->atom, f);
173      }    }
174    
175      /* function parameters */    /* function parameters */
176      Stream_write_string(f, "(");    Stream_write_string(f, "(");
177      JSAtom ** params = xnew(JSAtom *, function->nargs);    JSAtom ** params = xnew(JSAtom *, function->nargs);
178      for (int i = 0; i < function->nargs; i++) {    for (int i = 0; i < function->nargs; i++) {
179        /* initialize to NULL for sanity check */      /* initialize to NULL for sanity check */
180        params[i] = NULL;      params[i] = NULL;
181      }    }
182      JSScope * scope = OBJ_SCOPE(object);    JSScope * scope = OBJ_SCOPE(object);
183      for (JSScopeProperty * scope_property = SCOPE_LAST_PROP(scope); scope_property != NULL; scope_property = scope_property->parent) {    for (JSScopeProperty * scope_property = SCOPE_LAST_PROP(scope); scope_property != NULL; scope_property = scope_property->parent) {
184        if (scope_property->getter != js_GetArgument) {      if (scope_property->getter != js_GetArgument) {
185          continue;        continue;
186        }      }
187        assert(scope_property->flags & SPROP_HAS_SHORTID);      assert(scope_property->flags & SPROP_HAS_SHORTID);
188        assert((uint16) scope_property->shortid < function->nargs);      assert((uint16) scope_property->shortid < function->nargs);
189        assert(JSID_IS_ATOM(scope_property->id));      assert(JSID_IS_ATOM(scope_property->id));
190        params[(uint16) scope_property->shortid] = JSID_TO_ATOM(scope_property->id);      params[(uint16) scope_property->shortid] = JSID_TO_ATOM(scope_property->id);
191      }    }
192      for (int i = 0; i < function->nargs; i++) {    for (int i = 0; i < function->nargs; i++) {
193        assert(params[i] != NULL);      assert(params[i] != NULL);
194        if (i > 0) {      if (i > 0) {
195          Stream_write_string(f, ", ");        Stream_write_string(f, ", ");
       }  
       if (ATOM_IS_STRING(params[i])) {  
         print_string_atom(params[i], f);  
       }  
196      }      }
197      Stream_write_string(f, ") {\n");      if (ATOM_IS_STRING(params[i])) {
198      free(params);        print_string_atom(params[i], f);
199        }
200      }
201      Stream_write_string(f, ") {\n");
202      free(params);
203    
204      /* function body */    /* function body */
205      instrument_statement(node->pn_body, f, indent + 2);    instrument_statement(node->pn_body, f, indent + 2);
206    
207      Stream_write_string(f, "}\n");    Stream_write_string(f, "}\n");
208  }  }
209    
210  static void instrument_function_call(JSParseNode * node, Stream * f) {  static void instrument_function_call(JSParseNode * node, Stream * f) {
# Line 228  Line 235 
235  static void instrument_expression(JSParseNode * node, Stream * f) {  static void instrument_expression(JSParseNode * node, Stream * f) {
236    switch (node->pn_type) {    switch (node->pn_type) {
237    case TOK_FUNCTION:    case TOK_FUNCTION:
238      instrument_function(node, f, 0);      instrument_function(node, f, 0, FUNCTION_NORMAL);
239      break;      break;
240    case TOK_COMMA:    case TOK_COMMA:
241      for (struct JSParseNode * p = node->pn_head; p != NULL; p = p->pn_next) {      for (struct JSParseNode * p = node->pn_head; p != NULL; p = p->pn_next) {
# Line 435  Line 442 
442        if (p != node->pn_head) {        if (p != node->pn_head) {
443          Stream_write_string(f, ", ");          Stream_write_string(f, ", ");
444        }        }
445        instrument_expression(p->pn_left, f);  
446        Stream_write_string(f, ": ");        /* check whether this is a getter or setter */
447        instrument_expression(p->pn_right, f);        switch (p->pn_op) {
448          case JSOP_GETTER:
449            Stream_write_string(f, "get ");
450            instrument_expression(p->pn_left, f);
451            instrument_function(p->pn_right, f, 0, FUNCTION_GETTER_OR_SETTER);
452            break;
453          case JSOP_SETTER:
454            Stream_write_string(f, "set ");
455            instrument_expression(p->pn_left, f);
456            instrument_function(p->pn_right, f, 0, FUNCTION_GETTER_OR_SETTER);
457            break;
458          default:
459            instrument_expression(p->pn_left, f);
460            Stream_write_string(f, ": ");
461            instrument_expression(p->pn_right, f);
462            break;
463          }
464      }      }
465      Stream_write_char(f, '}');      Stream_write_char(f, '}');
466      break;      break;
# Line 541  Line 564 
564  static void output_statement(JSParseNode * node, Stream * f, int indent) {  static void output_statement(JSParseNode * node, Stream * f, int indent) {
565    switch (node->pn_type) {    switch (node->pn_type) {
566    case TOK_FUNCTION:    case TOK_FUNCTION:
567      instrument_function(node, f, indent);      instrument_function(node, f, indent, FUNCTION_NORMAL);
568      break;      break;
569    case TOK_LC:    case TOK_LC:
570      assert(node->pn_arity == PN_LIST);      assert(node->pn_arity == PN_LIST);
# Line 858  Line 881 
881    Stream_write(output, instrumented->data, instrumented->length);    Stream_write(output, instrumented->data, instrumented->length);
882    Stream_write_char(output, '\n');    Stream_write_char(output, '\n');
883    
884    /* copy the original source to the output */    /* conditionals */
885      bool has_conditionals = false;
886      size_t line_number = 0;
887    size_t i = 0;    size_t i = 0;
888    while (i < input_length) {    while (i < input_length) {
889        line_number++;
890        size_t line_start = i;
891        while (i < input_length && base[i] != '\r' && base[i] != '\n') {
892          i++;
893        }
894        size_t line_end = i;
895        if (i < input_length) {
896          if (base[i] == '\r') {
897            line_end = i;
898            i++;
899            if (i < input_length && base[i] == '\n') {
900              i++;
901            }
902          }
903          else if (base[i] == '\n') {
904            line_end = i;
905            i++;
906          }
907          else {
908            abort();
909          }
910        }
911        char * line = js_DeflateString(context, base + line_start, line_end - line_start);
912        if (str_starts_with(line, "//#JSCOVERAGE_IF")) {
913          if (! has_conditionals) {
914            has_conditionals = true;
915            Stream_printf(output, "_$jscoverage['%s'].conditionals = [];\n", file_id);
916          }
917          Stream_printf(output, "if (!%s) {\n", line + 16);
918          Stream_printf(output, "  _$jscoverage['%s'].conditionals[%d] = ", file_id, line_number);
919        }
920        else if (str_starts_with(line, "//#JSCOVERAGE_ENDIF")) {
921          Stream_printf(output, "%d;\n", line_number);
922          Stream_printf(output, "}\n");
923        }
924        JS_free(context, line);
925      }
926    
927      /* copy the original source to the output */
928      i = 0;
929      while (i < input_length) {
930      Stream_write_string(output, "// ");      Stream_write_string(output, "// ");
931      size_t line_start = i;      size_t line_start = i;
932      while (i < input_length && base[i] != '\r' && base[i] != '\n') {      while (i < input_length && base[i] != '\r' && base[i] != '\n') {
# Line 902  Line 968 
968    copy_resource("jscoverage.html", destination_directory);    copy_resource("jscoverage.html", destination_directory);
969    copy_resource("jscoverage.css", destination_directory);    copy_resource("jscoverage.css", destination_directory);
970    copy_resource("jscoverage.js", destination_directory);    copy_resource("jscoverage.js", destination_directory);
971      copy_resource("jscoverage-ie.js", destination_directory);
972    copy_resource("jscoverage-throbber.gif", destination_directory);    copy_resource("jscoverage-throbber.gif", destination_directory);
973    copy_resource("jscoverage-sh_main.js", destination_directory);    copy_resource("jscoverage-sh_main.js", destination_directory);
974    copy_resource("jscoverage-sh_javascript.js", destination_directory);    copy_resource("jscoverage-sh_javascript.js", destination_directory);

Legend:
Removed from v.116  
changed lines
  Added in v.167

  ViewVC Help
Powered by ViewVC 1.1.24