/[jscoverage]/trunk/jscoverage.jsm
ViewVC logotype

Diff of /trunk/jscoverage.jsm

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

revision 361 by siliconforks, Sun Oct 26 05:28:03 2008 UTC revision 441 by siliconforks, Tue Jul 14 16:14:24 2009 UTC
# Line 1  Line 1 
1  /*  /*
2      jscoverage.jsm - Firefox module      jscoverage.jsm - Firefox module
3      Copyright (C) 2008 siliconforks.com      Copyright (C) 2008, 2009 siliconforks.com
4    
5      This program is free software; you can redistribute it and/or modify      This program is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published by      it under the terms of the GNU General Public License as published by
# Line 20  Line 20 
20  var EXPORTED_SYMBOLS = ['_$jscoverage'];  var EXPORTED_SYMBOLS = ['_$jscoverage'];
21    
22  var _$jscoverage = {};  var _$jscoverage = {};
23    
24    function jscoverage_pad(s) {
25      return '0000'.substr(s.length) + s;
26    }
27    
28    function jscoverage_quote(s) {
29      return '"' + s.replace(/[\u0000-\u001f"\\\u007f-\uffff]/g, function (c) {
30        switch (c) {
31        case '\b':
32          return '\\b';
33        case '\f':
34          return '\\f';
35        case '\n':
36          return '\\n';
37        case '\r':
38          return '\\r';
39        case '\t':
40          return '\\t';
41        case '\v':
42          return '\\v';
43        case '"':
44          return '\\"';
45        case '\\':
46          return '\\\\';
47        default:
48          return '\\u' + jscoverage_pad(c.charCodeAt(0).toString(16));
49        }
50      }) + '"';
51    }
52    
53    var JSCoverageUtils = {
54      QueryInterface: function (aIID) {
55        if (! aIID.equals(nsIObserver) && ! aIID.equals(nsISupports)) {
56          throw Components.results.NS_ERROR_NO_INTERFACE;
57        }
58        return this;
59      },
60    
61      getReportDirectory: function() {
62        const Cc = Components.classes;
63        const Ci = Components.interfaces;
64    
65        var directoryService = Cc['@mozilla.org/file/directory_service;1'].getService(Ci.nsIProperties);
66        /*
67        CurProcD - directory in which the firefox process was started
68        CurWorkD - current working directory
69        Home - home directory
70        TmpD - temp directory
71        See xpcom/io/nsDirectoryServiceDefs.h
72        */
73        var reportDirectory = directoryService.get('CurProcD', Ci.nsILocalFile);
74        reportDirectory.appendRelativePath('jscoverage-report');
75        return reportDirectory;
76      },
77    
78      readExistingCoverage: function() {
79        try {
80          const Cc = Components.classes;
81          const Ci = Components.interfaces;
82    
83          var reportDirectory = this.getReportDirectory();
84          if (! reportDirectory.exists()) {
85            return;
86          }
87          var jsonFile = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsILocalFile);
88          jsonFile.initWithFile(reportDirectory);
89          jsonFile.appendRelativePath('jscoverage.json');
90          if (! jsonFile.exists()) {
91            return;
92          }
93          var fileInputStream = Cc['@mozilla.org/network/file-input-stream;1'].createInstance(Ci.nsIFileInputStream);
94          var json = null;
95          try {
96            fileInputStream.init(jsonFile, 1, 0, 0);
97            var scriptableInputStream = Cc['@mozilla.org/scriptableinputstream;1'].createInstance(Ci.nsIScriptableInputStream);
98            scriptableInputStream.init(fileInputStream);
99            try {
100              json = scriptableInputStream.read(-1);
101            }
102            finally {
103              scriptableInputStream.close();
104            }
105          }
106          finally {
107            fileInputStream.close();
108          }
109          var coverage = eval('(' + json + ')');
110          for (var file in coverage) {
111            _$jscoverage[file] = coverage[file].coverage;
112            _$jscoverage[file].source = coverage[file].source;
113          }
114        }
115        catch (e) {
116          dump('jscoverage.jsm: error reading existing coverage report\n');
117          dump(e);
118          dump('\n');
119        }
120      },
121    
122      observe: function (aSubject, aTopic, aData) {
123        try {
124          dump('jscoverage.jsm: storing coverage data ...\n');
125    
126          const Cc = Components.classes;
127          const Ci = Components.interfaces;
128    
129          var reportDirectory = this.getReportDirectory();
130          if (! reportDirectory.exists()) {
131            reportDirectory.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
132          }
133    
134          var ioService = Cc['@mozilla.org/network/io-service;1'].getService(Ci.nsIIOService);
135          var copyChrome = function(filename) {
136            var channel = ioService.newChannel('chrome://jscoverage/content/' + filename, null, null);
137            var binaryInputStream = Cc['@mozilla.org/binaryinputstream;1'].createInstance(Ci.nsIBinaryInputStream);
138            try {
139              binaryInputStream.setInputStream(channel.open());
140    
141              var file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsILocalFile);
142              file.initWithFile(reportDirectory);
143              file.appendRelativePath(filename);
144              var fileOutputStream = Cc['@mozilla.org/network/file-output-stream;1'].createInstance(Ci.nsIFileOutputStream);
145              fileOutputStream.init(file, 0x02 | 0x08 | 0x20, 0644, 0);
146              var binaryOutputStream = Cc['@mozilla.org/binaryoutputstream;1'].createInstance(Ci.nsIBinaryOutputStream);
147              try {
148                binaryOutputStream.setOutputStream(fileOutputStream);
149    
150                for (;;) {
151                  var available = binaryInputStream.available();
152                  if (available === 0) {
153                    break;
154                  }
155                  var bytes = binaryInputStream.readBytes(available);
156                  binaryOutputStream.writeBytes(bytes, bytes.length);
157                }
158    
159                if (filename === 'jscoverage.js') {
160                  var s = 'jscoverage_isReport = true;\n';
161                  binaryOutputStream.write(s, s.length);
162                }
163              }
164              finally {
165                binaryOutputStream.close();
166              }
167            }
168            finally {
169              binaryInputStream.close();
170            }
171          };
172          copyChrome('jscoverage.html');
173          copyChrome('jscoverage.js');
174          copyChrome('jscoverage.css');
175          copyChrome('jscoverage-throbber.gif');
176          copyChrome('jscoverage-highlight.css');
177    
178          // write the coverage data
179          var file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsILocalFile);
180          file.initWithFile(reportDirectory);
181          file.appendRelativePath('jscoverage.json');
182          var fileOutputStream = Cc['@mozilla.org/network/file-output-stream;1'].createInstance(Ci.nsIFileOutputStream);
183          try {
184            fileOutputStream.init(file, 0x02 | 0x08 | 0x20, 0644, 0);
185            function write(s) {
186              fileOutputStream.write(s, s.length);
187            }
188            write('{');
189            var first = true;
190            for (var file in _$jscoverage) {
191              dump('jscoverage.jsm: storing coverage data for file ' + file + ' ...\n');
192              if (first) {
193                first = false;
194              }
195              else {
196                write(',');
197              }
198              write(jscoverage_quote(file));
199              write(':{"coverage":[');
200              var coverage = _$jscoverage[file];
201              var length = coverage.length;
202              for (var line = 0; line < length; line++) {
203                if (line > 0) {
204                  write(',');
205                }
206                var value = coverage[line];
207                if (value === undefined || value === null) {
208                  value = 'null';
209                }
210                write(value.toString());
211              }
212              write('],"source":[');
213              var source = coverage.source;
214              length = source.length;
215              for (line = 0; line < length; line++) {
216                if (line > 0) {
217                  write(',');
218                }
219                write(jscoverage_quote(source[line]));
220              }
221              write(']}');
222            }
223            write('}');
224            dump('jscoverage.jsm: coverage data stored\n');
225          }
226          finally {
227            fileOutputStream.close();
228          }
229        }
230        catch (e) {
231          dump('jscoverage.jsm: error saving coverage report\n');
232          dump(e);
233          dump('\n');
234        }
235      }
236    };
237    
238    try {
239      JSCoverageUtils.readExistingCoverage();
240    
241      const Cc = Components.classes;
242      const Ci = Components.interfaces;
243      const jscoverage_observerService = Cc['@mozilla.org/observer-service;1'].getService(Ci.nsIObserverService);
244      jscoverage_observerService.addObserver(JSCoverageUtils, 'quit-application', false);
245    
246      dump('jscoverage.jsm: initialized\n');
247    }
248    catch (e) {
249      dump('jscoverage.jsm: initialization error\n');
250      dump(e);
251      dump('\n');
252    }

Legend:
Removed from v.361  
changed lines
  Added in v.441

  ViewVC Help
Powered by ViewVC 1.1.24