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

Contents of /trunk/jscoverage.jsm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 505 - (show annotations)
Sat Jan 2 04:55:54 2010 UTC (8 years, 6 months ago) by siliconforks
File size: 8373 byte(s)
Update copyright year.

1 /*
2 jscoverage.jsm - Firefox module
3 Copyright (C) 2008, 2009, 2010 siliconforks.com
4
5 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
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 var EXPORTED_SYMBOLS = ['_$jscoverage'];
21
22 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 const Cc = Components.classes;
56 const Ci = Components.interfaces;
57
58 if (! aIID.equals(Ci.nsIObserver) && ! aIID.equals(Ci.nsISupports)) {
59 throw Components.results.NS_ERROR_NO_INTERFACE;
60 }
61 return this;
62 },
63
64 getReportDirectory: function() {
65 const Cc = Components.classes;
66 const Ci = Components.interfaces;
67
68 var directoryService = Cc['@mozilla.org/file/directory_service;1'].getService(Ci.nsIProperties);
69 /*
70 CurProcD - directory in which the firefox process was started
71 CurWorkD - current working directory
72 Home - home directory
73 TmpD - temp directory
74 See xpcom/io/nsDirectoryServiceDefs.h
75 */
76 var reportDirectory = directoryService.get('CurProcD', Ci.nsILocalFile);
77 reportDirectory.appendRelativePath('jscoverage-report');
78 return reportDirectory;
79 },
80
81 readExistingCoverage: function() {
82 try {
83 const Cc = Components.classes;
84 const Ci = Components.interfaces;
85
86 var reportDirectory = this.getReportDirectory();
87 if (! reportDirectory.exists()) {
88 return;
89 }
90 var jsonFile = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsILocalFile);
91 jsonFile.initWithFile(reportDirectory);
92 jsonFile.appendRelativePath('jscoverage.json');
93 if (! jsonFile.exists()) {
94 return;
95 }
96 var fileInputStream = Cc['@mozilla.org/network/file-input-stream;1'].createInstance(Ci.nsIFileInputStream);
97 var json = null;
98 try {
99 fileInputStream.init(jsonFile, 1, 0, 0);
100 var scriptableInputStream = Cc['@mozilla.org/scriptableinputstream;1'].createInstance(Ci.nsIScriptableInputStream);
101 scriptableInputStream.init(fileInputStream);
102 try {
103 json = scriptableInputStream.read(-1);
104 }
105 finally {
106 scriptableInputStream.close();
107 }
108 }
109 finally {
110 fileInputStream.close();
111 }
112 var coverage = eval('(' + json + ')');
113 for (var file in coverage) {
114 _$jscoverage[file] = coverage[file].coverage;
115 _$jscoverage[file].source = coverage[file].source;
116 }
117 }
118 catch (e) {
119 dump('jscoverage.jsm: error reading existing coverage report\n');
120 dump(e);
121 dump('\n');
122 }
123 },
124
125 observe: function (aSubject, aTopic, aData) {
126 try {
127 dump('jscoverage.jsm: storing coverage data ...\n');
128
129 const Cc = Components.classes;
130 const Ci = Components.interfaces;
131
132 var reportDirectory = this.getReportDirectory();
133 if (! reportDirectory.exists()) {
134 reportDirectory.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
135 }
136
137 var ioService = Cc['@mozilla.org/network/io-service;1'].getService(Ci.nsIIOService);
138 var copyChrome = function(filename) {
139 var channel = ioService.newChannel('chrome://jscoverage/content/' + filename, null, null);
140 var binaryInputStream = Cc['@mozilla.org/binaryinputstream;1'].createInstance(Ci.nsIBinaryInputStream);
141 try {
142 binaryInputStream.setInputStream(channel.open());
143
144 var file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsILocalFile);
145 file.initWithFile(reportDirectory);
146 file.appendRelativePath(filename);
147 var fileOutputStream = Cc['@mozilla.org/network/file-output-stream;1'].createInstance(Ci.nsIFileOutputStream);
148 fileOutputStream.init(file, 0x02 | 0x08 | 0x20, 0644, 0);
149 var binaryOutputStream = Cc['@mozilla.org/binaryoutputstream;1'].createInstance(Ci.nsIBinaryOutputStream);
150 try {
151 binaryOutputStream.setOutputStream(fileOutputStream);
152
153 for (;;) {
154 var available = binaryInputStream.available();
155 if (available === 0) {
156 break;
157 }
158 var bytes = binaryInputStream.readBytes(available);
159 binaryOutputStream.writeBytes(bytes, bytes.length);
160 }
161
162 if (filename === 'jscoverage.js') {
163 var s = 'jscoverage_isReport = true;\n';
164 binaryOutputStream.write(s, s.length);
165 }
166 }
167 finally {
168 binaryOutputStream.close();
169 }
170 }
171 finally {
172 binaryInputStream.close();
173 }
174 };
175 copyChrome('jscoverage.html');
176 copyChrome('jscoverage.js');
177 copyChrome('jscoverage.css');
178 copyChrome('jscoverage-throbber.gif');
179 copyChrome('jscoverage-highlight.css');
180
181 // write the coverage data
182 var file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsILocalFile);
183 file.initWithFile(reportDirectory);
184 file.appendRelativePath('jscoverage.json');
185 var fileOutputStream = Cc['@mozilla.org/network/file-output-stream;1'].createInstance(Ci.nsIFileOutputStream);
186 try {
187 fileOutputStream.init(file, 0x02 | 0x08 | 0x20, 0644, 0);
188 function write(s) {
189 fileOutputStream.write(s, s.length);
190 }
191 write('{');
192 var first = true;
193 for (var file in _$jscoverage) {
194 dump('jscoverage.jsm: storing coverage data for file ' + file + ' ...\n');
195 if (first) {
196 first = false;
197 }
198 else {
199 write(',');
200 }
201 write(jscoverage_quote(file));
202 write(':{"coverage":[');
203 var coverage = _$jscoverage[file];
204 var length = coverage.length;
205 for (var line = 0; line < length; line++) {
206 if (line > 0) {
207 write(',');
208 }
209 var value = coverage[line];
210 if (value === undefined || value === null) {
211 value = 'null';
212 }
213 write(value.toString());
214 }
215 write('],"source":[');
216 var source = coverage.source;
217 length = source.length;
218 for (line = 0; line < length; line++) {
219 if (line > 0) {
220 write(',');
221 }
222 write(jscoverage_quote(source[line]));
223 }
224 write(']}');
225 }
226 write('}');
227 dump('jscoverage.jsm: coverage data stored\n');
228 }
229 finally {
230 fileOutputStream.close();
231 }
232 }
233 catch (e) {
234 dump('jscoverage.jsm: error saving coverage report\n');
235 dump(e);
236 dump('\n');
237 }
238 }
239 };
240
241 try {
242 JSCoverageUtils.readExistingCoverage();
243
244 const Cc = Components.classes;
245 const Ci = Components.interfaces;
246 const jscoverage_observerService = Cc['@mozilla.org/observer-service;1'].getService(Ci.nsIObserverService);
247 // 'xpcom-shutdown' works under xpcshell
248 // jscoverage_observerService.addObserver(JSCoverageUtils, 'quit-application', false);
249 jscoverage_observerService.addObserver(JSCoverageUtils, 'xpcom-shutdown', false);
250
251 dump('jscoverage.jsm: initialized\n');
252 }
253 catch (e) {
254 dump('jscoverage.jsm: initialization error\n');
255 dump(e);
256 dump('\n');
257 }

  ViewVC Help
Powered by ViewVC 1.1.24