#! /usr/bin/env node
global.DIGITS_OVERRIDE_FOR_TESTING = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_0123456789";
'use strict';
/*jshint bitwise:true, curly:true, eqeqeq:true, forin:true, immed:true,
latedef:true, newcap:true, noarge:true, noempty:true, nonew:true,
onevar:true, plusplus:true, regexp:true, undef:true, strict:true,
sub:false, trailing:true */
var _,
/**
* NodeJS module for unit testing.
* @namespace
* @type {!TAssert}
* @see http://nodejs.org/docs/v0.6.10/api/all.html#assert
*/
oAssert = (/** @type {!TAssert} */ require('assert')),
/**
* Consolidates null, Boolean, and String values found inside an
* AST. The object under test.
* @namespace
* @type {!TConsolidator}
*/
oConsolidator = (/** @type {!TConsolidator} */ require('../lib/consolidator')),
/**
* The parser of ECMA-262 found in UglifyJS.
* @namespace
* @type {!TParser}
*/
oParser = (/** @type {!TParser} */ require('../lib/parse-js')),
/**
* The processor of ASTs
* found in UglifyJS.
* @namespace
* @type {!TProcessor}
*/
oProcessor = (/** @type {!TProcessor} */ require('../lib/process')),
/**
* An instance of an object that allows the traversal of an AST.
* @type {!TWalker}
*/
oWalker,
/**
* A collection of functions for the removal of the scope information
* during the traversal of an AST.
* @namespace
* @type {!Object.}
*/
oWalkersPurifiers = {
/**#nocode+*/ // JsDoc Toolkit 2.4.0 hides some of the keys.
/**
* Deletes the scope information from the branch of the abstract
* syntax tree representing the encountered function declaration.
* @param {string} sIdentifier The identifier of the function.
* @param {!Array.} aFormalParameterList Formal parameters.
* @param {!TSyntacticCodeUnit} oFunctionBody Function code.
*/
'defun': function(
sIdentifier,
aFormalParameterList,
oFunctionBody) {
delete oFunctionBody.scope;
},
/**
* Deletes the scope information from the branch of the abstract
* syntax tree representing the encountered function expression.
* @param {?string} sIdentifier The optional identifier of the
* function.
* @param {!Array.} aFormalParameterList Formal parameters.
* @param {!TSyntacticCodeUnit} oFunctionBody Function code.
*/
'function': function(
sIdentifier,
aFormalParameterList,
oFunctionBody) {
delete oFunctionBody.scope;
}
/**#nocode-*/ // JsDoc Toolkit 2.4.0 hides some of the keys.
},
/**
* Initiates the traversal of a source element.
* @param {!TWalker} oWalker An instance of an object that allows the
* traversal of an abstract syntax tree.
* @param {!TSyntacticCodeUnit} oSourceElement A source element from
* which the traversal should commence.
* @return {function(): !TSyntacticCodeUnit} A function that is able to
* initiate the traversal from a given source element.
*/
cContext = function(oWalker, oSourceElement) {
/**
* @return {!TSyntacticCodeUnit} A function that is able to
* initiate the traversal from a given source element.
*/
var fLambda = function() {
return oWalker.walk(oSourceElement);
};
return fLambda;
},
/**
* A record consisting of configuration for the code generation phase.
* @type {!Object}
*/
oCodeGenerationOptions = {
beautify: true
},
/**
* A boolean to track whether all tests have passed.
* @type {boolean}
*/
bTestsPassed = true,
/**
* Tests whether consolidation of an ECMAScript program yields expected
* results.
* @param {{
* sTitle: string,
* sInput: string,
* sOutput: string
* }} oUnitTest A record consisting of data about a unit test: its
* name, an ECMAScript program, and, if consolidation is to take
* place, the resulting ECMAScript program.
*/
cAssert = function(oUnitTest) {
var _,
/**
* An array-like object representing the AST obtained after consolidation.
* @type {!TSyntacticCodeUnit}
*/
oSyntacticCodeUnitActual =
oConsolidator.ast_consolidate(oParser.parse(oUnitTest.sInput)),
/**
* An array-like object representing the expected AST.
* @type {!TSyntacticCodeUnit}
*/
oSyntacticCodeUnitExpected = oParser.parse(
oUnitTest.hasOwnProperty('sOutput') ?
oUnitTest.sOutput : oUnitTest.sInput);
delete oSyntacticCodeUnitActual.scope;
oWalker = oProcessor.ast_walker();
oWalker.with_walkers(
oWalkersPurifiers,
cContext(oWalker, oSyntacticCodeUnitActual));
try {
oAssert.deepEqual(
oSyntacticCodeUnitActual,
oSyntacticCodeUnitExpected);
} catch (oException) {
console.error(
'########## A unit test has failed.\n' +
oUnitTest.sTitle + '\n' +
'##### actual code (' +
oProcessor.gen_code(oSyntacticCodeUnitActual).length +
' bytes)\n' +
oProcessor.gen_code(
oSyntacticCodeUnitActual,
oCodeGenerationOptions) + '\n' +
'##### expected code (' +
oProcessor.gen_code(oSyntacticCodeUnitExpected).length +
' bytes)\n' +
oProcessor.gen_code(
oSyntacticCodeUnitExpected,
oCodeGenerationOptions));
bTestsPassed = false;
}
};
[
// 7.6.1 Reserved Words.
{
sTitle:
'Omission of keywords while choosing an identifier name.',
sInput:
'(function() {' +
' var a, b, c, d, e, f, g, h, i, j, k, l, m,' +
' n, o, p, q, r, s, t, u, v, w, x, y, z,' +
' A, B, C, D, E, F, G, H, I, J, K, L, M,' +
' N, O, P, Q, R, S, T, U, V, W, X, Y, Z,' +
' $, _,' +
' aa, ab, ac, ad, ae, af, ag, ah, ai, aj, ak, al, am,' +
' an, ao, ap, aq, ar, as, at, au, av, aw, ax, ay, az,' +
' aA, aB, aC, aD, aE, aF, aG, aH, aI, aJ, aK, aL, aM,' +
' aN, aO, aP, aQ, aR, aS, aT, aU, aV, aW, aX, aY, aZ,' +
' a$, a_,' +
' ba, bb, bc, bd, be, bf, bg, bh, bi, bj, bk, bl, bm,' +
' bn, bo, bp, bq, br, bs, bt, bu, bv, bw, bx, by, bz,' +
' bA, bB, bC, bD, bE, bF, bG, bH, bI, bJ, bK, bL, bM,' +
' bN, bO, bP, bQ, bR, bS, bT, bU, bV, bW, bX, bY, bZ,' +
' b$, b_,' +
' ca, cb, cc, cd, ce, cf, cg, ch, ci, cj, ck, cl, cm,' +
' cn, co, cp, cq, cr, cs, ct, cu, cv, cw, cx, cy, cz,' +
' cA, cB, cC, cD, cE, cF, cG, cH, cI, cJ, cK, cL, cM,' +
' cN, cO, cP, cQ, cR, cS, cT, cU, cV, cW, cX, cY, cZ,' +
' c$, c_,' +
' da, db, dc, dd, de, df, dg, dh, di, dj, dk, dl, dm,' +
' dn, dq, dr, ds, dt, du, dv, dw, dx, dy, dz,' +
' dA, dB, dC, dD, dE, dF, dG, dH, dI, dJ, dK, dL, dM,' +
' dN, dO, dP, dQ, dR, dS, dT, dU, dV, dW, dX, dY, dZ,' +
' d$, d_;' +
' void ["abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",' +
' "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"];' +
'}());',
sOutput:
'(function() {' +
' var eb =' +
' "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",' +
' a, b, c, d, e, f, g, h, i, j, k, l, m,' +
' n, o, p, q, r, s, t, u, v, w, x, y, z,' +
' A, B, C, D, E, F, G, H, I, J, K, L, M,' +
' N, O, P, Q, R, S, T, U, V, W, X, Y, Z,' +
' $, _,' +
' aa, ab, ac, ad, ae, af, ag, ah, ai, aj, ak, al, am,' +
' an, ao, ap, aq, ar, as, at, au, av, aw, ax, ay, az,' +
' aA, aB, aC, aD, aE, aF, aG, aH, aI, aJ, aK, aL, aM,' +
' aN, aO, aP, aQ, aR, aS, aT, aU, aV, aW, aX, aY, aZ,' +
' a$, a_,' +
' ba, bb, bc, bd, be, bf, bg, bh, bi, bj, bk, bl, bm,' +
' bn, bo, bp, bq, br, bs, bt, bu, bv, bw, bx, by, bz,' +
' bA, bB, bC, bD, bE, bF, bG, bH, bI, bJ, bK, bL, bM,' +
' bN, bO, bP, bQ, bR, bS, bT, bU, bV, bW, bX, bY, bZ,' +
' b$, b_,' +
' ca, cb, cc, cd, ce, cf, cg, ch, ci, cj, ck, cl, cm,' +
' cn, co, cp, cq, cr, cs, ct, cu, cv, cw, cx, cy, cz,' +
' cA, cB, cC, cD, cE, cF, cG, cH, cI, cJ, cK, cL, cM,' +
' cN, cO, cP, cQ, cR, cS, cT, cU, cV, cW, cX, cY, cZ,' +
' c$, c_,' +
' da, db, dc, dd, de, df, dg, dh, di, dj, dk, dl, dm,' +
' dn, dq, dr, ds, dt, du, dv, dw, dx, dy, dz,' +
' dA, dB, dC, dD, dE, dF, dG, dH, dI, dJ, dK, dL, dM,' +
' dN, dO, dP, dQ, dR, dS, dT, dU, dV, dW, dX, dY, dZ,' +
' d$, d_;' +
' void [eb, eb];' +
'}());'
},
// 7.8.1 Null Literals.
{
sTitle:
'Evaluation with regard to the null value.',
sInput:
'/*jshint evil:true */' +
'(function() {' +
' var foo;' +
' void [null, null, null];' +
'}());' +
'eval("");' +
'(function() {' +
' var foo;' +
' void [null, null];' +
'}());',
sOutput:
'/*jshint evil:true */' +
'(function() {' +
' var a = null, foo;' +
' void [a, a, a];' +
'}());' +
'eval("");' +
'(function() {' +
' var foo;' +
' void [null, null];' +
'}());'
},
// 7.8.2 Boolean Literals.
{
sTitle:
'Evaluation with regard to the false value.',
sInput:
'/*jshint evil:true */' +
'(function() {' +
' var foo;' +
' void [false, false, false];' +
'}());' +
'eval("");' +
'(function() {' +
' var foo;' +
' void [false, false];' +
'}());',
sOutput:
'/*jshint evil:true */' +
'(function() {' +
' var a = false, foo;' +
' void [a, a, a];' +
'}());' +
'eval("");' +
'(function() {' +
' var foo;' +
' void [false, false];' +
'}());'
},
{
sTitle:
'Evaluation with regard to the true value.',
sInput:
'/*jshint evil:true */' +
'(function() {' +
' var foo;' +
' void [true, true, true];' +
'}());' +
'eval("");' +
'(function() {' +
' var foo;' +
' void [true, true];' +
'}());',
sOutput:
'/*jshint evil:true */' +
'(function() {' +
' var a = true, foo;' +
' void [a, a, a];' +
'}());' +
'eval("");' +
'(function() {' +
' var foo;' +
' void [true, true];' +
'}());'
},
// 7.8.4 String Literals.
{
sTitle:
'Evaluation with regard to the String value of a string literal.',
sInput:
'(function() {' +
' var foo;' +
' void ["abcd", "abcd", "abc", "abc"];' +
'}());',
sOutput:
'(function() {' +
' var a = "abcd", foo;' +
' void [a, a, "abc", "abc"];' +
'}());'
},
// 7.8.5 Regular Expression Literals.
{
sTitle:
'Preservation of the pattern of a regular expression literal.',
sInput:
'void [/abcdefghijklmnopqrstuvwxyz/, /abcdefghijklmnopqrstuvwxyz/];'
},
{
sTitle:
'Preservation of the flags of a regular expression literal.',
sInput:
'void [/(?:)/gim, /(?:)/gim, /(?:)/gim, /(?:)/gim, /(?:)/gim,' +
' /(?:)/gim, /(?:)/gim, /(?:)/gim, /(?:)/gim, /(?:)/gim,' +
' /(?:)/gim, /(?:)/gim, /(?:)/gim, /(?:)/gim, /(?:)/gim];'
},
// 10.2 Lexical Environments.
{
sTitle:
'Preservation of identifier names in the same scope.',
sInput:
'/*jshint shadow:true */' +
'var a;' +
'function b(i) {' +
'}' +
'for (var c; 0 === Math.random(););' +
'for (var d in {});' +
'void ["abcdefghijklmnopqrstuvwxyz"];' +
'void [b(a), b(c), b(d)];' +
'void [typeof e];' +
'i: for (; 0 === Math.random();) {' +
' if (42 === (new Date()).getMinutes()) {' +
' continue i;' +
' } else {' +
' break i;' +
' }' +
'}' +
'try {' +
'} catch (f) {' +
'} finally {' +
'}' +
'(function g(h) {' +
'}());' +
'void [{' +
' i: 42,' +
' "j": 42,' +
' \'k\': 42' +
'}];' +
'void ["abcdefghijklmnopqrstuvwxyz"];',
sOutput:
'/*jshint shadow:true */' +
'var a;' +
'function b(i) {' +
'}' +
'for (var c; 0 === Math.random(););' +
'for (var d in {});' +
'(function() {' +
' var i = "abcdefghijklmnopqrstuvwxyz";' +
' void [i];' +
' void [b(a), b(c), b(d)];' +
' void [typeof e];' +
' i: for (; 0 === Math.random();) {' +
' if (42 === (new Date()).getMinutes()) {' +
' continue i;' +
' } else {' +
' break i;' +
' }' +
' }' +
' try {' +
' } catch (f) {' +
' } finally {' +
' }' +
' (function g(h) {' +
' }());' +
' void [{' +
' i: 42,' +
' "j": 42,' +
' \'k\': 42' +
' }];' +
' void [i];' +
'}());'
},
{
sTitle:
'Preservation of identifier names in nested function code.',
sInput:
'(function() {' +
' void ["abcdefghijklmnopqrstuvwxyz"];' +
' (function() {' +
' var a;' +
' for (var b; 0 === Math.random(););' +
' for (var c in {});' +
' void [typeof d];' +
' h: for (; 0 === Math.random();) {' +
' if (42 === (new Date()).getMinutes()) {' +
' continue h;' +
' } else {' +
' break h;' +
' }' +
' }' +
' try {' +
' } catch (e) {' +
' } finally {' +
' }' +
' (function f(g) {' +
' }());' +
' void [{' +
' h: 42,' +
' "i": 42,' +
' \'j\': 42' +
' }];' +
' }());' +
' void ["abcdefghijklmnopqrstuvwxyz"];' +
'}());',
sOutput:
'(function() {' +
' var h = "abcdefghijklmnopqrstuvwxyz";' +
' void [h];' +
' (function() {' +
' var a;' +
' for (var b; 0 === Math.random(););' +
' for (var c in {});' +
' void [typeof d];' +
' h: for (; 0 === Math.random();) {' +
' if (42 === (new Date()).getMinutes()) {' +
' continue h;' +
' } else {' +
' break h;' +
' }' +
' }' +
' try {' +
' } catch (e) {' +
' } finally {' +
' }' +
' (function f(g) {' +
' }());' +
' void [{' +
' h: 42,' +
' "i": 42,' +
' \'j\': 42' +
' }];' +
' }());' +
' void [h];' +
'}());'
},
{
sTitle:
'Consolidation of a closure with other source elements.',
sInput:
'(function(foo) {' +
'}("abcdefghijklmnopqrstuvwxyz"));' +
'void ["abcdefghijklmnopqrstuvwxyz"];',
sOutput:
'(function() {' +
' var a = "abcdefghijklmnopqrstuvwxyz";' +
' (function(foo) {' +
' })(a);' +
' void [a];' +
'}());'
},
{
sTitle:
'Consolidation of function code instead of a sole closure.',
sInput:
'(function(foo, bar) {' +
' void ["abcdefghijklmnopqrstuvwxyz",' +
' "abcdefghijklmnopqrstuvwxyz"];' +
'}("abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz"));',
sOutput:
'(function(foo, bar) {' +
' var a = "abcdefghijklmnopqrstuvwxyz";' +
' void [a, a];' +
'}("abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz"));'
},
// 11.1.5 Object Initialiser.
{
sTitle:
'Preservation of property names of an object initialiser.',
sInput:
'var foo = {' +
' abcdefghijklmnopqrstuvwxyz: 42,' +
' "zyxwvutsrqponmlkjihgfedcba": 42,' +
' \'mlkjihgfedcbanopqrstuvwxyz\': 42' +
'};' +
'void [' +
' foo.abcdefghijklmnopqrstuvwxyz,' +
' "zyxwvutsrqponmlkjihgfedcba",' +
' \'mlkjihgfedcbanopqrstuvwxyz\'' +
'];'
},
{
sTitle:
'Evaluation with regard to String values derived from identifier ' +
'names used as property accessors.',
sInput:
'(function() {' +
' var foo;' +
' void [' +
' Math.abcdefghij,' +
' Math.abcdefghij,' +
' Math.abcdefghi,' +
' Math.abcdefghi' +
' ];' +
'}());',
sOutput:
'(function() {' +
' var a = "abcdefghij", foo;' +
' void [' +
' Math[a],' +
' Math[a],' +
' Math.abcdefghi,' +
' Math.abcdefghi' +
' ];' +
'}());'
},
// 11.2.1 Property Accessors.
{
sTitle:
'Preservation of identifiers in the nonterminal MemberExpression.',
sInput:
'void [' +
' Math.E,' +
' Math.LN10,' +
' Math.LN2,' +
' Math.LOG2E,' +
' Math.LOG10E,' +
' Math.PI,' +
' Math.SQRT1_2,' +
' Math.SQRT2,' +
' Math.abs,' +
' Math.acos' +
'];'
},
// 12.2 Variable Statement.
{
sTitle:
'Preservation of the identifier of a variable that is being ' +
'declared in a variable statement.',
sInput:
'(function() {' +
' var abcdefghijklmnopqrstuvwxyz;' +
' void [abcdefghijklmnopqrstuvwxyz];' +
'}());'
},
{
sTitle:
'Exclusion of a variable statement in global code.',
sInput:
'void ["abcdefghijklmnopqrstuvwxyz"];' +
'var foo = "abcdefghijklmnopqrstuvwxyz",' +
' bar = "abcdefghijklmnopqrstuvwxyz";' +
'void ["abcdefghijklmnopqrstuvwxyz"];'
},
{
sTitle:
'Exclusion of a variable statement in function code that ' +
'contains a with statement.',
sInput:
'(function() {' +
' with ({});' +
' void ["abcdefghijklmnopqrstuvwxyz"];' +
' var foo;' +
' void ["abcdefghijklmnopqrstuvwxyz"];' +
'}());'
},
{
sTitle:
'Exclusion of a variable statement in function code that ' +
'contains a direct call to the eval function.',
sInput:
'/*jshint evil:true */' +
'void [' +
' function() {' +
' eval("");' +
' void ["abcdefghijklmnopqrstuvwxyz"];' +
' var foo;' +
' void ["abcdefghijklmnopqrstuvwxyz"];' +
' }' +
'];'
},
{
sTitle:
'Consolidation within a variable statement in global code.',
sInput:
'var foo = function() {' +
' void ["abcdefghijklmnopqrstuvwxyz",' +
' "abcdefghijklmnopqrstuvwxyz"];' +
'};',
sOutput:
'var foo = function() {' +
' var a = "abcdefghijklmnopqrstuvwxyz";' +
' void [a, a];' +
'};'
},
{
sTitle:
'Consolidation within a variable statement excluded in function ' +
'code due to the presence of a with statement.',
sInput:
'(function() {' +
' with ({});' +
' var foo = function() {' +
' void ["abcdefghijklmnopqrstuvwxyz",' +
' "abcdefghijklmnopqrstuvwxyz"];' +
' };' +
'}());',
sOutput:
'(function() {' +
' with ({});' +
' var foo = function() {' +
' var a = "abcdefghijklmnopqrstuvwxyz";' +
' void [a, a];' +
' };' +
'}());'
},
{
sTitle:
'Consolidation within a variable statement excluded in function ' +
'code due to the presence of a direct call to the eval function.',
sInput:
'/*jshint evil:true */' +
'(function() {' +
' eval("");' +
' var foo = function() {' +
' void ["abcdefghijklmnopqrstuvwxyz",' +
' "abcdefghijklmnopqrstuvwxyz"];' +
' };' +
'}());',
sOutput:
'/*jshint evil:true */' +
'(function() {' +
' eval("");' +
' var foo = function() {' +
' var a = "abcdefghijklmnopqrstuvwxyz";' +
' void [a, a];' +
' };' +
'}());'
},
{
sTitle:
'Inclusion of a variable statement in function code that ' +
'contains no with statement and no direct call to the eval ' +
'function.',
sInput:
'(function() {' +
' void ["abcdefghijklmnopqrstuvwxyz"];' +
' var foo;' +
' void ["abcdefghijklmnopqrstuvwxyz"];' +
'}());',
sOutput:
'(function() {' +
' var a = "abcdefghijklmnopqrstuvwxyz";' +
' void [a];' +
' var foo;' +
' void [a];' +
'}());'
},
{
sTitle:
'Ignorance with regard to a variable statement in global code.',
sInput:
'var foo = "abcdefghijklmnopqrstuvwxyz";' +
'void ["abcdefghijklmnopqrstuvwxyz",' +
' "abcdefghijklmnopqrstuvwxyz"];',
sOutput:
'var foo = "abcdefghijklmnopqrstuvwxyz";' +
'(function() {' +
' var a = "abcdefghijklmnopqrstuvwxyz";' +
' void [a, a];' +
'}());'
},
// 12.4 Expression Statement.
{
sTitle:
'Preservation of identifiers in an expression statement.',
sInput:
'void [typeof abcdefghijklmnopqrstuvwxyz,' +
' typeof abcdefghijklmnopqrstuvwxyz];'
},
// 12.6.3 The {@code for} Statement.
{
sTitle:
'Preservation of identifiers in the variable declaration list of ' +
'a for statement.',
sInput:
'for (var abcdefghijklmnopqrstuvwxyz; 0 === Math.random(););' +
'for (var abcdefghijklmnopqrstuvwxyz; 0 === Math.random(););'
},
// 12.6.4 The {@code for-in} Statement.
{
sTitle:
'Preservation of identifiers in the variable declaration list of ' +
'a for-in statement.',
sInput:
'for (var abcdefghijklmnopqrstuvwxyz in {});' +
'for (var abcdefghijklmnopqrstuvwxyz in {});'
},
// 12.7 The {@code continue} Statement.
{
sTitle:
'Preservation of the identifier in a continue statement.',
sInput:
'abcdefghijklmnopqrstuvwxyz: for (; 0 === Math.random();) {' +
' continue abcdefghijklmnopqrstuvwxyz;' +
'}' +
'abcdefghijklmnopqrstuvwxyz: for (; 0 === Math.random();) {' +
' continue abcdefghijklmnopqrstuvwxyz;' +
'}'
},
// 12.8 The {@code break} Statement.
{
sTitle:
'Preservation of the identifier in a break statement.',
sInput:
'abcdefghijklmnopqrstuvwxyz: for (; 0 === Math.random();) {' +
' break abcdefghijklmnopqrstuvwxyz;' +
'}' +
'abcdefghijklmnopqrstuvwxyz: for (; 0 === Math.random();) {' +
' break abcdefghijklmnopqrstuvwxyz;' +
'}'
},
// 12.9 The {@code return} Statement.
{
sTitle:
'Exclusion of a return statement in function code that contains ' +
'a with statement.',
sInput:
'(function() {' +
' with ({});' +
' void ["abcdefghijklmnopqrstuvwxyz"];' +
' if (0 === Math.random()) {' +
' return;' +
' } else {' +
' }' +
' void ["abcdefghijklmnopqrstuvwxyz"];' +
'}());'
},
{
sTitle:
'Exclusion of a return statement in function code that contains ' +
'a direct call to the eval function.',
sInput:
'/*jshint evil:true */' +
'(function() {' +
' eval("");' +
' void ["abcdefghijklmnopqrstuvwxyz"];' +
' if (0 === Math.random()) {' +
' return;' +
' } else {' +
' }' +
' void ["abcdefghijklmnopqrstuvwxyz"];' +
'}());'
},
{
sTitle:
'Consolidation within a return statement excluded in function ' +
'code due to the presence of a with statement.',
sInput:
'(function() {' +
' with ({});' +
' return function() {' +
' void ["abcdefghijklmnopqrstuvwxyz",' +
' "abcdefghijklmnopqrstuvwxyz"];' +
' };' +
'}());',
sOutput:
'(function() {' +
' with ({});' +
' return function() {' +
' var a = "abcdefghijklmnopqrstuvwxyz";' +
' void [a, a];' +
' };' +
'}());'
},
{
sTitle:
'Consolidation within a return statement excluded in function ' +
'code due to the presence of a direct call to the eval function.',
sInput:
'/*jshint evil:true */' +
'(function() {' +
' eval("");' +
' return function() {' +
' void ["abcdefghijklmnopqrstuvwxyz",' +
' "abcdefghijklmnopqrstuvwxyz"];' +
' };' +
'}());',
sOutput:
'/*jshint evil:true */' +
'(function() {' +
' eval("");' +
' return function() {' +
' var a = "abcdefghijklmnopqrstuvwxyz";' +
' void [a, a];' +
' };' +
'}());'
},
{
sTitle:
'Inclusion of a return statement in function code that contains ' +
'no with statement and no direct call to the eval function.',
sInput:
'(function() {' +
' void ["abcdefghijklmnopqrstuvwxyz"];' +
' if (0 === Math.random()) {' +
' return;' +
' } else {' +
' }' +
' void ["abcdefghijklmnopqrstuvwxyz"];' +
'}());',
sOutput:
'(function() {' +
' var a = "abcdefghijklmnopqrstuvwxyz";' +
' void [a];' +
' if (0 === Math.random()) {' +
' return;' +
' } else {' +
' }' +
' void [a];' +
'}());'
},
// 12.10 The {@code with} Statement.
{
sTitle:
'Preservation of the statement in a with statement.',
sInput:
'with ({}) {' +
' void ["abcdefghijklmnopqrstuvwxyz",' +
' "abcdefghijklmnopqrstuvwxyz"];' +
'}'
},
{
sTitle:
'Exclusion of a with statement in the same syntactic code unit.',
sInput:
'void ["abcdefghijklmnopqrstuvwxyz"];' +
'with ({' +
' foo: "abcdefghijklmnopqrstuvwxyz",' +
' bar: "abcdefghijklmnopqrstuvwxyz"' +
'}) {' +
' void ["abcdefghijklmnopqrstuvwxyz",' +
' "abcdefghijklmnopqrstuvwxyz"];' +
'}' +
'void ["abcdefghijklmnopqrstuvwxyz"];'
},
{
sTitle:
'Exclusion of a with statement in nested function code.',
sInput:
'void ["abcdefghijklmnopqrstuvwxyz"];' +
'(function() {' +
' with ({' +
' foo: "abcdefghijklmnopqrstuvwxyz",' +
' bar: "abcdefghijklmnopqrstuvwxyz"' +
' }) {' +
' void ["abcdefghijklmnopqrstuvwxyz",' +
' "abcdefghijklmnopqrstuvwxyz"];' +
' }' +
'}());' +
'void ["abcdefghijklmnopqrstuvwxyz"];'
},
// 12.12 Labelled Statements.
{
sTitle:
'Preservation of the label of a labelled statement.',
sInput:
'abcdefghijklmnopqrstuvwxyz: for (; 0 === Math.random(););' +
'abcdefghijklmnopqrstuvwxyz: for (; 0 === Math.random(););'
},
// 12.14 The {@code try} Statement.
{
sTitle:
'Preservation of the identifier in the catch clause of a try' +
'statement.',
sInput:
'try {' +
'} catch (abcdefghijklmnopqrstuvwxyz) {' +
'} finally {' +
'}' +
'try {' +
'} catch (abcdefghijklmnopqrstuvwxyz) {' +
'} finally {' +
'}'
},
// 13 Function Definition.
{
sTitle:
'Preservation of the identifier of a function declaration.',
sInput:
'function abcdefghijklmnopqrstuvwxyz() {' +
'}' +
'void [abcdefghijklmnopqrstuvwxyz];'
},
{
sTitle:
'Preservation of the identifier of a function expression.',
sInput:
'void [' +
' function abcdefghijklmnopqrstuvwxyz() {' +
' },' +
' function abcdefghijklmnopqrstuvwxyz() {' +
' }' +
'];'
},
{
sTitle:
'Preservation of a formal parameter of a function declaration.',
sInput:
'function foo(abcdefghijklmnopqrstuvwxyz) {' +
'}' +
'function bar(abcdefghijklmnopqrstuvwxyz) {' +
'}'
},
{
sTitle:
'Preservation of a formal parameter in a function expression.',
sInput:
'void [' +
' function(abcdefghijklmnopqrstuvwxyz) {' +
' },' +
' function(abcdefghijklmnopqrstuvwxyz) {' +
' }' +
'];'
},
{
sTitle:
'Exclusion of a function declaration.',
sInput:
'void ["abcdefghijklmnopqrstuvwxyz"];' +
'function foo() {' +
'}' +
'void ["abcdefghijklmnopqrstuvwxyz"];'
},
{
sTitle:
'Consolidation within a function declaration.',
sInput:
'function foo() {' +
' void ["abcdefghijklmnopqrstuvwxyz",' +
' "abcdefghijklmnopqrstuvwxyz"];' +
'}',
sOutput:
'function foo() {' +
' var a = "abcdefghijklmnopqrstuvwxyz";' +
' void [a, a];' +
'}'
},
// 14 Program.
{
sTitle:
'Preservation of a program without source elements.',
sInput:
''
},
// 14.1 Directive Prologues and the Use Strict Directive.
{
sTitle:
'Preservation of a Directive Prologue in global code.',
sInput:
'"abcdefghijklmnopqrstuvwxyz";' +
'\'zyxwvutsrqponmlkjihgfedcba\';'
},
{
sTitle:
'Preservation of a Directive Prologue in a function declaration.',
sInput:
'function foo() {' +
' "abcdefghijklmnopqrstuvwxyz";' +
' \'zyxwvutsrqponmlkjihgfedcba\';' +
'}'
},
{
sTitle:
'Preservation of a Directive Prologue in a function expression.',
sInput:
'void [' +
' function() {' +
' "abcdefghijklmnopqrstuvwxyz";' +
' \'zyxwvutsrqponmlkjihgfedcba\';' +
' }' +
'];'
},
{
sTitle:
'Ignorance with regard to a Directive Prologue in global code.',
sInput:
'"abcdefghijklmnopqrstuvwxyz";' +
'void ["abcdefghijklmnopqrstuvwxyz",' +
' "abcdefghijklmnopqrstuvwxyz"];',
sOutput:
'"abcdefghijklmnopqrstuvwxyz";' +
'(function() {' +
' var a = "abcdefghijklmnopqrstuvwxyz";' +
' void [a, a];' +
'}());'
},
{
sTitle:
'Ignorance with regard to a Directive Prologue in a function' +
'declaration.',
sInput:
'function foo() {' +
' "abcdefghijklmnopqrstuvwxyz";' +
' void ["abcdefghijklmnopqrstuvwxyz",' +
' "abcdefghijklmnopqrstuvwxyz"];' +
'}',
sOutput:
'function foo() {' +
' "abcdefghijklmnopqrstuvwxyz";' +
' var a = "abcdefghijklmnopqrstuvwxyz";' +
' void [a, a];' +
'}'
},
{
sTitle:
'Ignorance with regard to a Directive Prologue in a function' +
'expression.',
sInput:
'(function() {' +
' "abcdefghijklmnopqrstuvwxyz";' +
' void ["abcdefghijklmnopqrstuvwxyz",' +
' "abcdefghijklmnopqrstuvwxyz"];' +
'}());',
sOutput:
'(function() {' +
' "abcdefghijklmnopqrstuvwxyz";' +
' var a = "abcdefghijklmnopqrstuvwxyz";' +
' void [a, a];' +
'}());'
},
// 15.1 The Global Object.
{
sTitle:
'Preservation of a property of the global object.',
sInput:
'void [undefined, undefined, undefined, undefined, undefined];'
},
// 15.1.2.1.1 Direct Call to Eval.
{
sTitle:
'Exclusion of a direct call to the eval function in the same ' +
'syntactic code unit.',
sInput:
'/*jshint evil:true */' +
'void ["abcdefghijklmnopqrstuvwxyz"];' +
'eval("");' +
'void ["abcdefghijklmnopqrstuvwxyz"];'
},
{
sTitle:
'Exclusion of a direct call to the eval function in nested ' +
'function code.',
sInput:
'/*jshint evil:true */' +
'void ["abcdefghijklmnopqrstuvwxyz"];' +
'(function() {' +
' eval("");' +
'}());' +
'void ["abcdefghijklmnopqrstuvwxyz"];'
},
{
sTitle:
'Consolidation within a direct call to the eval function.',
sInput:
'/*jshint evil:true */' +
'eval(function() {' +
' void ["abcdefghijklmnopqrstuvwxyz",' +
' "abcdefghijklmnopqrstuvwxyz"];' +
'}());',
sOutput:
'/*jshint evil:true */' +
'eval(function() {' +
' var a = "abcdefghijklmnopqrstuvwxyz";' +
' void [a, a];' +
'}());'
},
// Consolidation proper.
{
sTitle:
'No consolidation if it does not result in a reduction of the ' +
'number of source characters.',
sInput:
'(function() {' +
' var foo;' +
' void ["ab", "ab", "abc", "abc"];' +
'}());'
},
{
sTitle:
'Identification of a range of source elements at the beginning ' +
'of global code.',
sInput:
'/*jshint evil:true */' +
'"abcdefghijklmnopqrstuvwxyz";' +
'void ["abcdefghijklmnopqrstuvwxyz",' +
' "abcdefghijklmnopqrstuvwxyz"];' +
'eval("");',
sOutput:
'/*jshint evil:true */' +
'"abcdefghijklmnopqrstuvwxyz";' +
'(function() {' +
' var a = "abcdefghijklmnopqrstuvwxyz";' +
' void [a, a];' +
'}());' +
'eval("");'
},
{
sTitle:
'Identification of a range of source elements in the middle of ' +
'global code.',
sInput:
'/*jshint evil:true */' +
'"abcdefghijklmnopqrstuvwxyz";' +
'eval("");' +
'void ["abcdefghijklmnopqrstuvwxyz",' +
' "abcdefghijklmnopqrstuvwxyz"];' +
'eval("");',
sOutput:
'/*jshint evil:true */' +
'"abcdefghijklmnopqrstuvwxyz";' +
'eval("");' +
'(function() {' +
' var a = "abcdefghijklmnopqrstuvwxyz";' +
' void [a, a];' +
'}());' +
'eval("");'
},
{
sTitle:
'Identification of a range of source elements at the end of ' +
'global code.',
sInput:
'/*jshint evil:true */' +
'"abcdefghijklmnopqrstuvwxyz";' +
'eval("");' +
'void ["abcdefghijklmnopqrstuvwxyz",' +
' "abcdefghijklmnopqrstuvwxyz"];',
sOutput:
'/*jshint evil:true */' +
'"abcdefghijklmnopqrstuvwxyz";' +
'eval("");' +
'(function() {' +
' var a = "abcdefghijklmnopqrstuvwxyz";' +
' void [a, a];' +
'}());'
},
{
sTitle:
'Identification of a range of source elements at the beginning ' +
'of function code.',
sInput:
'/*jshint evil:true */' +
'(function() {' +
' "abcdefghijklmnopqrstuvwxyz";' +
' void ["abcdefghijklmnopqrstuvwxyz",' +
' "abcdefghijklmnopqrstuvwxyz"];' +
' eval("");' +
'}());',
sOutput:
'/*jshint evil:true */' +
'(function() {' +
' "abcdefghijklmnopqrstuvwxyz";' +
' (function() {' +
' var a = "abcdefghijklmnopqrstuvwxyz";' +
' void [a, a];' +
' }());' +
' eval("");' +
'}());'
},
{
sTitle:
'Identification of a range of source elements in the middle of ' +
'function code.',
sInput:
'/*jshint evil:true */' +
'(function() {' +
' "abcdefghijklmnopqrstuvwxyz";' +
' eval("");' +
' void ["abcdefghijklmnopqrstuvwxyz",' +
' "abcdefghijklmnopqrstuvwxyz"];' +
' eval("");' +
'}());',
sOutput:
'/*jshint evil:true */' +
'(function() {' +
' "abcdefghijklmnopqrstuvwxyz";' +
' eval("");' +
' (function() {' +
' var a = "abcdefghijklmnopqrstuvwxyz";' +
' void [a, a];' +
' }());' +
' eval("");' +
'}());'
},
{
sTitle:
'Identification of a range of source elements at the end of ' +
'function code.',
sInput:
'/*jshint evil:true */' +
'(function() {' +
' "abcdefghijklmnopqrstuvwxyz";' +
' eval("");' +
' void ["abcdefghijklmnopqrstuvwxyz",' +
' "abcdefghijklmnopqrstuvwxyz"];' +
'}());',
sOutput:
'/*jshint evil:true */' +
'(function() {' +
' "abcdefghijklmnopqrstuvwxyz";' +
' eval("");' +
' (function() {' +
' var a = "abcdefghijklmnopqrstuvwxyz";' +
' void [a, a];' +
' }());' +
'}());'
},
{
sTitle:
'Evaluation with regard to String values of String literals and ' +
'String values derived from identifier names used as property' +
'accessors.',
sInput:
'(function() {' +
' var foo;' +
' void ["abcdefg", Math.abcdefg, "abcdef", Math.abcdef];' +
'}());',
sOutput:
'(function() {' +
' var a = "abcdefg", foo;' +
' void [a, Math[a], "abcdef", Math.abcdef];' +
'}());'
},
{
sTitle:
'Evaluation with regard to the necessity of adding a variable ' +
'statement.',
sInput:
'/*jshint evil:true */' +
'(function() {' +
' void ["abcdefgh", "abcdefgh"];' +
'}());' +
'eval("");' +
'(function() {' +
' void ["abcdefg", "abcdefg"];' +
'}());' +
'eval("");' +
'(function() {' +
' var foo;' +
' void ["abcd", "abcd"];' +
'}());',
sOutput:
'/*jshint evil:true */' +
'(function() {' +
' var a = "abcdefgh";' +
' void [a, a];' +
'}());' +
'eval("");' +
'(function() {' +
' void ["abcdefg", "abcdefg"];' +
'}());' +
'eval("");' +
'(function() {' +
' var a = "abcd", foo;' +
' void [a, a];' +
'}());'
},
{
sTitle:
'Evaluation with regard to the necessity of enclosing source ' +
'elements.',
sInput:
'/*jshint evil:true */' +
'void ["abcdefghijklmnopqrstuvwxy", "abcdefghijklmnopqrstuvwxy"];' +
'eval("");' +
'void ["abcdefghijklmnopqrstuvwx", "abcdefghijklmnopqrstuvwx"];' +
'eval("");' +
'(function() {' +
' void ["abcdefgh", "abcdefgh"];' +
'}());' +
'(function() {' +
' void ["abcdefghijklmnopqrstuvwxy",' +
' "abcdefghijklmnopqrstuvwxy"];' +
' eval("");' +
' void ["abcdefghijklmnopqrstuvwx",' +
' "abcdefghijklmnopqrstuvwx"];' +
' eval("");' +
' (function() {' +
' void ["abcdefgh", "abcdefgh"];' +
' }());' +
'}());',
sOutput:
'/*jshint evil:true */' +
'(function() {' +
' var a = "abcdefghijklmnopqrstuvwxy";' +
' void [a, a];' +
'}());' +
'eval("");' +
'void ["abcdefghijklmnopqrstuvwx", "abcdefghijklmnopqrstuvwx"];' +
'eval("");' +
'(function() {' +
' var a = "abcdefgh";' +
' void [a, a];' +
'}());' +
'(function() {' +
' (function() {' +
' var a = "abcdefghijklmnopqrstuvwxy";' +
' void [a, a];' +
' }());' +
' eval("");' +
' void ["abcdefghijklmnopqrstuvwx", "abcdefghijklmnopqrstuvwx"];' +
' eval("");' +
' (function() {' +
' var a = "abcdefgh";' +
' void [a, a];' +
' }());' +
'}());'
},
{
sTitle:
'Employment of a closure while consolidating in global code.',
sInput:
'void ["abcdefghijklmnopqrstuvwxyz",' +
' "abcdefghijklmnopqrstuvwxyz"];',
sOutput:
'(function() {' +
' var a = "abcdefghijklmnopqrstuvwxyz";' +
' void [a, a];' +
'}());'
},
{
sTitle:
'Assignment of a shorter identifier to a value whose ' +
'consolidation results in a greater reduction of the number of ' +
'source characters.',
sInput:
'(function() {' +
' var b, c, d, e, f, g, h, i, j, k, l, m,' +
' n, o, p, q, r, s, t, u, v, w, x, y, z,' +
' A, B, C, D, E, F, G, H, I, J, K, L, M,' +
' N, O, P, Q, R, S, T, U, V, W, X, Y, Z,' +
' $, _;' +
' void ["abcde", "abcde", "edcba", "edcba", "edcba"];' +
'}());',
sOutput:
'(function() {' +
' var a = "edcba",' +
' b, c, d, e, f, g, h, i, j, k, l, m,' +
' n, o, p, q, r, s, t, u, v, w, x, y, z,' +
' A, B, C, D, E, F, G, H, I, J, K, L, M,' +
' N, O, P, Q, R, S, T, U, V, W, X, Y, Z,' +
' $, _;' +
' void ["abcde", "abcde", a, a, a];' +
'}());'
}
].forEach(cAssert);
process.exit(bTestsPassed ? 0 : 1);