jsinstrument 0.0.10 → 0.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/jsinstrument/inserting.js +67 -24
- data/lib/jsinstrument/instrumenter.rb +34 -17
- data/lib/jsinstrument/version.rb +1 -1
- metadata +2 -2
| @@ -6,34 +6,70 @@ | |
| 6 6 | 
             
            !function(root){
         | 
| 7 7 | 
             
              if (root && (typeof root.%{js_object_name} === 'undefined')) {
         | 
| 8 8 | 
             
                root.%{js_object_name} = {
         | 
| 9 | 
            +
                  /**
         | 
| 10 | 
            +
                   * Const for coverage data types
         | 
| 11 | 
            +
                   */
         | 
| 12 | 
            +
                  TYPES: ['line', 'func', 'branch'],
         | 
| 9 13 | 
             
                  /**
         | 
| 10 14 | 
             
                   * Coverage data
         | 
| 15 | 
            +
                   * data = {
         | 
| 16 | 
            +
                   *   filename: {
         | 
| 17 | 
            +
                   *     line: [lines],
         | 
| 18 | 
            +
                   *     func: [lines],
         | 
| 19 | 
            +
                   *     branch: [lines]
         | 
| 20 | 
            +
                   *   }
         | 
| 21 | 
            +
                   * }
         | 
| 11 22 | 
             
                   */
         | 
| 12 | 
            -
                   | 
| 23 | 
            +
                  data: {},
         | 
| 13 24 | 
             
                  /**
         | 
| 14 25 | 
             
                   * register instrumented lines for the file
         | 
| 15 26 | 
             
                   */
         | 
| 16 | 
            -
                  register: function(file, lines) {
         | 
| 27 | 
            +
                  register: function(file, lines, func_lines) {
         | 
| 17 28 | 
             
                    // replace the dot in the filename by underscore to be competible with mongodb
         | 
| 18 29 | 
             
                    file = file.replace(/\./g, '_')
         | 
| 19 30 | 
             
                    // can't register twice for one file
         | 
| 20 | 
            -
                    if(!this. | 
| 21 | 
            -
                      this. | 
| 31 | 
            +
                    if(!this.data[file]) {
         | 
| 32 | 
            +
                      this.data[file] = {
         | 
| 33 | 
            +
                        line: [],
         | 
| 34 | 
            +
                        func: [],
         | 
| 35 | 
            +
                        branch: []
         | 
| 36 | 
            +
                      };
         | 
| 22 37 | 
             
                      for (var i in lines) {
         | 
| 23 | 
            -
                        this. | 
| 38 | 
            +
                        this.data[file].line[lines[i]] = 0;
         | 
| 39 | 
            +
                      }
         | 
| 40 | 
            +
                      for (var i in func_lines) {
         | 
| 41 | 
            +
                        this.data[file].func[func_lines[i]] = 0;
         | 
| 42 | 
            +
                      }
         | 
| 43 | 
            +
                    }
         | 
| 44 | 
            +
                  },
         | 
| 45 | 
            +
                  /**
         | 
| 46 | 
            +
                   * Hit a data
         | 
| 47 | 
            +
                   */
         | 
| 48 | 
            +
                  _hit: function(type, file, line) {
         | 
| 49 | 
            +
                    if (file && (this.TYPES.indexOf(type) !== -1)) {
         | 
| 50 | 
            +
                      file = file.replace(/\./g, '_');
         | 
| 51 | 
            +
                      if (this.data[file] && this.data[file][type]) {
         | 
| 52 | 
            +
                        this.data[file][type][line] = (this.data[file][type][line]) ? (this.data[file][type][line] + 1) : 1;
         | 
| 24 53 | 
             
                      }
         | 
| 25 54 | 
             
                    }
         | 
| 26 55 | 
             
                  },
         | 
| 27 56 | 
             
                  /**
         | 
| 28 57 | 
             
                   * Hit a line
         | 
| 29 58 | 
             
                   */
         | 
| 30 | 
            -
                   | 
| 31 | 
            -
                     | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
| 59 | 
            +
                  hit_line: function(file, line) {
         | 
| 60 | 
            +
                    this._hit('line', file, line);
         | 
| 61 | 
            +
                  },
         | 
| 62 | 
            +
                  /**
         | 
| 63 | 
            +
                   * Hit a func
         | 
| 64 | 
            +
                   */
         | 
| 65 | 
            +
                  hit_func: function(file, line) {
         | 
| 66 | 
            +
                    this._hit('func', file, line);
         | 
| 67 | 
            +
                  },
         | 
| 68 | 
            +
                  /**
         | 
| 69 | 
            +
                   * Hit a branch
         | 
| 70 | 
            +
                   */
         | 
| 71 | 
            +
                  hit_branch: function(file, line) {
         | 
| 72 | 
            +
                    this._hit('branch', file, line);
         | 
| 37 73 | 
             
                  },
         | 
| 38 74 | 
             
                  /**
         | 
| 39 75 | 
             
                   * Upload coverage data to server
         | 
| @@ -46,7 +82,7 @@ | |
| 46 82 | 
             
                    this._uploading = true;
         | 
| 47 83 |  | 
| 48 84 | 
             
                    try {
         | 
| 49 | 
            -
                      $.post('%{upload_url}', this._serialize( | 
| 85 | 
            +
                      $.post('%{upload_url}', this._serialize(mark)).done(function() {
         | 
| 50 86 | 
             
                        console.log('Coverage data uploaded!');
         | 
| 51 87 | 
             
                      }).always(function() {
         | 
| 52 88 | 
             
                        self._uploading = false;
         | 
| @@ -58,23 +94,30 @@ | |
| 58 94 | 
             
                  /**
         | 
| 59 95 | 
             
                   * serialize data for data uploading
         | 
| 60 96 | 
             
                   */
         | 
| 61 | 
            -
                  _serialize: function( | 
| 97 | 
            +
                  _serialize: function(mark) {
         | 
| 98 | 
            +
                    var data = this.data;
         | 
| 62 99 | 
             
                    var json = [];
         | 
| 63 100 |  | 
| 64 101 | 
             
                    for (var file in data) {
         | 
| 65 | 
            -
                      var  | 
| 102 | 
            +
                      var file_json = [];
         | 
| 103 | 
            +
                      
         | 
| 104 | 
            +
                      for (var i in TYPES) {
         | 
| 105 | 
            +
                        var type = TYPES[i];
         | 
| 106 | 
            +
                        var type_coverage = data[file][type];
         | 
| 66 107 |  | 
| 67 | 
            -
             | 
| 68 | 
            -
             | 
| 69 | 
            -
             | 
| 70 | 
            -
             | 
| 71 | 
            -
             | 
| 72 | 
            -
             | 
| 108 | 
            +
                        var array = [];
         | 
| 109 | 
            +
                        var length = type_coverage.length;
         | 
| 110 | 
            +
                        for (var line = 0; line < length; line++) {
         | 
| 111 | 
            +
                          var value = type_coverage[line];
         | 
| 112 | 
            +
                          if (value === undefined || value === null) {
         | 
| 113 | 
            +
                            value = '';
         | 
| 114 | 
            +
                          }
         | 
| 115 | 
            +
                          array.push(value);
         | 
| 73 116 | 
             
                        }
         | 
| 74 | 
            -
                         | 
| 117 | 
            +
                        file_json.push(this._quote(type) + ':[' + array.join(',') + ']');
         | 
| 75 118 | 
             
                      }
         | 
| 76 119 |  | 
| 77 | 
            -
                      json.push(this._quote(file) + ': | 
| 120 | 
            +
                      json.push(this._quote(file) + ':{' + file_json.join(',') + '}');
         | 
| 78 121 | 
             
                    }
         | 
| 79 122 |  | 
| 80 123 | 
             
                    var result = '{' + json.join(',') + '}';
         | 
| @@ -119,7 +162,7 @@ | |
| 119 162 | 
             
              }
         | 
| 120 163 |  | 
| 121 164 | 
             
              // register the instrumented lines for current file
         | 
| 122 | 
            -
              root.%{js_object_name}.register('%{src_filename}', %{instrumented_lines});
         | 
| 165 | 
            +
              root.%{js_object_name}.register('%{src_filename}', %{instrumented_lines}, %{instrumented_func_lines});
         | 
| 123 166 | 
             
            }(this);
         | 
| 124 167 |  | 
| 125 168 |  | 
| @@ -22,7 +22,7 @@ module JSInstrument | |
| 22 22 | 
             
                  self.src_filename = filename
         | 
| 23 23 | 
             
                  ast = RKelly::Parser.new.parse src
         | 
| 24 24 | 
             
                  raise 'Parse source failed.' unless ast
         | 
| 25 | 
            -
                  ast, instrumented_lines = instrument_ast ast
         | 
| 25 | 
            +
                  ast, instrumented_lines, instrumented_func_lines = instrument_ast ast
         | 
| 26 26 | 
             
                  instrumented_src = ast.to_ecma
         | 
| 27 27 |  | 
| 28 28 | 
             
                  inserting = File.open(File.dirname(__FILE__) + '/inserting.js').read
         | 
| @@ -35,7 +35,8 @@ module JSInstrument | |
| 35 35 | 
             
                    commit_hash: self.commit_hash,
         | 
| 36 36 | 
             
                    batch_text: self.batch_text,
         | 
| 37 37 | 
             
                    data_compress_method: self.data_compress_method,
         | 
| 38 | 
            -
                    instrumented_lines: instrumented_lines
         | 
| 38 | 
            +
                    instrumented_lines: instrumented_lines,
         | 
| 39 | 
            +
                    instrumented_func_lines: instrumented_func_lines
         | 
| 39 40 | 
             
                  }
         | 
| 40 41 |  | 
| 41 42 | 
             
                  (inserting % bindings) + instrumented_src
         | 
| @@ -46,12 +47,16 @@ module JSInstrument | |
| 46 47 | 
             
                  #
         | 
| 47 48 | 
             
                  ast = RKelly::Visitors::ParentBuilder.new.build ast
         | 
| 48 49 | 
             
                  instrumented_lines = Set.new
         | 
| 50 | 
            +
                  instrumented_func_lines = Set.new
         | 
| 49 51 | 
             
                  ast.each do |node|
         | 
| 50 52 | 
             
                    parent = node.parent
         | 
| 51 53 | 
             
                    line = node.line
         | 
| 52 54 | 
             
                    node_classname = node.class.name.split(/::/)[-1].sub('Node', '')
         | 
| 53 55 | 
             
                    parent_classname = parent.class.name.split(/::/)[-1].sub('Node', '')
         | 
| 56 | 
            +
             | 
| 54 57 | 
             
                    # instrument only if we can get the line no. and we haven't instrumented it
         | 
| 58 | 
            +
                    
         | 
| 59 | 
            +
                    # line coverage
         | 
| 55 60 | 
             
                    #
         | 
| 56 61 | 
             
                    if line and not instrumented_lines.member? line
         | 
| 57 62 | 
             
                      if ['ExpressionStatement', 'EmptyStatement', 'DoWhile', 'While', 'For', 'ForIn', 'Continue',
         | 
| @@ -60,7 +65,7 @@ module JSInstrument | |
| 60 65 | 
             
                        if 'DoWhile' == parent_classname
         | 
| 61 66 | 
             
                          if parent.left.eql? node
         | 
| 62 67 | 
             
                            instrumented_lines.add line
         | 
| 63 | 
            -
                            parent.left =  | 
| 68 | 
            +
                            parent.left = get_hitline_call_block node
         | 
| 64 69 | 
             
                          end
         | 
| 65 70 | 
             
                        # in RKelly, ConditionalNode extends IfNode
         | 
| 66 71 | 
             
                        # which is so annoying
         | 
| @@ -68,39 +73,45 @@ module JSInstrument | |
| 68 73 | 
             
                        elsif ['If', 'While', 'For', 'ForIn', 'With'].index parent_classname
         | 
| 69 74 | 
             
                          if parent.value.eql? node
         | 
| 70 75 | 
             
                            instrumented_lines.add line
         | 
| 71 | 
            -
                            parent.value =  | 
| 76 | 
            +
                            parent.value = get_hitline_call_block node
         | 
| 72 77 | 
             
                          elsif parent.else.eql? node
         | 
| 73 78 | 
             
                            instrumented_lines.add line
         | 
| 74 | 
            -
                            parent.else =  | 
| 79 | 
            +
                            parent.else = get_hitline_call_block node
         | 
| 75 80 | 
             
                          end
         | 
| 76 81 | 
             
                        elsif ['CaseBlock', 'Label'].index parent_classname
         | 
| 77 82 | 
             
                          # do nothing here
         | 
| 78 83 | 
             
                        elsif 'SourceElements' == parent_classname
         | 
| 79 | 
            -
                          if  | 
| 84 | 
            +
                          if insert_hitline_before node
         | 
| 80 85 | 
             
                            instrumented_lines.add line
         | 
| 81 86 | 
             
                          end
         | 
| 82 87 | 
             
                        end
         | 
| 83 88 | 
             
                      elsif ['With', 'Try'].index node_classname
         | 
| 84 89 | 
             
                        if 'SourceElements' == parent_classname
         | 
| 85 | 
            -
                          if  | 
| 90 | 
            +
                          if insert_hitline_before node
         | 
| 86 91 | 
             
                            instrumented_lines.add line
         | 
| 87 92 | 
             
                          end
         | 
| 88 93 | 
             
                        end
         | 
| 89 | 
            -
                       | 
| 90 | 
            -
             | 
| 91 | 
            -
             | 
| 94 | 
            +
                      end
         | 
| 95 | 
            +
                    end
         | 
| 96 | 
            +
                    # function coverage
         | 
| 97 | 
            +
                    #
         | 
| 98 | 
            +
                    if line and not instrumented_func_lines.member? line
         | 
| 99 | 
            +
                      if ['FunctionDecl', 'FunctionExpr'].index node_classname
         | 
| 100 | 
            +
                        if node.function_body
         | 
| 101 | 
            +
                          insert_hitfunc_in node.function_body, line
         | 
| 102 | 
            +
                          instrumented_func_lines.add line
         | 
| 92 103 | 
             
                        end
         | 
| 93 104 | 
             
                      end
         | 
| 94 105 | 
             
                    end
         | 
| 95 106 | 
             
                  end
         | 
| 96 | 
            -
                  [ast, instrumented_lines.sort]
         | 
| 107 | 
            +
                  [ast, instrumented_lines.sort, instrumented_func_lines.sort]
         | 
| 97 108 | 
             
                end
         | 
| 98 109 |  | 
| 99 110 | 
             
                private
         | 
| 100 | 
            -
                def  | 
| 111 | 
            +
                def get_hit_call line, func
         | 
| 101 112 | 
             
                  ExpressionStatementNode.new(
         | 
| 102 113 | 
             
                    FunctionCallNode.new(
         | 
| 103 | 
            -
                      ResolveNode.new("#{self.js_object_name} | 
| 114 | 
            +
                      ResolveNode.new("#{self.js_object_name}.#{func}"),
         | 
| 104 115 | 
             
                      ArgumentsNode.new([
         | 
| 105 116 | 
             
                        StringNode.new("\"#{self.src_filename}\""),
         | 
| 106 117 | 
             
                        NumberNode.new(line)
         | 
| @@ -109,16 +120,16 @@ module JSInstrument | |
| 109 120 | 
             
                  )
         | 
| 110 121 | 
             
                end
         | 
| 111 122 |  | 
| 112 | 
            -
                def  | 
| 123 | 
            +
                def get_hitline_call_block node
         | 
| 113 124 | 
             
                  BlockNode.new(
         | 
| 114 125 | 
             
                    SourceElementsNode.new([
         | 
| 115 | 
            -
                       | 
| 126 | 
            +
                      get_hit_call(node.line, "hit_line"),
         | 
| 116 127 | 
             
                      node
         | 
| 117 128 | 
             
                    ])
         | 
| 118 129 | 
             
                  )
         | 
| 119 130 | 
             
                end
         | 
| 120 131 |  | 
| 121 | 
            -
                def  | 
| 132 | 
            +
                def insert_hitline_before node
         | 
| 122 133 | 
             
                  # get the original node line
         | 
| 123 134 | 
             
                  #
         | 
| 124 135 | 
             
                  line = node.line
         | 
| @@ -131,9 +142,15 @@ module JSInstrument | |
| 131 142 | 
             
                    false
         | 
| 132 143 | 
             
                  else
         | 
| 133 144 | 
             
                    index = node.parent.value.index{|x| x.eql? node}
         | 
| 134 | 
            -
                    node.parent.value.insert index,  | 
| 145 | 
            +
                    node.parent.value.insert index, get_hit_call(line, "hit_line")
         | 
| 135 146 | 
             
                    true
         | 
| 136 147 | 
             
                  end
         | 
| 137 148 | 
             
                end
         | 
| 149 | 
            +
             | 
| 150 | 
            +
                def insert_hitfunc_in function_body_node, line
         | 
| 151 | 
            +
                  # FunctionBody.value(SourceElement).value(array).unshift hit_func
         | 
| 152 | 
            +
                  function_body_node.value.value.unshift get_hit_call(line, "hit_func")
         | 
| 153 | 
            +
                end
         | 
| 154 | 
            +
             | 
| 138 155 | 
             
              end
         | 
| 139 156 | 
             
            end
         | 
    
        data/lib/jsinstrument/version.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: jsinstrument
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.0. | 
| 4 | 
            +
              version: 0.0.11
         | 
| 5 5 | 
             
              prerelease: 
         | 
| 6 6 | 
             
            platform: ruby
         | 
| 7 7 | 
             
            authors:
         | 
| @@ -9,7 +9,7 @@ authors: | |
| 9 9 | 
             
            autorequire: 
         | 
| 10 10 | 
             
            bindir: bin
         | 
| 11 11 | 
             
            cert_chain: []
         | 
| 12 | 
            -
            date: 2013-10- | 
| 12 | 
            +
            date: 2013-10-21 00:00:00.000000000 Z
         | 
| 13 13 | 
             
            dependencies:
         | 
| 14 14 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 15 15 | 
             
              name: rkelly
         |