requirejs-rails 0.7.2 → 0.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 () {