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

Contents of /trunk/jscoverage.jsm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 439 - (show annotations)
Sun Jul 12 05:52:40 2009 UTC (9 years, 8 months ago) by siliconforks
File size: 7938 byte(s)
Make Mozilla platform application store coverage on exit.
1 /*
2 jscoverage.jsm - Firefox module
3 Copyright (C) 2008, 2009 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 if (! aIID.equals(nsIObserver) && ! aIID.equals(nsISupports)) {
56 throw Components.results.NS_ERROR_NO_INTERFACE;
57 }
58 return this;
59 },
60
61 readExistingCoverage: function() {
62 try {
63 const Cc = Components.classes;
64 const Ci = Components.interfaces;
65
66 var directoryService = Cc['@mozilla.org/file/directory_service;1'].getService(Ci.nsIProperties);
67 var reportDirectory = directoryService.get('CurWorkD', Ci.nsILocalFile);
68 reportDirectory.appendRelativePath('jscoverage-report');
69 if (! reportDirectory.exists()) {
70 return;
71 }
72 var jsonFile = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsILocalFile);
73 jsonFile.initWithFile(reportDirectory);
74 jsonFile.appendRelativePath('jscoverage.json');
75 if (! jsonFile.exists()) {
76 return;
77 }
78 var fileInputStream = Cc['@mozilla.org/network/file-input-stream;1'].createInstance(Ci.nsIFileInputStream);
79 var json = null;
80 try {
81 fileInputStream.init(jsonFile, 1, 0, 0);
82 var scriptableInputStream = Cc['@mozilla.org/scriptableinputstream;1'].createInstance(Ci.nsIScriptableInputStream);
83 scriptableInputStream.init(fileInputStream);
84 try {
85 json = scriptableInputStream.read(-1);
86 }
87 finally {
88 scriptableInputStream.close();
89 }
90 }
91 finally {
92 fileInputStream.close();
93 }
94 var coverage = eval('(' + json + ')');
95 for (var file in coverage) {
96 _$jscoverage[file] = coverage[file].coverage;
97 _$jscoverage[file].source = coverage[file].source;
98 }
99 }
100 catch (e) {
101 dump('jscoverage.jsm: error reading existing coverage report\n');
102 dump(e);
103 dump('\n');
104 }
105 },
106
107 observe: function (aSubject, aTopic, aData) {
108 try {
109 dump('jscoverage.jsm: storing coverage data ...\n');
110
111 const Cc = Components.classes;
112 const Ci = Components.interfaces;
113
114 var directoryService = Cc['@mozilla.org/file/directory_service;1'].getService(Ci.nsIProperties);
115 var reportDirectory = directoryService.get('CurWorkD', Ci.nsILocalFile);
116 reportDirectory.appendRelativePath('jscoverage-report');
117 if (! reportDirectory.exists()) {
118 reportDirectory.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
119 }
120
121 var ioService = Cc['@mozilla.org/network/io-service;1'].getService(Ci.nsIIOService);
122 var copyChrome = function(filename) {
123 var channel = ioService.newChannel('chrome://jscoverage/content/' + filename, null, null);
124 var binaryInputStream = Cc['@mozilla.org/binaryinputstream;1'].createInstance(Ci.nsIBinaryInputStream);
125 try {
126 binaryInputStream.setInputStream(channel.open());
127
128 var file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsILocalFile);
129 file.initWithFile(reportDirectory);
130 file.appendRelativePath(filename);
131 var fileOutputStream = Cc['@mozilla.org/network/file-output-stream;1'].createInstance(Ci.nsIFileOutputStream);
132 fileOutputStream.init(file, 0x02 | 0x08 | 0x20, 0644, 0);
133 var binaryOutputStream = Cc['@mozilla.org/binaryoutputstream;1'].createInstance(Ci.nsIBinaryOutputStream);
134 try {
135 binaryOutputStream.setOutputStream(fileOutputStream);
136
137 for (;;) {
138 var available = binaryInputStream.available();
139 if (available === 0) {
140 break;
141 }
142 var bytes = binaryInputStream.readBytes(available);
143 binaryOutputStream.writeBytes(bytes, bytes.length);
144 }
145
146 if (filename === 'jscoverage.js') {
147 var s = 'jscoverage_isReport = true;\n';
148 binaryOutputStream.write(s, s.length);
149 }
150 }
151 finally {
152 binaryOutputStream.close();
153 }
154 }
155 finally {
156 binaryInputStream.close();
157 }
158 };
159 copyChrome('jscoverage.html');
160 copyChrome('jscoverage.js');
161 copyChrome('jscoverage.css');
162 copyChrome('jscoverage-throbber.gif');
163 copyChrome('jscoverage-highlight.css');
164
165 // write the coverage data
166 var file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsILocalFile);
167 file.initWithFile(reportDirectory);
168 file.appendRelativePath('jscoverage.json');
169 var fileOutputStream = Cc['@mozilla.org/network/file-output-stream;1'].createInstance(Ci.nsIFileOutputStream);
170 try {
171 fileOutputStream.init(file, 0x02 | 0x08 | 0x20, 0644, 0);
172 function write(s) {
173 fileOutputStream.write(s, s.length);
174 }
175 write('{');
176 var first = true;
177 for (var file in _$jscoverage) {
178 dump('jscoverage.jsm: storing coverage data for file ' + file + ' ...\n');
179 if (first) {
180 first = false;
181 }
182 else {
183 write(',');
184 }
185 write(jscoverage_quote(file));
186 write(':{"coverage":[');
187 var coverage = _$jscoverage[file];
188 var length = coverage.length;
189 for (var line = 0; line < length; line++) {
190 if (line > 0) {
191 write(',');
192 }
193 var value = coverage[line];
194 if (value === undefined || value === null) {
195 value = 'null';
196 }
197 write(value.toString());
198 }
199 write('],"source":[');
200 var source = coverage.source;
201 length = source.length;
202 for (line = 0; line < length; line++) {
203 if (line > 0) {
204 write(',');
205 }
206 write(jscoverage_quote(source[line]));
207 }
208 write(']}');
209 }
210 write('}');
211 dump('jscoverage.jsm: coverage data stored\n');
212 }
213 finally {
214 fileOutputStream.close();
215 }
216 }
217 catch (e) {
218 dump('jscoverage.jsm: error saving coverage report\n');
219 dump(e);
220 dump('\n');
221 }
222 }
223 };
224
225 try {
226 JSCoverageUtils.readExistingCoverage();
227
228 const Cc = Components.classes;
229 const Ci = Components.interfaces;
230 const jscoverage_observerService = Cc['@mozilla.org/observer-service;1'].getService(Ci.nsIObserverService);
231 jscoverage_observerService.addObserver(JSCoverageUtils, 'xpcom-shutdown', false);
232
233 dump('jscoverage.jsm: initialized\n');
234 }
235 catch (e) {
236 dump('jscoverage.jsm: initialization error\n');
237 dump(e);
238 dump('\n');
239 }

  ViewVC Help
Powered by ViewVC 1.1.24