requirejs-rails 0.7.2 → 0.7.3

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ # v0.7.3
2
+
3
+ - Upgrade RequireJS and r.js to v1.0.8
4
+
1
5
  # v0.7.2
2
6
 
3
7
  - Add require.js to config.assets.precompile in all environments. Closes #45.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- requirejs-rails (0.7.2)
4
+ requirejs-rails (0.7.3)
5
5
  railties (>= 3.1.1, < 3.3)
6
6
 
7
7
  GEM
data/bin/r.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license r.js 1.0.7 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
2
+ * @license r.js 1.0.8 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
3
3
  * Available via the MIT or new BSD license.
4
4
  * see: http://github.com/jrburke/requirejs for details
5
5
  */
@@ -11,16 +11,16 @@
11
11
  * the shell of the r.js file.
12
12
  */
13
13
 
14
- /*jslint strict: false, evil: true, nomen: false */
14
+ /*jslint evil: true, nomen: true */
15
15
  /*global readFile: true, process: false, Packages: false, print: false,
16
- console: false, java: false, module: false */
16
+ console: false, java: false, module: false, requirejsVars */
17
17
 
18
18
  var requirejs, require, define;
19
19
  (function (console, args, readFileFunc) {
20
20
 
21
21
  var fileName, env, fs, vm, path, exec, rhinoContext, dir, nodeRequire,
22
22
  nodeDefine, exists, reqMain, loadedOptimizedLib,
23
- version = '1.0.7',
23
+ version = '1.0.8',
24
24
  jsSuffixRegExp = /\.js$/,
25
25
  commandOption = '',
26
26
  useLibLoaded = {},
@@ -102,7 +102,7 @@ var requirejs, require, define;
102
102
  }
103
103
 
104
104
  /** vim: et:ts=4:sw=4:sts=4
105
- * @license RequireJS 1.0.7 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
105
+ * @license RequireJS 1.0.8 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
106
106
  * Available via the MIT or new BSD license.
107
107
  * see: http://github.com/jrburke/requirejs for details
108
108
  */
@@ -110,9 +110,9 @@ var requirejs, require, define;
110
110
  /*global window, navigator, document, importScripts, jQuery, setTimeout, opera */
111
111
 
112
112
 
113
- (function () {
113
+ (function (undefined) {
114
114
  //Change this version number for each release.
115
- var version = "1.0.7",
115
+ var version = "1.0.8",
116
116
  commentRegExp = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,
117
117
  cjsRequireRegExp = /require\(\s*["']([^'"\s]+)["']\s*\)/g,
118
118
  currDirRegExp = /^\.\//,
@@ -526,18 +526,19 @@ var requirejs, require, define;
526
526
  fullName = map.fullName,
527
527
  args = manager.deps,
528
528
  listeners = manager.listeners,
529
+ execCb = config.requireExecCb || req.execCb,
529
530
  cjsModule;
530
531
 
531
532
  //Call the callback to define the module, if necessary.
532
533
  if (cb && isFunction(cb)) {
533
534
  if (config.catchError.define) {
534
535
  try {
535
- ret = req.execCb(fullName, manager.callback, args, defined[fullName]);
536
+ ret = execCb(fullName, manager.callback, args, defined[fullName]);
536
537
  } catch (e) {
537
538
  err = e;
538
539
  }
539
540
  } else {
540
- ret = req.execCb(fullName, manager.callback, args, defined[fullName]);
541
+ ret = execCb(fullName, manager.callback, args, defined[fullName]);
541
542
  }
542
543
 
543
544
  if (fullName) {
@@ -1277,7 +1278,7 @@ var requirejs, require, define;
1277
1278
  } else {
1278
1279
  //Regular dependency.
1279
1280
  if (!urlFetched[url] && !loaded[fullName]) {
1280
- req.load(context, fullName, url);
1281
+ (config.requireLoad || req.load)(context, fullName, url);
1281
1282
 
1282
1283
  //Mark the URL as fetched, but only if it is
1283
1284
  //not an empty: URL, used by the optimizer.
@@ -1581,7 +1582,8 @@ var requirejs, require, define;
1581
1582
  moduleName = normalize(moduleName, relModuleMap && relModuleMap.fullName);
1582
1583
 
1583
1584
  //If a colon is in the URL, it indicates a protocol is used and it is just
1584
- //an URL to a file, or if it starts with a slash or ends with .js, it is just a plain file.
1585
+ //an URL to a file, or if it starts with a slash, contains a query arg (i.e. ?)
1586
+ //or ends with .js, then assume the user meant to use an url and not a module id.
1585
1587
  //The slash is important for protocol-less URLs as well as full paths.
1586
1588
  if (req.jsExtRegExp.test(moduleName)) {
1587
1589
  //Just a plain path, not module name lookup, so just return it.
@@ -1617,7 +1619,7 @@ var requirejs, require, define;
1617
1619
 
1618
1620
  //Join the path parts together, then figure out if baseUrl is needed.
1619
1621
  url = syms.join("/") + (ext || ".js");
1620
- url = (url.charAt(0) === '/' || url.match(/^\w+:/) ? "" : config.baseUrl) + url;
1622
+ url = (url.charAt(0) === '/' || url.match(/^[\w\+\.\-]+:/) ? "" : config.baseUrl) + url;
1621
1623
  }
1622
1624
 
1623
1625
  return config.urlArgs ? url +
@@ -1981,7 +1983,15 @@ var requirejs, require, define;
1981
1983
  //https://connect.microsoft.com/IE/feedback/details/648057/script-onload-event-is-not-fired-immediately-after-script-execution
1982
1984
  //UNFORTUNATELY Opera implements attachEvent but does not follow the script
1983
1985
  //script execution mode.
1984
- if (node.attachEvent && !isOpera) {
1986
+ if (node.attachEvent &&
1987
+ // check if node.attachEvent is artificially added by custom script or
1988
+ // natively supported by browser
1989
+ // read https://github.com/jrburke/requirejs/issues/187
1990
+ // if we can NOT find [native code] then it must NOT natively supported.
1991
+ // in IE8, node.attachEvent does not have toString()
1992
+ // TODO: a better way to check interactive mode
1993
+ !(node.attachEvent.toString && node.attachEvent.toString().indexOf('[native code]') < 0) &&
1994
+ !isOpera) {
1985
1995
  //Probably IE. IE (at least 6-8) do not fire
1986
1996
  //script onload right after executing the script, so
1987
1997
  //we cannot tie the anonymous define call to a name.
@@ -2247,7 +2257,7 @@ var requirejs, require, define;
2247
2257
  '\n}(requirejsVars.require, requirejsVars.requirejs, requirejsVars.define));';
2248
2258
  };
2249
2259
 
2250
- req.load = function (context, moduleName, url) {
2260
+ requirejsVars.nodeLoad = req.load = function (context, moduleName, url) {
2251
2261
  var contents, err;
2252
2262
 
2253
2263
  //Indicate a the module is in process of loading.
@@ -2293,6 +2303,9 @@ var requirejs, require, define;
2293
2303
  text = req.makeNodeWrapper(text);
2294
2304
  return eval(text);
2295
2305
  };
2306
+
2307
+ //Hold on to the original execCb to use in useLib calls.
2308
+ requirejsVars.nodeRequireExecCb = require.execCb;
2296
2309
  }());
2297
2310
 
2298
2311
  }
@@ -2356,6 +2369,40 @@ var requirejs, require, define;
2356
2369
  }
2357
2370
  });
2358
2371
  }());
2372
+ if(env === 'node') {
2373
+ /**
2374
+ * @license RequireJS Copyright (c) 2012, The Dojo Foundation All Rights Reserved.
2375
+ * Available via the MIT or new BSD license.
2376
+ * see: http://github.com/jrburke/requirejs for details
2377
+ */
2378
+
2379
+ /*jslint strict: false */
2380
+ /*global define: false, load: false */
2381
+
2382
+ //Needed so that rhino/assert can return a stub for uglify's consolidator.js
2383
+ define('node/assert', ['assert'], function (assert) {
2384
+ return assert;
2385
+ });
2386
+
2387
+ }
2388
+
2389
+ if(env === 'rhino') {
2390
+ /**
2391
+ * @license RequireJS Copyright (c) 2012, The Dojo Foundation All Rights Reserved.
2392
+ * Available via the MIT or new BSD license.
2393
+ * see: http://github.com/jrburke/requirejs for details
2394
+ */
2395
+
2396
+ /*jslint strict: false */
2397
+ /*global define: false, load: false */
2398
+
2399
+ //Just a stub for use with uglify's consolidator.js
2400
+ define('rhino/assert', function () {
2401
+ return {};
2402
+ });
2403
+
2404
+ }
2405
+
2359
2406
  if(env === 'node') {
2360
2407
  /**
2361
2408
  * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
@@ -3149,7 +3196,2610 @@ define('logger', ['env!env/print'], function (print) {
3149
3196
  //so that the build does not attempt to inline some env modules,
3150
3197
  //like Node's fs and path.
3151
3198
 
3152
- define('uglifyjs/parse-js', ["require", "exports", "module"], function(require, exports, module) {
3199
+ define('uglifyjs/consolidator', ["require", "exports", "module", "env!env/assert", "./parse-js", "./process"], function(require, exports, module, assert) {
3200
+
3201
+ /**
3202
+ * @preserve Copyright 2012 Robert Gust-Bardon <http://robert.gust-bardon.org/>.
3203
+ * All rights reserved.
3204
+ *
3205
+ * Redistribution and use in source and binary forms, with or without
3206
+ * modification, are permitted provided that the following conditions
3207
+ * are met:
3208
+ *
3209
+ * * Redistributions of source code must retain the above
3210
+ * copyright notice, this list of conditions and the following
3211
+ * disclaimer.
3212
+ *
3213
+ * * Redistributions in binary form must reproduce the above
3214
+ * copyright notice, this list of conditions and the following
3215
+ * disclaimer in the documentation and/or other materials
3216
+ * provided with the distribution.
3217
+ *
3218
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
3219
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3220
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
3221
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
3222
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
3223
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
3224
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
3225
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3226
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
3227
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
3228
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3229
+ * SUCH DAMAGE.
3230
+ */
3231
+
3232
+ /**
3233
+ * @fileoverview Enhances <a href="https://github.com/mishoo/UglifyJS/"
3234
+ * >UglifyJS</a> with consolidation of null, Boolean, and String values.
3235
+ * <p>Also known as aliasing, this feature has been deprecated in <a href=
3236
+ * "http://closure-compiler.googlecode.com/">the Closure Compiler</a> since its
3237
+ * initial release, where it is unavailable from the <abbr title=
3238
+ * "command line interface">CLI</a>. The Closure Compiler allows one to log and
3239
+ * influence this process. In contrast, this implementation does not introduce
3240
+ * any variable declarations in global code and derives String values from
3241
+ * identifier names used as property accessors.</p>
3242
+ * <p>Consolidating literals may worsen the data compression ratio when an <a
3243
+ * href="http://tools.ietf.org/html/rfc2616#section-3.5">encoding
3244
+ * transformation</a> is applied. For instance, <a href=
3245
+ * "http://code.jquery.com/jquery-1.7.1.js">jQuery 1.7.1</a> takes 248235 bytes.
3246
+ * Building it with <a href="https://github.com/mishoo/UglifyJS/tarball/v1.2.5">
3247
+ * UglifyJS v1.2.5</a> results in 93647 bytes (37.73% of the original) which are
3248
+ * then compressed to 33154 bytes (13.36% of the original) using <a href=
3249
+ * "http://linux.die.net/man/1/gzip">gzip(1)</a>. Building it with the same
3250
+ * version of UglifyJS 1.2.5 patched with the implementation of consolidation
3251
+ * results in 80784 bytes (a decrease of 12863 bytes, i.e. 13.74%, in comparison
3252
+ * to the aforementioned 93647 bytes) which are then compressed to 34013 bytes
3253
+ * (an increase of 859 bytes, i.e. 2.59%, in comparison to the aforementioned
3254
+ * 33154 bytes).</p>
3255
+ * <p>Written in <a href="http://es5.github.com/#x4.2.2">the strict variant</a>
3256
+ * of <a href="http://es5.github.com/">ECMA-262 5.1 Edition</a>. Encoded in <a
3257
+ * href="http://tools.ietf.org/html/rfc3629">UTF-8</a>. Follows <a href=
3258
+ * "http://google-styleguide.googlecode.com/svn-history/r76/trunk/javascriptguide.xml"
3259
+ * >Revision 2.28 of the Google JavaScript Style Guide</a> (except for the
3260
+ * discouraged use of the {@code function} tag and the {@code namespace} tag).
3261
+ * 100% typed for the <a href=
3262
+ * "http://closure-compiler.googlecode.com/files/compiler-20120123.tar.gz"
3263
+ * >Closure Compiler Version 1741</a>.</p>
3264
+ * <p>Should you find this software useful, please consider <a href=
3265
+ * "https://paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=JZLW72X8FD4WG"
3266
+ * >a donation</a>.</p>
3267
+ * @author follow.me@RGustBardon (Robert Gust-Bardon)
3268
+ * @supported Tested with:
3269
+ * <ul>
3270
+ * <li><a href="http://nodejs.org/dist/v0.6.10/">Node v0.6.10</a>,</li>
3271
+ * <li><a href="https://github.com/mishoo/UglifyJS/tarball/v1.2.5">UglifyJS
3272
+ * v1.2.5</a>.</li>
3273
+ * </ul>
3274
+ */
3275
+
3276
+ /*global console:false, exports:true, module:false, require:false */
3277
+ /*jshint sub:true */
3278
+ /**
3279
+ * Consolidates null, Boolean, and String values found inside an <abbr title=
3280
+ * "abstract syntax tree">AST</abbr>.
3281
+ * @param {!TSyntacticCodeUnit} oAbstractSyntaxTree An array-like object
3282
+ * representing an <abbr title="abstract syntax tree">AST</abbr>.
3283
+ * @return {!TSyntacticCodeUnit} An array-like object representing an <abbr
3284
+ * title="abstract syntax tree">AST</abbr> with its null, Boolean, and
3285
+ * String values consolidated.
3286
+ */
3287
+ // TODO(user) Consolidation of mathematical values found in numeric literals.
3288
+ // TODO(user) Unconsolidation.
3289
+ // TODO(user) Consolidation of ECMA-262 6th Edition programs.
3290
+ // TODO(user) Rewrite in ECMA-262 6th Edition.
3291
+ exports['ast_consolidate'] = function(oAbstractSyntaxTree) {
3292
+ 'use strict';
3293
+ /*jshint bitwise:true, curly:true, eqeqeq:true, forin:true, immed:true,
3294
+ latedef:true, newcap:true, noarge:true, noempty:true, nonew:true,
3295
+ onevar:true, plusplus:true, regexp:true, undef:true, strict:true,
3296
+ sub:false, trailing:true */
3297
+
3298
+ var _,
3299
+ /**
3300
+ * A record consisting of data about one or more source elements.
3301
+ * @constructor
3302
+ * @nosideeffects
3303
+ */
3304
+ TSourceElementsData = function() {
3305
+ /**
3306
+ * The category of the elements.
3307
+ * @type {number}
3308
+ * @see ESourceElementCategories
3309
+ */
3310
+ this.nCategory = ESourceElementCategories.N_OTHER;
3311
+ /**
3312
+ * The number of occurrences (within the elements) of each primitive
3313
+ * value that could be consolidated.
3314
+ * @type {!Array.<!Object.<string, number>>}
3315
+ */
3316
+ this.aCount = [];
3317
+ this.aCount[EPrimaryExpressionCategories.N_IDENTIFIER_NAMES] = {};
3318
+ this.aCount[EPrimaryExpressionCategories.N_STRING_LITERALS] = {};
3319
+ this.aCount[EPrimaryExpressionCategories.N_NULL_AND_BOOLEAN_LITERALS] =
3320
+ {};
3321
+ /**
3322
+ * Identifier names found within the elements.
3323
+ * @type {!Array.<string>}
3324
+ */
3325
+ this.aIdentifiers = [];
3326
+ /**
3327
+ * Prefixed representation Strings of each primitive value that could be
3328
+ * consolidated within the elements.
3329
+ * @type {!Array.<string>}
3330
+ */
3331
+ this.aPrimitiveValues = [];
3332
+ },
3333
+ /**
3334
+ * A record consisting of data about a primitive value that could be
3335
+ * consolidated.
3336
+ * @constructor
3337
+ * @nosideeffects
3338
+ */
3339
+ TPrimitiveValue = function() {
3340
+ /**
3341
+ * The difference in the number of terminal symbols between the original
3342
+ * source text and the one with the primitive value consolidated. If the
3343
+ * difference is positive, the primitive value is considered worthwhile.
3344
+ * @type {number}
3345
+ */
3346
+ this.nSaving = 0;
3347
+ /**
3348
+ * An identifier name of the variable that will be declared and assigned
3349
+ * the primitive value if the primitive value is consolidated.
3350
+ * @type {string}
3351
+ */
3352
+ this.sName = '';
3353
+ },
3354
+ /**
3355
+ * A record consisting of data on what to consolidate within the range of
3356
+ * source elements that is currently being considered.
3357
+ * @constructor
3358
+ * @nosideeffects
3359
+ */
3360
+ TSolution = function() {
3361
+ /**
3362
+ * An object whose keys are prefixed representation Strings of each
3363
+ * primitive value that could be consolidated within the elements and
3364
+ * whose values are corresponding data about those primitive values.
3365
+ * @type {!Object.<string, {nSaving: number, sName: string}>}
3366
+ * @see TPrimitiveValue
3367
+ */
3368
+ this.oPrimitiveValues = {};
3369
+ /**
3370
+ * The difference in the number of terminal symbols between the original
3371
+ * source text and the one with all the worthwhile primitive values
3372
+ * consolidated.
3373
+ * @type {number}
3374
+ * @see TPrimitiveValue#nSaving
3375
+ */
3376
+ this.nSavings = 0;
3377
+ },
3378
+ /**
3379
+ * The processor of <abbr title="abstract syntax tree">AST</abbr>s found
3380
+ * in UglifyJS.
3381
+ * @namespace
3382
+ * @type {!TProcessor}
3383
+ */
3384
+ oProcessor = (/** @type {!TProcessor} */ require('./process')),
3385
+ /**
3386
+ * A record consisting of a number of constants that represent the
3387
+ * difference in the number of terminal symbols between a source text with
3388
+ * a modified syntactic code unit and the original one.
3389
+ * @namespace
3390
+ * @type {!Object.<string, number>}
3391
+ */
3392
+ oWeights = {
3393
+ /**
3394
+ * The difference in the number of punctuators required by the bracket
3395
+ * notation and the dot notation.
3396
+ * <p><code>'[]'.length - '.'.length</code></p>
3397
+ * @const
3398
+ * @type {number}
3399
+ */
3400
+ N_PROPERTY_ACCESSOR: 1,
3401
+ /**
3402
+ * The number of punctuators required by a variable declaration with an
3403
+ * initialiser.
3404
+ * <p><code>':'.length + ';'.length</code></p>
3405
+ * @const
3406
+ * @type {number}
3407
+ */
3408
+ N_VARIABLE_DECLARATION: 2,
3409
+ /**
3410
+ * The number of terminal symbols required to introduce a variable
3411
+ * statement (excluding its variable declaration list).
3412
+ * <p><code>'var '.length</code></p>
3413
+ * @const
3414
+ * @type {number}
3415
+ */
3416
+ N_VARIABLE_STATEMENT_AFFIXATION: 4,
3417
+ /**
3418
+ * The number of terminal symbols needed to enclose source elements
3419
+ * within a function call with no argument values to a function with an
3420
+ * empty parameter list.
3421
+ * <p><code>'(function(){}());'.length</code></p>
3422
+ * @const
3423
+ * @type {number}
3424
+ */
3425
+ N_CLOSURE: 17
3426
+ },
3427
+ /**
3428
+ * Categories of primary expressions from which primitive values that
3429
+ * could be consolidated are derivable.
3430
+ * @namespace
3431
+ * @enum {number}
3432
+ */
3433
+ EPrimaryExpressionCategories = {
3434
+ /**
3435
+ * Identifier names used as property accessors.
3436
+ * @type {number}
3437
+ */
3438
+ N_IDENTIFIER_NAMES: 0,
3439
+ /**
3440
+ * String literals.
3441
+ * @type {number}
3442
+ */
3443
+ N_STRING_LITERALS: 1,
3444
+ /**
3445
+ * Null and Boolean literals.
3446
+ * @type {number}
3447
+ */
3448
+ N_NULL_AND_BOOLEAN_LITERALS: 2
3449
+ },
3450
+ /**
3451
+ * Prefixes of primitive values that could be consolidated.
3452
+ * The String values of the prefixes must have same number of characters.
3453
+ * The prefixes must not be used in any properties defined in any version
3454
+ * of <a href=
3455
+ * "http://www.ecma-international.org/publications/standards/Ecma-262.htm"
3456
+ * >ECMA-262</a>.
3457
+ * @namespace
3458
+ * @enum {string}
3459
+ */
3460
+ EValuePrefixes = {
3461
+ /**
3462
+ * Identifies String values.
3463
+ * @type {string}
3464
+ */
3465
+ S_STRING: '#S',
3466
+ /**
3467
+ * Identifies null and Boolean values.
3468
+ * @type {string}
3469
+ */
3470
+ S_SYMBOLIC: '#O'
3471
+ },
3472
+ /**
3473
+ * Categories of source elements in terms of their appropriateness of
3474
+ * having their primitive values consolidated.
3475
+ * @namespace
3476
+ * @enum {number}
3477
+ */
3478
+ ESourceElementCategories = {
3479
+ /**
3480
+ * Identifies a source element that includes the <a href=
3481
+ * "http://es5.github.com/#x12.10">{@code with}</a> statement.
3482
+ * @type {number}
3483
+ */
3484
+ N_WITH: 0,
3485
+ /**
3486
+ * Identifies a source element that includes the <a href=
3487
+ * "http://es5.github.com/#x15.1.2.1">{@code eval}</a> identifier name.
3488
+ * @type {number}
3489
+ */
3490
+ N_EVAL: 1,
3491
+ /**
3492
+ * Identifies a source element that must be excluded from the process
3493
+ * unless its whole scope is examined.
3494
+ * @type {number}
3495
+ */
3496
+ N_EXCLUDABLE: 2,
3497
+ /**
3498
+ * Identifies source elements not posing any problems.
3499
+ * @type {number}
3500
+ */
3501
+ N_OTHER: 3
3502
+ },
3503
+ /**
3504
+ * The list of literals (other than the String ones) whose primitive
3505
+ * values can be consolidated.
3506
+ * @const
3507
+ * @type {!Array.<string>}
3508
+ */
3509
+ A_OTHER_SUBSTITUTABLE_LITERALS = [
3510
+ 'null', // The null literal.
3511
+ 'false', // The Boolean literal {@code false}.
3512
+ 'true' // The Boolean literal {@code true}.
3513
+ ];
3514
+
3515
+ (/**
3516
+ * Consolidates all worthwhile primitive values in a syntactic code unit.
3517
+ * @param {!TSyntacticCodeUnit} oSyntacticCodeUnit An array-like object
3518
+ * representing the branch of the abstract syntax tree representing the
3519
+ * syntactic code unit along with its scope.
3520
+ * @see TPrimitiveValue#nSaving
3521
+ */
3522
+ function fExamineSyntacticCodeUnit(oSyntacticCodeUnit) {
3523
+ var _,
3524
+ /**
3525
+ * Indicates whether the syntactic code unit represents global code.
3526
+ * @type {boolean}
3527
+ */
3528
+ bIsGlobal = 'toplevel' === oSyntacticCodeUnit[0],
3529
+ /**
3530
+ * Indicates whether the whole scope is being examined.
3531
+ * @type {boolean}
3532
+ */
3533
+ bIsWhollyExaminable = !bIsGlobal,
3534
+ /**
3535
+ * An array-like object representing source elements that constitute a
3536
+ * syntactic code unit.
3537
+ * @type {!TSyntacticCodeUnit}
3538
+ */
3539
+ oSourceElements,
3540
+ /**
3541
+ * A record consisting of data about the source element that is
3542
+ * currently being examined.
3543
+ * @type {!TSourceElementsData}
3544
+ */
3545
+ oSourceElementData,
3546
+ /**
3547
+ * The scope of the syntactic code unit.
3548
+ * @type {!TScope}
3549
+ */
3550
+ oScope,
3551
+ /**
3552
+ * An instance of an object that allows the traversal of an <abbr
3553
+ * title="abstract syntax tree">AST</abbr>.
3554
+ * @type {!TWalker}
3555
+ */
3556
+ oWalker,
3557
+ /**
3558
+ * An object encompassing collections of functions used during the
3559
+ * traversal of an <abbr title="abstract syntax tree">AST</abbr>.
3560
+ * @namespace
3561
+ * @type {!Object.<string, !Object.<string, function(...[*])>>}
3562
+ */
3563
+ oWalkers = {
3564
+ /**
3565
+ * A collection of functions used during the surveyance of source
3566
+ * elements.
3567
+ * @namespace
3568
+ * @type {!Object.<string, function(...[*])>}
3569
+ */
3570
+ oSurveySourceElement: {
3571
+ /**#nocode+*/ // JsDoc Toolkit 2.4.0 hides some of the keys.
3572
+ /**
3573
+ * Classifies the source element as excludable if it does not
3574
+ * contain a {@code with} statement or the {@code eval} identifier
3575
+ * name. Adds the identifier of the function and its formal
3576
+ * parameters to the list of identifier names found.
3577
+ * @param {string} sIdentifier The identifier of the function.
3578
+ * @param {!Array.<string>} aFormalParameterList Formal parameters.
3579
+ * @param {!TSyntacticCodeUnit} oFunctionBody Function code.
3580
+ */
3581
+ 'defun': function(
3582
+ sIdentifier,
3583
+ aFormalParameterList,
3584
+ oFunctionBody) {
3585
+ fClassifyAsExcludable();
3586
+ fAddIdentifier(sIdentifier);
3587
+ aFormalParameterList.forEach(fAddIdentifier);
3588
+ },
3589
+ /**
3590
+ * Increments the count of the number of occurrences of the String
3591
+ * value that is equivalent to the sequence of terminal symbols
3592
+ * that constitute the encountered identifier name.
3593
+ * @param {!TSyntacticCodeUnit} oExpression The nonterminal
3594
+ * MemberExpression.
3595
+ * @param {string} sIdentifierName The identifier name used as the
3596
+ * property accessor.
3597
+ * @return {!Array} The encountered branch of an <abbr title=
3598
+ * "abstract syntax tree">AST</abbr> with its nonterminal
3599
+ * MemberExpression traversed.
3600
+ */
3601
+ 'dot': function(oExpression, sIdentifierName) {
3602
+ fCountPrimaryExpression(
3603
+ EPrimaryExpressionCategories.N_IDENTIFIER_NAMES,
3604
+ EValuePrefixes.S_STRING + sIdentifierName);
3605
+ return ['dot', oWalker.walk(oExpression), sIdentifierName];
3606
+ },
3607
+ /**
3608
+ * Adds the optional identifier of the function and its formal
3609
+ * parameters to the list of identifier names found.
3610
+ * @param {?string} sIdentifier The optional identifier of the
3611
+ * function.
3612
+ * @param {!Array.<string>} aFormalParameterList Formal parameters.
3613
+ * @param {!TSyntacticCodeUnit} oFunctionBody Function code.
3614
+ */
3615
+ 'function': function(
3616
+ sIdentifier,
3617
+ aFormalParameterList,
3618
+ oFunctionBody) {
3619
+ if ('string' === typeof sIdentifier) {
3620
+ fAddIdentifier(sIdentifier);
3621
+ }
3622
+ aFormalParameterList.forEach(fAddIdentifier);
3623
+ },
3624
+ /**
3625
+ * Either increments the count of the number of occurrences of the
3626
+ * encountered null or Boolean value or classifies a source element
3627
+ * as containing the {@code eval} identifier name.
3628
+ * @param {string} sIdentifier The identifier encountered.
3629
+ */
3630
+ 'name': function(sIdentifier) {
3631
+ if (-1 !== A_OTHER_SUBSTITUTABLE_LITERALS.indexOf(sIdentifier)) {
3632
+ fCountPrimaryExpression(
3633
+ EPrimaryExpressionCategories.N_NULL_AND_BOOLEAN_LITERALS,
3634
+ EValuePrefixes.S_SYMBOLIC + sIdentifier);
3635
+ } else {
3636
+ if ('eval' === sIdentifier) {
3637
+ oSourceElementData.nCategory =
3638
+ ESourceElementCategories.N_EVAL;
3639
+ }
3640
+ fAddIdentifier(sIdentifier);
3641
+ }
3642
+ },
3643
+ /**
3644
+ * Classifies the source element as excludable if it does not
3645
+ * contain a {@code with} statement or the {@code eval} identifier
3646
+ * name.
3647
+ * @param {TSyntacticCodeUnit} oExpression The expression whose
3648
+ * value is to be returned.
3649
+ */
3650
+ 'return': function(oExpression) {
3651
+ fClassifyAsExcludable();
3652
+ },
3653
+ /**
3654
+ * Increments the count of the number of occurrences of the
3655
+ * encountered String value.
3656
+ * @param {string} sStringValue The String value of the string
3657
+ * literal encountered.
3658
+ */
3659
+ 'string': function(sStringValue) {
3660
+ if (sStringValue.length > 0) {
3661
+ fCountPrimaryExpression(
3662
+ EPrimaryExpressionCategories.N_STRING_LITERALS,
3663
+ EValuePrefixes.S_STRING + sStringValue);
3664
+ }
3665
+ },
3666
+ /**
3667
+ * Adds the identifier reserved for an exception to the list of
3668
+ * identifier names found.
3669
+ * @param {!TSyntacticCodeUnit} oTry A block of code in which an
3670
+ * exception can occur.
3671
+ * @param {Array} aCatch The identifier reserved for an exception
3672
+ * and a block of code to handle the exception.
3673
+ * @param {TSyntacticCodeUnit} oFinally An optional block of code
3674
+ * to be evaluated regardless of whether an exception occurs.
3675
+ */
3676
+ 'try': function(oTry, aCatch, oFinally) {
3677
+ if (Array.isArray(aCatch)) {
3678
+ fAddIdentifier(aCatch[0]);
3679
+ }
3680
+ },
3681
+ /**
3682
+ * Classifies the source element as excludable if it does not
3683
+ * contain a {@code with} statement or the {@code eval} identifier
3684
+ * name. Adds the identifier of each declared variable to the list
3685
+ * of identifier names found.
3686
+ * @param {!Array.<!Array>} aVariableDeclarationList Variable
3687
+ * declarations.
3688
+ */
3689
+ 'var': function(aVariableDeclarationList) {
3690
+ fClassifyAsExcludable();
3691
+ aVariableDeclarationList.forEach(fAddVariable);
3692
+ },
3693
+ /**
3694
+ * Classifies a source element as containing the {@code with}
3695
+ * statement.
3696
+ * @param {!TSyntacticCodeUnit} oExpression An expression whose
3697
+ * value is to be converted to a value of type Object and
3698
+ * become the binding object of a new object environment
3699
+ * record of a new lexical environment in which the statement
3700
+ * is to be executed.
3701
+ * @param {!TSyntacticCodeUnit} oStatement The statement to be
3702
+ * executed in the augmented lexical environment.
3703
+ * @return {!Array} An empty array to stop the traversal.
3704
+ */
3705
+ 'with': function(oExpression, oStatement) {
3706
+ oSourceElementData.nCategory = ESourceElementCategories.N_WITH;
3707
+ return [];
3708
+ }
3709
+ /**#nocode-*/ // JsDoc Toolkit 2.4.0 hides some of the keys.
3710
+ },
3711
+ /**
3712
+ * A collection of functions used while looking for nested functions.
3713
+ * @namespace
3714
+ * @type {!Object.<string, function(...[*])>}
3715
+ */
3716
+ oExamineFunctions: {
3717
+ /**#nocode+*/ // JsDoc Toolkit 2.4.0 hides some of the keys.
3718
+ /**
3719
+ * Orders an examination of a nested function declaration.
3720
+ * @this {!TSyntacticCodeUnit} An array-like object representing
3721
+ * the branch of an <abbr title="abstract syntax tree"
3722
+ * >AST</abbr> representing the syntactic code unit along with
3723
+ * its scope.
3724
+ * @return {!Array} An empty array to stop the traversal.
3725
+ */
3726
+ 'defun': function() {
3727
+ fExamineSyntacticCodeUnit(this);
3728
+ return [];
3729
+ },
3730
+ /**
3731
+ * Orders an examination of a nested function expression.
3732
+ * @this {!TSyntacticCodeUnit} An array-like object representing
3733
+ * the branch of an <abbr title="abstract syntax tree"
3734
+ * >AST</abbr> representing the syntactic code unit along with
3735
+ * its scope.
3736
+ * @return {!Array} An empty array to stop the traversal.
3737
+ */
3738
+ 'function': function() {
3739
+ fExamineSyntacticCodeUnit(this);
3740
+ return [];
3741
+ }
3742
+ /**#nocode-*/ // JsDoc Toolkit 2.4.0 hides some of the keys.
3743
+ }
3744
+ },
3745
+ /**
3746
+ * Records containing data about source elements.
3747
+ * @type {Array.<TSourceElementsData>}
3748
+ */
3749
+ aSourceElementsData = [],
3750
+ /**
3751
+ * The index (in the source text order) of the source element
3752
+ * immediately following a <a href="http://es5.github.com/#x14.1"
3753
+ * >Directive Prologue</a>.
3754
+ * @type {number}
3755
+ */
3756
+ nAfterDirectivePrologue = 0,
3757
+ /**
3758
+ * The index (in the source text order) of the source element that is
3759
+ * currently being considered.
3760
+ * @type {number}
3761
+ */
3762
+ nPosition,
3763
+ /**
3764
+ * The index (in the source text order) of the source element that is
3765
+ * the last element of the range of source elements that is currently
3766
+ * being considered.
3767
+ * @type {(undefined|number)}
3768
+ */
3769
+ nTo,
3770
+ /**
3771
+ * Initiates the traversal of a source element.
3772
+ * @param {!TWalker} oWalker An instance of an object that allows the
3773
+ * traversal of an abstract syntax tree.
3774
+ * @param {!TSyntacticCodeUnit} oSourceElement A source element from
3775
+ * which the traversal should commence.
3776
+ * @return {function(): !TSyntacticCodeUnit} A function that is able to
3777
+ * initiate the traversal from a given source element.
3778
+ */
3779
+ cContext = function(oWalker, oSourceElement) {
3780
+ /**
3781
+ * @return {!TSyntacticCodeUnit} A function that is able to
3782
+ * initiate the traversal from a given source element.
3783
+ */
3784
+ var fLambda = function() {
3785
+ return oWalker.walk(oSourceElement);
3786
+ };
3787
+
3788
+ return fLambda;
3789
+ },
3790
+ /**
3791
+ * Classifies the source element as excludable if it does not
3792
+ * contain a {@code with} statement or the {@code eval} identifier
3793
+ * name.
3794
+ */
3795
+ fClassifyAsExcludable = function() {
3796
+ if (oSourceElementData.nCategory ===
3797
+ ESourceElementCategories.N_OTHER) {
3798
+ oSourceElementData.nCategory =
3799
+ ESourceElementCategories.N_EXCLUDABLE;
3800
+ }
3801
+ },
3802
+ /**
3803
+ * Adds an identifier to the list of identifier names found.
3804
+ * @param {string} sIdentifier The identifier to be added.
3805
+ */
3806
+ fAddIdentifier = function(sIdentifier) {
3807
+ if (-1 === oSourceElementData.aIdentifiers.indexOf(sIdentifier)) {
3808
+ oSourceElementData.aIdentifiers.push(sIdentifier);
3809
+ }
3810
+ },
3811
+ /**
3812
+ * Adds the identifier of a variable to the list of identifier names
3813
+ * found.
3814
+ * @param {!Array} aVariableDeclaration A variable declaration.
3815
+ */
3816
+ fAddVariable = function(aVariableDeclaration) {
3817
+ fAddIdentifier(/** @type {string} */ aVariableDeclaration[0]);
3818
+ },
3819
+ /**
3820
+ * Increments the count of the number of occurrences of the prefixed
3821
+ * String representation attributed to the primary expression.
3822
+ * @param {number} nCategory The category of the primary expression.
3823
+ * @param {string} sName The prefixed String representation attributed
3824
+ * to the primary expression.
3825
+ */
3826
+ fCountPrimaryExpression = function(nCategory, sName) {
3827
+ if (!oSourceElementData.aCount[nCategory].hasOwnProperty(sName)) {
3828
+ oSourceElementData.aCount[nCategory][sName] = 0;
3829
+ if (-1 === oSourceElementData.aPrimitiveValues.indexOf(sName)) {
3830
+ oSourceElementData.aPrimitiveValues.push(sName);
3831
+ }
3832
+ }
3833
+ oSourceElementData.aCount[nCategory][sName] += 1;
3834
+ },
3835
+ /**
3836
+ * Consolidates all worthwhile primitive values in a range of source
3837
+ * elements.
3838
+ * @param {number} nFrom The index (in the source text order) of the
3839
+ * source element that is the first element of the range.
3840
+ * @param {number} nTo The index (in the source text order) of the
3841
+ * source element that is the last element of the range.
3842
+ * @param {boolean} bEnclose Indicates whether the range should be
3843
+ * enclosed within a function call with no argument values to a
3844
+ * function with an empty parameter list if any primitive values
3845
+ * are consolidated.
3846
+ * @see TPrimitiveValue#nSaving
3847
+ */
3848
+ fExamineSourceElements = function(nFrom, nTo, bEnclose) {
3849
+ var _,
3850
+ /**
3851
+ * The index of the last mangled name.
3852
+ * @type {number}
3853
+ */
3854
+ nIndex = oScope.cname,
3855
+ /**
3856
+ * The index of the source element that is currently being
3857
+ * considered.
3858
+ * @type {number}
3859
+ */
3860
+ nPosition,
3861
+ /**
3862
+ * A collection of functions used during the consolidation of
3863
+ * primitive values and identifier names used as property
3864
+ * accessors.
3865
+ * @namespace
3866
+ * @type {!Object.<string, function(...[*])>}
3867
+ */
3868
+ oWalkersTransformers = {
3869
+ /**
3870
+ * If the String value that is equivalent to the sequence of
3871
+ * terminal symbols that constitute the encountered identifier
3872
+ * name is worthwhile, a syntactic conversion from the dot
3873
+ * notation to the bracket notation ensues with that sequence
3874
+ * being substituted by an identifier name to which the value
3875
+ * is assigned.
3876
+ * Applies to property accessors that use the dot notation.
3877
+ * @param {!TSyntacticCodeUnit} oExpression The nonterminal
3878
+ * MemberExpression.
3879
+ * @param {string} sIdentifierName The identifier name used as
3880
+ * the property accessor.
3881
+ * @return {!Array} A syntactic code unit that is equivalent to
3882
+ * the one encountered.
3883
+ * @see TPrimitiveValue#nSaving
3884
+ */
3885
+ 'dot': function(oExpression, sIdentifierName) {
3886
+ /**
3887
+ * The prefixed String value that is equivalent to the
3888
+ * sequence of terminal symbols that constitute the
3889
+ * encountered identifier name.
3890
+ * @type {string}
3891
+ */
3892
+ var sPrefixed = EValuePrefixes.S_STRING + sIdentifierName;
3893
+
3894
+ return oSolutionBest.oPrimitiveValues.hasOwnProperty(
3895
+ sPrefixed) &&
3896
+ oSolutionBest.oPrimitiveValues[sPrefixed].nSaving > 0 ?
3897
+ ['sub',
3898
+ oWalker.walk(oExpression),
3899
+ ['name',
3900
+ oSolutionBest.oPrimitiveValues[sPrefixed].sName]] :
3901
+ ['dot', oWalker.walk(oExpression), sIdentifierName];
3902
+ },
3903
+ /**
3904
+ * If the encountered identifier is a null or Boolean literal
3905
+ * and its value is worthwhile, the identifier is substituted
3906
+ * by an identifier name to which that value is assigned.
3907
+ * Applies to identifier names.
3908
+ * @param {string} sIdentifier The identifier encountered.
3909
+ * @return {!Array} A syntactic code unit that is equivalent to
3910
+ * the one encountered.
3911
+ * @see TPrimitiveValue#nSaving
3912
+ */
3913
+ 'name': function(sIdentifier) {
3914
+ /**
3915
+ * The prefixed representation String of the identifier.
3916
+ * @type {string}
3917
+ */
3918
+ var sPrefixed = EValuePrefixes.S_SYMBOLIC + sIdentifier;
3919
+
3920
+ return [
3921
+ 'name',
3922
+ oSolutionBest.oPrimitiveValues.hasOwnProperty(sPrefixed) &&
3923
+ oSolutionBest.oPrimitiveValues[sPrefixed].nSaving > 0 ?
3924
+ oSolutionBest.oPrimitiveValues[sPrefixed].sName :
3925
+ sIdentifier
3926
+ ];
3927
+ },
3928
+ /**
3929
+ * If the encountered String value is worthwhile, it is
3930
+ * substituted by an identifier name to which that value is
3931
+ * assigned.
3932
+ * Applies to String values.
3933
+ * @param {string} sStringValue The String value of the string
3934
+ * literal encountered.
3935
+ * @return {!Array} A syntactic code unit that is equivalent to
3936
+ * the one encountered.
3937
+ * @see TPrimitiveValue#nSaving
3938
+ */
3939
+ 'string': function(sStringValue) {
3940
+ /**
3941
+ * The prefixed representation String of the primitive value
3942
+ * of the literal.
3943
+ * @type {string}
3944
+ */
3945
+ var sPrefixed =
3946
+ EValuePrefixes.S_STRING + sStringValue;
3947
+
3948
+ return oSolutionBest.oPrimitiveValues.hasOwnProperty(
3949
+ sPrefixed) &&
3950
+ oSolutionBest.oPrimitiveValues[sPrefixed].nSaving > 0 ?
3951
+ ['name',
3952
+ oSolutionBest.oPrimitiveValues[sPrefixed].sName] :
3953
+ ['string', sStringValue];
3954
+ }
3955
+ },
3956
+ /**
3957
+ * Such data on what to consolidate within the range of source
3958
+ * elements that is currently being considered that lead to the
3959
+ * greatest known reduction of the number of the terminal symbols
3960
+ * in comparison to the original source text.
3961
+ * @type {!TSolution}
3962
+ */
3963
+ oSolutionBest = new TSolution(),
3964
+ /**
3965
+ * Data representing an ongoing attempt to find a better
3966
+ * reduction of the number of the terminal symbols in comparison
3967
+ * to the original source text than the best one that is
3968
+ * currently known.
3969
+ * @type {!TSolution}
3970
+ * @see oSolutionBest
3971
+ */
3972
+ oSolutionCandidate = new TSolution(),
3973
+ /**
3974
+ * A record consisting of data about the range of source elements
3975
+ * that is currently being examined.
3976
+ * @type {!TSourceElementsData}
3977
+ */
3978
+ oSourceElementsData = new TSourceElementsData(),
3979
+ /**
3980
+ * Variable declarations for each primitive value that is to be
3981
+ * consolidated within the elements.
3982
+ * @type {!Array.<!Array>}
3983
+ */
3984
+ aVariableDeclarations = [],
3985
+ /**
3986
+ * Augments a list with a prefixed representation String.
3987
+ * @param {!Array.<string>} aList A list that is to be augmented.
3988
+ * @return {function(string)} A function that augments a list
3989
+ * with a prefixed representation String.
3990
+ */
3991
+ cAugmentList = function(aList) {
3992
+ /**
3993
+ * @param {string} sPrefixed Prefixed representation String of
3994
+ * a primitive value that could be consolidated within the
3995
+ * elements.
3996
+ */
3997
+ var fLambda = function(sPrefixed) {
3998
+ if (-1 === aList.indexOf(sPrefixed)) {
3999
+ aList.push(sPrefixed);
4000
+ }
4001
+ };
4002
+
4003
+ return fLambda;
4004
+ },
4005
+ /**
4006
+ * Adds the number of occurrences of a primitive value of a given
4007
+ * category that could be consolidated in the source element with
4008
+ * a given index to the count of occurrences of that primitive
4009
+ * value within the range of source elements that is currently
4010
+ * being considered.
4011
+ * @param {number} nPosition The index (in the source text order)
4012
+ * of a source element.
4013
+ * @param {number} nCategory The category of the primary
4014
+ * expression from which the primitive value is derived.
4015
+ * @return {function(string)} A function that performs the
4016
+ * addition.
4017
+ * @see cAddOccurrencesInCategory
4018
+ */
4019
+ cAddOccurrences = function(nPosition, nCategory) {
4020
+ /**
4021
+ * @param {string} sPrefixed The prefixed representation String
4022
+ * of a primitive value.
4023
+ */
4024
+ var fLambda = function(sPrefixed) {
4025
+ if (!oSourceElementsData.aCount[nCategory].hasOwnProperty(
4026
+ sPrefixed)) {
4027
+ oSourceElementsData.aCount[nCategory][sPrefixed] = 0;
4028
+ }
4029
+ oSourceElementsData.aCount[nCategory][sPrefixed] +=
4030
+ aSourceElementsData[nPosition].aCount[nCategory][
4031
+ sPrefixed];
4032
+ };
4033
+
4034
+ return fLambda;
4035
+ },
4036
+ /**
4037
+ * Adds the number of occurrences of each primitive value of a
4038
+ * given category that could be consolidated in the source
4039
+ * element with a given index to the count of occurrences of that
4040
+ * primitive values within the range of source elements that is
4041
+ * currently being considered.
4042
+ * @param {number} nPosition The index (in the source text order)
4043
+ * of a source element.
4044
+ * @return {function(number)} A function that performs the
4045
+ * addition.
4046
+ * @see fAddOccurrences
4047
+ */
4048
+ cAddOccurrencesInCategory = function(nPosition) {
4049
+ /**
4050
+ * @param {number} nCategory The category of the primary
4051
+ * expression from which the primitive value is derived.
4052
+ */
4053
+ var fLambda = function(nCategory) {
4054
+ Object.keys(
4055
+ aSourceElementsData[nPosition].aCount[nCategory]
4056
+ ).forEach(cAddOccurrences(nPosition, nCategory));
4057
+ };
4058
+
4059
+ return fLambda;
4060
+ },
4061
+ /**
4062
+ * Adds the number of occurrences of each primitive value that
4063
+ * could be consolidated in the source element with a given index
4064
+ * to the count of occurrences of that primitive values within
4065
+ * the range of source elements that is currently being
4066
+ * considered.
4067
+ * @param {number} nPosition The index (in the source text order)
4068
+ * of a source element.
4069
+ */
4070
+ fAddOccurrences = function(nPosition) {
4071
+ Object.keys(aSourceElementsData[nPosition].aCount).forEach(
4072
+ cAddOccurrencesInCategory(nPosition));
4073
+ },
4074
+ /**
4075
+ * Creates a variable declaration for a primitive value if that
4076
+ * primitive value is to be consolidated within the elements.
4077
+ * @param {string} sPrefixed Prefixed representation String of a
4078
+ * primitive value that could be consolidated within the
4079
+ * elements.
4080
+ * @see aVariableDeclarations
4081
+ */
4082
+ cAugmentVariableDeclarations = function(sPrefixed) {
4083
+ if (oSolutionBest.oPrimitiveValues[sPrefixed].nSaving > 0) {
4084
+ aVariableDeclarations.push([
4085
+ oSolutionBest.oPrimitiveValues[sPrefixed].sName,
4086
+ [0 === sPrefixed.indexOf(EValuePrefixes.S_SYMBOLIC) ?
4087
+ 'name' : 'string',
4088
+ sPrefixed.substring(EValuePrefixes.S_SYMBOLIC.length)]
4089
+ ]);
4090
+ }
4091
+ },
4092
+ /**
4093
+ * Sorts primitive values with regard to the difference in the
4094
+ * number of terminal symbols between the original source text
4095
+ * and the one with those primitive values consolidated.
4096
+ * @param {string} sPrefixed0 The prefixed representation String
4097
+ * of the first of the two primitive values that are being
4098
+ * compared.
4099
+ * @param {string} sPrefixed1 The prefixed representation String
4100
+ * of the second of the two primitive values that are being
4101
+ * compared.
4102
+ * @return {number}
4103
+ * <dl>
4104
+ * <dt>-1</dt>
4105
+ * <dd>if the first primitive value must be placed before
4106
+ * the other one,</dd>
4107
+ * <dt>0</dt>
4108
+ * <dd>if the first primitive value may be placed before
4109
+ * the other one,</dd>
4110
+ * <dt>1</dt>
4111
+ * <dd>if the first primitive value must not be placed
4112
+ * before the other one.</dd>
4113
+ * </dl>
4114
+ * @see TSolution.oPrimitiveValues
4115
+ */
4116
+ cSortPrimitiveValues = function(sPrefixed0, sPrefixed1) {
4117
+ /**
4118
+ * The difference between:
4119
+ * <ol>
4120
+ * <li>the difference in the number of terminal symbols
4121
+ * between the original source text and the one with the
4122
+ * first primitive value consolidated, and</li>
4123
+ * <li>the difference in the number of terminal symbols
4124
+ * between the original source text and the one with the
4125
+ * second primitive value consolidated.</li>
4126
+ * </ol>
4127
+ * @type {number}
4128
+ */
4129
+ var nDifference =
4130
+ oSolutionCandidate.oPrimitiveValues[sPrefixed0].nSaving -
4131
+ oSolutionCandidate.oPrimitiveValues[sPrefixed1].nSaving;
4132
+
4133
+ return nDifference > 0 ? -1 : nDifference < 0 ? 1 : 0;
4134
+ },
4135
+ /**
4136
+ * Assigns an identifier name to a primitive value and calculates
4137
+ * whether instances of that primitive value are worth
4138
+ * consolidating.
4139
+ * @param {string} sPrefixed The prefixed representation String
4140
+ * of a primitive value that is being evaluated.
4141
+ */
4142
+ fEvaluatePrimitiveValue = function(sPrefixed) {
4143
+ var _,
4144
+ /**
4145
+ * The index of the last mangled name.
4146
+ * @type {number}
4147
+ */
4148
+ nIndex,
4149
+ /**
4150
+ * The representation String of the primitive value that is
4151
+ * being evaluated.
4152
+ * @type {string}
4153
+ */
4154
+ sName =
4155
+ sPrefixed.substring(EValuePrefixes.S_SYMBOLIC.length),
4156
+ /**
4157
+ * The number of source characters taken up by the
4158
+ * representation String of the primitive value that is
4159
+ * being evaluated.
4160
+ * @type {number}
4161
+ */
4162
+ nLengthOriginal = sName.length,
4163
+ /**
4164
+ * The number of source characters taken up by the
4165
+ * identifier name that could substitute the primitive
4166
+ * value that is being evaluated.
4167
+ * substituted.
4168
+ * @type {number}
4169
+ */
4170
+ nLengthSubstitution,
4171
+ /**
4172
+ * The number of source characters taken up by by the
4173
+ * representation String of the primitive value that is
4174
+ * being evaluated when it is represented by a string
4175
+ * literal.
4176
+ * @type {number}
4177
+ */
4178
+ nLengthString = oProcessor.make_string(sName).length;
4179
+
4180
+ oSolutionCandidate.oPrimitiveValues[sPrefixed] =
4181
+ new TPrimitiveValue();
4182
+ do { // Find an identifier unused in this or any nested scope.
4183
+ nIndex = oScope.cname;
4184
+ oSolutionCandidate.oPrimitiveValues[sPrefixed].sName =
4185
+ oScope.next_mangled();
4186
+ } while (-1 !== oSourceElementsData.aIdentifiers.indexOf(
4187
+ oSolutionCandidate.oPrimitiveValues[sPrefixed].sName));
4188
+ nLengthSubstitution = oSolutionCandidate.oPrimitiveValues[
4189
+ sPrefixed].sName.length;
4190
+ if (0 === sPrefixed.indexOf(EValuePrefixes.S_SYMBOLIC)) {
4191
+ // foo:null, or foo:null;
4192
+ oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving -=
4193
+ nLengthSubstitution + nLengthOriginal +
4194
+ oWeights.N_VARIABLE_DECLARATION;
4195
+ // null vs foo
4196
+ oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving +=
4197
+ oSourceElementsData.aCount[
4198
+ EPrimaryExpressionCategories.
4199
+ N_NULL_AND_BOOLEAN_LITERALS][sPrefixed] *
4200
+ (nLengthOriginal - nLengthSubstitution);
4201
+ } else {
4202
+ // foo:'fromCharCode';
4203
+ oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving -=
4204
+ nLengthSubstitution + nLengthString +
4205
+ oWeights.N_VARIABLE_DECLARATION;
4206
+ // .fromCharCode vs [foo]
4207
+ if (oSourceElementsData.aCount[
4208
+ EPrimaryExpressionCategories.N_IDENTIFIER_NAMES
4209
+ ].hasOwnProperty(sPrefixed)) {
4210
+ oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving +=
4211
+ oSourceElementsData.aCount[
4212
+ EPrimaryExpressionCategories.N_IDENTIFIER_NAMES
4213
+ ][sPrefixed] *
4214
+ (nLengthOriginal - nLengthSubstitution -
4215
+ oWeights.N_PROPERTY_ACCESSOR);
4216
+ }
4217
+ // 'fromCharCode' vs foo
4218
+ if (oSourceElementsData.aCount[
4219
+ EPrimaryExpressionCategories.N_STRING_LITERALS
4220
+ ].hasOwnProperty(sPrefixed)) {
4221
+ oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving +=
4222
+ oSourceElementsData.aCount[
4223
+ EPrimaryExpressionCategories.N_STRING_LITERALS
4224
+ ][sPrefixed] *
4225
+ (nLengthString - nLengthSubstitution);
4226
+ }
4227
+ }
4228
+ if (oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving >
4229
+ 0) {
4230
+ oSolutionCandidate.nSavings +=
4231
+ oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving;
4232
+ } else {
4233
+ oScope.cname = nIndex; // Free the identifier name.
4234
+ }
4235
+ },
4236
+ /**
4237
+ * Adds a variable declaration to an existing variable statement.
4238
+ * @param {!Array} aVariableDeclaration A variable declaration
4239
+ * with an initialiser.
4240
+ */
4241
+ cAddVariableDeclaration = function(aVariableDeclaration) {
4242
+ (/** @type {!Array} */ oSourceElements[nFrom][1]).unshift(
4243
+ aVariableDeclaration);
4244
+ };
4245
+
4246
+ if (nFrom > nTo) {
4247
+ return;
4248
+ }
4249
+ // If the range is a closure, reuse the closure.
4250
+ if (nFrom === nTo &&
4251
+ 'stat' === oSourceElements[nFrom][0] &&
4252
+ 'call' === oSourceElements[nFrom][1][0] &&
4253
+ 'function' === oSourceElements[nFrom][1][1][0]) {
4254
+ fExamineSyntacticCodeUnit(oSourceElements[nFrom][1][1]);
4255
+ return;
4256
+ }
4257
+ // Create a list of all derived primitive values within the range.
4258
+ for (nPosition = nFrom; nPosition <= nTo; nPosition += 1) {
4259
+ aSourceElementsData[nPosition].aPrimitiveValues.forEach(
4260
+ cAugmentList(oSourceElementsData.aPrimitiveValues));
4261
+ }
4262
+ if (0 === oSourceElementsData.aPrimitiveValues.length) {
4263
+ return;
4264
+ }
4265
+ for (nPosition = nFrom; nPosition <= nTo; nPosition += 1) {
4266
+ // Add the number of occurrences to the total count.
4267
+ fAddOccurrences(nPosition);
4268
+ // Add identifiers of this or any nested scope to the list.
4269
+ aSourceElementsData[nPosition].aIdentifiers.forEach(
4270
+ cAugmentList(oSourceElementsData.aIdentifiers));
4271
+ }
4272
+ // Distribute identifier names among derived primitive values.
4273
+ do { // If there was any progress, find a better distribution.
4274
+ oSolutionBest = oSolutionCandidate;
4275
+ if (Object.keys(oSolutionCandidate.oPrimitiveValues).length > 0) {
4276
+ // Sort primitive values descending by their worthwhileness.
4277
+ oSourceElementsData.aPrimitiveValues.sort(cSortPrimitiveValues);
4278
+ }
4279
+ oSolutionCandidate = new TSolution();
4280
+ oSourceElementsData.aPrimitiveValues.forEach(
4281
+ fEvaluatePrimitiveValue);
4282
+ oScope.cname = nIndex;
4283
+ } while (oSolutionCandidate.nSavings > oSolutionBest.nSavings);
4284
+ // Take the necessity of adding a variable statement into account.
4285
+ if ('var' !== oSourceElements[nFrom][0]) {
4286
+ oSolutionBest.nSavings -= oWeights.N_VARIABLE_STATEMENT_AFFIXATION;
4287
+ }
4288
+ if (bEnclose) {
4289
+ // Take the necessity of forming a closure into account.
4290
+ oSolutionBest.nSavings -= oWeights.N_CLOSURE;
4291
+ }
4292
+ if (oSolutionBest.nSavings > 0) {
4293
+ // Create variable declarations suitable for UglifyJS.
4294
+ Object.keys(oSolutionBest.oPrimitiveValues).forEach(
4295
+ cAugmentVariableDeclarations);
4296
+ // Rewrite expressions that contain worthwhile primitive values.
4297
+ for (nPosition = nFrom; nPosition <= nTo; nPosition += 1) {
4298
+ oWalker = oProcessor.ast_walker();
4299
+ oSourceElements[nPosition] =
4300
+ oWalker.with_walkers(
4301
+ oWalkersTransformers,
4302
+ cContext(oWalker, oSourceElements[nPosition]));
4303
+ }
4304
+ if ('var' === oSourceElements[nFrom][0]) { // Reuse the statement.
4305
+ (/** @type {!Array.<!Array>} */ aVariableDeclarations.reverse(
4306
+ )).forEach(cAddVariableDeclaration);
4307
+ } else { // Add a variable statement.
4308
+ Array.prototype.splice.call(
4309
+ oSourceElements,
4310
+ nFrom,
4311
+ 0,
4312
+ ['var', aVariableDeclarations]);
4313
+ nTo += 1;
4314
+ }
4315
+ if (bEnclose) {
4316
+ // Add a closure.
4317
+ Array.prototype.splice.call(
4318
+ oSourceElements,
4319
+ nFrom,
4320
+ 0,
4321
+ ['stat', ['call', ['function', null, [], []], []]]);
4322
+ // Copy source elements into the closure.
4323
+ for (nPosition = nTo + 1; nPosition > nFrom; nPosition -= 1) {
4324
+ Array.prototype.unshift.call(
4325
+ oSourceElements[nFrom][1][1][3],
4326
+ oSourceElements[nPosition]);
4327
+ }
4328
+ // Remove source elements outside the closure.
4329
+ Array.prototype.splice.call(
4330
+ oSourceElements,
4331
+ nFrom + 1,
4332
+ nTo - nFrom + 1);
4333
+ }
4334
+ }
4335
+ if (bEnclose) {
4336
+ // Restore the availability of identifier names.
4337
+ oScope.cname = nIndex;
4338
+ }
4339
+ };
4340
+
4341
+ oSourceElements = (/** @type {!TSyntacticCodeUnit} */
4342
+ oSyntacticCodeUnit[bIsGlobal ? 1 : 3]);
4343
+ if (0 === oSourceElements.length) {
4344
+ return;
4345
+ }
4346
+ oScope = bIsGlobal ? oSyntacticCodeUnit.scope : oSourceElements.scope;
4347
+ // Skip a Directive Prologue.
4348
+ while (nAfterDirectivePrologue < oSourceElements.length &&
4349
+ 'stat' === oSourceElements[nAfterDirectivePrologue][0] &&
4350
+ 'string' === oSourceElements[nAfterDirectivePrologue][1][0]) {
4351
+ nAfterDirectivePrologue += 1;
4352
+ aSourceElementsData.push(null);
4353
+ }
4354
+ if (oSourceElements.length === nAfterDirectivePrologue) {
4355
+ return;
4356
+ }
4357
+ for (nPosition = nAfterDirectivePrologue;
4358
+ nPosition < oSourceElements.length;
4359
+ nPosition += 1) {
4360
+ oSourceElementData = new TSourceElementsData();
4361
+ oWalker = oProcessor.ast_walker();
4362
+ // Classify a source element.
4363
+ // Find its derived primitive values and count their occurrences.
4364
+ // Find all identifiers used (including nested scopes).
4365
+ oWalker.with_walkers(
4366
+ oWalkers.oSurveySourceElement,
4367
+ cContext(oWalker, oSourceElements[nPosition]));
4368
+ // Establish whether the scope is still wholly examinable.
4369
+ bIsWhollyExaminable = bIsWhollyExaminable &&
4370
+ ESourceElementCategories.N_WITH !== oSourceElementData.nCategory &&
4371
+ ESourceElementCategories.N_EVAL !== oSourceElementData.nCategory;
4372
+ aSourceElementsData.push(oSourceElementData);
4373
+ }
4374
+ if (bIsWhollyExaminable) { // Examine the whole scope.
4375
+ fExamineSourceElements(
4376
+ nAfterDirectivePrologue,
4377
+ oSourceElements.length - 1,
4378
+ false);
4379
+ } else { // Examine unexcluded ranges of source elements.
4380
+ for (nPosition = oSourceElements.length - 1;
4381
+ nPosition >= nAfterDirectivePrologue;
4382
+ nPosition -= 1) {
4383
+ oSourceElementData = (/** @type {!TSourceElementsData} */
4384
+ aSourceElementsData[nPosition]);
4385
+ if (ESourceElementCategories.N_OTHER ===
4386
+ oSourceElementData.nCategory) {
4387
+ if ('undefined' === typeof nTo) {
4388
+ nTo = nPosition; // Indicate the end of a range.
4389
+ }
4390
+ // Examine the range if it immediately follows a Directive Prologue.
4391
+ if (nPosition === nAfterDirectivePrologue) {
4392
+ fExamineSourceElements(nPosition, nTo, true);
4393
+ }
4394
+ } else {
4395
+ if ('undefined' !== typeof nTo) {
4396
+ // Examine the range that immediately follows this source element.
4397
+ fExamineSourceElements(nPosition + 1, nTo, true);
4398
+ nTo = void 0; // Obliterate the range.
4399
+ }
4400
+ // Examine nested functions.
4401
+ oWalker = oProcessor.ast_walker();
4402
+ oWalker.with_walkers(
4403
+ oWalkers.oExamineFunctions,
4404
+ cContext(oWalker, oSourceElements[nPosition]));
4405
+ }
4406
+ }
4407
+ }
4408
+ }(oAbstractSyntaxTree = oProcessor.ast_add_scope(oAbstractSyntaxTree)));
4409
+ return oAbstractSyntaxTree;
4410
+ };
4411
+ /*jshint sub:false */
4412
+
4413
+
4414
+ if (require.main === module) {
4415
+ (function() {
4416
+ 'use strict';
4417
+ /*jshint bitwise:true, curly:true, eqeqeq:true, forin:true, immed:true,
4418
+ latedef:true, newcap:true, noarge:true, noempty:true, nonew:true,
4419
+ onevar:true, plusplus:true, regexp:true, undef:true, strict:true,
4420
+ sub:false, trailing:true */
4421
+
4422
+ var _,
4423
+ /**
4424
+ * NodeJS module for unit testing.
4425
+ * @namespace
4426
+ * @type {!TAssert}
4427
+ * @see http://nodejs.org/docs/v0.6.10/api/all.html#assert
4428
+ */
4429
+ oAssert = (/** @type {!TAssert} */ require('env!env/assert')),
4430
+ /**
4431
+ * The parser of ECMA-262 found in UglifyJS.
4432
+ * @namespace
4433
+ * @type {!TParser}
4434
+ */
4435
+ oParser = (/** @type {!TParser} */ require('./parse-js')),
4436
+ /**
4437
+ * The processor of <abbr title="abstract syntax tree">AST</abbr>s
4438
+ * found in UglifyJS.
4439
+ * @namespace
4440
+ * @type {!TProcessor}
4441
+ */
4442
+ oProcessor = (/** @type {!TProcessor} */ require('./process')),
4443
+ /**
4444
+ * An instance of an object that allows the traversal of an <abbr
4445
+ * title="abstract syntax tree">AST</abbr>.
4446
+ * @type {!TWalker}
4447
+ */
4448
+ oWalker,
4449
+ /**
4450
+ * A collection of functions for the removal of the scope information
4451
+ * during the traversal of an <abbr title="abstract syntax tree"
4452
+ * >AST</abbr>.
4453
+ * @namespace
4454
+ * @type {!Object.<string, function(...[*])>}
4455
+ */
4456
+ oWalkersPurifiers = {
4457
+ /**#nocode+*/ // JsDoc Toolkit 2.4.0 hides some of the keys.
4458
+ /**
4459
+ * Deletes the scope information from the branch of the abstract
4460
+ * syntax tree representing the encountered function declaration.
4461
+ * @param {string} sIdentifier The identifier of the function.
4462
+ * @param {!Array.<string>} aFormalParameterList Formal parameters.
4463
+ * @param {!TSyntacticCodeUnit} oFunctionBody Function code.
4464
+ */
4465
+ 'defun': function(
4466
+ sIdentifier,
4467
+ aFormalParameterList,
4468
+ oFunctionBody) {
4469
+ delete oFunctionBody.scope;
4470
+ },
4471
+ /**
4472
+ * Deletes the scope information from the branch of the abstract
4473
+ * syntax tree representing the encountered function expression.
4474
+ * @param {?string} sIdentifier The optional identifier of the
4475
+ * function.
4476
+ * @param {!Array.<string>} aFormalParameterList Formal parameters.
4477
+ * @param {!TSyntacticCodeUnit} oFunctionBody Function code.
4478
+ */
4479
+ 'function': function(
4480
+ sIdentifier,
4481
+ aFormalParameterList,
4482
+ oFunctionBody) {
4483
+ delete oFunctionBody.scope;
4484
+ }
4485
+ /**#nocode-*/ // JsDoc Toolkit 2.4.0 hides some of the keys.
4486
+ },
4487
+ /**
4488
+ * Initiates the traversal of a source element.
4489
+ * @param {!TWalker} oWalker An instance of an object that allows the
4490
+ * traversal of an abstract syntax tree.
4491
+ * @param {!TSyntacticCodeUnit} oSourceElement A source element from
4492
+ * which the traversal should commence.
4493
+ * @return {function(): !TSyntacticCodeUnit} A function that is able to
4494
+ * initiate the traversal from a given source element.
4495
+ */
4496
+ cContext = function(oWalker, oSourceElement) {
4497
+ /**
4498
+ * @return {!TSyntacticCodeUnit} A function that is able to
4499
+ * initiate the traversal from a given source element.
4500
+ */
4501
+ var fLambda = function() {
4502
+ return oWalker.walk(oSourceElement);
4503
+ };
4504
+
4505
+ return fLambda;
4506
+ },
4507
+ /**
4508
+ * A record consisting of configuration for the code generation phase.
4509
+ * @type {!Object}
4510
+ */
4511
+ oCodeGenerationOptions = {
4512
+ beautify: true
4513
+ },
4514
+ /**
4515
+ * Tests whether consolidation of an ECMAScript program yields expected
4516
+ * results.
4517
+ * @param {{
4518
+ * sTitle: string,
4519
+ * sInput: string,
4520
+ * sOutput: string
4521
+ * }} oUnitTest A record consisting of data about a unit test: its
4522
+ * name, an ECMAScript program, and, if consolidation is to take
4523
+ * place, the resulting ECMAScript program.
4524
+ */
4525
+ cAssert = function(oUnitTest) {
4526
+ var _,
4527
+ /**
4528
+ * An array-like object representing the <abbr title=
4529
+ * "abstract syntax tree">AST</abbr> obtained after consolidation.
4530
+ * @type {!TSyntacticCodeUnit}
4531
+ */
4532
+ oSyntacticCodeUnitActual =
4533
+ exports.ast_consolidate(oParser.parse(oUnitTest.sInput)),
4534
+ /**
4535
+ * An array-like object representing the expected <abbr title=
4536
+ * "abstract syntax tree">AST</abbr>.
4537
+ * @type {!TSyntacticCodeUnit}
4538
+ */
4539
+ oSyntacticCodeUnitExpected = oParser.parse(
4540
+ oUnitTest.hasOwnProperty('sOutput') ?
4541
+ oUnitTest.sOutput : oUnitTest.sInput);
4542
+
4543
+ delete oSyntacticCodeUnitActual.scope;
4544
+ oWalker = oProcessor.ast_walker();
4545
+ oWalker.with_walkers(
4546
+ oWalkersPurifiers,
4547
+ cContext(oWalker, oSyntacticCodeUnitActual));
4548
+ try {
4549
+ oAssert.deepEqual(
4550
+ oSyntacticCodeUnitActual,
4551
+ oSyntacticCodeUnitExpected);
4552
+ } catch (oException) {
4553
+ console.error(
4554
+ '########## A unit test has failed.\n' +
4555
+ oUnitTest.sTitle + '\n' +
4556
+ '##### actual code (' +
4557
+ oProcessor.gen_code(oSyntacticCodeUnitActual).length +
4558
+ ' bytes)\n' +
4559
+ oProcessor.gen_code(
4560
+ oSyntacticCodeUnitActual,
4561
+ oCodeGenerationOptions) + '\n' +
4562
+ '##### expected code (' +
4563
+ oProcessor.gen_code(oSyntacticCodeUnitExpected).length +
4564
+ ' bytes)\n' +
4565
+ oProcessor.gen_code(
4566
+ oSyntacticCodeUnitExpected,
4567
+ oCodeGenerationOptions));
4568
+ }
4569
+ };
4570
+
4571
+ [
4572
+ // 7.6.1 Reserved Words.
4573
+ {
4574
+ sTitle:
4575
+ 'Omission of keywords while choosing an identifier name.',
4576
+ sInput:
4577
+ '(function() {' +
4578
+ ' var a, b, c, d, e, f, g, h, i, j, k, l, m,' +
4579
+ ' n, o, p, q, r, s, t, u, v, w, x, y, z,' +
4580
+ ' A, B, C, D, E, F, G, H, I, J, K, L, M,' +
4581
+ ' N, O, P, Q, R, S, T, U, V, W, X, Y, Z,' +
4582
+ ' $, _,' +
4583
+ ' aa, ab, ac, ad, ae, af, ag, ah, ai, aj, ak, al, am,' +
4584
+ ' an, ao, ap, aq, ar, as, at, au, av, aw, ax, ay, az,' +
4585
+ ' aA, aB, aC, aD, aE, aF, aG, aH, aI, aJ, aK, aL, aM,' +
4586
+ ' aN, aO, aP, aQ, aR, aS, aT, aU, aV, aW, aX, aY, aZ,' +
4587
+ ' a$, a_,' +
4588
+ ' ba, bb, bc, bd, be, bf, bg, bh, bi, bj, bk, bl, bm,' +
4589
+ ' bn, bo, bp, bq, br, bs, bt, bu, bv, bw, bx, by, bz,' +
4590
+ ' bA, bB, bC, bD, bE, bF, bG, bH, bI, bJ, bK, bL, bM,' +
4591
+ ' bN, bO, bP, bQ, bR, bS, bT, bU, bV, bW, bX, bY, bZ,' +
4592
+ ' b$, b_,' +
4593
+ ' ca, cb, cc, cd, ce, cf, cg, ch, ci, cj, ck, cl, cm,' +
4594
+ ' cn, co, cp, cq, cr, cs, ct, cu, cv, cw, cx, cy, cz,' +
4595
+ ' cA, cB, cC, cD, cE, cF, cG, cH, cI, cJ, cK, cL, cM,' +
4596
+ ' cN, cO, cP, cQ, cR, cS, cT, cU, cV, cW, cX, cY, cZ,' +
4597
+ ' c$, c_,' +
4598
+ ' da, db, dc, dd, de, df, dg, dh, di, dj, dk, dl, dm,' +
4599
+ ' dn, dq, dr, ds, dt, du, dv, dw, dx, dy, dz,' +
4600
+ ' dA, dB, dC, dD, dE, dF, dG, dH, dI, dJ, dK, dL, dM,' +
4601
+ ' dN, dO, dP, dQ, dR, dS, dT, dU, dV, dW, dX, dY, dZ,' +
4602
+ ' d$, d_;' +
4603
+ ' void ["abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",' +
4604
+ ' "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"];' +
4605
+ '}());',
4606
+ sOutput:
4607
+ '(function() {' +
4608
+ ' var dp =' +
4609
+ ' "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",' +
4610
+ ' a, b, c, d, e, f, g, h, i, j, k, l, m,' +
4611
+ ' n, o, p, q, r, s, t, u, v, w, x, y, z,' +
4612
+ ' A, B, C, D, E, F, G, H, I, J, K, L, M,' +
4613
+ ' N, O, P, Q, R, S, T, U, V, W, X, Y, Z,' +
4614
+ ' $, _,' +
4615
+ ' aa, ab, ac, ad, ae, af, ag, ah, ai, aj, ak, al, am,' +
4616
+ ' an, ao, ap, aq, ar, as, at, au, av, aw, ax, ay, az,' +
4617
+ ' aA, aB, aC, aD, aE, aF, aG, aH, aI, aJ, aK, aL, aM,' +
4618
+ ' aN, aO, aP, aQ, aR, aS, aT, aU, aV, aW, aX, aY, aZ,' +
4619
+ ' a$, a_,' +
4620
+ ' ba, bb, bc, bd, be, bf, bg, bh, bi, bj, bk, bl, bm,' +
4621
+ ' bn, bo, bp, bq, br, bs, bt, bu, bv, bw, bx, by, bz,' +
4622
+ ' bA, bB, bC, bD, bE, bF, bG, bH, bI, bJ, bK, bL, bM,' +
4623
+ ' bN, bO, bP, bQ, bR, bS, bT, bU, bV, bW, bX, bY, bZ,' +
4624
+ ' b$, b_,' +
4625
+ ' ca, cb, cc, cd, ce, cf, cg, ch, ci, cj, ck, cl, cm,' +
4626
+ ' cn, co, cp, cq, cr, cs, ct, cu, cv, cw, cx, cy, cz,' +
4627
+ ' cA, cB, cC, cD, cE, cF, cG, cH, cI, cJ, cK, cL, cM,' +
4628
+ ' cN, cO, cP, cQ, cR, cS, cT, cU, cV, cW, cX, cY, cZ,' +
4629
+ ' c$, c_,' +
4630
+ ' da, db, dc, dd, de, df, dg, dh, di, dj, dk, dl, dm,' +
4631
+ ' dn, dq, dr, ds, dt, du, dv, dw, dx, dy, dz,' +
4632
+ ' dA, dB, dC, dD, dE, dF, dG, dH, dI, dJ, dK, dL, dM,' +
4633
+ ' dN, dO, dP, dQ, dR, dS, dT, dU, dV, dW, dX, dY, dZ,' +
4634
+ ' d$, d_;' +
4635
+ ' void [dp, dp];' +
4636
+ '}());'
4637
+ },
4638
+ // 7.8.1 Null Literals.
4639
+ {
4640
+ sTitle:
4641
+ 'Evaluation with regard to the null value.',
4642
+ sInput:
4643
+ '/*jshint evil:true */' +
4644
+ '(function() {' +
4645
+ ' var foo;' +
4646
+ ' void [null, null, null];' +
4647
+ '}());' +
4648
+ 'eval("");' +
4649
+ '(function() {' +
4650
+ ' var foo;' +
4651
+ ' void [null, null];' +
4652
+ '}());',
4653
+ sOutput:
4654
+ '/*jshint evil:true */' +
4655
+ '(function() {' +
4656
+ ' var a = null, foo;' +
4657
+ ' void [a, a, a];' +
4658
+ '}());' +
4659
+ 'eval("");' +
4660
+ '(function() {' +
4661
+ ' var foo;' +
4662
+ ' void [null, null];' +
4663
+ '}());'
4664
+ },
4665
+ // 7.8.2 Boolean Literals.
4666
+ {
4667
+ sTitle:
4668
+ 'Evaluation with regard to the false value.',
4669
+ sInput:
4670
+ '/*jshint evil:true */' +
4671
+ '(function() {' +
4672
+ ' var foo;' +
4673
+ ' void [false, false, false];' +
4674
+ '}());' +
4675
+ 'eval("");' +
4676
+ '(function() {' +
4677
+ ' var foo;' +
4678
+ ' void [false, false];' +
4679
+ '}());',
4680
+ sOutput:
4681
+ '/*jshint evil:true */' +
4682
+ '(function() {' +
4683
+ ' var a = false, foo;' +
4684
+ ' void [a, a, a];' +
4685
+ '}());' +
4686
+ 'eval("");' +
4687
+ '(function() {' +
4688
+ ' var foo;' +
4689
+ ' void [false, false];' +
4690
+ '}());'
4691
+ },
4692
+ {
4693
+ sTitle:
4694
+ 'Evaluation with regard to the true value.',
4695
+ sInput:
4696
+ '/*jshint evil:true */' +
4697
+ '(function() {' +
4698
+ ' var foo;' +
4699
+ ' void [true, true, true];' +
4700
+ '}());' +
4701
+ 'eval("");' +
4702
+ '(function() {' +
4703
+ ' var foo;' +
4704
+ ' void [true, true];' +
4705
+ '}());',
4706
+ sOutput:
4707
+ '/*jshint evil:true */' +
4708
+ '(function() {' +
4709
+ ' var a = true, foo;' +
4710
+ ' void [a, a, a];' +
4711
+ '}());' +
4712
+ 'eval("");' +
4713
+ '(function() {' +
4714
+ ' var foo;' +
4715
+ ' void [true, true];' +
4716
+ '}());'
4717
+ },
4718
+ // 7.8.4 String Literals.
4719
+ {
4720
+ sTitle:
4721
+ 'Evaluation with regard to the String value of a string literal.',
4722
+ sInput:
4723
+ '(function() {' +
4724
+ ' var foo;' +
4725
+ ' void ["abcd", "abcd", "abc", "abc"];' +
4726
+ '}());',
4727
+ sOutput:
4728
+ '(function() {' +
4729
+ ' var a = "abcd", foo;' +
4730
+ ' void [a, a, "abc", "abc"];' +
4731
+ '}());'
4732
+ },
4733
+ // 7.8.5 Regular Expression Literals.
4734
+ {
4735
+ sTitle:
4736
+ 'Preservation of the pattern of a regular expression literal.',
4737
+ sInput:
4738
+ 'void [/abcdefghijklmnopqrstuvwxyz/, /abcdefghijklmnopqrstuvwxyz/];'
4739
+ },
4740
+ {
4741
+ sTitle:
4742
+ 'Preservation of the flags of a regular expression literal.',
4743
+ sInput:
4744
+ 'void [/(?:)/gim, /(?:)/gim, /(?:)/gim, /(?:)/gim, /(?:)/gim,' +
4745
+ ' /(?:)/gim, /(?:)/gim, /(?:)/gim, /(?:)/gim, /(?:)/gim,' +
4746
+ ' /(?:)/gim, /(?:)/gim, /(?:)/gim, /(?:)/gim, /(?:)/gim];'
4747
+ },
4748
+ // 10.2 Lexical Environments.
4749
+ {
4750
+ sTitle:
4751
+ 'Preservation of identifier names in the same scope.',
4752
+ sInput:
4753
+ '/*jshint shadow:true */' +
4754
+ 'var a;' +
4755
+ 'function b(i) {' +
4756
+ '}' +
4757
+ 'for (var c; 0 === Math.random(););' +
4758
+ 'for (var d in {});' +
4759
+ 'void ["abcdefghijklmnopqrstuvwxyz"];' +
4760
+ 'void [b(a), b(c), b(d)];' +
4761
+ 'void [typeof e];' +
4762
+ 'i: for (; 0 === Math.random();) {' +
4763
+ ' if (42 === (new Date()).getMinutes()) {' +
4764
+ ' continue i;' +
4765
+ ' } else {' +
4766
+ ' break i;' +
4767
+ ' }' +
4768
+ '}' +
4769
+ 'try {' +
4770
+ '} catch (f) {' +
4771
+ '} finally {' +
4772
+ '}' +
4773
+ '(function g(h) {' +
4774
+ '}());' +
4775
+ 'void [{' +
4776
+ ' i: 42,' +
4777
+ ' "j": 42,' +
4778
+ ' \'k\': 42' +
4779
+ '}];' +
4780
+ 'void ["abcdefghijklmnopqrstuvwxyz"];',
4781
+ sOutput:
4782
+ '/*jshint shadow:true */' +
4783
+ 'var a;' +
4784
+ 'function b(i) {' +
4785
+ '}' +
4786
+ 'for (var c; 0 === Math.random(););' +
4787
+ 'for (var d in {});' +
4788
+ '(function() {' +
4789
+ ' var i = "abcdefghijklmnopqrstuvwxyz";' +
4790
+ ' void [i];' +
4791
+ ' void [b(a), b(c), b(d)];' +
4792
+ ' void [typeof e];' +
4793
+ ' i: for (; 0 === Math.random();) {' +
4794
+ ' if (42 === (new Date()).getMinutes()) {' +
4795
+ ' continue i;' +
4796
+ ' } else {' +
4797
+ ' break i;' +
4798
+ ' }' +
4799
+ ' }' +
4800
+ ' try {' +
4801
+ ' } catch (f) {' +
4802
+ ' } finally {' +
4803
+ ' }' +
4804
+ ' (function g(h) {' +
4805
+ ' }());' +
4806
+ ' void [{' +
4807
+ ' i: 42,' +
4808
+ ' "j": 42,' +
4809
+ ' \'k\': 42' +
4810
+ ' }];' +
4811
+ ' void [i];' +
4812
+ '}());'
4813
+ },
4814
+ {
4815
+ sTitle:
4816
+ 'Preservation of identifier names in nested function code.',
4817
+ sInput:
4818
+ '(function() {' +
4819
+ ' void ["abcdefghijklmnopqrstuvwxyz"];' +
4820
+ ' (function() {' +
4821
+ ' var a;' +
4822
+ ' for (var b; 0 === Math.random(););' +
4823
+ ' for (var c in {});' +
4824
+ ' void [typeof d];' +
4825
+ ' h: for (; 0 === Math.random();) {' +
4826
+ ' if (42 === (new Date()).getMinutes()) {' +
4827
+ ' continue h;' +
4828
+ ' } else {' +
4829
+ ' break h;' +
4830
+ ' }' +
4831
+ ' }' +
4832
+ ' try {' +
4833
+ ' } catch (e) {' +
4834
+ ' } finally {' +
4835
+ ' }' +
4836
+ ' (function f(g) {' +
4837
+ ' }());' +
4838
+ ' void [{' +
4839
+ ' h: 42,' +
4840
+ ' "i": 42,' +
4841
+ ' \'j\': 42' +
4842
+ ' }];' +
4843
+ ' }());' +
4844
+ ' void ["abcdefghijklmnopqrstuvwxyz"];' +
4845
+ '}());',
4846
+ sOutput:
4847
+ '(function() {' +
4848
+ ' var h = "abcdefghijklmnopqrstuvwxyz";' +
4849
+ ' void [h];' +
4850
+ ' (function() {' +
4851
+ ' var a;' +
4852
+ ' for (var b; 0 === Math.random(););' +
4853
+ ' for (var c in {});' +
4854
+ ' void [typeof d];' +
4855
+ ' h: for (; 0 === Math.random();) {' +
4856
+ ' if (42 === (new Date()).getMinutes()) {' +
4857
+ ' continue h;' +
4858
+ ' } else {' +
4859
+ ' break h;' +
4860
+ ' }' +
4861
+ ' }' +
4862
+ ' try {' +
4863
+ ' } catch (e) {' +
4864
+ ' } finally {' +
4865
+ ' }' +
4866
+ ' (function f(g) {' +
4867
+ ' }());' +
4868
+ ' void [{' +
4869
+ ' h: 42,' +
4870
+ ' "i": 42,' +
4871
+ ' \'j\': 42' +
4872
+ ' }];' +
4873
+ ' }());' +
4874
+ ' void [h];' +
4875
+ '}());'
4876
+ },
4877
+ {
4878
+ sTitle:
4879
+ 'Consolidation of a closure with other source elements.',
4880
+ sInput:
4881
+ '(function(foo) {' +
4882
+ '}("abcdefghijklmnopqrstuvwxyz"));' +
4883
+ 'void ["abcdefghijklmnopqrstuvwxyz"];',
4884
+ sOutput:
4885
+ '(function() {' +
4886
+ ' var a = "abcdefghijklmnopqrstuvwxyz";' +
4887
+ ' (function(foo) {' +
4888
+ ' })(a);' +
4889
+ ' void [a];' +
4890
+ '}());'
4891
+ },
4892
+ {
4893
+ sTitle:
4894
+ 'Consolidation of function code instead of a sole closure.',
4895
+ sInput:
4896
+ '(function(foo, bar) {' +
4897
+ ' void ["abcdefghijklmnopqrstuvwxyz",' +
4898
+ ' "abcdefghijklmnopqrstuvwxyz"];' +
4899
+ '}("abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz"));',
4900
+ sOutput:
4901
+ '(function(foo, bar) {' +
4902
+ ' var a = "abcdefghijklmnopqrstuvwxyz";' +
4903
+ ' void [a, a];' +
4904
+ '}("abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz"));'
4905
+ },
4906
+ // 11.1.5 Object Initialiser.
4907
+ {
4908
+ sTitle:
4909
+ 'Preservation of property names of an object initialiser.',
4910
+ sInput:
4911
+ 'var foo = {' +
4912
+ ' abcdefghijklmnopqrstuvwxyz: 42,' +
4913
+ ' "zyxwvutsrqponmlkjihgfedcba": 42,' +
4914
+ ' \'mlkjihgfedcbanopqrstuvwxyz\': 42' +
4915
+ '};' +
4916
+ 'void [' +
4917
+ ' foo.abcdefghijklmnopqrstuvwxyz,' +
4918
+ ' "zyxwvutsrqponmlkjihgfedcba",' +
4919
+ ' \'mlkjihgfedcbanopqrstuvwxyz\'' +
4920
+ '];'
4921
+ },
4922
+ {
4923
+ sTitle:
4924
+ 'Evaluation with regard to String values derived from identifier ' +
4925
+ 'names used as property accessors.',
4926
+ sInput:
4927
+ '(function() {' +
4928
+ ' var foo;' +
4929
+ ' void [' +
4930
+ ' Math.abcdefghij,' +
4931
+ ' Math.abcdefghij,' +
4932
+ ' Math.abcdefghi,' +
4933
+ ' Math.abcdefghi' +
4934
+ ' ];' +
4935
+ '}());',
4936
+ sOutput:
4937
+ '(function() {' +
4938
+ ' var a = "abcdefghij", foo;' +
4939
+ ' void [' +
4940
+ ' Math[a],' +
4941
+ ' Math[a],' +
4942
+ ' Math.abcdefghi,' +
4943
+ ' Math.abcdefghi' +
4944
+ ' ];' +
4945
+ '}());'
4946
+ },
4947
+ // 11.2.1 Property Accessors.
4948
+ {
4949
+ sTitle:
4950
+ 'Preservation of identifiers in the nonterminal MemberExpression.',
4951
+ sInput:
4952
+ 'void [' +
4953
+ ' Math.E,' +
4954
+ ' Math.LN10,' +
4955
+ ' Math.LN2,' +
4956
+ ' Math.LOG2E,' +
4957
+ ' Math.LOG10E,' +
4958
+ ' Math.PI,' +
4959
+ ' Math.SQRT1_2,' +
4960
+ ' Math.SQRT2,' +
4961
+ ' Math.abs,' +
4962
+ ' Math.acos' +
4963
+ '];'
4964
+ },
4965
+ // 12.2 Variable Statement.
4966
+ {
4967
+ sTitle:
4968
+ 'Preservation of the identifier of a variable that is being ' +
4969
+ 'declared in a variable statement.',
4970
+ sInput:
4971
+ '(function() {' +
4972
+ ' var abcdefghijklmnopqrstuvwxyz;' +
4973
+ ' void [abcdefghijklmnopqrstuvwxyz];' +
4974
+ '}());'
4975
+ },
4976
+ {
4977
+ sTitle:
4978
+ 'Exclusion of a variable statement in global code.',
4979
+ sInput:
4980
+ 'void ["abcdefghijklmnopqrstuvwxyz"];' +
4981
+ 'var foo = "abcdefghijklmnopqrstuvwxyz",' +
4982
+ ' bar = "abcdefghijklmnopqrstuvwxyz";' +
4983
+ 'void ["abcdefghijklmnopqrstuvwxyz"];'
4984
+ },
4985
+ {
4986
+ sTitle:
4987
+ 'Exclusion of a variable statement in function code that ' +
4988
+ 'contains a with statement.',
4989
+ sInput:
4990
+ '(function() {' +
4991
+ ' with ({});' +
4992
+ ' void ["abcdefghijklmnopqrstuvwxyz"];' +
4993
+ ' var foo;' +
4994
+ ' void ["abcdefghijklmnopqrstuvwxyz"];' +
4995
+ '}());'
4996
+ },
4997
+ {
4998
+ sTitle:
4999
+ 'Exclusion of a variable statement in function code that ' +
5000
+ 'contains a direct call to the eval function.',
5001
+ sInput:
5002
+ '/*jshint evil:true */' +
5003
+ 'void [' +
5004
+ ' function() {' +
5005
+ ' eval("");' +
5006
+ ' void ["abcdefghijklmnopqrstuvwxyz"];' +
5007
+ ' var foo;' +
5008
+ ' void ["abcdefghijklmnopqrstuvwxyz"];' +
5009
+ ' }' +
5010
+ '];'
5011
+ },
5012
+ {
5013
+ sTitle:
5014
+ 'Consolidation within a variable statement in global code.',
5015
+ sInput:
5016
+ 'var foo = function() {' +
5017
+ ' void ["abcdefghijklmnopqrstuvwxyz",' +
5018
+ ' "abcdefghijklmnopqrstuvwxyz"];' +
5019
+ '};',
5020
+ sOutput:
5021
+ 'var foo = function() {' +
5022
+ ' var a = "abcdefghijklmnopqrstuvwxyz";' +
5023
+ ' void [a, a];' +
5024
+ '};'
5025
+ },
5026
+ {
5027
+ sTitle:
5028
+ 'Consolidation within a variable statement excluded in function ' +
5029
+ 'code due to the presence of a with statement.',
5030
+ sInput:
5031
+ '(function() {' +
5032
+ ' with ({});' +
5033
+ ' var foo = function() {' +
5034
+ ' void ["abcdefghijklmnopqrstuvwxyz",' +
5035
+ ' "abcdefghijklmnopqrstuvwxyz"];' +
5036
+ ' };' +
5037
+ '}());',
5038
+ sOutput:
5039
+ '(function() {' +
5040
+ ' with ({});' +
5041
+ ' var foo = function() {' +
5042
+ ' var a = "abcdefghijklmnopqrstuvwxyz";' +
5043
+ ' void [a, a];' +
5044
+ ' };' +
5045
+ '}());'
5046
+ },
5047
+ {
5048
+ sTitle:
5049
+ 'Consolidation within a variable statement excluded in function ' +
5050
+ 'code due to the presence of a direct call to the eval function.',
5051
+ sInput:
5052
+ '/*jshint evil:true */' +
5053
+ '(function() {' +
5054
+ ' eval("");' +
5055
+ ' var foo = function() {' +
5056
+ ' void ["abcdefghijklmnopqrstuvwxyz",' +
5057
+ ' "abcdefghijklmnopqrstuvwxyz"];' +
5058
+ ' };' +
5059
+ '}());',
5060
+ sOutput:
5061
+ '/*jshint evil:true */' +
5062
+ '(function() {' +
5063
+ ' eval("");' +
5064
+ ' var foo = function() {' +
5065
+ ' var a = "abcdefghijklmnopqrstuvwxyz";' +
5066
+ ' void [a, a];' +
5067
+ ' };' +
5068
+ '}());'
5069
+ },
5070
+ {
5071
+ sTitle:
5072
+ 'Inclusion of a variable statement in function code that ' +
5073
+ 'contains no with statement and no direct call to the eval ' +
5074
+ 'function.',
5075
+ sInput:
5076
+ '(function() {' +
5077
+ ' void ["abcdefghijklmnopqrstuvwxyz"];' +
5078
+ ' var foo;' +
5079
+ ' void ["abcdefghijklmnopqrstuvwxyz"];' +
5080
+ '}());',
5081
+ sOutput:
5082
+ '(function() {' +
5083
+ ' var a = "abcdefghijklmnopqrstuvwxyz";' +
5084
+ ' void [a];' +
5085
+ ' var foo;' +
5086
+ ' void [a];' +
5087
+ '}());'
5088
+ },
5089
+ {
5090
+ sTitle:
5091
+ 'Ignorance with regard to a variable statement in global code.',
5092
+ sInput:
5093
+ 'var foo = "abcdefghijklmnopqrstuvwxyz";' +
5094
+ 'void ["abcdefghijklmnopqrstuvwxyz",' +
5095
+ ' "abcdefghijklmnopqrstuvwxyz"];',
5096
+ sOutput:
5097
+ 'var foo = "abcdefghijklmnopqrstuvwxyz";' +
5098
+ '(function() {' +
5099
+ ' var a = "abcdefghijklmnopqrstuvwxyz";' +
5100
+ ' void [a, a];' +
5101
+ '}());'
5102
+ },
5103
+ // 12.4 Expression Statement.
5104
+ {
5105
+ sTitle:
5106
+ 'Preservation of identifiers in an expression statement.',
5107
+ sInput:
5108
+ 'void [typeof abcdefghijklmnopqrstuvwxyz,' +
5109
+ ' typeof abcdefghijklmnopqrstuvwxyz];'
5110
+ },
5111
+ // 12.6.3 The {@code for} Statement.
5112
+ {
5113
+ sTitle:
5114
+ 'Preservation of identifiers in the variable declaration list of ' +
5115
+ 'a for statement.',
5116
+ sInput:
5117
+ 'for (var abcdefghijklmnopqrstuvwxyz; 0 === Math.random(););' +
5118
+ 'for (var abcdefghijklmnopqrstuvwxyz; 0 === Math.random(););'
5119
+ },
5120
+ // 12.6.4 The {@code for-in} Statement.
5121
+ {
5122
+ sTitle:
5123
+ 'Preservation of identifiers in the variable declaration list of ' +
5124
+ 'a for-in statement.',
5125
+ sInput:
5126
+ 'for (var abcdefghijklmnopqrstuvwxyz in {});' +
5127
+ 'for (var abcdefghijklmnopqrstuvwxyz in {});'
5128
+ },
5129
+ // 12.7 The {@code continue} Statement.
5130
+ {
5131
+ sTitle:
5132
+ 'Preservation of the identifier in a continue statement.',
5133
+ sInput:
5134
+ 'abcdefghijklmnopqrstuvwxyz: for (; 0 === Math.random();) {' +
5135
+ ' continue abcdefghijklmnopqrstuvwxyz;' +
5136
+ '}' +
5137
+ 'abcdefghijklmnopqrstuvwxyz: for (; 0 === Math.random();) {' +
5138
+ ' continue abcdefghijklmnopqrstuvwxyz;' +
5139
+ '}'
5140
+ },
5141
+ // 12.8 The {@code break} Statement.
5142
+ {
5143
+ sTitle:
5144
+ 'Preservation of the identifier in a break statement.',
5145
+ sInput:
5146
+ 'abcdefghijklmnopqrstuvwxyz: for (; 0 === Math.random();) {' +
5147
+ ' break abcdefghijklmnopqrstuvwxyz;' +
5148
+ '}' +
5149
+ 'abcdefghijklmnopqrstuvwxyz: for (; 0 === Math.random();) {' +
5150
+ ' break abcdefghijklmnopqrstuvwxyz;' +
5151
+ '}'
5152
+ },
5153
+ // 12.9 The {@code return} Statement.
5154
+ {
5155
+ sTitle:
5156
+ 'Exclusion of a return statement in function code that contains ' +
5157
+ 'a with statement.',
5158
+ sInput:
5159
+ '(function() {' +
5160
+ ' with ({});' +
5161
+ ' void ["abcdefghijklmnopqrstuvwxyz"];' +
5162
+ ' if (0 === Math.random()) {' +
5163
+ ' return;' +
5164
+ ' } else {' +
5165
+ ' }' +
5166
+ ' void ["abcdefghijklmnopqrstuvwxyz"];' +
5167
+ '}());'
5168
+ },
5169
+ {
5170
+ sTitle:
5171
+ 'Exclusion of a return statement in function code that contains ' +
5172
+ 'a direct call to the eval function.',
5173
+ sInput:
5174
+ '/*jshint evil:true */' +
5175
+ '(function() {' +
5176
+ ' eval("");' +
5177
+ ' void ["abcdefghijklmnopqrstuvwxyz"];' +
5178
+ ' if (0 === Math.random()) {' +
5179
+ ' return;' +
5180
+ ' } else {' +
5181
+ ' }' +
5182
+ ' void ["abcdefghijklmnopqrstuvwxyz"];' +
5183
+ '}());'
5184
+ },
5185
+ {
5186
+ sTitle:
5187
+ 'Consolidation within a return statement excluded in function ' +
5188
+ 'code due to the presence of a with statement.',
5189
+ sInput:
5190
+ '(function() {' +
5191
+ ' with ({});' +
5192
+ ' return function() {' +
5193
+ ' void ["abcdefghijklmnopqrstuvwxyz",' +
5194
+ ' "abcdefghijklmnopqrstuvwxyz"];' +
5195
+ ' };' +
5196
+ '}());',
5197
+ sOutput:
5198
+ '(function() {' +
5199
+ ' with ({});' +
5200
+ ' return function() {' +
5201
+ ' var a = "abcdefghijklmnopqrstuvwxyz";' +
5202
+ ' void [a, a];' +
5203
+ ' };' +
5204
+ '}());'
5205
+ },
5206
+ {
5207
+ sTitle:
5208
+ 'Consolidation within a return statement excluded in function ' +
5209
+ 'code due to the presence of a direct call to the eval function.',
5210
+ sInput:
5211
+ '/*jshint evil:true */' +
5212
+ '(function() {' +
5213
+ ' eval("");' +
5214
+ ' return function() {' +
5215
+ ' void ["abcdefghijklmnopqrstuvwxyz",' +
5216
+ ' "abcdefghijklmnopqrstuvwxyz"];' +
5217
+ ' };' +
5218
+ '}());',
5219
+ sOutput:
5220
+ '/*jshint evil:true */' +
5221
+ '(function() {' +
5222
+ ' eval("");' +
5223
+ ' return function() {' +
5224
+ ' var a = "abcdefghijklmnopqrstuvwxyz";' +
5225
+ ' void [a, a];' +
5226
+ ' };' +
5227
+ '}());'
5228
+ },
5229
+ {
5230
+ sTitle:
5231
+ 'Inclusion of a return statement in function code that contains ' +
5232
+ 'no with statement and no direct call to the eval function.',
5233
+ sInput:
5234
+ '(function() {' +
5235
+ ' void ["abcdefghijklmnopqrstuvwxyz"];' +
5236
+ ' if (0 === Math.random()) {' +
5237
+ ' return;' +
5238
+ ' } else {' +
5239
+ ' }' +
5240
+ ' void ["abcdefghijklmnopqrstuvwxyz"];' +
5241
+ '}());',
5242
+ sOutput:
5243
+ '(function() {' +
5244
+ ' var a = "abcdefghijklmnopqrstuvwxyz";' +
5245
+ ' void [a];' +
5246
+ ' if (0 === Math.random()) {' +
5247
+ ' return;' +
5248
+ ' } else {' +
5249
+ ' }' +
5250
+ ' void [a];' +
5251
+ '}());'
5252
+ },
5253
+ // 12.10 The {@code with} Statement.
5254
+ {
5255
+ sTitle:
5256
+ 'Preservation of the statement in a with statement.',
5257
+ sInput:
5258
+ 'with ({}) {' +
5259
+ ' void ["abcdefghijklmnopqrstuvwxyz",' +
5260
+ ' "abcdefghijklmnopqrstuvwxyz"];' +
5261
+ '}'
5262
+ },
5263
+ {
5264
+ sTitle:
5265
+ 'Exclusion of a with statement in the same syntactic code unit.',
5266
+ sInput:
5267
+ 'void ["abcdefghijklmnopqrstuvwxyz"];' +
5268
+ 'with ({' +
5269
+ ' foo: "abcdefghijklmnopqrstuvwxyz",' +
5270
+ ' bar: "abcdefghijklmnopqrstuvwxyz"' +
5271
+ '}) {' +
5272
+ ' void ["abcdefghijklmnopqrstuvwxyz",' +
5273
+ ' "abcdefghijklmnopqrstuvwxyz"];' +
5274
+ '}' +
5275
+ 'void ["abcdefghijklmnopqrstuvwxyz"];'
5276
+ },
5277
+ {
5278
+ sTitle:
5279
+ 'Exclusion of a with statement in nested function code.',
5280
+ sInput:
5281
+ 'void ["abcdefghijklmnopqrstuvwxyz"];' +
5282
+ '(function() {' +
5283
+ ' with ({' +
5284
+ ' foo: "abcdefghijklmnopqrstuvwxyz",' +
5285
+ ' bar: "abcdefghijklmnopqrstuvwxyz"' +
5286
+ ' }) {' +
5287
+ ' void ["abcdefghijklmnopqrstuvwxyz",' +
5288
+ ' "abcdefghijklmnopqrstuvwxyz"];' +
5289
+ ' }' +
5290
+ '}());' +
5291
+ 'void ["abcdefghijklmnopqrstuvwxyz"];'
5292
+ },
5293
+ // 12.12 Labelled Statements.
5294
+ {
5295
+ sTitle:
5296
+ 'Preservation of the label of a labelled statement.',
5297
+ sInput:
5298
+ 'abcdefghijklmnopqrstuvwxyz: for (; 0 === Math.random(););' +
5299
+ 'abcdefghijklmnopqrstuvwxyz: for (; 0 === Math.random(););'
5300
+ },
5301
+ // 12.14 The {@code try} Statement.
5302
+ {
5303
+ sTitle:
5304
+ 'Preservation of the identifier in the catch clause of a try' +
5305
+ 'statement.',
5306
+ sInput:
5307
+ 'try {' +
5308
+ '} catch (abcdefghijklmnopqrstuvwxyz) {' +
5309
+ '} finally {' +
5310
+ '}' +
5311
+ 'try {' +
5312
+ '} catch (abcdefghijklmnopqrstuvwxyz) {' +
5313
+ '} finally {' +
5314
+ '}'
5315
+ },
5316
+ // 13 Function Definition.
5317
+ {
5318
+ sTitle:
5319
+ 'Preservation of the identifier of a function declaration.',
5320
+ sInput:
5321
+ 'function abcdefghijklmnopqrstuvwxyz() {' +
5322
+ '}' +
5323
+ 'void [abcdefghijklmnopqrstuvwxyz];'
5324
+ },
5325
+ {
5326
+ sTitle:
5327
+ 'Preservation of the identifier of a function expression.',
5328
+ sInput:
5329
+ 'void [' +
5330
+ ' function abcdefghijklmnopqrstuvwxyz() {' +
5331
+ ' },' +
5332
+ ' function abcdefghijklmnopqrstuvwxyz() {' +
5333
+ ' }' +
5334
+ '];'
5335
+ },
5336
+ {
5337
+ sTitle:
5338
+ 'Preservation of a formal parameter of a function declaration.',
5339
+ sInput:
5340
+ 'function foo(abcdefghijklmnopqrstuvwxyz) {' +
5341
+ '}' +
5342
+ 'function bar(abcdefghijklmnopqrstuvwxyz) {' +
5343
+ '}'
5344
+ },
5345
+ {
5346
+ sTitle:
5347
+ 'Preservation of a formal parameter in a function expression.',
5348
+ sInput:
5349
+ 'void [' +
5350
+ ' function(abcdefghijklmnopqrstuvwxyz) {' +
5351
+ ' },' +
5352
+ ' function(abcdefghijklmnopqrstuvwxyz) {' +
5353
+ ' }' +
5354
+ '];'
5355
+ },
5356
+ {
5357
+ sTitle:
5358
+ 'Exclusion of a function declaration.',
5359
+ sInput:
5360
+ 'void ["abcdefghijklmnopqrstuvwxyz"];' +
5361
+ 'function foo() {' +
5362
+ '}' +
5363
+ 'void ["abcdefghijklmnopqrstuvwxyz"];'
5364
+ },
5365
+ {
5366
+ sTitle:
5367
+ 'Consolidation within a function declaration.',
5368
+ sInput:
5369
+ 'function foo() {' +
5370
+ ' void ["abcdefghijklmnopqrstuvwxyz",' +
5371
+ ' "abcdefghijklmnopqrstuvwxyz"];' +
5372
+ '}',
5373
+ sOutput:
5374
+ 'function foo() {' +
5375
+ ' var a = "abcdefghijklmnopqrstuvwxyz";' +
5376
+ ' void [a, a];' +
5377
+ '}'
5378
+ },
5379
+ // 14 Program.
5380
+ {
5381
+ sTitle:
5382
+ 'Preservation of a program without source elements.',
5383
+ sInput:
5384
+ ''
5385
+ },
5386
+ // 14.1 Directive Prologues and the Use Strict Directive.
5387
+ {
5388
+ sTitle:
5389
+ 'Preservation of a Directive Prologue in global code.',
5390
+ sInput:
5391
+ '"abcdefghijklmnopqrstuvwxyz";' +
5392
+ '\'zyxwvutsrqponmlkjihgfedcba\';'
5393
+ },
5394
+ {
5395
+ sTitle:
5396
+ 'Preservation of a Directive Prologue in a function declaration.',
5397
+ sInput:
5398
+ 'function foo() {' +
5399
+ ' "abcdefghijklmnopqrstuvwxyz";' +
5400
+ ' \'zyxwvutsrqponmlkjihgfedcba\';' +
5401
+ '}'
5402
+ },
5403
+ {
5404
+ sTitle:
5405
+ 'Preservation of a Directive Prologue in a function expression.',
5406
+ sInput:
5407
+ 'void [' +
5408
+ ' function() {' +
5409
+ ' "abcdefghijklmnopqrstuvwxyz";' +
5410
+ ' \'zyxwvutsrqponmlkjihgfedcba\';' +
5411
+ ' }' +
5412
+ '];'
5413
+ },
5414
+ {
5415
+ sTitle:
5416
+ 'Ignorance with regard to a Directive Prologue in global code.',
5417
+ sInput:
5418
+ '"abcdefghijklmnopqrstuvwxyz";' +
5419
+ 'void ["abcdefghijklmnopqrstuvwxyz",' +
5420
+ ' "abcdefghijklmnopqrstuvwxyz"];',
5421
+ sOutput:
5422
+ '"abcdefghijklmnopqrstuvwxyz";' +
5423
+ '(function() {' +
5424
+ ' var a = "abcdefghijklmnopqrstuvwxyz";' +
5425
+ ' void [a, a];' +
5426
+ '}());'
5427
+ },
5428
+ {
5429
+ sTitle:
5430
+ 'Ignorance with regard to a Directive Prologue in a function' +
5431
+ 'declaration.',
5432
+ sInput:
5433
+ 'function foo() {' +
5434
+ ' "abcdefghijklmnopqrstuvwxyz";' +
5435
+ ' void ["abcdefghijklmnopqrstuvwxyz",' +
5436
+ ' "abcdefghijklmnopqrstuvwxyz"];' +
5437
+ '}',
5438
+ sOutput:
5439
+ 'function foo() {' +
5440
+ ' "abcdefghijklmnopqrstuvwxyz";' +
5441
+ ' var a = "abcdefghijklmnopqrstuvwxyz";' +
5442
+ ' void [a, a];' +
5443
+ '}'
5444
+ },
5445
+ {
5446
+ sTitle:
5447
+ 'Ignorance with regard to a Directive Prologue in a function' +
5448
+ 'expression.',
5449
+ sInput:
5450
+ '(function() {' +
5451
+ ' "abcdefghijklmnopqrstuvwxyz";' +
5452
+ ' void ["abcdefghijklmnopqrstuvwxyz",' +
5453
+ ' "abcdefghijklmnopqrstuvwxyz"];' +
5454
+ '}());',
5455
+ sOutput:
5456
+ '(function() {' +
5457
+ ' "abcdefghijklmnopqrstuvwxyz";' +
5458
+ ' var a = "abcdefghijklmnopqrstuvwxyz";' +
5459
+ ' void [a, a];' +
5460
+ '}());'
5461
+ },
5462
+ // 15.1 The Global Object.
5463
+ {
5464
+ sTitle:
5465
+ 'Preservation of a property of the global object.',
5466
+ sInput:
5467
+ 'void [undefined, undefined, undefined, undefined, undefined];'
5468
+ },
5469
+ // 15.1.2.1.1 Direct Call to Eval.
5470
+ {
5471
+ sTitle:
5472
+ 'Exclusion of a direct call to the eval function in the same ' +
5473
+ 'syntactic code unit.',
5474
+ sInput:
5475
+ '/*jshint evil:true */' +
5476
+ 'void ["abcdefghijklmnopqrstuvwxyz"];' +
5477
+ 'eval("");' +
5478
+ 'void ["abcdefghijklmnopqrstuvwxyz"];'
5479
+ },
5480
+ {
5481
+ sTitle:
5482
+ 'Exclusion of a direct call to the eval function in nested ' +
5483
+ 'function code.',
5484
+ sInput:
5485
+ '/*jshint evil:true */' +
5486
+ 'void ["abcdefghijklmnopqrstuvwxyz"];' +
5487
+ '(function() {' +
5488
+ ' eval("");' +
5489
+ '}());' +
5490
+ 'void ["abcdefghijklmnopqrstuvwxyz"];'
5491
+ },
5492
+ {
5493
+ sTitle:
5494
+ 'Consolidation within a direct call to the eval function.',
5495
+ sInput:
5496
+ '/*jshint evil:true */' +
5497
+ 'eval(function() {' +
5498
+ ' void ["abcdefghijklmnopqrstuvwxyz",' +
5499
+ ' "abcdefghijklmnopqrstuvwxyz"];' +
5500
+ '}());',
5501
+ sOutput:
5502
+ '/*jshint evil:true */' +
5503
+ 'eval(function() {' +
5504
+ ' var a = "abcdefghijklmnopqrstuvwxyz";' +
5505
+ ' void [a, a];' +
5506
+ '}());'
5507
+ },
5508
+ // Consolidation proper.
5509
+ {
5510
+ sTitle:
5511
+ 'No consolidation if it does not result in a reduction of the ' +
5512
+ 'number of source characters.',
5513
+ sInput:
5514
+ '(function() {' +
5515
+ ' var foo;' +
5516
+ ' void ["ab", "ab", "abc", "abc"];' +
5517
+ '}());'
5518
+ },
5519
+ {
5520
+ sTitle:
5521
+ 'Identification of a range of source elements at the beginning ' +
5522
+ 'of global code.',
5523
+ sInput:
5524
+ '/*jshint evil:true */' +
5525
+ '"abcdefghijklmnopqrstuvwxyz";' +
5526
+ 'void ["abcdefghijklmnopqrstuvwxyz",' +
5527
+ ' "abcdefghijklmnopqrstuvwxyz"];' +
5528
+ 'eval("");',
5529
+ sOutput:
5530
+ '/*jshint evil:true */' +
5531
+ '"abcdefghijklmnopqrstuvwxyz";' +
5532
+ '(function() {' +
5533
+ ' var a = "abcdefghijklmnopqrstuvwxyz";' +
5534
+ ' void [a, a];' +
5535
+ '}());' +
5536
+ 'eval("");'
5537
+ },
5538
+ {
5539
+ sTitle:
5540
+ 'Identification of a range of source elements in the middle of ' +
5541
+ 'global code.',
5542
+ sInput:
5543
+ '/*jshint evil:true */' +
5544
+ '"abcdefghijklmnopqrstuvwxyz";' +
5545
+ 'eval("");' +
5546
+ 'void ["abcdefghijklmnopqrstuvwxyz",' +
5547
+ ' "abcdefghijklmnopqrstuvwxyz"];' +
5548
+ 'eval("");',
5549
+ sOutput:
5550
+ '/*jshint evil:true */' +
5551
+ '"abcdefghijklmnopqrstuvwxyz";' +
5552
+ 'eval("");' +
5553
+ '(function() {' +
5554
+ ' var a = "abcdefghijklmnopqrstuvwxyz";' +
5555
+ ' void [a, a];' +
5556
+ '}());' +
5557
+ 'eval("");'
5558
+ },
5559
+ {
5560
+ sTitle:
5561
+ 'Identification of a range of source elements at the end of ' +
5562
+ 'global code.',
5563
+ sInput:
5564
+ '/*jshint evil:true */' +
5565
+ '"abcdefghijklmnopqrstuvwxyz";' +
5566
+ 'eval("");' +
5567
+ 'void ["abcdefghijklmnopqrstuvwxyz",' +
5568
+ ' "abcdefghijklmnopqrstuvwxyz"];',
5569
+ sOutput:
5570
+ '/*jshint evil:true */' +
5571
+ '"abcdefghijklmnopqrstuvwxyz";' +
5572
+ 'eval("");' +
5573
+ '(function() {' +
5574
+ ' var a = "abcdefghijklmnopqrstuvwxyz";' +
5575
+ ' void [a, a];' +
5576
+ '}());'
5577
+ },
5578
+ {
5579
+ sTitle:
5580
+ 'Identification of a range of source elements at the beginning ' +
5581
+ 'of function code.',
5582
+ sInput:
5583
+ '/*jshint evil:true */' +
5584
+ '(function() {' +
5585
+ ' "abcdefghijklmnopqrstuvwxyz";' +
5586
+ ' void ["abcdefghijklmnopqrstuvwxyz",' +
5587
+ ' "abcdefghijklmnopqrstuvwxyz"];' +
5588
+ ' eval("");' +
5589
+ '}());',
5590
+ sOutput:
5591
+ '/*jshint evil:true */' +
5592
+ '(function() {' +
5593
+ ' "abcdefghijklmnopqrstuvwxyz";' +
5594
+ ' (function() {' +
5595
+ ' var a = "abcdefghijklmnopqrstuvwxyz";' +
5596
+ ' void [a, a];' +
5597
+ ' }());' +
5598
+ ' eval("");' +
5599
+ '}());'
5600
+ },
5601
+ {
5602
+ sTitle:
5603
+ 'Identification of a range of source elements in the middle of ' +
5604
+ 'function code.',
5605
+ sInput:
5606
+ '/*jshint evil:true */' +
5607
+ '(function() {' +
5608
+ ' "abcdefghijklmnopqrstuvwxyz";' +
5609
+ ' eval("");' +
5610
+ ' void ["abcdefghijklmnopqrstuvwxyz",' +
5611
+ ' "abcdefghijklmnopqrstuvwxyz"];' +
5612
+ ' eval("");' +
5613
+ '}());',
5614
+ sOutput:
5615
+ '/*jshint evil:true */' +
5616
+ '(function() {' +
5617
+ ' "abcdefghijklmnopqrstuvwxyz";' +
5618
+ ' eval("");' +
5619
+ ' (function() {' +
5620
+ ' var a = "abcdefghijklmnopqrstuvwxyz";' +
5621
+ ' void [a, a];' +
5622
+ ' }());' +
5623
+ ' eval("");' +
5624
+ '}());'
5625
+ },
5626
+ {
5627
+ sTitle:
5628
+ 'Identification of a range of source elements at the end of ' +
5629
+ 'function code.',
5630
+ sInput:
5631
+ '/*jshint evil:true */' +
5632
+ '(function() {' +
5633
+ ' "abcdefghijklmnopqrstuvwxyz";' +
5634
+ ' eval("");' +
5635
+ ' void ["abcdefghijklmnopqrstuvwxyz",' +
5636
+ ' "abcdefghijklmnopqrstuvwxyz"];' +
5637
+ '}());',
5638
+ sOutput:
5639
+ '/*jshint evil:true */' +
5640
+ '(function() {' +
5641
+ ' "abcdefghijklmnopqrstuvwxyz";' +
5642
+ ' eval("");' +
5643
+ ' (function() {' +
5644
+ ' var a = "abcdefghijklmnopqrstuvwxyz";' +
5645
+ ' void [a, a];' +
5646
+ ' }());' +
5647
+ '}());'
5648
+ },
5649
+ {
5650
+ sTitle:
5651
+ 'Evaluation with regard to String values of String literals and ' +
5652
+ 'String values derived from identifier names used as property' +
5653
+ 'accessors.',
5654
+ sInput:
5655
+ '(function() {' +
5656
+ ' var foo;' +
5657
+ ' void ["abcdefg", Math.abcdefg, "abcdef", Math.abcdef];' +
5658
+ '}());',
5659
+ sOutput:
5660
+ '(function() {' +
5661
+ ' var a = "abcdefg", foo;' +
5662
+ ' void [a, Math[a], "abcdef", Math.abcdef];' +
5663
+ '}());'
5664
+ },
5665
+ {
5666
+ sTitle:
5667
+ 'Evaluation with regard to the necessity of adding a variable ' +
5668
+ 'statement.',
5669
+ sInput:
5670
+ '/*jshint evil:true */' +
5671
+ '(function() {' +
5672
+ ' void ["abcdefgh", "abcdefgh"];' +
5673
+ '}());' +
5674
+ 'eval("");' +
5675
+ '(function() {' +
5676
+ ' void ["abcdefg", "abcdefg"];' +
5677
+ '}());' +
5678
+ 'eval("");' +
5679
+ '(function() {' +
5680
+ ' var foo;' +
5681
+ ' void ["abcd", "abcd"];' +
5682
+ '}());',
5683
+ sOutput:
5684
+ '/*jshint evil:true */' +
5685
+ '(function() {' +
5686
+ ' var a = "abcdefgh";' +
5687
+ ' void [a, a];' +
5688
+ '}());' +
5689
+ 'eval("");' +
5690
+ '(function() {' +
5691
+ ' void ["abcdefg", "abcdefg"];' +
5692
+ '}());' +
5693
+ 'eval("");' +
5694
+ '(function() {' +
5695
+ ' var a = "abcd", foo;' +
5696
+ ' void [a, a];' +
5697
+ '}());'
5698
+ },
5699
+ {
5700
+ sTitle:
5701
+ 'Evaluation with regard to the necessity of enclosing source ' +
5702
+ 'elements.',
5703
+ sInput:
5704
+ '/*jshint evil:true */' +
5705
+ 'void ["abcdefghijklmnopqrstuvwxy", "abcdefghijklmnopqrstuvwxy"];' +
5706
+ 'eval("");' +
5707
+ 'void ["abcdefghijklmnopqrstuvwx", "abcdefghijklmnopqrstuvwx"];' +
5708
+ 'eval("");' +
5709
+ '(function() {' +
5710
+ ' void ["abcdefgh", "abcdefgh"];' +
5711
+ '}());' +
5712
+ '(function() {' +
5713
+ ' void ["abcdefghijklmnopqrstuvwxy",' +
5714
+ ' "abcdefghijklmnopqrstuvwxy"];' +
5715
+ ' eval("");' +
5716
+ ' void ["abcdefghijklmnopqrstuvwx",' +
5717
+ ' "abcdefghijklmnopqrstuvwx"];' +
5718
+ ' eval("");' +
5719
+ ' (function() {' +
5720
+ ' void ["abcdefgh", "abcdefgh"];' +
5721
+ ' }());' +
5722
+ '}());',
5723
+ sOutput:
5724
+ '/*jshint evil:true */' +
5725
+ '(function() {' +
5726
+ ' var a = "abcdefghijklmnopqrstuvwxy";' +
5727
+ ' void [a, a];' +
5728
+ '}());' +
5729
+ 'eval("");' +
5730
+ 'void ["abcdefghijklmnopqrstuvwx", "abcdefghijklmnopqrstuvwx"];' +
5731
+ 'eval("");' +
5732
+ '(function() {' +
5733
+ ' var a = "abcdefgh";' +
5734
+ ' void [a, a];' +
5735
+ '}());' +
5736
+ '(function() {' +
5737
+ ' (function() {' +
5738
+ ' var a = "abcdefghijklmnopqrstuvwxy";' +
5739
+ ' void [a, a];' +
5740
+ ' }());' +
5741
+ ' eval("");' +
5742
+ ' void ["abcdefghijklmnopqrstuvwx", "abcdefghijklmnopqrstuvwx"];' +
5743
+ ' eval("");' +
5744
+ ' (function() {' +
5745
+ ' var a = "abcdefgh";' +
5746
+ ' void [a, a];' +
5747
+ ' }());' +
5748
+ '}());'
5749
+ },
5750
+ {
5751
+ sTitle:
5752
+ 'Employment of a closure while consolidating in global code.',
5753
+ sInput:
5754
+ 'void ["abcdefghijklmnopqrstuvwxyz",' +
5755
+ ' "abcdefghijklmnopqrstuvwxyz"];',
5756
+ sOutput:
5757
+ '(function() {' +
5758
+ ' var a = "abcdefghijklmnopqrstuvwxyz";' +
5759
+ ' void [a, a];' +
5760
+ '}());'
5761
+ },
5762
+ {
5763
+ sTitle:
5764
+ 'Assignment of a shorter identifier to a value whose ' +
5765
+ 'consolidation results in a greater reduction of the number of ' +
5766
+ 'source characters.',
5767
+ sInput:
5768
+ '(function() {' +
5769
+ ' var b, c, d, e, f, g, h, i, j, k, l, m,' +
5770
+ ' n, o, p, q, r, s, t, u, v, w, x, y, z,' +
5771
+ ' A, B, C, D, E, F, G, H, I, J, K, L, M,' +
5772
+ ' N, O, P, Q, R, S, T, U, V, W, X, Y, Z,' +
5773
+ ' $, _;' +
5774
+ ' void ["abcde", "abcde", "edcba", "edcba", "edcba"];' +
5775
+ '}());',
5776
+ sOutput:
5777
+ '(function() {' +
5778
+ ' var a = "edcba",' +
5779
+ ' b, c, d, e, f, g, h, i, j, k, l, m,' +
5780
+ ' n, o, p, q, r, s, t, u, v, w, x, y, z,' +
5781
+ ' A, B, C, D, E, F, G, H, I, J, K, L, M,' +
5782
+ ' N, O, P, Q, R, S, T, U, V, W, X, Y, Z,' +
5783
+ ' $, _;' +
5784
+ ' void ["abcde", "abcde", a, a, a];' +
5785
+ '}());'
5786
+ }
5787
+ ].forEach(cAssert);
5788
+ }());
5789
+ }
5790
+
5791
+ /* Local Variables: */
5792
+ /* mode: js */
5793
+ /* coding: utf-8 */
5794
+ /* indent-tabs-mode: nil */
5795
+ /* tab-width: 2 */
5796
+ /* End: */
5797
+ /* vim: set ft=javascript fenc=utf-8 et ts=2 sts=2 sw=2: */
5798
+ /* :mode=javascript:noTabs=true:tabSize=2:indentSize=2:deepIndent=true: */
5799
+
5800
+ });
5801
+ define('uglifyjs/parse-js', ["exports"], function(exports) {
5802
+
3153
5803
  /***********************************************************************
3154
5804
 
3155
5805
  A JavaScript tokenizer / parser / beautifier / compressor.
@@ -3217,6 +5867,7 @@ var KEYWORDS = array_to_hash([
3217
5867
  "catch",
3218
5868
  "const",
3219
5869
  "continue",
5870
+ "debugger",
3220
5871
  "default",
3221
5872
  "delete",
3222
5873
  "do",
@@ -3245,7 +5896,6 @@ var RESERVED_WORDS = array_to_hash([
3245
5896
  "byte",
3246
5897
  "char",
3247
5898
  "class",
3248
- "debugger",
3249
5899
  "double",
3250
5900
  "enum",
3251
5901
  "export",
@@ -3343,7 +5993,7 @@ var OPERATORS = array_to_hash([
3343
5993
 
3344
5994
  var WHITESPACE_CHARS = array_to_hash(characters(" \u00a0\n\r\t\f\u000b\u200b\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000"));
3345
5995
 
3346
- var PUNC_BEFORE_EXPRESSION = array_to_hash(characters("[{}(,.;:"));
5996
+ var PUNC_BEFORE_EXPRESSION = array_to_hash(characters("[{(,.;:"));
3347
5997
 
3348
5998
  var PUNC_CHARS = array_to_hash(characters("[]{}(),;:"));
3349
5999
 
@@ -3638,10 +6288,10 @@ function tokenizer($TEXT) {
3638
6288
  };
3639
6289
 
3640
6290
  function read_name() {
3641
- var backslash = false, name = "", ch;
6291
+ var backslash = false, name = "", ch, escaped = false, hex;
3642
6292
  while ((ch = peek()) != null) {
3643
6293
  if (!backslash) {
3644
- if (ch == "\\") backslash = true, next();
6294
+ if (ch == "\\") escaped = backslash = true, next();
3645
6295
  else if (is_identifier_char(ch)) name += next();
3646
6296
  else break;
3647
6297
  }
@@ -3653,6 +6303,10 @@ function tokenizer($TEXT) {
3653
6303
  backslash = false;
3654
6304
  }
3655
6305
  }
6306
+ if (HOP(KEYWORDS, name) && escaped) {
6307
+ hex = name.charCodeAt(0).toString(16).toUpperCase();
6308
+ name = "\\u" + "0000".substr(hex.length) + hex + name.slice(1);
6309
+ }
3656
6310
  return name;
3657
6311
  };
3658
6312
 
@@ -4061,8 +6715,11 @@ function parse($TEXT, exigent_mode, embed_tokens) {
4061
6715
  init = is("keyword", "var")
4062
6716
  ? (next(), var_(true))
4063
6717
  : expression(true, true);
4064
- if (is("operator", "in"))
6718
+ if (is("operator", "in")) {
6719
+ if (init[0] == "var" && init[1].length > 1)
6720
+ croak("Only one variable declaration allowed in for..in loop");
4065
6721
  return for_in(init);
6722
+ }
4066
6723
  }
4067
6724
  return regular_for(init);
4068
6725
  };
@@ -4540,6 +7197,10 @@ function ast_squeeze_more(ast) {
4540
7197
  }
4541
7198
  },
4542
7199
  "call": function(expr, args) {
7200
+ if (expr[0] == "dot" && expr[1][0] == "string" && args.length == 1
7201
+ && (args[0][1] > 0 && expr[2] == "substring" || expr[2] == "substr")) {
7202
+ return [ "call", [ "dot", expr[1], "slice"], args];
7203
+ }
4543
7204
  if (expr[0] == "dot" && expr[2] == "toString" && args.length == 0) {
4544
7205
  // foo.toString() ==> foo+""
4545
7206
  return [ "binary", "+", expr[1], [ "string", "" ]];
@@ -4706,6 +7367,9 @@ function ast_walker() {
4706
7367
  "function": function(name, args, body) {
4707
7368
  return [ this[0], name, args.slice(), MAP(body, walk) ];
4708
7369
  },
7370
+ "debugger": function() {
7371
+ return [ this[0] ];
7372
+ },
4709
7373
  "defun": function(name, args, body) {
4710
7374
  return [ this[0], name, args.slice(), MAP(body, walk) ];
4711
7375
  },
@@ -4849,12 +7513,13 @@ function Scope(parent) {
4849
7513
  };
4850
7514
 
4851
7515
  var base54 = (function(){
4852
- var DIGITS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_";
7516
+ var DIGITS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_0123456789";
4853
7517
  return function(num) {
4854
- var ret = "";
7518
+ var ret = "", base = 54;
4855
7519
  do {
4856
- ret = DIGITS.charAt(num % 54) + ret;
4857
- num = Math.floor(num / 54);
7520
+ ret += DIGITS.charAt(num % base);
7521
+ num = Math.floor(num / base);
7522
+ base = 64;
4858
7523
  } while (num > 0);
4859
7524
  return ret;
4860
7525
  };
@@ -5308,7 +7973,9 @@ var when_constant = (function(){
5308
7973
  case "string": ast = [ "string", val ]; break;
5309
7974
  case "number": ast = [ "num", val ]; break;
5310
7975
  case "boolean": ast = [ "name", String(val) ]; break;
5311
- default: throw new Error("Can't handle constant of type: " + (typeof val));
7976
+ default:
7977
+ if (val === null) { ast = [ "atom", "null" ]; break; }
7978
+ throw new Error("Can't handle constant of type: " + (typeof val));
5312
7979
  }
5313
7980
  return yes.call(expr, ast, val);
5314
7981
  } catch(ex) {
@@ -5377,17 +8044,15 @@ function prepare_ifs(ast) {
5377
8044
 
5378
8045
  var conditional = walk(fi[1]);
5379
8046
 
5380
- var e_body = statements.slice(i + 1);
8047
+ var e_body = redo_if(statements.slice(i + 1));
5381
8048
  var e = e_body.length == 1 ? e_body[0] : [ "block", e_body ];
5382
8049
 
5383
- var ret = statements.slice(0, i).concat([ [
8050
+ return statements.slice(0, i).concat([ [
5384
8051
  fi[0], // "if"
5385
8052
  conditional, // conditional
5386
8053
  t, // then
5387
8054
  e // else
5388
8055
  ] ]);
5389
-
5390
- return redo_if(ret);
5391
8056
  }
5392
8057
 
5393
8058
  return statements;
@@ -5752,6 +8417,16 @@ function ast_squeeze(ast, options) {
5752
8417
  });
5753
8418
  };
5754
8419
 
8420
+ function abort_else(c, t, e) {
8421
+ var ret = [ [ "if", negate(c), e ] ];
8422
+ if (t[0] == "block") {
8423
+ if (t[1]) ret = ret.concat(t[1]);
8424
+ } else {
8425
+ ret.push(t);
8426
+ }
8427
+ return walk([ "block", ret ]);
8428
+ };
8429
+
5755
8430
  function make_real_if(c, t, e) {
5756
8431
  c = walk(c);
5757
8432
  t = walk(t);
@@ -5785,9 +8460,10 @@ function ast_squeeze(ast, options) {
5785
8460
  }
5786
8461
  else if (t[0] == "stat") {
5787
8462
  if (e) {
5788
- if (e[0] == "stat") {
8463
+ if (e[0] == "stat")
5789
8464
  ret = best_of(ret, [ "stat", make_conditional(c, t[1], e[1]) ]);
5790
- }
8465
+ else if (aborts(e))
8466
+ ret = abort_else(c, t, e);
5791
8467
  }
5792
8468
  else {
5793
8469
  ret = best_of(ret, [ "stat", make_conditional(c, t[1]) ]);
@@ -5807,13 +8483,7 @@ function ast_squeeze(ast, options) {
5807
8483
  ret = walk([ "block", ret ]);
5808
8484
  }
5809
8485
  else if (t && aborts(e)) {
5810
- ret = [ [ "if", negate(c), e ] ];
5811
- if (t[0] == "block") {
5812
- if (t[1]) ret = ret.concat(t[1]);
5813
- } else {
5814
- ret.push(t);
5815
- }
5816
- ret = walk([ "block", ret ]);
8486
+ ret = abort_else(c, t, e);
5817
8487
  }
5818
8488
  return ret;
5819
8489
  };
@@ -5945,7 +8615,6 @@ function make_string(str, ascii_only) {
5945
8615
  case "\f": return "\\f";
5946
8616
  case "\n": return "\\n";
5947
8617
  case "\r": return "\\r";
5948
- case "\t": return "\\t";
5949
8618
  case "\u2028": return "\\u2028";
5950
8619
  case "\u2029": return "\\u2029";
5951
8620
  case '"': ++dq; return '"';
@@ -6106,6 +8775,7 @@ function gen_code(ast, options) {
6106
8775
  "string": encode_string,
6107
8776
  "num": make_num,
6108
8777
  "name": make_name,
8778
+ "debugger": function(){ return "debugger" },
6109
8779
  "toplevel": function(statements) {
6110
8780
  return make_block_statements(statements)
6111
8781
  .join(newline + newline);
@@ -6189,7 +8859,7 @@ function gen_code(ast, options) {
6189
8859
  if (expr[0] == "num") {
6190
8860
  if (!/\./.test(expr[1]))
6191
8861
  out += ".";
6192
- } else if (needs_parens(expr))
8862
+ } else if (expr[0] != "function" && needs_parens(expr))
6193
8863
  out = "(" + out + ")";
6194
8864
  while (i < arguments.length)
6195
8865
  out += "." + make_name(arguments[i++]);
@@ -6287,7 +8957,7 @@ function gen_code(ast, options) {
6287
8957
  if (p.length == 3) {
6288
8958
  // getter/setter. The name is in p[0], the arg.list in p[1][2], the
6289
8959
  // body in p[1][3] and type ("get" / "set") in p[2].
6290
- return indent(make_function(p[0], p[1][2], p[1][3], p[2]));
8960
+ return indent(make_function(p[0], p[1][2], p[1][3], p[2], true));
6291
8961
  }
6292
8962
  var key = p[0], val = parenthesize(p[1], "seq");
6293
8963
  if (options.quote_keys) {
@@ -6364,14 +9034,14 @@ function gen_code(ast, options) {
6364
9034
  return make(th);
6365
9035
  };
6366
9036
 
6367
- function make_function(name, args, body, keyword) {
9037
+ function make_function(name, args, body, keyword, no_parens) {
6368
9038
  var out = keyword || "function";
6369
9039
  if (name) {
6370
9040
  out += " " + make_name(name);
6371
9041
  }
6372
9042
  out += "(" + add_commas(MAP(args, make_name)) + ")";
6373
9043
  out = add_spaces([ out, make_block(body) ]);
6374
- return needs_parens(this) ? "(" + out + ")" : out;
9044
+ return (!no_parens && needs_parens(this)) ? "(" + out + ")" : out;
6375
9045
  };
6376
9046
 
6377
9047
  function must_has_semicolon(node) {
@@ -6568,7 +9238,7 @@ exports.MAP = MAP;
6568
9238
  // keep this last!
6569
9239
  exports.ast_squeeze_more = require("./squeeze-more").ast_squeeze_more;
6570
9240
 
6571
- });define('uglifyjs/index', ["require", "exports", "module", "./parse-js", "./process"], function(require, exports, module) {
9241
+ });define('uglifyjs/index', ["require", "exports", "module", "./parse-js", "./process", "./consolidator"], function(require, exports, module) {
6572
9242
 
6573
9243
  //convienence function(src, [options]);
6574
9244
  function uglify(orig_code, options){
@@ -6585,6 +9255,7 @@ function uglify(orig_code, options){
6585
9255
 
6586
9256
  uglify.parser = require("./parse-js");
6587
9257
  uglify.uglify = require("./process");
9258
+ uglify.consolidator = require("./consolidator");
6588
9259
 
6589
9260
  module.exports = uglify
6590
9261
 
@@ -7817,6 +10488,7 @@ function (lang, logger, envOptimize, file, parse,
7817
10488
 
7818
10489
  var optimize,
7819
10490
  cssImportRegExp = /\@import\s+(url\()?\s*([^);]+)\s*(\))?([\w, ]*)(;)?/g,
10491
+ cssCommentImportRegExp = /\/\*[^\*]*@import[^\*]*\*\//g,
7820
10492
  cssUrlRegExp = /\url\(\s*([^\)]+)\s*\)?/g;
7821
10493
 
7822
10494
  /**
@@ -7840,24 +10512,30 @@ function (lang, logger, envOptimize, file, parse,
7840
10512
 
7841
10513
  /**
7842
10514
  * Inlines nested stylesheets that have @import calls in them.
7843
- * @param {String} fileName
7844
- * @param {String} fileContents
7845
- * @param {String} [cssImportIgnore]
10515
+ * @param {String} fileName the file name
10516
+ * @param {String} fileContents the file contents
10517
+ * @param {String} cssImportIgnore comma delimited string of files to ignore
10518
+ * @param {Object} included an object used to track the files already imported
7846
10519
  */
7847
- function flattenCss(fileName, fileContents, cssImportIgnore) {
10520
+ function flattenCss(fileName, fileContents, cssImportIgnore, included) {
7848
10521
  //Find the last slash in the name.
7849
10522
  fileName = fileName.replace(lang.backSlashRegExp, "/");
7850
10523
  var endIndex = fileName.lastIndexOf("/"),
7851
10524
  //Make a file path based on the last slash.
7852
10525
  //If no slash, so must be just a file name. Use empty string then.
7853
- filePath = (endIndex !== -1) ? fileName.substring(0, endIndex + 1) : "";
10526
+ filePath = (endIndex !== -1) ? fileName.substring(0, endIndex + 1) : "",
10527
+ //store a list of merged files
10528
+ importList = [];
10529
+
10530
+ //First make a pass by removing an commented out @import calls.
10531
+ fileContents = fileContents.replace(cssCommentImportRegExp, '');
7854
10532
 
7855
10533
  //Make sure we have a delimited ignore list to make matching faster
7856
10534
  if (cssImportIgnore && cssImportIgnore.charAt(cssImportIgnore.length - 1) !== ",") {
7857
10535
  cssImportIgnore += ",";
7858
10536
  }
7859
10537
 
7860
- return fileContents.replace(cssImportRegExp, function (fullMatch, urlStart, importFileName, urlEnd, mediaTypes) {
10538
+ fileContents = fileContents.replace(cssImportRegExp, function (fullMatch, urlStart, importFileName, urlEnd, mediaTypes) {
7861
10539
  //Only process media type "all" or empty media type rules.
7862
10540
  if (mediaTypes && ((mediaTypes.replace(/^\s\s*/, '').replace(/\s\s*$/, '')) !== "all")) {
7863
10541
  return fullMatch;
@@ -7879,10 +10557,21 @@ function (lang, logger, envOptimize, file, parse,
7879
10557
  //and we will just skip that import.
7880
10558
  var fullImportFileName = importFileName.charAt(0) === "/" ? importFileName : filePath + importFileName,
7881
10559
  importContents = file.readFile(fullImportFileName), i,
7882
- importEndIndex, importPath, fixedUrlMatch, colonIndex, parts;
10560
+ importEndIndex, importPath, fixedUrlMatch, colonIndex, parts, flat;
10561
+
10562
+ //Skip the file if it has already been included.
10563
+ if (included[fullImportFileName]) {
10564
+ return '';
10565
+ }
10566
+ included[fullImportFileName] = true;
7883
10567
 
7884
10568
  //Make sure to flatten any nested imports.
7885
- importContents = flattenCss(fullImportFileName, importContents);
10569
+ flat = flattenCss(fullImportFileName, importContents, cssImportIgnore, included);
10570
+ importContents = flat.fileContents;
10571
+
10572
+ if (flat.importList.length) {
10573
+ importList.push.apply(importList, flat.importList);
10574
+ }
7886
10575
 
7887
10576
  //Make the full import path
7888
10577
  importEndIndex = importFileName.lastIndexOf("/");
@@ -7925,12 +10614,18 @@ function (lang, logger, envOptimize, file, parse,
7925
10614
  return "url(" + parts.join("/") + ")";
7926
10615
  });
7927
10616
 
10617
+ importList.push(fullImportFileName);
7928
10618
  return importContents;
7929
10619
  } catch (e) {
7930
- logger.trace(fileName + "\n Cannot inline css import, skipping: " + importFileName);
10620
+ logger.warn(fileName + "\n Cannot inline css import, skipping: " + importFileName);
7931
10621
  return fullMatch;
7932
10622
  }
7933
10623
  });
10624
+
10625
+ return {
10626
+ importList : importList,
10627
+ fileContents : fileContents
10628
+ };
7934
10629
  }
7935
10630
 
7936
10631
  optimize = {
@@ -7942,21 +10637,22 @@ function (lang, logger, envOptimize, file, parse,
7942
10637
  * through an minifier if one is specified via config.optimize.
7943
10638
  *
7944
10639
  * @param {String} fileName the name of the file to optimize
10640
+ * @param {String} fileContents the contents to optimize. If this is
10641
+ * a null value, then fileName will be used to read the fileContents.
7945
10642
  * @param {String} outFileName the name of the file to use for the
7946
10643
  * saved optimized content.
7947
10644
  * @param {Object} config the build config object.
7948
- * @param {String} [moduleName] the module name to use for the file.
7949
- * Used for plugin resource collection.
7950
10645
  * @param {Array} [pluginCollector] storage for any plugin resources
7951
10646
  * found.
7952
10647
  */
7953
- jsFile: function (fileName, outFileName, config, moduleName, pluginCollector) {
10648
+ jsFile: function (fileName, fileContents, outFileName, config, pluginCollector) {
7954
10649
  var parts = (config.optimize + "").split('.'),
7955
10650
  optimizerName = parts[0],
7956
- keepLines = parts[1] === 'keepLines',
7957
- fileContents;
10651
+ keepLines = parts[1] === 'keepLines';
7958
10652
 
7959
- fileContents = file.readFile(fileName);
10653
+ if (!fileContents) {
10654
+ fileContents = file.readFile(fileName);
10655
+ }
7960
10656
 
7961
10657
  fileContents = optimize.js(fileName, fileContents, optimizerName,
7962
10658
  keepLines, config, pluginCollector);
@@ -8026,21 +10722,25 @@ function (lang, logger, envOptimize, file, parse,
8026
10722
  * cssImportIgnore options.
8027
10723
  */
8028
10724
  cssFile: function (fileName, outFileName, config) {
10725
+
8029
10726
  //Read in the file. Make sure we have a JS string.
8030
10727
  var originalFileContents = file.readFile(fileName),
8031
- fileContents = flattenCss(fileName, originalFileContents, config.cssImportIgnore),
8032
- startIndex, endIndex;
10728
+ flat = flattenCss(fileName, originalFileContents, config.cssImportIgnore, {}),
10729
+ fileContents = flat.fileContents,
10730
+ startIndex, endIndex, buildText;
8033
10731
 
8034
10732
  //Do comment removal.
8035
10733
  try {
8036
- startIndex = -1;
8037
- //Get rid of comments.
8038
- while ((startIndex = fileContents.indexOf("/*")) !== -1) {
8039
- endIndex = fileContents.indexOf("*/", startIndex + 2);
8040
- if (endIndex === -1) {
8041
- throw "Improper comment in CSS file: " + fileName;
10734
+ if (config.optimizeCss.indexOf(".keepComments") === -1) {
10735
+ startIndex = -1;
10736
+ //Get rid of comments.
10737
+ while ((startIndex = fileContents.indexOf("/*")) !== -1) {
10738
+ endIndex = fileContents.indexOf("*/", startIndex + 2);
10739
+ if (endIndex === -1) {
10740
+ throw "Improper comment in CSS file: " + fileName;
10741
+ }
10742
+ fileContents = fileContents.substring(0, startIndex) + fileContents.substring(endIndex + 2, fileContents.length);
8042
10743
  }
8043
- fileContents = fileContents.substring(0, startIndex) + fileContents.substring(endIndex + 2, fileContents.length);
8044
10744
  }
8045
10745
  //Get rid of newlines.
8046
10746
  if (config.optimizeCss.indexOf(".keepLines") === -1) {
@@ -8059,6 +10759,14 @@ function (lang, logger, envOptimize, file, parse,
8059
10759
  }
8060
10760
 
8061
10761
  file.saveUtf8File(outFileName, fileContents);
10762
+
10763
+ //text output to stdout and/or written to build.txt file
10764
+ buildText = "\n"+ outFileName.replace(config.dir, "") +"\n----------------\n";
10765
+ flat.importList.push(fileName);
10766
+ buildText += flat.importList.map(function(path){
10767
+ return path.replace(config.dir, "");
10768
+ }).join("\n");
10769
+ return buildText +"\n";
8062
10770
  },
8063
10771
 
8064
10772
  /**
@@ -8069,17 +10777,19 @@ function (lang, logger, envOptimize, file, parse,
8069
10777
  * cssImportIgnore options.
8070
10778
  */
8071
10779
  css: function (startDir, config) {
10780
+ var buildText = "",
10781
+ i, fileName, fileList;
8072
10782
  if (config.optimizeCss.indexOf("standard") !== -1) {
8073
- var i, fileName,
8074
- fileList = file.getFilteredFileList(startDir, /\.css$/, true);
10783
+ fileList = file.getFilteredFileList(startDir, /\.css$/, true);
8075
10784
  if (fileList) {
8076
10785
  for (i = 0; i < fileList.length; i++) {
8077
10786
  fileName = fileList[i];
8078
10787
  logger.trace("Optimizing (" + config.optimizeCss + ") CSS file: " + fileName);
8079
- optimize.cssFile(fileName, fileName, config);
10788
+ buildText += optimize.cssFile(fileName, fileName, config);
8080
10789
  }
8081
10790
  }
8082
10791
  }
10792
+ return buildText;
8083
10793
  },
8084
10794
 
8085
10795
  optimizers: {
@@ -8702,7 +11412,7 @@ function (lang, logger, file, parse, optimize, pragma,
8702
11412
  baseConfig, config,
8703
11413
  modules, builtModule, srcPath, buildContext,
8704
11414
  destPath, moduleName, moduleMap, parentModuleMap, context,
8705
- resources, resource, pluginProcessed = {}, plugin;
11415
+ resources, resource, pluginProcessed = {}, plugin, fileContents;
8706
11416
 
8707
11417
  //Can now run the patches to require.js to allow it to be used for
8708
11418
  //build generation. Do it here instead of at the top of the module
@@ -8731,7 +11441,7 @@ function (lang, logger, file, parse, optimize, pragma,
8731
11441
  //the paths to use the dirBaseUrl
8732
11442
  for (prop in paths) {
8733
11443
  if (paths.hasOwnProperty(prop)) {
8734
- buildPaths[prop] = paths[prop].replace(config.baseUrl, config.dirBaseUrl);
11444
+ buildPaths[prop] = paths[prop].replace(config.appDir, config.dir);
8735
11445
  }
8736
11446
  }
8737
11447
  } else {
@@ -8831,7 +11541,7 @@ function (lang, logger, file, parse, optimize, pragma,
8831
11541
  //things like text loader plugins loading CSS to get the optimized
8832
11542
  //CSS.
8833
11543
  if (config.optimizeCss && config.optimizeCss !== "none" && config.dir) {
8834
- optimize.css(config.dir, config);
11544
+ buildFileContents += optimize.css(config.dir, config);
8835
11545
  }
8836
11546
 
8837
11547
  if (modules) {
@@ -8905,7 +11615,7 @@ function (lang, logger, file, parse, optimize, pragma,
8905
11615
  if (config.out && !config.cssIn) {
8906
11616
  //Just need to worry about one JS file.
8907
11617
  fileName = config.modules[0]._buildPath;
8908
- optimize.jsFile(fileName, fileName, config);
11618
+ optimize.jsFile(fileName, null, fileName, config);
8909
11619
  } else if (!config.cssIn) {
8910
11620
  //Normal optimizations across modules.
8911
11621
 
@@ -8916,7 +11626,18 @@ function (lang, logger, file, parse, optimize, pragma,
8916
11626
  moduleName = fileName.replace(config.dir, '');
8917
11627
  //Get rid of the extension
8918
11628
  moduleName = moduleName.substring(0, moduleName.length - 3);
8919
- optimize.jsFile(fileName, fileName, config, moduleName, pluginCollector);
11629
+
11630
+ //Convert the file to transport format, but without a name
11631
+ //inserted (by passing null for moduleName) since the files are
11632
+ //standalone, one module per file.
11633
+ fileContents = file.readFile(fileName);
11634
+ fileContents = build.toTransport(config.anonDefRegExp,
11635
+ config.namespaceWithDot,
11636
+ null,
11637
+ fileName,
11638
+ fileContents);
11639
+
11640
+ optimize.jsFile(fileName, fileContents, fileName, config, pluginCollector);
8920
11641
  }
8921
11642
 
8922
11643
  //Normalize all the plugin resources.
@@ -8984,7 +11705,7 @@ function (lang, logger, file, parse, optimize, pragma,
8984
11705
 
8985
11706
  //If just have one CSS file to optimize, do that here.
8986
11707
  if (config.cssIn) {
8987
- optimize.cssFile(config.cssIn, config.out, config);
11708
+ buildFileContents += optimize.cssFile(config.cssIn, config.out, config);
8988
11709
  }
8989
11710
 
8990
11711
  //Print out what was built into which layers.
@@ -9229,6 +11950,9 @@ function (lang, logger, file, parse, optimize, pragma,
9229
11950
  mainConfigFile = config.mainConfigFile || (buildFileConfig && buildFileConfig.mainConfigFile);
9230
11951
  if (mainConfigFile) {
9231
11952
  mainConfigFile = build.makeAbsPath(mainConfigFile, absFilePath);
11953
+ if (!file.exists(mainConfigFile)) {
11954
+ throw new Error(mainConfigFile + ' does not exist.');
11955
+ }
9232
11956
  try {
9233
11957
  mainConfig = parse.findConfig(mainConfigFile, file.readFile(mainConfigFile));
9234
11958
  } catch (configError) {
@@ -9382,6 +12106,9 @@ function (lang, logger, file, parse, optimize, pragma,
9382
12106
  file.exclusionRegExp = config.dirExclusionRegExp;
9383
12107
  }
9384
12108
 
12109
+ //Remove things that may cause problems in the build.
12110
+ delete config.jQuery;
12111
+
9385
12112
  return config;
9386
12113
  };
9387
12114
 
@@ -9633,7 +12360,8 @@ function (lang, logger, file, parse, optimize, pragma,
9633
12360
  layer.modulesWithNames[moduleName] = true;
9634
12361
  }
9635
12362
 
9636
- var deps = null;
12363
+ var deps = null,
12364
+ finalName;
9637
12365
 
9638
12366
  //Look for CommonJS require calls inside the function if this is
9639
12367
  //an anonymous define call that just has a function registered.
@@ -9651,7 +12379,12 @@ function (lang, logger, file, parse, optimize, pragma,
9651
12379
  }
9652
12380
  }
9653
12381
 
9654
- return start + namespace + "define('" + (namedModule || moduleName) + "'," +
12382
+ finalName = namedModule || moduleName || '';
12383
+ if (finalName) {
12384
+ finalName = "'" + (namedModule || moduleName) + "',";
12385
+ }
12386
+
12387
+ return start + namespace + "define(" + finalName +
9655
12388
  (deps ? ('[' + deps.toString() + '],') : '') +
9656
12389
  (namedModule ? namedFuncStart.replace(build.leadingCommaRegExp, '') : suffix);
9657
12390
  });
@@ -9734,7 +12467,9 @@ function (lang, logger, file, parse, optimize, pragma,
9734
12467
  }
9735
12468
 
9736
12469
  var req = requirejs({
9737
- context: contextName
12470
+ context: contextName,
12471
+ requireLoad: requirejsVars.nodeLoad,
12472
+ requireExecCb: requirejsVars.nodeRequireExecCb
9738
12473
  });
9739
12474
 
9740
12475
  req(['build'], function () {