Skip to content
This repository was archived by the owner on Sep 15, 2021. It is now read-only.

Commit 8444ed5

Browse files
author
Paul Theriault
committed
Merge pull request #113 from mozilla/error-results
Catch scan errors and show them alongside results
2 parents a637fa2 + 759c5b0 commit 8444ed5

File tree

6 files changed

+95
-32
lines changed

6 files changed

+95
-32
lines changed

client/img/throbber.png

669 Bytes
Loading

client/index.html

+26-3
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@
5050
<ul class="nav nav-sidebar">
5151
<li id="scan-input-nav" ng-click="navShowInput()" class="active"><a>Input<span class="badge pull-right">{{inputFiles.length}}</span></a></li>
5252
<li id="scan-output-nav">
53-
<a ng-click="navShowOutput()" >Output <span class="badge pull-right">{{results.length}}</span></a>
53+
<a ng-click="navShowOutput()">Output
54+
<img ng-show="throb" src="img/throbber.png">
55+
<span class="badge pull-right">{{results.length}}</span></a>
5456
<div id="scan-output-rules" class="hidden">
5557
<div class="bg-info">Rules</div>
5658
<ul>
@@ -108,7 +110,7 @@ <h4>Choose files to scan</h4>
108110

109111
<div id="scan-results" class="hidden">
110112
<h4>Results <span class="badge pull-right">{{filteredResults.length}}</span></h4>
111-
<div id="results-wrapper" ng-show="results<1">
113+
<div id="results-wrapper" ng-show="((results.length == 0) && (errors.length == 0))">
112114
Scan results will be loaded here.
113115
</div>
114116
<div id="results-wrapper" ng-show="results">
@@ -123,13 +125,34 @@ <h4>Results <span class="badge pull-right">{{filteredResults.length}}</span></h4
123125
</thead>
124126
<tr ng-repeat='result in filteredResults| orderBy:predicate:reverse' title={{result.rule.rec}}>
125127
<td>{{result.filename}}</td>
126-
<td><a ng-click="showResult(result.filename,result.line, result.col)">Line {{result.line}}</a>
128+
<td><a ng-click="showResult(result.filename,result.line, result.col)">Line {{result.line}}</a></td>
127129
<td>{{result.rule.name }}</td>
128130
<!-- <td>{{result.rule.desc}}</a>-->
129131
</td>
130132
</tr>
131133
</table>
132134
</div>
135+
<h4>Errors <span class="badge pull-right">{{errors.length}}</span></h4>
136+
<div id="error-wrapper" ng-show="(errors.length > 0)">
137+
<table id="error-table" class="table table-striped">
138+
<thead>
139+
<tr>
140+
<th><a href="" ng-click="predicate = 'filename'; reverse=!reverse">Filename</a></th>
141+
<th><a href="" ng-click="predicate = 'line'; reverse=!reverse">Line</a></th>
142+
<th><a href="" ng-click="predicate = 'name'; reverse=!reverse">Name</a></th>
143+
<th><a href="" ng-click="predicate = 'message'; reverse=!reverse">Message</a></th>
144+
</tr>
145+
</thead>
146+
<tr ng-repeat='error in errors'>
147+
<td>{{ error.filename }}</td>
148+
<td><a ng-click="showResult(error.filename, error.loc.line, error.loc.col)">Line {{error.loc.line }}</a></td>
149+
<td>{{ error.name }}</td>
150+
<td>{{ error.message }}</td>
151+
</td>
152+
</tr>
153+
</table>
154+
</div>
155+
133156
</div>
134157

135158
</div>

client/js/scanctrl.js

+35-16
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,23 @@ function ScanCtrl($scope, ScanSvc) {
33
$scope.codeMirrorManual = undefined;
44
$scope.inputFiles = [];
55
$scope.results=[];
6+
$scope.errors=[];
67
$scope.filteredResults=[];
78
$scope.inputFilename="";
89
$scope.issueList=[];
10+
$scope.throb = false;
911

12+
var pending = 0;
1013
var selectedFile = 0;
1114
var codeMirror_index = 0;
12-
$scope.loadPossible = false;
13-
localforage.length(function(len) {
14-
$scope.loadPossible = (len == 3);
15-
});
1615

1716
$scope.run = function (source, filename) {
1817
//empty last scan
1918
$scope.results=[];
19+
$scope.errors=[];
2020
$scope.inputFiles.forEach(function (scriptFile, i) {
2121
if (document.getElementById('doScan_'+i).checked) {
22+
pending++; $scope.throb = true;
2223
ScanSvc.newScan(scriptFile.name,scriptFile.asText());
2324
}
2425
});
@@ -36,9 +37,12 @@ function ScanCtrl($scope, ScanSvc) {
3637

3738
$scope.updateIssueList = function(){
3839
$scope.issueList = $scope.results.reduce(function(p, c) {
39-
if (p.indexOf(c.rule.name) < 0)
40-
p.push(c.rule.name);
41-
return p;
40+
if ((c.type == 'finding') && (typeof p !== "undefined")) {
41+
if (p.indexOf(c.rule.name) < 0) {
42+
p.push(c.rule.name);
43+
}
44+
return p;
45+
}
4246
}, []);
4347
}
4448

@@ -175,6 +179,9 @@ function ScanCtrl($scope, ScanSvc) {
175179
var serializedResults = JSON.stringify($scope.results, includedAttributes);
176180
localforage.setItem('results', serializedResults, function() { });
177181

182+
var serializedErrors = JSON.stringify($scope.errors);
183+
localforage.setItem('errors', serializedErrors, function() { });
184+
178185
var serializedInputFiles = $scope.inputFiles.map( function(el) { return {data: el.asText(), name: el.name }; });
179186
localforage.setItem("inputFiles", JSON.stringify(serializedInputFiles), function(r) { });
180187

@@ -187,15 +194,19 @@ function ScanCtrl($scope, ScanSvc) {
187194
};
188195

189196
//TODO loadstate isn't called anymore, need to make it work with new workflow
190-
$scope.loadState = function() {
191-
// restore results as is
197+
//TODO -> call loadState() around in main.js, line 36 (using the scanCtrlScope) and expose "reset" button in the UI.
198+
$scope.restoreState = function() {
199+
var apply = false;
192200
localforage.getItem('results', function (results_storage) {
193-
if(!results_storage){
194-
alert('No previous scan found.')
195-
}
196201
$scope.results = JSON.parse(results_storage);
197-
$scope.$apply();
202+
apply = true;
198203
});
204+
localforage.getItem('errors', function (errors_storage) {
205+
if (errors_storage) {
206+
$scope.errors = JSON.parse(errors_storage);
207+
apply = true;
208+
}
209+
});
199210
// restore files, by creating JSZip things :)
200211
localforage.getItem("inputFiles", function(inputFiles_storage) {
201212
// mimic behavior from handleFileUpload
@@ -215,8 +226,9 @@ function ScanCtrl($scope, ScanSvc) {
215226
document.getElementById("doScan_" + i).checked = checkboxes[i];
216227
}
217228
});
218-
$scope.$apply();
229+
apply = true;
219230
});
231+
if (apply) { $scope.$apply(); }
220232
};
221233

222234
$scope.selectAll = function () {
@@ -241,9 +253,11 @@ function ScanCtrl($scope, ScanSvc) {
241253
});
242254
var content=file.asText();
243255
return content.split('\n').splice(line,line+numLines).join('\n');
244-
}
256+
};
245257

246258
$scope.$on('NewResults', function (event, result) {
259+
pending--;
260+
if (pending == 0) { $scope.throb = false; }
247261
if (Object.keys(result).length === 0) {
248262
$scope.error = "Empty result set (this can also be a good thing, if you test a simple file)";
249263
return
@@ -259,6 +273,11 @@ function ScanCtrl($scope, ScanSvc) {
259273
});
260274

261275
$scope.$on('ScanError', function (event, exception) {
262-
$scope.error = exception.name + " at Line " + exception.loc.line + ", Column " + exception.loc.column + ": " + exception.message;
276+
pending--;
277+
if (pending == 0) { $scope.throb = false; }
278+
$scope.errors.push(exception);
279+
$scope.updateIssueList();
280+
$scope.$apply();
281+
$scope.saveState();
263282
});
264283
}

client/js/scanservice.js

+10-1
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,21 @@ scanjsModule.factory('ScanSvc', function($rootScope) {
1919
ScanService.scanWorker = new Worker("js/scanworker.js");
2020
ScanService.scanWorker.addEventListener("message", function (evt) {
2121
if (('findings' in evt.data) && ('filename' in evt.data)) {
22+
if (evt.data.findings.length > 0) {
23+
if (evt.data.findings[0].type == 'error') {
24+
$rootScope.$broadcast('ScanError', evt.data.findings[0])
25+
return;
26+
}
27+
}
2228
ScanService.addResults(evt.data);
2329
}
2430
else if ('error' in evt.data) {
31+
// This is for errors in the worker, not in the scanning.
32+
// Exceptions (like SyntaxErrors) when scanning files
33+
// are in the findings.
2534
var exception = evt.data.error;
2635
if (e instanceof SyntaxError) {
27-
$rootsScope.$broadcast('ScanError', {name: exception.name, loc: exception.loc, message: exception.message })
36+
$rootScope.$broadcast('ScanError', {filename: evt.data.filename, name: exception.name, loc: exception.loc, message: exception.message })
2837
} else {
2938
throw e; // keep throwing unexpected things.
3039
}

common/scan.js

+20-3
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,24 @@
8585
});
8686
}
8787
catch(e) {
88-
console.log("ERROR: Skipping " + filename +" (parsing failure)");
89-
console.log('Exception: '+e+ "\n");
90-
throw e;
88+
if (e instanceof SyntaxError) {
89+
scanresults.push({
90+
//TODO decide whether to leave our or include this (increases results size)
91+
type: 'error',
92+
name: e.name,
93+
pos: e.pos,
94+
loc: { column: e.loc.column, line: e.loc.line},
95+
message: e.message,
96+
filename: filename
97+
});
98+
// Assuming that we can't get more than 1 SyntaxError per file
99+
// from acorn and there's nothing left to do.
100+
//TODO investigate this.
101+
return scanresults;
102+
} else {
103+
console.log("uenxpected error!!", e);
104+
throw e;
105+
}
91106
}
92107

93108
//run all the rules against content.
@@ -108,6 +123,8 @@
108123
var result = testFunc.call(this, node);
109124
if(result) {
110125
scanresults.push({
126+
//TODO decide whether to leave our or include this (increases results size)
127+
type: 'finding',
111128
rule : rule,
112129
filename : filename,
113130
line : node.loc.start.line,

index.js

+4-9
Original file line numberDiff line numberDiff line change
@@ -61,16 +61,11 @@ if( typeof process != 'undefined' && process.argv[2]) {
6161

6262
if(ext == '.js') {
6363
var content = fs.readFileSync(fullpath, 'utf8');
64-
try {
65-
results[fullpath] = ScanJS.scan(content, signatures, fullpath);
66-
} catch(e) {
67-
if (e instanceof SyntaxError) { // e.g., parse failure
68-
//XXX this might be easy to overlook when scanning a big folder
69-
console.log("SKIPPING FILE: SyntaxError in "+ fullpath+", at Line "+ e.loc.line +", Column "+e.loc.column+ ": " + e.message);
70-
} else {
71-
throw e;
72-
}
64+
var scanresult = ScanJS.scan(content, signatures, fullpath);
65+
if (scanresult.type == 'error') {
66+
console.log("SKIPPING FILE: Error in "+ fullpath+", at Line "+ scanresult.error.loc.line +", Column "+scanresult.error.loc.column+ ": " + scanresult.error.message);
7367
}
68+
results[fullpath] = scanresult;
7469
}
7570
});
7671
// Flatten report file to remove files with no findings and tests with no results (i.e. empty arr)

0 commit comments

Comments
 (0)