This document introduces JavaScript Parser, an infrastructure for code quality analysis. It describes building blocks of a JavaScript engine including a parser, syntax tree, and virtual machine. It discusses producing a correct syntax tree and handling syntax errors. Code quality tools like linting, formatting, and coverage are demonstrated using the parser. Future directions include scope analysis, refactoring helpers, and smarter editing aids.
1 of 53
Downloaded 77 times
More Related Content
JavaScript Parser Infrastructure for Code Quality Analysis
3. Do you...
have a coding style/guidelines?
use code quality tool such as JSLint or JSHint?
actively prevent performance & coverage regressions?
wish you could write your own quality rules?
20. Specification, Parser Code, Syntax Tree
ECMA-262 Annex A.4 while ( Expression ) Statement
function parseWhileStatement() {
var test, body;
expectKeyword('while');
expect('(');
test = parseExpression();
expect(')');
body = parseStatement();
return {
type: Syntax.WhileStatement,
test: test,
body: body
};
}
21. High Performance http://esprima.org/test/compare.html
Speed Comparison
Chrome 18
Internet Explorer 9
Esprima 233 ms 567 ms
UglifyJS parse-js 620 ms 922 ms
Benchmark corpus:
jQuery, Prototype, MooTools, ExtCore, ...
23. Fit for Code Regeneration https://github.com/Constellation/escodegen
Source Esprima Escodegen Source
Syntax Tree
Shorten variable name
Syntax Transformation Automatically inline short function
Obfuscate
24. Easily Tweaked LLJS: Low Level JavaScript http://mbebenita.github.com/LLJS/
Block scope let x = 0;
let u8 flag;
Data types
let i32 position;
struct Point {
int x, y;
};
Pointers let u16 *p = q;
25. Error Tolerant Useful for IDE, editors, ...
Mismatched quote var msg = "Hello’;
Too many dots person..age = 18;
Incomplete, still typing if (person.
Strict mode violation 'use strict';
with (person) {
}
32. Identifier Length Distribution
750 mean of the identifier length is 8.27 characters
500
prototype-1.7.0.0.js SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING
prototype-1.7.0.0.js MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED
jquery-1.7.1.js subtractsBorderForOverflowNotVisible
jquery.mobile-1.0.js getClosestElementWithVirtualBinding
250 prototype-1.7.0.0.js HAS_EXTENDED_CREATE_ELEMENT_SYNTAX
0
0 5 10 15 20 25 30 35 40 45
http://ariya.ofilabs.com/2012/05/javascript-identifier-length-distribution.html
33. “Code Linting”
var fs = require('fs'),
esprima = require('./esprima'),
files = process.argv.splice(2);
Not a strict equal files.forEach(function (filename) {
var content = fs.readFileSync(filename, 'utf-8'),
syntax = esprima.parse(content, { loc: true });
if (x == 9) {
// do Something JSON.stringify(syntax, function (key, value) {
} if (key === 'test' && value.operator === '==')
console.log('Line', value.loc.start.line);
return value;
});
});
Another example: next-generation JSHint https://github.com/jshint/jshint-next
34. Strict Mode Checking
Duplicate data property in object
literal not allowed in strict mode
'use strict';
block = {
color: 'blue',
height: 20,
width: 10,
color: 'red'
};
http://ariya.ofilabs.com/2012/03/strict-mode-checks-with-esprima.html
35. http://ariya.ofilabs.com/2011/08/hall-of-api-shame-boolean-trap.html
“Boolean Trap” Finder
var volumeSlider = new Slider(false);
Obfuscated choice
component.setHidden(false);
Double-negative filter.setCaseInsensitive(false);
Can you make up your mind? treeItem.setState(true, false);
event.initKeyEvent("keypress", true, true, null, null,
The more the merrier? false, false, false, false, 9, 0);
38. Code Coverage
https://github.com/itay/node-cover
https://github.com/coveraje/coveraje
x = 42;
https://github.com/pmlopes/coberturajs
if (false)
x = -1;
http://ariya.ofilabs.com/2012/03/javascript-code-coverage-and-esprima.html
40. Non-Destructive Partial Source Modification
Do not remove comments
Intact
Preserve indentation & other formatting
Modified Add “contextual” information
Inject or change function invocation