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?
JavaScript in the Browser
User Interface
Data Persistence
Browser Engine
Render Engine
JavaScript Graphics
Networking I/O
Engine Stack
JavaScript Engine Building Blocks
Built-in objects,
Runtime
host objects, ...
Syntax Tree
Virtual
Source Parser Machine/
Interpreter
Fast and conservative
Tokenization
identifier number
var answer = 42;
keyword equal sign
semicolon
Syntax Tree
Variable Declaration
Identifier Literal Constant
answer 42
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
};
}
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, ...
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
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;
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) {
}
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
“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
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
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);
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
Non-Destructive Partial Source Modification
Do not remove comments
Intact
Preserve indentation & other formatting
Modified Add “contextual” information
Inject or change function invocation