diff --git a/freeipa.spec.in b/freeipa.spec.in index e0c9ee242..5fff89ee3 100644 --- a/freeipa.spec.in +++ b/freeipa.spec.in @@ -157,6 +157,7 @@ BuildRequires: libsss_certmap-devel # 1.15.3: sss_nss_getlistbycert (https://pagure.io/SSSD/sssd/issue/3050) BuildRequires: libsss_nss_idmap-devel >= 1.15.3 BuildRequires: rhino +BuildRequires: uglify-js BuildRequires: libverto-devel BuildRequires: libunistring-devel # 0.13.0: https://bugzilla.redhat.com/show_bug.cgi?id=1584773 diff --git a/install/ui/README-LICENSE.txt b/install/ui/README-LICENSE.txt index b9ef0e5e0..634d7625f 100644 --- a/install/ui/README-LICENSE.txt +++ b/install/ui/README-LICENSE.txt @@ -27,10 +27,6 @@ QUnit - dual licensed under MIT and GPLv2 licenses Font Awesome - code licensed under MIT license * less/font-awesome -UglifyJS - licensed under BSD license - * util/uglifyjs/uglify-js.js - * utli/uglifyjs/lib/* - Dojo, Dojo Builder - dual licensed under BSD license and AFL version 2.1 * full license text in util/build/LICENSE * util/build/build.js diff --git a/install/ui/util/compile.sh b/install/ui/util/compile.sh index f96da5db4..d14f90ab0 100755 --- a/install/ui/util/compile.sh +++ b/install/ui/util/compile.sh @@ -105,5 +105,7 @@ if [[ ! $OUTPUT_FILE ]] ; then OUTPUT_FILE=$RDIR/$RELEASE/$LAYER.js fi -# compile using uglify.js -$DIR/uglifyjs/uglify $RDIR/$RELEASE/$LAYER.js $OUTPUT_FILE +# compile using uglifyjs +echo "Minimizing: $RDIR/$RELEASE/$LAYER.js" +echo "Target file: $OUTPUT_FILE" +uglifyjs $RDIR/$RELEASE/$LAYER.js > $OUTPUT_FILE diff --git a/install/ui/util/uglifyjs/lib/consolidator.js b/install/ui/util/uglifyjs/lib/consolidator.js deleted file mode 100644 index 68169b375..000000000 --- a/install/ui/util/uglifyjs/lib/consolidator.js +++ /dev/null @@ -1,1219 +0,0 @@ -/** - * @preserve Copyright 2012 Robert Gust-Bardon . - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/** - * @fileoverview Enhances UglifyJS with consolidation of null, Boolean, and String values. - *

Also known as aliasing, this feature has been deprecated in the Closure Compiler since its - * initial release, where it is unavailable from the CLI. The Closure Compiler allows one to log and - * influence this process. In contrast, this implementation does not introduce - * any variable declarations in global code and derives String values from - * identifier names used as property accessors.

- *

Consolidating literals may worsen the data compression ratio when an encoding - * transformation is applied. For instance, jQuery 1.7.1 takes 248235 bytes. - * Building it with - * UglifyJS v1.2.5 results in 93647 bytes (37.73% of the original) which are - * then compressed to 33154 bytes (13.36% of the original) using gzip(1). Building it with the same - * version of UglifyJS 1.2.5 patched with the implementation of consolidation - * results in 80784 bytes (a decrease of 12863 bytes, i.e. 13.74%, in comparison - * to the aforementioned 93647 bytes) which are then compressed to 34013 bytes - * (an increase of 859 bytes, i.e. 2.59%, in comparison to the aforementioned - * 33154 bytes).

- *

Written in the strict variant - * of ECMA-262 5.1 Edition. Encoded in UTF-8. Follows Revision 2.28 of the Google JavaScript Style Guide (except for the - * discouraged use of the {@code function} tag and the {@code namespace} tag). - * 100% typed for the Closure Compiler Version 1741.

- *

Should you find this software useful, please consider a donation.

- * @author follow.me@RGustBardon (Robert Gust-Bardon) - * @supported Tested with: - * - */ - -/*global console:false, exports:true, module:false, require:false */ -/*jshint sub:true */ -/** - * Consolidates null, Boolean, and String values found inside an AST. - * @param {!TSyntacticCodeUnit} oAbstractSyntaxTree An array-like object - * representing an AST. - * @return {!TSyntacticCodeUnit} An array-like object representing an AST with its null, Boolean, and - * String values consolidated. - */ -// TODO(user) Consolidation of mathematical values found in numeric literals. -// TODO(user) Unconsolidation. -// TODO(user) Consolidation of ECMA-262 6th Edition programs. -// TODO(user) Rewrite in ECMA-262 6th Edition. -exports['ast_consolidate'] = function(oAbstractSyntaxTree) { - 'use strict'; - /*jshint bitwise:true, curly:true, eqeqeq:true, forin:true, immed:true, - latedef:true, newcap:true, noarge:true, noempty:true, nonew:true, - onevar:true, plusplus:true, regexp:true, undef:true, strict:true, - sub:false, trailing:true */ - - var _, - /** - * A record consisting of data about one or more source elements. - * @constructor - * @nosideeffects - */ - TSourceElementsData = function() { - /** - * The category of the elements. - * @type {number} - * @see ESourceElementCategories - */ - this.nCategory = ESourceElementCategories.N_OTHER; - /** - * The number of occurrences (within the elements) of each primitive - * value that could be consolidated. - * @type {!Array.>} - */ - this.aCount = []; - this.aCount[EPrimaryExpressionCategories.N_IDENTIFIER_NAMES] = {}; - this.aCount[EPrimaryExpressionCategories.N_STRING_LITERALS] = {}; - this.aCount[EPrimaryExpressionCategories.N_NULL_AND_BOOLEAN_LITERALS] = - {}; - /** - * Identifier names found within the elements. - * @type {!Array.} - */ - this.aIdentifiers = []; - /** - * Prefixed representation Strings of each primitive value that could be - * consolidated within the elements. - * @type {!Array.} - */ - this.aPrimitiveValues = []; - }, - /** - * A record consisting of data about a primitive value that could be - * consolidated. - * @constructor - * @nosideeffects - */ - TPrimitiveValue = function() { - /** - * The difference in the number of terminal symbols between the original - * source text and the one with the primitive value consolidated. If the - * difference is positive, the primitive value is considered worthwhile. - * @type {number} - */ - this.nSaving = 0; - /** - * An identifier name of the variable that will be declared and assigned - * the primitive value if the primitive value is consolidated. - * @type {string} - */ - this.sName = ''; - }, - /** - * A record consisting of data on what to consolidate within the range of - * source elements that is currently being considered. - * @constructor - * @nosideeffects - */ - TSolution = function() { - /** - * An object whose keys are prefixed representation Strings of each - * primitive value that could be consolidated within the elements and - * whose values are corresponding data about those primitive values. - * @type {!Object.} - * @see TPrimitiveValue - */ - this.oPrimitiveValues = {}; - /** - * The difference in the number of terminal symbols between the original - * source text and the one with all the worthwhile primitive values - * consolidated. - * @type {number} - * @see TPrimitiveValue#nSaving - */ - this.nSavings = 0; - }, - /** - * The processor of ASTs found - * in UglifyJS. - * @namespace - * @type {!TProcessor} - */ - oProcessor = (/** @type {!TProcessor} */ require('./process')), - /** - * A record consisting of a number of constants that represent the - * difference in the number of terminal symbols between a source text with - * a modified syntactic code unit and the original one. - * @namespace - * @type {!Object.} - */ - oWeights = { - /** - * The difference in the number of punctuators required by the bracket - * notation and the dot notation. - *

'[]'.length - '.'.length

- * @const - * @type {number} - */ - N_PROPERTY_ACCESSOR: 1, - /** - * The number of punctuators required by a variable declaration with an - * initialiser. - *

':'.length + ';'.length

- * @const - * @type {number} - */ - N_VARIABLE_DECLARATION: 2, - /** - * The number of terminal symbols required to introduce a variable - * statement (excluding its variable declaration list). - *

'var '.length

- * @const - * @type {number} - */ - N_VARIABLE_STATEMENT_AFFIXATION: 4, - /** - * The number of terminal symbols needed to enclose source elements - * within a function call with no argument values to a function with an - * empty parameter list. - *

'(function(){}());'.length

- * @const - * @type {number} - */ - N_CLOSURE: 17 - }, - /** - * Categories of primary expressions from which primitive values that - * could be consolidated are derivable. - * @namespace - * @enum {number} - */ - EPrimaryExpressionCategories = { - /** - * Identifier names used as property accessors. - * @type {number} - */ - N_IDENTIFIER_NAMES: 0, - /** - * String literals. - * @type {number} - */ - N_STRING_LITERALS: 1, - /** - * Null and Boolean literals. - * @type {number} - */ - N_NULL_AND_BOOLEAN_LITERALS: 2 - }, - /** - * Prefixes of primitive values that could be consolidated. - * The String values of the prefixes must have same number of characters. - * The prefixes must not be used in any properties defined in any version - * of ECMA-262. - * @namespace - * @enum {string} - */ - EValuePrefixes = { - /** - * Identifies String values. - * @type {string} - */ - S_STRING: '#S', - /** - * Identifies null and Boolean values. - * @type {string} - */ - S_SYMBOLIC: '#O' - }, - /** - * Categories of source elements in terms of their appropriateness of - * having their primitive values consolidated. - * @namespace - * @enum {number} - */ - ESourceElementCategories = { - /** - * Identifies a source element that includes the {@code with} statement. - * @type {number} - */ - N_WITH: 0, - /** - * Identifies a source element that includes the {@code eval} identifier name. - * @type {number} - */ - N_EVAL: 1, - /** - * Identifies a source element that must be excluded from the process - * unless its whole scope is examined. - * @type {number} - */ - N_EXCLUDABLE: 2, - /** - * Identifies source elements not posing any problems. - * @type {number} - */ - N_OTHER: 3 - }, - /** - * The list of literals (other than the String ones) whose primitive - * values can be consolidated. - * @const - * @type {!Array.} - */ - A_OTHER_SUBSTITUTABLE_LITERALS = [ - 'null', // The null literal. - 'false', // The Boolean literal {@code false}. - 'true' // The Boolean literal {@code true}. - ]; - - (/** - * Consolidates all worthwhile primitive values in a syntactic code unit. - * @param {!TSyntacticCodeUnit} oSyntacticCodeUnit An array-like object - * representing the branch of the abstract syntax tree representing the - * syntactic code unit along with its scope. - * @see TPrimitiveValue#nSaving - */ - function fExamineSyntacticCodeUnit(oSyntacticCodeUnit) { - var _, - /** - * Indicates whether the syntactic code unit represents global code. - * @type {boolean} - */ - bIsGlobal = 'toplevel' === oSyntacticCodeUnit[0], - /** - * Indicates whether the whole scope is being examined. - * @type {boolean} - */ - bIsWhollyExaminable = !bIsGlobal, - /** - * An array-like object representing source elements that constitute a - * syntactic code unit. - * @type {!TSyntacticCodeUnit} - */ - oSourceElements, - /** - * A record consisting of data about the source element that is - * currently being examined. - * @type {!TSourceElementsData} - */ - oSourceElementData, - /** - * The scope of the syntactic code unit. - * @type {!TScope} - */ - oScope, - /** - * An instance of an object that allows the traversal of an AST. - * @type {!TWalker} - */ - oWalker, - /** - * An object encompassing collections of functions used during the - * traversal of an AST. - * @namespace - * @type {!Object.>} - */ - oWalkers = { - /** - * A collection of functions used during the surveyance of source - * elements. - * @namespace - * @type {!Object.} - */ - oSurveySourceElement: { - /**#nocode+*/ // JsDoc Toolkit 2.4.0 hides some of the keys. - /** - * Classifies the source element as excludable if it does not - * contain a {@code with} statement or the {@code eval} identifier - * name. Adds the identifier of the function and its formal - * parameters to the list of identifier names found. - * @param {string} sIdentifier The identifier of the function. - * @param {!Array.} aFormalParameterList Formal parameters. - * @param {!TSyntacticCodeUnit} oFunctionBody Function code. - */ - 'defun': function( - sIdentifier, - aFormalParameterList, - oFunctionBody) { - fClassifyAsExcludable(); - fAddIdentifier(sIdentifier); - aFormalParameterList.forEach(fAddIdentifier); - }, - /** - * Increments the count of the number of occurrences of the String - * value that is equivalent to the sequence of terminal symbols - * that constitute the encountered identifier name. - * @param {!TSyntacticCodeUnit} oExpression The nonterminal - * MemberExpression. - * @param {string} sIdentifierName The identifier name used as the - * property accessor. - * @return {!Array} The encountered branch of an AST with its nonterminal - * MemberExpression traversed. - */ - 'dot': function(oExpression, sIdentifierName) { - fCountPrimaryExpression( - EPrimaryExpressionCategories.N_IDENTIFIER_NAMES, - EValuePrefixes.S_STRING + sIdentifierName); - return ['dot', oWalker.walk(oExpression), sIdentifierName]; - }, - /** - * Adds the optional identifier of the function and its formal - * parameters to the list of identifier names found. - * @param {?string} sIdentifier The optional identifier of the - * function. - * @param {!Array.} aFormalParameterList Formal parameters. - * @param {!TSyntacticCodeUnit} oFunctionBody Function code. - */ - 'function': function( - sIdentifier, - aFormalParameterList, - oFunctionBody) { - if ('string' === typeof sIdentifier) { - fAddIdentifier(sIdentifier); - } - aFormalParameterList.forEach(fAddIdentifier); - }, - /** - * Either increments the count of the number of occurrences of the - * encountered null or Boolean value or classifies a source element - * as containing the {@code eval} identifier name. - * @param {string} sIdentifier The identifier encountered. - */ - 'name': function(sIdentifier) { - if (-1 !== A_OTHER_SUBSTITUTABLE_LITERALS.indexOf(sIdentifier)) { - fCountPrimaryExpression( - EPrimaryExpressionCategories.N_NULL_AND_BOOLEAN_LITERALS, - EValuePrefixes.S_SYMBOLIC + sIdentifier); - } else { - if ('eval' === sIdentifier) { - oSourceElementData.nCategory = - ESourceElementCategories.N_EVAL; - } - fAddIdentifier(sIdentifier); - } - }, - /** - * Classifies the source element as excludable if it does not - * contain a {@code with} statement or the {@code eval} identifier - * name. - * @param {TSyntacticCodeUnit} oExpression The expression whose - * value is to be returned. - */ - 'return': function(oExpression) { - fClassifyAsExcludable(); - }, - /** - * Increments the count of the number of occurrences of the - * encountered String value. - * @param {string} sStringValue The String value of the string - * literal encountered. - */ - 'string': function(sStringValue) { - if (sStringValue.length > 0) { - fCountPrimaryExpression( - EPrimaryExpressionCategories.N_STRING_LITERALS, - EValuePrefixes.S_STRING + sStringValue); - } - }, - /** - * Adds the identifier reserved for an exception to the list of - * identifier names found. - * @param {!TSyntacticCodeUnit} oTry A block of code in which an - * exception can occur. - * @param {Array} aCatch The identifier reserved for an exception - * and a block of code to handle the exception. - * @param {TSyntacticCodeUnit} oFinally An optional block of code - * to be evaluated regardless of whether an exception occurs. - */ - 'try': function(oTry, aCatch, oFinally) { - if (Array.isArray(aCatch)) { - fAddIdentifier(aCatch[0]); - } - }, - /** - * Classifies the source element as excludable if it does not - * contain a {@code with} statement or the {@code eval} identifier - * name. Adds the identifier of each declared variable to the list - * of identifier names found. - * @param {!Array.} aVariableDeclarationList Variable - * declarations. - */ - 'var': function(aVariableDeclarationList) { - fClassifyAsExcludable(); - aVariableDeclarationList.forEach(fAddVariable); - }, - /** - * Classifies a source element as containing the {@code with} - * statement. - * @param {!TSyntacticCodeUnit} oExpression An expression whose - * value is to be converted to a value of type Object and - * become the binding object of a new object environment - * record of a new lexical environment in which the statement - * is to be executed. - * @param {!TSyntacticCodeUnit} oStatement The statement to be - * executed in the augmented lexical environment. - * @return {!Array} An empty array to stop the traversal. - */ - 'with': function(oExpression, oStatement) { - oSourceElementData.nCategory = ESourceElementCategories.N_WITH; - return []; - } - /**#nocode-*/ // JsDoc Toolkit 2.4.0 hides some of the keys. - }, - /** - * A collection of functions used while looking for nested functions. - * @namespace - * @type {!Object.} - */ - oExamineFunctions: { - /**#nocode+*/ // JsDoc Toolkit 2.4.0 hides some of the keys. - /** - * Orders an examination of a nested function declaration. - * @this {!TSyntacticCodeUnit} An array-like object representing - * the branch of an AST representing the syntactic code unit along with - * its scope. - * @return {!Array} An empty array to stop the traversal. - */ - 'defun': function() { - fExamineSyntacticCodeUnit(this); - return []; - }, - /** - * Orders an examination of a nested function expression. - * @this {!TSyntacticCodeUnit} An array-like object representing - * the branch of an AST representing the syntactic code unit along with - * its scope. - * @return {!Array} An empty array to stop the traversal. - */ - 'function': function() { - fExamineSyntacticCodeUnit(this); - return []; - } - /**#nocode-*/ // JsDoc Toolkit 2.4.0 hides some of the keys. - } - }, - /** - * Records containing data about source elements. - * @type {Array.} - */ - aSourceElementsData = [], - /** - * The index (in the source text order) of the source element - * immediately following a Directive Prologue. - * @type {number} - */ - nAfterDirectivePrologue = 0, - /** - * The index (in the source text order) of the source element that is - * currently being considered. - * @type {number} - */ - nPosition, - /** - * The index (in the source text order) of the source element that is - * the last element of the range of source elements that is currently - * being considered. - * @type {(undefined|number)} - */ - nTo, - /** - * Initiates the traversal of a source element. - * @param {!TWalker} oWalker An instance of an object that allows the - * traversal of an abstract syntax tree. - * @param {!TSyntacticCodeUnit} oSourceElement A source element from - * which the traversal should commence. - * @return {function(): !TSyntacticCodeUnit} A function that is able to - * initiate the traversal from a given source element. - */ - cContext = function(oWalker, oSourceElement) { - /** - * @return {!TSyntacticCodeUnit} A function that is able to - * initiate the traversal from a given source element. - */ - var fLambda = function() { - return oWalker.walk(oSourceElement); - }; - - return fLambda; - }, - /** - * Classifies the source element as excludable if it does not - * contain a {@code with} statement or the {@code eval} identifier - * name. - */ - fClassifyAsExcludable = function() { - if (oSourceElementData.nCategory === - ESourceElementCategories.N_OTHER) { - oSourceElementData.nCategory = - ESourceElementCategories.N_EXCLUDABLE; - } - }, - /** - * Adds an identifier to the list of identifier names found. - * @param {string} sIdentifier The identifier to be added. - */ - fAddIdentifier = function(sIdentifier) { - if (-1 === oSourceElementData.aIdentifiers.indexOf(sIdentifier)) { - oSourceElementData.aIdentifiers.push(sIdentifier); - } - }, - /** - * Adds the identifier of a variable to the list of identifier names - * found. - * @param {!Array} aVariableDeclaration A variable declaration. - */ - fAddVariable = function(aVariableDeclaration) { - fAddIdentifier(/** @type {string} */ aVariableDeclaration[0]); - }, - /** - * Increments the count of the number of occurrences of the prefixed - * String representation attributed to the primary expression. - * @param {number} nCategory The category of the primary expression. - * @param {string} sName The prefixed String representation attributed - * to the primary expression. - */ - fCountPrimaryExpression = function(nCategory, sName) { - if (!oSourceElementData.aCount[nCategory].hasOwnProperty(sName)) { - oSourceElementData.aCount[nCategory][sName] = 0; - if (-1 === oSourceElementData.aPrimitiveValues.indexOf(sName)) { - oSourceElementData.aPrimitiveValues.push(sName); - } - } - oSourceElementData.aCount[nCategory][sName] += 1; - }, - /** - * Consolidates all worthwhile primitive values in a range of source - * elements. - * @param {number} nFrom The index (in the source text order) of the - * source element that is the first element of the range. - * @param {number} nTo The index (in the source text order) of the - * source element that is the last element of the range. - * @param {boolean} bEnclose Indicates whether the range should be - * enclosed within a function call with no argument values to a - * function with an empty parameter list if any primitive values - * are consolidated. - * @see TPrimitiveValue#nSaving - */ - fExamineSourceElements = function(nFrom, nTo, bEnclose) { - var _, - /** - * The index of the last mangled name. - * @type {number} - */ - nIndex = oScope.cname, - /** - * The index of the source element that is currently being - * considered. - * @type {number} - */ - nPosition, - /** - * A collection of functions used during the consolidation of - * primitive values and identifier names used as property - * accessors. - * @namespace - * @type {!Object.} - */ - oWalkersTransformers = { - /** - * If the String value that is equivalent to the sequence of - * terminal symbols that constitute the encountered identifier - * name is worthwhile, a syntactic conversion from the dot - * notation to the bracket notation ensues with that sequence - * being substituted by an identifier name to which the value - * is assigned. - * Applies to property accessors that use the dot notation. - * @param {!TSyntacticCodeUnit} oExpression The nonterminal - * MemberExpression. - * @param {string} sIdentifierName The identifier name used as - * the property accessor. - * @return {!Array} A syntactic code unit that is equivalent to - * the one encountered. - * @see TPrimitiveValue#nSaving - */ - 'dot': function(oExpression, sIdentifierName) { - /** - * The prefixed String value that is equivalent to the - * sequence of terminal symbols that constitute the - * encountered identifier name. - * @type {string} - */ - var sPrefixed = EValuePrefixes.S_STRING + sIdentifierName; - - return oSolutionBest.oPrimitiveValues.hasOwnProperty( - sPrefixed) && - oSolutionBest.oPrimitiveValues[sPrefixed].nSaving > 0 ? - ['sub', - oWalker.walk(oExpression), - ['name', - oSolutionBest.oPrimitiveValues[sPrefixed].sName]] : - ['dot', oWalker.walk(oExpression), sIdentifierName]; - }, - /** - * If the encountered identifier is a null or Boolean literal - * and its value is worthwhile, the identifier is substituted - * by an identifier name to which that value is assigned. - * Applies to identifier names. - * @param {string} sIdentifier The identifier encountered. - * @return {!Array} A syntactic code unit that is equivalent to - * the one encountered. - * @see TPrimitiveValue#nSaving - */ - 'name': function(sIdentifier) { - /** - * The prefixed representation String of the identifier. - * @type {string} - */ - var sPrefixed = EValuePrefixes.S_SYMBOLIC + sIdentifier; - - return [ - 'name', - oSolutionBest.oPrimitiveValues.hasOwnProperty(sPrefixed) && - oSolutionBest.oPrimitiveValues[sPrefixed].nSaving > 0 ? - oSolutionBest.oPrimitiveValues[sPrefixed].sName : - sIdentifier - ]; - }, - /** - * If the encountered String value is worthwhile, it is - * substituted by an identifier name to which that value is - * assigned. - * Applies to String values. - * @param {string} sStringValue The String value of the string - * literal encountered. - * @return {!Array} A syntactic code unit that is equivalent to - * the one encountered. - * @see TPrimitiveValue#nSaving - */ - 'string': function(sStringValue) { - /** - * The prefixed representation String of the primitive value - * of the literal. - * @type {string} - */ - var sPrefixed = - EValuePrefixes.S_STRING + sStringValue; - - return oSolutionBest.oPrimitiveValues.hasOwnProperty( - sPrefixed) && - oSolutionBest.oPrimitiveValues[sPrefixed].nSaving > 0 ? - ['name', - oSolutionBest.oPrimitiveValues[sPrefixed].sName] : - ['string', sStringValue]; - } - }, - /** - * Such data on what to consolidate within the range of source - * elements that is currently being considered that lead to the - * greatest known reduction of the number of the terminal symbols - * in comparison to the original source text. - * @type {!TSolution} - */ - oSolutionBest = new TSolution(), - /** - * Data representing an ongoing attempt to find a better - * reduction of the number of the terminal symbols in comparison - * to the original source text than the best one that is - * currently known. - * @type {!TSolution} - * @see oSolutionBest - */ - oSolutionCandidate = new TSolution(), - /** - * A record consisting of data about the range of source elements - * that is currently being examined. - * @type {!TSourceElementsData} - */ - oSourceElementsData = new TSourceElementsData(), - /** - * Variable declarations for each primitive value that is to be - * consolidated within the elements. - * @type {!Array.} - */ - aVariableDeclarations = [], - /** - * Augments a list with a prefixed representation String. - * @param {!Array.} aList A list that is to be augmented. - * @return {function(string)} A function that augments a list - * with a prefixed representation String. - */ - cAugmentList = function(aList) { - /** - * @param {string} sPrefixed Prefixed representation String of - * a primitive value that could be consolidated within the - * elements. - */ - var fLambda = function(sPrefixed) { - if (-1 === aList.indexOf(sPrefixed)) { - aList.push(sPrefixed); - } - }; - - return fLambda; - }, - /** - * Adds the number of occurrences of a primitive value of a given - * category that could be consolidated in the source element with - * a given index to the count of occurrences of that primitive - * value within the range of source elements that is currently - * being considered. - * @param {number} nPosition The index (in the source text order) - * of a source element. - * @param {number} nCategory The category of the primary - * expression from which the primitive value is derived. - * @return {function(string)} A function that performs the - * addition. - * @see cAddOccurrencesInCategory - */ - cAddOccurrences = function(nPosition, nCategory) { - /** - * @param {string} sPrefixed The prefixed representation String - * of a primitive value. - */ - var fLambda = function(sPrefixed) { - if (!oSourceElementsData.aCount[nCategory].hasOwnProperty( - sPrefixed)) { - oSourceElementsData.aCount[nCategory][sPrefixed] = 0; - } - oSourceElementsData.aCount[nCategory][sPrefixed] += - aSourceElementsData[nPosition].aCount[nCategory][ - sPrefixed]; - }; - - return fLambda; - }, - /** - * Adds the number of occurrences of each primitive value of a - * given category that could be consolidated in the source - * element with a given index to the count of occurrences of that - * primitive values within the range of source elements that is - * currently being considered. - * @param {number} nPosition The index (in the source text order) - * of a source element. - * @return {function(number)} A function that performs the - * addition. - * @see fAddOccurrences - */ - cAddOccurrencesInCategory = function(nPosition) { - /** - * @param {number} nCategory The category of the primary - * expression from which the primitive value is derived. - */ - var fLambda = function(nCategory) { - Object.keys( - aSourceElementsData[nPosition].aCount[nCategory] - ).forEach(cAddOccurrences(nPosition, nCategory)); - }; - - return fLambda; - }, - /** - * Adds the number of occurrences of each primitive value that - * could be consolidated in the source element with a given index - * to the count of occurrences of that primitive values within - * the range of source elements that is currently being - * considered. - * @param {number} nPosition The index (in the source text order) - * of a source element. - */ - fAddOccurrences = function(nPosition) { - Object.keys(aSourceElementsData[nPosition].aCount).forEach( - cAddOccurrencesInCategory(nPosition)); - }, - /** - * Creates a variable declaration for a primitive value if that - * primitive value is to be consolidated within the elements. - * @param {string} sPrefixed Prefixed representation String of a - * primitive value that could be consolidated within the - * elements. - * @see aVariableDeclarations - */ - cAugmentVariableDeclarations = function(sPrefixed) { - if (oSolutionBest.oPrimitiveValues[sPrefixed].nSaving > 0) { - aVariableDeclarations.push([ - oSolutionBest.oPrimitiveValues[sPrefixed].sName, - [0 === sPrefixed.indexOf(EValuePrefixes.S_SYMBOLIC) ? - 'name' : 'string', - sPrefixed.substring(EValuePrefixes.S_SYMBOLIC.length)] - ]); - } - }, - /** - * Sorts primitive values with regard to the difference in the - * number of terminal symbols between the original source text - * and the one with those primitive values consolidated. - * @param {string} sPrefixed0 The prefixed representation String - * of the first of the two primitive values that are being - * compared. - * @param {string} sPrefixed1 The prefixed representation String - * of the second of the two primitive values that are being - * compared. - * @return {number} - *
- *
-1
- *
if the first primitive value must be placed before - * the other one,
- *
0
- *
if the first primitive value may be placed before - * the other one,
- *
1
- *
if the first primitive value must not be placed - * before the other one.
- *
- * @see TSolution.oPrimitiveValues - */ - cSortPrimitiveValues = function(sPrefixed0, sPrefixed1) { - /** - * The difference between: - *
    - *
  1. the difference in the number of terminal symbols - * between the original source text and the one with the - * first primitive value consolidated, and
  2. - *
  3. the difference in the number of terminal symbols - * between the original source text and the one with the - * second primitive value consolidated.
  4. - *
- * @type {number} - */ - var nDifference = - oSolutionCandidate.oPrimitiveValues[sPrefixed0].nSaving - - oSolutionCandidate.oPrimitiveValues[sPrefixed1].nSaving; - - return nDifference > 0 ? -1 : nDifference < 0 ? 1 : 0; - }, - /** - * Assigns an identifier name to a primitive value and calculates - * whether instances of that primitive value are worth - * consolidating. - * @param {string} sPrefixed The prefixed representation String - * of a primitive value that is being evaluated. - */ - fEvaluatePrimitiveValue = function(sPrefixed) { - var _, - /** - * The index of the last mangled name. - * @type {number} - */ - nIndex, - /** - * The representation String of the primitive value that is - * being evaluated. - * @type {string} - */ - sName = - sPrefixed.substring(EValuePrefixes.S_SYMBOLIC.length), - /** - * The number of source characters taken up by the - * representation String of the primitive value that is - * being evaluated. - * @type {number} - */ - nLengthOriginal = sName.length, - /** - * The number of source characters taken up by the - * identifier name that could substitute the primitive - * value that is being evaluated. - * substituted. - * @type {number} - */ - nLengthSubstitution, - /** - * The number of source characters taken up by by the - * representation String of the primitive value that is - * being evaluated when it is represented by a string - * literal. - * @type {number} - */ - nLengthString = oProcessor.make_string(sName).length; - - oSolutionCandidate.oPrimitiveValues[sPrefixed] = - new TPrimitiveValue(); - do { // Find an identifier unused in this or any nested scope. - nIndex = oScope.cname; - oSolutionCandidate.oPrimitiveValues[sPrefixed].sName = - oScope.next_mangled(); - } while (-1 !== oSourceElementsData.aIdentifiers.indexOf( - oSolutionCandidate.oPrimitiveValues[sPrefixed].sName)); - nLengthSubstitution = oSolutionCandidate.oPrimitiveValues[ - sPrefixed].sName.length; - if (0 === sPrefixed.indexOf(EValuePrefixes.S_SYMBOLIC)) { - // foo:null, or foo:null; - oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving -= - nLengthSubstitution + nLengthOriginal + - oWeights.N_VARIABLE_DECLARATION; - // null vs foo - oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving += - oSourceElementsData.aCount[ - EPrimaryExpressionCategories. - N_NULL_AND_BOOLEAN_LITERALS][sPrefixed] * - (nLengthOriginal - nLengthSubstitution); - } else { - // foo:'fromCharCode'; - oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving -= - nLengthSubstitution + nLengthString + - oWeights.N_VARIABLE_DECLARATION; - // .fromCharCode vs [foo] - if (oSourceElementsData.aCount[ - EPrimaryExpressionCategories.N_IDENTIFIER_NAMES - ].hasOwnProperty(sPrefixed)) { - oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving += - oSourceElementsData.aCount[ - EPrimaryExpressionCategories.N_IDENTIFIER_NAMES - ][sPrefixed] * - (nLengthOriginal - nLengthSubstitution - - oWeights.N_PROPERTY_ACCESSOR); - } - // 'fromCharCode' vs foo - if (oSourceElementsData.aCount[ - EPrimaryExpressionCategories.N_STRING_LITERALS - ].hasOwnProperty(sPrefixed)) { - oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving += - oSourceElementsData.aCount[ - EPrimaryExpressionCategories.N_STRING_LITERALS - ][sPrefixed] * - (nLengthString - nLengthSubstitution); - } - } - if (oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving > - 0) { - oSolutionCandidate.nSavings += - oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving; - } else { - oScope.cname = nIndex; // Free the identifier name. - } - }, - /** - * Adds a variable declaration to an existing variable statement. - * @param {!Array} aVariableDeclaration A variable declaration - * with an initialiser. - */ - cAddVariableDeclaration = function(aVariableDeclaration) { - (/** @type {!Array} */ oSourceElements[nFrom][1]).unshift( - aVariableDeclaration); - }; - - if (nFrom > nTo) { - return; - } - // If the range is a closure, reuse the closure. - if (nFrom === nTo && - 'stat' === oSourceElements[nFrom][0] && - 'call' === oSourceElements[nFrom][1][0] && - 'function' === oSourceElements[nFrom][1][1][0]) { - fExamineSyntacticCodeUnit(oSourceElements[nFrom][1][1]); - return; - } - // Create a list of all derived primitive values within the range. - for (nPosition = nFrom; nPosition <= nTo; nPosition += 1) { - aSourceElementsData[nPosition].aPrimitiveValues.forEach( - cAugmentList(oSourceElementsData.aPrimitiveValues)); - } - if (0 === oSourceElementsData.aPrimitiveValues.length) { - return; - } - for (nPosition = nFrom; nPosition <= nTo; nPosition += 1) { - // Add the number of occurrences to the total count. - fAddOccurrences(nPosition); - // Add identifiers of this or any nested scope to the list. - aSourceElementsData[nPosition].aIdentifiers.forEach( - cAugmentList(oSourceElementsData.aIdentifiers)); - } - // Distribute identifier names among derived primitive values. - do { // If there was any progress, find a better distribution. - oSolutionBest = oSolutionCandidate; - if (Object.keys(oSolutionCandidate.oPrimitiveValues).length > 0) { - // Sort primitive values descending by their worthwhileness. - oSourceElementsData.aPrimitiveValues.sort(cSortPrimitiveValues); - } - oSolutionCandidate = new TSolution(); - oSourceElementsData.aPrimitiveValues.forEach( - fEvaluatePrimitiveValue); - oScope.cname = nIndex; - } while (oSolutionCandidate.nSavings > oSolutionBest.nSavings); - // Take the necessity of adding a variable statement into account. - if ('var' !== oSourceElements[nFrom][0]) { - oSolutionBest.nSavings -= oWeights.N_VARIABLE_STATEMENT_AFFIXATION; - } - if (bEnclose) { - // Take the necessity of forming a closure into account. - oSolutionBest.nSavings -= oWeights.N_CLOSURE; - } - if (oSolutionBest.nSavings > 0) { - // Create variable declarations suitable for UglifyJS. - Object.keys(oSolutionBest.oPrimitiveValues).forEach( - cAugmentVariableDeclarations); - // Rewrite expressions that contain worthwhile primitive values. - for (nPosition = nFrom; nPosition <= nTo; nPosition += 1) { - oWalker = oProcessor.ast_walker(); - oSourceElements[nPosition] = - oWalker.with_walkers( - oWalkersTransformers, - cContext(oWalker, oSourceElements[nPosition])); - } - if ('var' === oSourceElements[nFrom][0]) { // Reuse the statement. - (/** @type {!Array.} */ aVariableDeclarations.reverse( - )).forEach(cAddVariableDeclaration); - } else { // Add a variable statement. - Array.prototype.splice.call( - oSourceElements, - nFrom, - 0, - ['var', aVariableDeclarations]); - nTo += 1; - } - if (bEnclose) { - // Add a closure. - Array.prototype.splice.call( - oSourceElements, - nFrom, - 0, - ['stat', ['call', ['function', null, [], []], []]]); - // Copy source elements into the closure. - for (nPosition = nTo + 1; nPosition > nFrom; nPosition -= 1) { - Array.prototype.unshift.call( - oSourceElements[nFrom][1][1][3], - oSourceElements[nPosition]); - } - // Remove source elements outside the closure. - Array.prototype.splice.call( - oSourceElements, - nFrom + 1, - nTo - nFrom + 1); - } - } - if (bEnclose) { - // Restore the availability of identifier names. - oScope.cname = nIndex; - } - }; - - oSourceElements = (/** @type {!TSyntacticCodeUnit} */ - oSyntacticCodeUnit[bIsGlobal ? 1 : 3]); - if (0 === oSourceElements.length) { - return; - } - oScope = bIsGlobal ? oSyntacticCodeUnit.scope : oSourceElements.scope; - // Skip a Directive Prologue. - while (nAfterDirectivePrologue < oSourceElements.length && - 'directive' === oSourceElements[nAfterDirectivePrologue][0]) { - nAfterDirectivePrologue += 1; - aSourceElementsData.push(null); - } - if (oSourceElements.length === nAfterDirectivePrologue) { - return; - } - for (nPosition = nAfterDirectivePrologue; - nPosition < oSourceElements.length; - nPosition += 1) { - oSourceElementData = new TSourceElementsData(); - oWalker = oProcessor.ast_walker(); - // Classify a source element. - // Find its derived primitive values and count their occurrences. - // Find all identifiers used (including nested scopes). - oWalker.with_walkers( - oWalkers.oSurveySourceElement, - cContext(oWalker, oSourceElements[nPosition])); - // Establish whether the scope is still wholly examinable. - bIsWhollyExaminable = bIsWhollyExaminable && - ESourceElementCategories.N_WITH !== oSourceElementData.nCategory && - ESourceElementCategories.N_EVAL !== oSourceElementData.nCategory; - aSourceElementsData.push(oSourceElementData); - } - if (bIsWhollyExaminable) { // Examine the whole scope. - fExamineSourceElements( - nAfterDirectivePrologue, - oSourceElements.length - 1, - false); - } else { // Examine unexcluded ranges of source elements. - for (nPosition = oSourceElements.length - 1; - nPosition >= nAfterDirectivePrologue; - nPosition -= 1) { - oSourceElementData = (/** @type {!TSourceElementsData} */ - aSourceElementsData[nPosition]); - if (ESourceElementCategories.N_OTHER === - oSourceElementData.nCategory) { - if ('undefined' === typeof nTo) { - nTo = nPosition; // Indicate the end of a range. - } - // Examine the range if it immediately follows a Directive Prologue. - if (nPosition === nAfterDirectivePrologue) { - fExamineSourceElements(nPosition, nTo, true); - } - } else { - if ('undefined' !== typeof nTo) { - // Examine the range that immediately follows this source element. - fExamineSourceElements(nPosition + 1, nTo, true); - nTo = void 0; // Obliterate the range. - } - // Examine nested functions. - oWalker = oProcessor.ast_walker(); - oWalker.with_walkers( - oWalkers.oExamineFunctions, - cContext(oWalker, oSourceElements[nPosition])); - } - } - } - }(oAbstractSyntaxTree = oProcessor.ast_add_scope(oAbstractSyntaxTree))); - return oAbstractSyntaxTree; -}; -/*jshint sub:false */ - -/* Local Variables: */ -/* mode: js */ -/* coding: utf-8 */ -/* indent-tabs-mode: nil */ -/* tab-width: 2 */ -/* End: */ -/* vim: set ft=javascript fenc=utf-8 et ts=2 sts=2 sw=2: */ -/* :mode=javascript:noTabs=true:tabSize=2:indentSize=2:deepIndent=true: */ \ No newline at end of file diff --git a/install/ui/util/uglifyjs/lib/parse-js.js b/install/ui/util/uglifyjs/lib/parse-js.js deleted file mode 100644 index 372801814..000000000 --- a/install/ui/util/uglifyjs/lib/parse-js.js +++ /dev/null @@ -1,1369 +0,0 @@ -/*********************************************************************** - - A JavaScript tokenizer / parser / beautifier / compressor. - - This version is suitable for Node.js. With minimal changes (the - exports stuff) it should work on any JS platform. - - This file contains the tokenizer/parser. It is a port to JavaScript - of parse-js [1], a JavaScript parser library written in Common Lisp - by Marijn Haverbeke. Thank you Marijn! - - [1] http://marijn.haverbeke.nl/parse-js/ - - Exported functions: - - - tokenizer(code) -- returns a function. Call the returned - function to fetch the next token. - - - parse(code) -- returns an AST of the given JavaScript code. - - -------------------------------- (C) --------------------------------- - - Author: Mihai Bazon - - http://mihai.bazon.net/blog - - Distributed under the BSD license: - - Copyright 2010 (c) Mihai Bazon - Based on parse-js (http://marijn.haverbeke.nl/parse-js/). - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - * Redistributions of source code must retain the above - copyright notice, this list of conditions and the following - disclaimer. - - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials - provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - SUCH DAMAGE. - - ***********************************************************************/ - -/* -----[ Tokenizer (constants) ]----- */ - -var KEYWORDS = array_to_hash([ - "break", - "case", - "catch", - "const", - "continue", - "debugger", - "default", - "delete", - "do", - "else", - "finally", - "for", - "function", - "if", - "in", - "instanceof", - "new", - "return", - "switch", - "throw", - "try", - "typeof", - "var", - "void", - "while", - "with" -]); - -var RESERVED_WORDS = array_to_hash([ - "abstract", - "boolean", - "byte", - "char", - "class", - "double", - "enum", - "export", - "extends", - "final", - "float", - "goto", - "implements", - "import", - "int", - "interface", - "long", - "native", - "package", - "private", - "protected", - "public", - "short", - "static", - "super", - "synchronized", - "throws", - "transient", - "volatile" -]); - -var KEYWORDS_BEFORE_EXPRESSION = array_to_hash([ - "return", - "new", - "delete", - "throw", - "else", - "case" -]); - -var KEYWORDS_ATOM = array_to_hash([ - "false", - "null", - "true", - "undefined" -]); - -var OPERATOR_CHARS = array_to_hash(characters("+-*&%=<>!?|~^")); - -var RE_HEX_NUMBER = /^0x[0-9a-f]+$/i; -var RE_OCT_NUMBER = /^0[0-7]+$/; -var RE_DEC_NUMBER = /^\d*\.?\d*(?:e[+-]?\d*(?:\d\.?|\.?\d)\d*)?$/i; - -var OPERATORS = array_to_hash([ - "in", - "instanceof", - "typeof", - "new", - "void", - "delete", - "++", - "--", - "+", - "-", - "!", - "~", - "&", - "|", - "^", - "*", - "/", - "%", - ">>", - "<<", - ">>>", - "<", - ">", - "<=", - ">=", - "==", - "===", - "!=", - "!==", - "?", - "=", - "+=", - "-=", - "/=", - "*=", - "%=", - ">>=", - "<<=", - ">>>=", - "|=", - "^=", - "&=", - "&&", - "||" -]); - -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\uFEFF")); - -var PUNC_BEFORE_EXPRESSION = array_to_hash(characters("[{(,.;:")); - -var PUNC_CHARS = array_to_hash(characters("[]{}(),;:")); - -var REGEXP_MODIFIERS = array_to_hash(characters("gmsiy")); - -/* -----[ Tokenizer ]----- */ - -var UNICODE = { // Unicode 6.1 - letter: new RegExp("[\\u0041-\\u005A\\u0061-\\u007A\\u00AA\\u00B5\\u00BA\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u0527\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0620-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0800-\\u0815\\u081A\\u0824\\u0828\\u0840-\\u0858\\u08A0\\u08A2-\\u08AC\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971-\\u0977\\u0979-\\u097F\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0\\u0AE1\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C33\\u0C35-\\u0C39\\u0C3D\\u0C58\\u0C59\\u0C60\\u0C61\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDE\\u0CE0\\u0CE1\\u0CF1\\u0CF2\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D\\u0D4E\\u0D60\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E46\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC-\\u0EDF\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8C\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10C7\\u10CD\\u10D0-\\u10FA\\u10FC-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u167F\\u1681-\\u169A\\u16A0-\\u16EA\\u16EE-\\u16F0\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u18A8\\u18AA\\u18B0-\\u18F5\\u1900-\\u191C\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19AB\\u19C1-\\u19C7\\u1A00-\\u1A16\\u1A20-\\u1A54\\u1AA7\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1BBA-\\u1BE5\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1CE9-\\u1CEC\\u1CEE-\\u1CF1\\u1CF5\\u1CF6\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u209C\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2160-\\u2188\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2CE4\\u2CEB-\\u2CEE\\u2CF2\\u2CF3\\u2D00-\\u2D25\\u2D27\\u2D2D\\u2D30-\\u2D67\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005-\\u3007\\u3021-\\u3029\\u3031-\\u3035\\u3038-\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31BA\\u31F0-\\u31FF\\u3400-\\u4DB5\\u4E00-\\u9FCC\\uA000-\\uA48C\\uA4D0-\\uA4FD\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA66E\\uA67F-\\uA697\\uA6A0-\\uA6EF\\uA717-\\uA71F\\uA722-\\uA788\\uA78B-\\uA78E\\uA790-\\uA793\\uA7A0-\\uA7AA\\uA7F8-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA8F2-\\uA8F7\\uA8FB\\uA90A-\\uA925\\uA930-\\uA946\\uA960-\\uA97C\\uA984-\\uA9B2\\uA9CF\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAA60-\\uAA76\\uAA7A\\uAA80-\\uAAAF\\uAAB1\\uAAB5\\uAAB6\\uAAB9-\\uAABD\\uAAC0\\uAAC2\\uAADB-\\uAADD\\uAAE0-\\uAAEA\\uAAF2-\\uAAF4\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uABC0-\\uABE2\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFA6D\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC]"), - combining_mark: new RegExp("[\\u0300-\\u036F\\u0483-\\u0487\\u0591-\\u05BD\\u05BF\\u05C1\\u05C2\\u05C4\\u05C5\\u05C7\\u0610-\\u061A\\u064B-\\u065F\\u0670\\u06D6-\\u06DC\\u06DF-\\u06E4\\u06E7\\u06E8\\u06EA-\\u06ED\\u0711\\u0730-\\u074A\\u07A6-\\u07B0\\u07EB-\\u07F3\\u0816-\\u0819\\u081B-\\u0823\\u0825-\\u0827\\u0829-\\u082D\\u0859-\\u085B\\u08E4-\\u08FE\\u0900-\\u0903\\u093A-\\u093C\\u093E-\\u094F\\u0951-\\u0957\\u0962\\u0963\\u0981-\\u0983\\u09BC\\u09BE-\\u09C4\\u09C7\\u09C8\\u09CB-\\u09CD\\u09D7\\u09E2\\u09E3\\u0A01-\\u0A03\\u0A3C\\u0A3E-\\u0A42\\u0A47\\u0A48\\u0A4B-\\u0A4D\\u0A51\\u0A70\\u0A71\\u0A75\\u0A81-\\u0A83\\u0ABC\\u0ABE-\\u0AC5\\u0AC7-\\u0AC9\\u0ACB-\\u0ACD\\u0AE2\\u0AE3\\u0B01-\\u0B03\\u0B3C\\u0B3E-\\u0B44\\u0B47\\u0B48\\u0B4B-\\u0B4D\\u0B56\\u0B57\\u0B62\\u0B63\\u0B82\\u0BBE-\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCD\\u0BD7\\u0C01-\\u0C03\\u0C3E-\\u0C44\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55\\u0C56\\u0C62\\u0C63\\u0C82\\u0C83\\u0CBC\\u0CBE-\\u0CC4\\u0CC6-\\u0CC8\\u0CCA-\\u0CCD\\u0CD5\\u0CD6\\u0CE2\\u0CE3\\u0D02\\u0D03\\u0D3E-\\u0D44\\u0D46-\\u0D48\\u0D4A-\\u0D4D\\u0D57\\u0D62\\u0D63\\u0D82\\u0D83\\u0DCA\\u0DCF-\\u0DD4\\u0DD6\\u0DD8-\\u0DDF\\u0DF2\\u0DF3\\u0E31\\u0E34-\\u0E3A\\u0E47-\\u0E4E\\u0EB1\\u0EB4-\\u0EB9\\u0EBB\\u0EBC\\u0EC8-\\u0ECD\\u0F18\\u0F19\\u0F35\\u0F37\\u0F39\\u0F3E\\u0F3F\\u0F71-\\u0F84\\u0F86\\u0F87\\u0F8D-\\u0F97\\u0F99-\\u0FBC\\u0FC6\\u102B-\\u103E\\u1056-\\u1059\\u105E-\\u1060\\u1062-\\u1064\\u1067-\\u106D\\u1071-\\u1074\\u1082-\\u108D\\u108F\\u109A-\\u109D\\u135D-\\u135F\\u1712-\\u1714\\u1732-\\u1734\\u1752\\u1753\\u1772\\u1773\\u17B4-\\u17D3\\u17DD\\u180B-\\u180D\\u18A9\\u1920-\\u192B\\u1930-\\u193B\\u19B0-\\u19C0\\u19C8\\u19C9\\u1A17-\\u1A1B\\u1A55-\\u1A5E\\u1A60-\\u1A7C\\u1A7F\\u1B00-\\u1B04\\u1B34-\\u1B44\\u1B6B-\\u1B73\\u1B80-\\u1B82\\u1BA1-\\u1BAD\\u1BE6-\\u1BF3\\u1C24-\\u1C37\\u1CD0-\\u1CD2\\u1CD4-\\u1CE8\\u1CED\\u1CF2-\\u1CF4\\u1DC0-\\u1DE6\\u1DFC-\\u1DFF\\u20D0-\\u20DC\\u20E1\\u20E5-\\u20F0\\u2CEF-\\u2CF1\\u2D7F\\u2DE0-\\u2DFF\\u302A-\\u302F\\u3099\\u309A\\uA66F\\uA674-\\uA67D\\uA69F\\uA6F0\\uA6F1\\uA802\\uA806\\uA80B\\uA823-\\uA827\\uA880\\uA881\\uA8B4-\\uA8C4\\uA8E0-\\uA8F1\\uA926-\\uA92D\\uA947-\\uA953\\uA980-\\uA983\\uA9B3-\\uA9C0\\uAA29-\\uAA36\\uAA43\\uAA4C\\uAA4D\\uAA7B\\uAAB0\\uAAB2-\\uAAB4\\uAAB7\\uAAB8\\uAABE\\uAABF\\uAAC1\\uAAEB-\\uAAEF\\uAAF5\\uAAF6\\uABE3-\\uABEA\\uABEC\\uABED\\uFB1E\\uFE00-\\uFE0F\\uFE20-\\uFE26]"), - connector_punctuation: new RegExp("[\\u005F\\u203F\\u2040\\u2054\\uFE33\\uFE34\\uFE4D-\\uFE4F\\uFF3F]"), - digit: new RegExp("[\\u0030-\\u0039\\u0660-\\u0669\\u06F0-\\u06F9\\u07C0-\\u07C9\\u0966-\\u096F\\u09E6-\\u09EF\\u0A66-\\u0A6F\\u0AE6-\\u0AEF\\u0B66-\\u0B6F\\u0BE6-\\u0BEF\\u0C66-\\u0C6F\\u0CE6-\\u0CEF\\u0D66-\\u0D6F\\u0E50-\\u0E59\\u0ED0-\\u0ED9\\u0F20-\\u0F29\\u1040-\\u1049\\u1090-\\u1099\\u17E0-\\u17E9\\u1810-\\u1819\\u1946-\\u194F\\u19D0-\\u19D9\\u1A80-\\u1A89\\u1A90-\\u1A99\\u1B50-\\u1B59\\u1BB0-\\u1BB9\\u1C40-\\u1C49\\u1C50-\\u1C59\\uA620-\\uA629\\uA8D0-\\uA8D9\\uA900-\\uA909\\uA9D0-\\uA9D9\\uAA50-\\uAA59\\uABF0-\\uABF9\\uFF10-\\uFF19]") -}; - -function is_letter(ch) { - return UNICODE.letter.test(ch); -}; - -function is_digit(ch) { - ch = ch.charCodeAt(0); - return ch >= 48 && ch <= 57; -}; - -function is_unicode_digit(ch) { - return UNICODE.digit.test(ch); -} - -function is_alphanumeric_char(ch) { - return is_digit(ch) || is_letter(ch); -}; - -function is_unicode_combining_mark(ch) { - return UNICODE.combining_mark.test(ch); -}; - -function is_unicode_connector_punctuation(ch) { - return UNICODE.connector_punctuation.test(ch); -}; - -function is_identifier_start(ch) { - return ch == "$" || ch == "_" || is_letter(ch); -}; - -function is_identifier_char(ch) { - return is_identifier_start(ch) - || is_unicode_combining_mark(ch) - || is_unicode_digit(ch) - || is_unicode_connector_punctuation(ch) - || ch == "\u200c" // zero-width non-joiner - || ch == "\u200d" // zero-width joiner (in my ECMA-262 PDF, this is also 200c) - ; -}; - -function parse_js_number(num) { - if (RE_HEX_NUMBER.test(num)) { - return parseInt(num.substr(2), 16); - } else if (RE_OCT_NUMBER.test(num)) { - return parseInt(num.substr(1), 8); - } else if (RE_DEC_NUMBER.test(num)) { - return parseFloat(num); - } -}; - -function JS_Parse_Error(message, line, col, pos) { - this.message = message; - this.line = line + 1; - this.col = col + 1; - this.pos = pos + 1; - this.stack = new Error().stack; -}; - -JS_Parse_Error.prototype.toString = function() { - return this.message + " (line: " + this.line + ", col: " + this.col + ", pos: " + this.pos + ")" + "\n\n" + this.stack; -}; - -function js_error(message, line, col, pos) { - throw new JS_Parse_Error(message, line, col, pos); -}; - -function is_token(token, type, val) { - return token.type == type && (val == null || token.value == val); -}; - -var EX_EOF = {}; - -function tokenizer($TEXT) { - - var S = { - text : $TEXT.replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/^\uFEFF/, ''), - pos : 0, - tokpos : 0, - line : 0, - tokline : 0, - col : 0, - tokcol : 0, - newline_before : false, - regex_allowed : false, - comments_before : [] - }; - - function peek() { return S.text.charAt(S.pos); }; - - function next(signal_eof, in_string) { - var ch = S.text.charAt(S.pos++); - if (signal_eof && !ch) - throw EX_EOF; - if (ch == "\n") { - S.newline_before = S.newline_before || !in_string; - ++S.line; - S.col = 0; - } else { - ++S.col; - } - return ch; - }; - - function eof() { - return !S.peek(); - }; - - function find(what, signal_eof) { - var pos = S.text.indexOf(what, S.pos); - if (signal_eof && pos == -1) throw EX_EOF; - return pos; - }; - - function start_token() { - S.tokline = S.line; - S.tokcol = S.col; - S.tokpos = S.pos; - }; - - function token(type, value, is_comment) { - S.regex_allowed = ((type == "operator" && !HOP(UNARY_POSTFIX, value)) || - (type == "keyword" && HOP(KEYWORDS_BEFORE_EXPRESSION, value)) || - (type == "punc" && HOP(PUNC_BEFORE_EXPRESSION, value))); - var ret = { - type : type, - value : value, - line : S.tokline, - col : S.tokcol, - pos : S.tokpos, - endpos : S.pos, - nlb : S.newline_before - }; - if (!is_comment) { - ret.comments_before = S.comments_before; - S.comments_before = []; - // make note of any newlines in the comments that came before - for (var i = 0, len = ret.comments_before.length; i < len; i++) { - ret.nlb = ret.nlb || ret.comments_before[i].nlb; - } - } - S.newline_before = false; - return ret; - }; - - function skip_whitespace() { - while (HOP(WHITESPACE_CHARS, peek())) - next(); - }; - - function read_while(pred) { - var ret = "", ch = peek(), i = 0; - while (ch && pred(ch, i++)) { - ret += next(); - ch = peek(); - } - return ret; - }; - - function parse_error(err) { - js_error(err, S.tokline, S.tokcol, S.tokpos); - }; - - function read_num(prefix) { - var has_e = false, after_e = false, has_x = false, has_dot = prefix == "."; - var num = read_while(function(ch, i){ - if (ch == "x" || ch == "X") { - if (has_x) return false; - return has_x = true; - } - if (!has_x && (ch == "E" || ch == "e")) { - if (has_e) return false; - return has_e = after_e = true; - } - if (ch == "-") { - if (after_e || (i == 0 && !prefix)) return true; - return false; - } - if (ch == "+") return after_e; - after_e = false; - if (ch == ".") { - if (!has_dot && !has_x && !has_e) - return has_dot = true; - return false; - } - return is_alphanumeric_char(ch); - }); - if (prefix) - num = prefix + num; - var valid = parse_js_number(num); - if (!isNaN(valid)) { - return token("num", valid); - } else { - parse_error("Invalid syntax: " + num); - } - }; - - function read_escaped_char(in_string) { - var ch = next(true, in_string); - switch (ch) { - case "n" : return "\n"; - case "r" : return "\r"; - case "t" : return "\t"; - case "b" : return "\b"; - case "v" : return "\u000b"; - case "f" : return "\f"; - case "0" : return "\0"; - case "x" : return String.fromCharCode(hex_bytes(2)); - case "u" : return String.fromCharCode(hex_bytes(4)); - case "\n": return ""; - default : return ch; - } - }; - - function hex_bytes(n) { - var num = 0; - for (; n > 0; --n) { - var digit = parseInt(next(true), 16); - if (isNaN(digit)) - parse_error("Invalid hex-character pattern in string"); - num = (num << 4) | digit; - } - return num; - }; - - function read_string() { - return with_eof_error("Unterminated string constant", function(){ - var quote = next(), ret = ""; - for (;;) { - var ch = next(true); - if (ch == "\\") { - // read OctalEscapeSequence (XXX: deprecated if "strict mode") - // https://github.com/mishoo/UglifyJS/issues/178 - var octal_len = 0, first = null; - ch = read_while(function(ch){ - if (ch >= "0" && ch <= "7") { - if (!first) { - first = ch; - return ++octal_len; - } - else if (first <= "3" && octal_len <= 2) return ++octal_len; - else if (first >= "4" && octal_len <= 1) return ++octal_len; - } - return false; - }); - if (octal_len > 0) ch = String.fromCharCode(parseInt(ch, 8)); - else ch = read_escaped_char(true); - } - else if (ch == quote) break; - else if (ch == "\n") throw EX_EOF; - ret += ch; - } - return token("string", ret); - }); - }; - - function read_line_comment() { - next(); - var i = find("\n"), ret; - if (i == -1) { - ret = S.text.substr(S.pos); - S.pos = S.text.length; - } else { - ret = S.text.substring(S.pos, i); - S.pos = i; - } - return token("comment1", ret, true); - }; - - function read_multiline_comment() { - next(); - return with_eof_error("Unterminated multiline comment", function(){ - var i = find("*/", true), - text = S.text.substring(S.pos, i); - S.pos = i + 2; - S.line += text.split("\n").length - 1; - S.newline_before = S.newline_before || text.indexOf("\n") >= 0; - - // https://github.com/mishoo/UglifyJS/issues/#issue/100 - if (/^@cc_on/i.test(text)) { - warn("WARNING: at line " + S.line); - warn("*** Found \"conditional comment\": " + text); - warn("*** UglifyJS DISCARDS ALL COMMENTS. This means your code might no longer work properly in Internet Explorer."); - } - - return token("comment2", text, true); - }); - }; - - function read_name() { - var backslash = false, name = "", ch, escaped = false, hex; - while ((ch = peek()) != null) { - if (!backslash) { - if (ch == "\\") escaped = backslash = true, next(); - else if (is_identifier_char(ch)) name += next(); - else break; - } - else { - if (ch != "u") parse_error("Expecting UnicodeEscapeSequence -- uXXXX"); - ch = read_escaped_char(); - if (!is_identifier_char(ch)) parse_error("Unicode char: " + ch.charCodeAt(0) + " is not valid in identifier"); - name += ch; - backslash = false; - } - } - if (HOP(KEYWORDS, name) && escaped) { - hex = name.charCodeAt(0).toString(16).toUpperCase(); - name = "\\u" + "0000".substr(hex.length) + hex + name.slice(1); - } - return name; - }; - - function read_regexp(regexp) { - return with_eof_error("Unterminated regular expression", function(){ - var prev_backslash = false, ch, in_class = false; - while ((ch = next(true))) if (prev_backslash) { - regexp += "\\" + ch; - prev_backslash = false; - } else if (ch == "[") { - in_class = true; - regexp += ch; - } else if (ch == "]" && in_class) { - in_class = false; - regexp += ch; - } else if (ch == "/" && !in_class) { - break; - } else if (ch == "\\") { - prev_backslash = true; - } else { - regexp += ch; - } - var mods = read_name(); - return token("regexp", [ regexp, mods ]); - }); - }; - - function read_operator(prefix) { - function grow(op) { - if (!peek()) return op; - var bigger = op + peek(); - if (HOP(OPERATORS, bigger)) { - next(); - return grow(bigger); - } else { - return op; - } - }; - return token("operator", grow(prefix || next())); - }; - - function handle_slash() { - next(); - var regex_allowed = S.regex_allowed; - switch (peek()) { - case "/": - S.comments_before.push(read_line_comment()); - S.regex_allowed = regex_allowed; - return next_token(); - case "*": - S.comments_before.push(read_multiline_comment()); - S.regex_allowed = regex_allowed; - return next_token(); - } - return S.regex_allowed ? read_regexp("") : read_operator("/"); - }; - - function handle_dot() { - next(); - return is_digit(peek()) - ? read_num(".") - : token("punc", "."); - }; - - function read_word() { - var word = read_name(); - return !HOP(KEYWORDS, word) - ? token("name", word) - : HOP(OPERATORS, word) - ? token("operator", word) - : HOP(KEYWORDS_ATOM, word) - ? token("atom", word) - : token("keyword", word); - }; - - function with_eof_error(eof_error, cont) { - try { - return cont(); - } catch(ex) { - if (ex === EX_EOF) parse_error(eof_error); - else throw ex; - } - }; - - function next_token(force_regexp) { - if (force_regexp != null) - return read_regexp(force_regexp); - skip_whitespace(); - start_token(); - var ch = peek(); - if (!ch) return token("eof"); - if (is_digit(ch)) return read_num(); - if (ch == '"' || ch == "'") return read_string(); - if (HOP(PUNC_CHARS, ch)) return token("punc", next()); - if (ch == ".") return handle_dot(); - if (ch == "/") return handle_slash(); - if (HOP(OPERATOR_CHARS, ch)) return read_operator(); - if (ch == "\\" || is_identifier_start(ch)) return read_word(); - parse_error("Unexpected character '" + ch + "'"); - }; - - next_token.context = function(nc) { - if (nc) S = nc; - return S; - }; - - return next_token; - -}; - -/* -----[ Parser (constants) ]----- */ - -var UNARY_PREFIX = array_to_hash([ - "typeof", - "void", - "delete", - "--", - "++", - "!", - "~", - "-", - "+" -]); - -var UNARY_POSTFIX = array_to_hash([ "--", "++" ]); - -var ASSIGNMENT = (function(a, ret, i){ - while (i < a.length) { - ret[a[i]] = a[i].substr(0, a[i].length - 1); - i++; - } - return ret; -})( - ["+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&="], - { "=": true }, - 0 -); - -var PRECEDENCE = (function(a, ret){ - for (var i = 0, n = 1; i < a.length; ++i, ++n) { - var b = a[i]; - for (var j = 0; j < b.length; ++j) { - ret[b[j]] = n; - } - } - return ret; -})( - [ - ["||"], - ["&&"], - ["|"], - ["^"], - ["&"], - ["==", "===", "!=", "!=="], - ["<", ">", "<=", ">=", "in", "instanceof"], - [">>", "<<", ">>>"], - ["+", "-"], - ["*", "/", "%"] - ], - {} -); - -var STATEMENTS_WITH_LABELS = array_to_hash([ "for", "do", "while", "switch" ]); - -var ATOMIC_START_TOKEN = array_to_hash([ "atom", "num", "string", "regexp", "name" ]); - -/* -----[ Parser ]----- */ - -function NodeWithToken(str, start, end) { - this.name = str; - this.start = start; - this.end = end; -}; - -NodeWithToken.prototype.toString = function() { return this.name; }; - -function parse($TEXT, exigent_mode, embed_tokens) { - - var S = { - input : typeof $TEXT == "string" ? tokenizer($TEXT, true) : $TEXT, - token : null, - prev : null, - peeked : null, - in_function : 0, - in_directives : true, - in_loop : 0, - labels : [] - }; - - S.token = next(); - - function is(type, value) { - return is_token(S.token, type, value); - }; - - function peek() { return S.peeked || (S.peeked = S.input()); }; - - function next() { - S.prev = S.token; - if (S.peeked) { - S.token = S.peeked; - S.peeked = null; - } else { - S.token = S.input(); - } - S.in_directives = S.in_directives && ( - S.token.type == "string" || is("punc", ";") - ); - return S.token; - }; - - function prev() { - return S.prev; - }; - - function croak(msg, line, col, pos) { - var ctx = S.input.context(); - js_error(msg, - line != null ? line : ctx.tokline, - col != null ? col : ctx.tokcol, - pos != null ? pos : ctx.tokpos); - }; - - function token_error(token, msg) { - croak(msg, token.line, token.col); - }; - - function unexpected(token) { - if (token == null) - token = S.token; - token_error(token, "Unexpected token: " + token.type + " (" + token.value + ")"); - }; - - function expect_token(type, val) { - if (is(type, val)) { - return next(); - } - token_error(S.token, "Unexpected token " + S.token.type + ", expected " + type); - }; - - function expect(punc) { return expect_token("punc", punc); }; - - function can_insert_semicolon() { - return !exigent_mode && ( - S.token.nlb || is("eof") || is("punc", "}") - ); - }; - - function semicolon() { - if (is("punc", ";")) next(); - else if (!can_insert_semicolon()) unexpected(); - }; - - function as() { - return slice(arguments); - }; - - function parenthesised() { - expect("("); - var ex = expression(); - expect(")"); - return ex; - }; - - function add_tokens(str, start, end) { - return str instanceof NodeWithToken ? str : new NodeWithToken(str, start, end); - }; - - function maybe_embed_tokens(parser) { - if (embed_tokens) return function() { - var start = S.token; - var ast = parser.apply(this, arguments); - ast[0] = add_tokens(ast[0], start, prev()); - return ast; - }; - else return parser; - }; - - var statement = maybe_embed_tokens(function() { - if (is("operator", "/") || is("operator", "/=")) { - S.peeked = null; - S.token = S.input(S.token.value.substr(1)); // force regexp - } - switch (S.token.type) { - case "string": - var dir = S.in_directives, stat = simple_statement(); - if (dir && stat[1][0] == "string" && !is("punc", ",")) - return as("directive", stat[1][1]); - return stat; - case "num": - case "regexp": - case "operator": - case "atom": - return simple_statement(); - - case "name": - return is_token(peek(), "punc", ":") - ? labeled_statement(prog1(S.token.value, next, next)) - : simple_statement(); - - case "punc": - switch (S.token.value) { - case "{": - return as("block", block_()); - case "[": - case "(": - return simple_statement(); - case ";": - next(); - return as("block"); - default: - unexpected(); - } - - case "keyword": - switch (prog1(S.token.value, next)) { - case "break": - return break_cont("break"); - - case "continue": - return break_cont("continue"); - - case "debugger": - semicolon(); - return as("debugger"); - - case "do": - return (function(body){ - expect_token("keyword", "while"); - return as("do", prog1(parenthesised, semicolon), body); - })(in_loop(statement)); - - case "for": - return for_(); - - case "function": - return function_(true); - - case "if": - return if_(); - - case "return": - if (S.in_function == 0) - croak("'return' outside of function"); - return as("return", - is("punc", ";") - ? (next(), null) - : can_insert_semicolon() - ? null - : prog1(expression, semicolon)); - - case "switch": - return as("switch", parenthesised(), switch_block_()); - - case "throw": - if (S.token.nlb) - croak("Illegal newline after 'throw'"); - return as("throw", prog1(expression, semicolon)); - - case "try": - return try_(); - - case "var": - return prog1(var_, semicolon); - - case "const": - return prog1(const_, semicolon); - - case "while": - return as("while", parenthesised(), in_loop(statement)); - - case "with": - return as("with", parenthesised(), statement()); - - default: - unexpected(); - } - } - }); - - function labeled_statement(label) { - S.labels.push(label); - var start = S.token, stat = statement(); - if (exigent_mode && !HOP(STATEMENTS_WITH_LABELS, stat[0])) - unexpected(start); - S.labels.pop(); - return as("label", label, stat); - }; - - function simple_statement() { - return as("stat", prog1(expression, semicolon)); - }; - - function break_cont(type) { - var name; - if (!can_insert_semicolon()) { - name = is("name") ? S.token.value : null; - } - if (name != null) { - next(); - if (!member(name, S.labels)) - croak("Label " + name + " without matching loop or statement"); - } - else if (S.in_loop == 0) - croak(type + " not inside a loop or switch"); - semicolon(); - return as(type, name); - }; - - function for_() { - expect("("); - var init = null; - if (!is("punc", ";")) { - init = is("keyword", "var") - ? (next(), var_(true)) - : expression(true, true); - if (is("operator", "in")) { - if (init[0] == "var" && init[1].length > 1) - croak("Only one variable declaration allowed in for..in loop"); - return for_in(init); - } - } - return regular_for(init); - }; - - function regular_for(init) { - expect(";"); - var test = is("punc", ";") ? null : expression(); - expect(";"); - var step = is("punc", ")") ? null : expression(); - expect(")"); - return as("for", init, test, step, in_loop(statement)); - }; - - function for_in(init) { - var lhs = init[0] == "var" ? as("name", init[1][0]) : init; - next(); - var obj = expression(); - expect(")"); - return as("for-in", init, lhs, obj, in_loop(statement)); - }; - - var function_ = function(in_statement) { - var name = is("name") ? prog1(S.token.value, next) : null; - if (in_statement && !name) - unexpected(); - expect("("); - return as(in_statement ? "defun" : "function", - name, - // arguments - (function(first, a){ - while (!is("punc", ")")) { - if (first) first = false; else expect(","); - if (!is("name")) unexpected(); - a.push(S.token.value); - next(); - } - next(); - return a; - })(true, []), - // body - (function(){ - ++S.in_function; - var loop = S.in_loop; - S.in_directives = true; - S.in_loop = 0; - var a = block_(); - --S.in_function; - S.in_loop = loop; - return a; - })()); - }; - - function if_() { - var cond = parenthesised(), body = statement(), belse; - if (is("keyword", "else")) { - next(); - belse = statement(); - } - return as("if", cond, body, belse); - }; - - function block_() { - expect("{"); - var a = []; - while (!is("punc", "}")) { - if (is("eof")) unexpected(); - a.push(statement()); - } - next(); - return a; - }; - - var switch_block_ = curry(in_loop, function(){ - expect("{"); - var a = [], cur = null; - while (!is("punc", "}")) { - if (is("eof")) unexpected(); - if (is("keyword", "case")) { - next(); - cur = []; - a.push([ expression(), cur ]); - expect(":"); - } - else if (is("keyword", "default")) { - next(); - expect(":"); - cur = []; - a.push([ null, cur ]); - } - else { - if (!cur) unexpected(); - cur.push(statement()); - } - } - next(); - return a; - }); - - function try_() { - var body = block_(), bcatch, bfinally; - if (is("keyword", "catch")) { - next(); - expect("("); - if (!is("name")) - croak("Name expected"); - var name = S.token.value; - next(); - expect(")"); - bcatch = [ name, block_() ]; - } - if (is("keyword", "finally")) { - next(); - bfinally = block_(); - } - if (!bcatch && !bfinally) - croak("Missing catch/finally blocks"); - return as("try", body, bcatch, bfinally); - }; - - function vardefs(no_in) { - var a = []; - for (;;) { - if (!is("name")) - unexpected(); - var name = S.token.value; - next(); - if (is("operator", "=")) { - next(); - a.push([ name, expression(false, no_in) ]); - } else { - a.push([ name ]); - } - if (!is("punc", ",")) - break; - next(); - } - return a; - }; - - function var_(no_in) { - return as("var", vardefs(no_in)); - }; - - function const_() { - return as("const", vardefs()); - }; - - function new_() { - var newexp = expr_atom(false), args; - if (is("punc", "(")) { - next(); - args = expr_list(")"); - } else { - args = []; - } - return subscripts(as("new", newexp, args), true); - }; - - var expr_atom = maybe_embed_tokens(function(allow_calls) { - if (is("operator", "new")) { - next(); - return new_(); - } - if (is("punc")) { - switch (S.token.value) { - case "(": - next(); - return subscripts(prog1(expression, curry(expect, ")")), allow_calls); - case "[": - next(); - return subscripts(array_(), allow_calls); - case "{": - next(); - return subscripts(object_(), allow_calls); - } - unexpected(); - } - if (is("keyword", "function")) { - next(); - return subscripts(function_(false), allow_calls); - } - if (HOP(ATOMIC_START_TOKEN, S.token.type)) { - var atom = S.token.type == "regexp" - ? as("regexp", S.token.value[0], S.token.value[1]) - : as(S.token.type, S.token.value); - return subscripts(prog1(atom, next), allow_calls); - } - unexpected(); - }); - - function expr_list(closing, allow_trailing_comma, allow_empty) { - var first = true, a = []; - while (!is("punc", closing)) { - if (first) first = false; else expect(","); - if (allow_trailing_comma && is("punc", closing)) break; - if (is("punc", ",") && allow_empty) { - a.push([ "atom", "undefined" ]); - } else { - a.push(expression(false)); - } - } - next(); - return a; - }; - - function array_() { - return as("array", expr_list("]", !exigent_mode, true)); - }; - - function object_() { - var first = true, a = []; - while (!is("punc", "}")) { - if (first) first = false; else expect(","); - if (!exigent_mode && is("punc", "}")) - // allow trailing comma - break; - var type = S.token.type; - var name = as_property_name(); - if (type == "name" && (name == "get" || name == "set") && !is("punc", ":")) { - a.push([ as_name(), function_(false), name ]); - } else { - expect(":"); - a.push([ name, expression(false) ]); - } - } - next(); - return as("object", a); - }; - - function as_property_name() { - switch (S.token.type) { - case "num": - case "string": - return prog1(S.token.value, next); - } - return as_name(); - }; - - function as_name() { - switch (S.token.type) { - case "name": - case "operator": - case "keyword": - case "atom": - return prog1(S.token.value, next); - default: - unexpected(); - } - }; - - function subscripts(expr, allow_calls) { - if (is("punc", ".")) { - next(); - return subscripts(as("dot", expr, as_name()), allow_calls); - } - if (is("punc", "[")) { - next(); - return subscripts(as("sub", expr, prog1(expression, curry(expect, "]"))), allow_calls); - } - if (allow_calls && is("punc", "(")) { - next(); - return subscripts(as("call", expr, expr_list(")")), true); - } - return expr; - }; - - function maybe_unary(allow_calls) { - if (is("operator") && HOP(UNARY_PREFIX, S.token.value)) { - return make_unary("unary-prefix", - prog1(S.token.value, next), - maybe_unary(allow_calls)); - } - var val = expr_atom(allow_calls); - while (is("operator") && HOP(UNARY_POSTFIX, S.token.value) && !S.token.nlb) { - val = make_unary("unary-postfix", S.token.value, val); - next(); - } - return val; - }; - - function make_unary(tag, op, expr) { - if ((op == "++" || op == "--") && !is_assignable(expr)) - croak("Invalid use of " + op + " operator"); - return as(tag, op, expr); - }; - - function expr_op(left, min_prec, no_in) { - var op = is("operator") ? S.token.value : null; - if (op && op == "in" && no_in) op = null; - var prec = op != null ? PRECEDENCE[op] : null; - if (prec != null && prec > min_prec) { - next(); - var right = expr_op(maybe_unary(true), prec, no_in); - return expr_op(as("binary", op, left, right), min_prec, no_in); - } - return left; - }; - - function expr_ops(no_in) { - return expr_op(maybe_unary(true), 0, no_in); - }; - - function maybe_conditional(no_in) { - var expr = expr_ops(no_in); - if (is("operator", "?")) { - next(); - var yes = expression(false); - expect(":"); - return as("conditional", expr, yes, expression(false, no_in)); - } - return expr; - }; - - function is_assignable(expr) { - if (!exigent_mode) return true; - switch (expr[0]+"") { - case "dot": - case "sub": - case "new": - case "call": - return true; - case "name": - return expr[1] != "this"; - } - }; - - function maybe_assign(no_in) { - var left = maybe_conditional(no_in), val = S.token.value; - if (is("operator") && HOP(ASSIGNMENT, val)) { - if (is_assignable(left)) { - next(); - return as("assign", ASSIGNMENT[val], left, maybe_assign(no_in)); - } - croak("Invalid assignment"); - } - return left; - }; - - var expression = maybe_embed_tokens(function(commas, no_in) { - if (arguments.length == 0) - commas = true; - var expr = maybe_assign(no_in); - if (commas && is("punc", ",")) { - next(); - return as("seq", expr, expression(true, no_in)); - } - return expr; - }); - - function in_loop(cont) { - try { - ++S.in_loop; - return cont(); - } finally { - --S.in_loop; - } - }; - - return as("toplevel", (function(a){ - while (!is("eof")) - a.push(statement()); - return a; - })([])); - -}; - -/* -----[ Utilities ]----- */ - -function curry(f) { - var args = slice(arguments, 1); - return function() { return f.apply(this, args.concat(slice(arguments))); }; -}; - -function prog1(ret) { - if (ret instanceof Function) - ret = ret(); - for (var i = 1, n = arguments.length; --n > 0; ++i) - arguments[i](); - return ret; -}; - -function array_to_hash(a) { - var ret = {}; - for (var i = 0; i < a.length; ++i) - ret[a[i]] = true; - return ret; -}; - -function slice(a, start) { - return Array.prototype.slice.call(a, start || 0); -}; - -function characters(str) { - return str.split(""); -}; - -function member(name, array) { - for (var i = array.length; --i >= 0;) - if (array[i] == name) - return true; - return false; -}; - -function HOP(obj, prop) { - return Object.prototype.hasOwnProperty.call(obj, prop); -}; - -var warn = function() {}; - -/* -----[ Exports ]----- */ - -exports.tokenizer = tokenizer; -exports.parse = parse; -exports.slice = slice; -exports.curry = curry; -exports.member = member; -exports.array_to_hash = array_to_hash; -exports.PRECEDENCE = PRECEDENCE; -exports.KEYWORDS_ATOM = KEYWORDS_ATOM; -exports.RESERVED_WORDS = RESERVED_WORDS; -exports.KEYWORDS = KEYWORDS; -exports.ATOMIC_START_TOKEN = ATOMIC_START_TOKEN; -exports.OPERATORS = OPERATORS; -exports.is_alphanumeric_char = is_alphanumeric_char; -exports.is_identifier_start = is_identifier_start; -exports.is_identifier_char = is_identifier_char; -exports.set_logger = function(logger) { - warn = logger; -}; - -// Local variables: -// js-indent-level: 4 -// End: diff --git a/install/ui/util/uglifyjs/lib/process.js b/install/ui/util/uglifyjs/lib/process.js deleted file mode 100644 index 42d61dfcf..000000000 --- a/install/ui/util/uglifyjs/lib/process.js +++ /dev/null @@ -1,2117 +0,0 @@ -/*********************************************************************** - - A JavaScript tokenizer / parser / beautifier / compressor. - - This version is suitable for Node.js. With minimal changes (the - exports stuff) it should work on any JS platform. - - This file implements some AST processors. They work on data built - by parse-js. - - Exported functions: - - - ast_mangle(ast, options) -- mangles the variable/function names - in the AST. Returns an AST. - - - ast_squeeze(ast) -- employs various optimizations to make the - final generated code even smaller. Returns an AST. - - - gen_code(ast, options) -- generates JS code from the AST. Pass - true (or an object, see the code for some options) as second - argument to get "pretty" (indented) code. - - -------------------------------- (C) --------------------------------- - - Author: Mihai Bazon - - http://mihai.bazon.net/blog - - Distributed under the BSD license: - - Copyright 2010 (c) Mihai Bazon - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - * Redistributions of source code must retain the above - copyright notice, this list of conditions and the following - disclaimer. - - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials - provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - SUCH DAMAGE. - - ***********************************************************************/ - -var jsp = require("./parse-js"), - curry = jsp.curry, - slice = jsp.slice, - member = jsp.member, - is_identifier_char = jsp.is_identifier_char, - PRECEDENCE = jsp.PRECEDENCE, - OPERATORS = jsp.OPERATORS; - -/* -----[ helper for AST traversal ]----- */ - -function ast_walker() { - function _vardefs(defs) { - return [ this[0], MAP(defs, function(def){ - var a = [ def[0] ]; - if (def.length > 1) - a[1] = walk(def[1]); - return a; - }) ]; - }; - function _block(statements) { - var out = [ this[0] ]; - if (statements != null) - out.push(MAP(statements, walk)); - return out; - }; - var walkers = { - "string": function(str) { - return [ this[0], str ]; - }, - "num": function(num) { - return [ this[0], num ]; - }, - "name": function(name) { - return [ this[0], name ]; - }, - "toplevel": function(statements) { - return [ this[0], MAP(statements, walk) ]; - }, - "block": _block, - "splice": _block, - "var": _vardefs, - "const": _vardefs, - "try": function(t, c, f) { - return [ - this[0], - MAP(t, walk), - c != null ? [ c[0], MAP(c[1], walk) ] : null, - f != null ? MAP(f, walk) : null - ]; - }, - "throw": function(expr) { - return [ this[0], walk(expr) ]; - }, - "new": function(ctor, args) { - return [ this[0], walk(ctor), MAP(args, walk) ]; - }, - "switch": function(expr, body) { - return [ this[0], walk(expr), MAP(body, function(branch){ - return [ branch[0] ? walk(branch[0]) : null, - MAP(branch[1], walk) ]; - }) ]; - }, - "break": function(label) { - return [ this[0], label ]; - }, - "continue": function(label) { - return [ this[0], label ]; - }, - "conditional": function(cond, t, e) { - return [ this[0], walk(cond), walk(t), walk(e) ]; - }, - "assign": function(op, lvalue, rvalue) { - return [ this[0], op, walk(lvalue), walk(rvalue) ]; - }, - "dot": function(expr) { - return [ this[0], walk(expr) ].concat(slice(arguments, 1)); - }, - "call": function(expr, args) { - return [ this[0], walk(expr), MAP(args, walk) ]; - }, - "function": function(name, args, body) { - return [ this[0], name, args.slice(), MAP(body, walk) ]; - }, - "debugger": function() { - return [ this[0] ]; - }, - "defun": function(name, args, body) { - return [ this[0], name, args.slice(), MAP(body, walk) ]; - }, - "if": function(conditional, t, e) { - return [ this[0], walk(conditional), walk(t), walk(e) ]; - }, - "for": function(init, cond, step, block) { - return [ this[0], walk(init), walk(cond), walk(step), walk(block) ]; - }, - "for-in": function(vvar, key, hash, block) { - return [ this[0], walk(vvar), walk(key), walk(hash), walk(block) ]; - }, - "while": function(cond, block) { - return [ this[0], walk(cond), walk(block) ]; - }, - "do": function(cond, block) { - return [ this[0], walk(cond), walk(block) ]; - }, - "return": function(expr) { - return [ this[0], walk(expr) ]; - }, - "binary": function(op, left, right) { - return [ this[0], op, walk(left), walk(right) ]; - }, - "unary-prefix": function(op, expr) { - return [ this[0], op, walk(expr) ]; - }, - "unary-postfix": function(op, expr) { - return [ this[0], op, walk(expr) ]; - }, - "sub": function(expr, subscript) { - return [ this[0], walk(expr), walk(subscript) ]; - }, - "object": function(props) { - return [ this[0], MAP(props, function(p){ - return p.length == 2 - ? [ p[0], walk(p[1]) ] - : [ p[0], walk(p[1]), p[2] ]; // get/set-ter - }) ]; - }, - "regexp": function(rx, mods) { - return [ this[0], rx, mods ]; - }, - "array": function(elements) { - return [ this[0], MAP(elements, walk) ]; - }, - "stat": function(stat) { - return [ this[0], walk(stat) ]; - }, - "seq": function() { - return [ this[0] ].concat(MAP(slice(arguments), walk)); - }, - "label": function(name, block) { - return [ this[0], name, walk(block) ]; - }, - "with": function(expr, block) { - return [ this[0], walk(expr), walk(block) ]; - }, - "atom": function(name) { - return [ this[0], name ]; - }, - "directive": function(dir) { - return [ this[0], dir ]; - } - }; - - var user = {}; - var stack = []; - function walk(ast) { - if (ast == null) - return null; - try { - stack.push(ast); - var type = ast[0]; - var gen = user[type]; - if (gen) { - var ret = gen.apply(ast, ast.slice(1)); - if (ret != null) - return ret; - } - gen = walkers[type]; - return gen.apply(ast, ast.slice(1)); - } finally { - stack.pop(); - } - }; - - function dive(ast) { - if (ast == null) - return null; - try { - stack.push(ast); - return walkers[ast[0]].apply(ast, ast.slice(1)); - } finally { - stack.pop(); - } - }; - - function with_walkers(walkers, cont){ - var save = {}, i; - for (i in walkers) if (HOP(walkers, i)) { - save[i] = user[i]; - user[i] = walkers[i]; - } - var ret = cont(); - for (i in save) if (HOP(save, i)) { - if (!save[i]) delete user[i]; - else user[i] = save[i]; - } - return ret; - }; - - return { - walk: walk, - dive: dive, - with_walkers: with_walkers, - parent: function() { - return stack[stack.length - 2]; // last one is current node - }, - stack: function() { - return stack; - } - }; -}; - -/* -----[ Scope and mangling ]----- */ - -function Scope(parent) { - this.names = {}; // names defined in this scope - this.mangled = {}; // mangled names (orig.name => mangled) - this.rev_mangled = {}; // reverse lookup (mangled => orig.name) - this.cname = -1; // current mangled name - this.refs = {}; // names referenced from this scope - this.uses_with = false; // will become TRUE if with() is detected in this or any subscopes - this.uses_eval = false; // will become TRUE if eval() is detected in this or any subscopes - this.directives = []; // directives activated from this scope - this.parent = parent; // parent scope - this.children = []; // sub-scopes - if (parent) { - this.level = parent.level + 1; - parent.children.push(this); - } else { - this.level = 0; - } -}; - -function base54_digits() { - if (typeof DIGITS_OVERRIDE_FOR_TESTING != "undefined") - return DIGITS_OVERRIDE_FOR_TESTING; - else - return "etnrisouaflchpdvmgybwESxTNCkLAOM_DPHBjFIqRUzWXV$JKQGYZ0516372984"; -} - -var base54 = (function(){ - var DIGITS = base54_digits(); - return function(num) { - var ret = "", base = 54; - do { - ret += DIGITS.charAt(num % base); - num = Math.floor(num / base); - base = 64; - } while (num > 0); - return ret; - }; -})(); - -Scope.prototype = { - has: function(name) { - for (var s = this; s; s = s.parent) - if (HOP(s.names, name)) - return s; - }, - has_mangled: function(mname) { - for (var s = this; s; s = s.parent) - if (HOP(s.rev_mangled, mname)) - return s; - }, - toJSON: function() { - return { - names: this.names, - uses_eval: this.uses_eval, - uses_with: this.uses_with - }; - }, - - next_mangled: function() { - // we must be careful that the new mangled name: - // - // 1. doesn't shadow a mangled name from a parent - // scope, unless we don't reference the original - // name from this scope OR from any sub-scopes! - // This will get slow. - // - // 2. doesn't shadow an original name from a parent - // scope, in the event that the name is not mangled - // in the parent scope and we reference that name - // here OR IN ANY SUBSCOPES! - // - // 3. doesn't shadow a name that is referenced but not - // defined (possibly global defined elsewhere). - for (;;) { - var m = base54(++this.cname), prior; - - // case 1. - prior = this.has_mangled(m); - if (prior && this.refs[prior.rev_mangled[m]] === prior) - continue; - - // case 2. - prior = this.has(m); - if (prior && prior !== this && this.refs[m] === prior && !prior.has_mangled(m)) - continue; - - // case 3. - if (HOP(this.refs, m) && this.refs[m] == null) - continue; - - // I got "do" once. :-/ - if (!is_identifier(m)) - continue; - - return m; - } - }, - set_mangle: function(name, m) { - this.rev_mangled[m] = name; - return this.mangled[name] = m; - }, - get_mangled: function(name, newMangle) { - if (this.uses_eval || this.uses_with) return name; // no mangle if eval or with is in use - var s = this.has(name); - if (!s) return name; // not in visible scope, no mangle - if (HOP(s.mangled, name)) return s.mangled[name]; // already mangled in this scope - if (!newMangle) return name; // not found and no mangling requested - return s.set_mangle(name, s.next_mangled()); - }, - references: function(name) { - return name && !this.parent || this.uses_with || this.uses_eval || this.refs[name]; - }, - define: function(name, type) { - if (name != null) { - if (type == "var" || !HOP(this.names, name)) - this.names[name] = type || "var"; - return name; - } - }, - active_directive: function(dir) { - return member(dir, this.directives) || this.parent && this.parent.active_directive(dir); - } -}; - -function ast_add_scope(ast) { - - var current_scope = null; - var w = ast_walker(), walk = w.walk; - var having_eval = []; - - function with_new_scope(cont) { - current_scope = new Scope(current_scope); - current_scope.labels = new Scope(); - var ret = current_scope.body = cont(); - ret.scope = current_scope; - current_scope = current_scope.parent; - return ret; - }; - - function define(name, type) { - return current_scope.define(name, type); - }; - - function reference(name) { - current_scope.refs[name] = true; - }; - - function _lambda(name, args, body) { - var is_defun = this[0] == "defun"; - return [ this[0], is_defun ? define(name, "defun") : name, args, with_new_scope(function(){ - if (!is_defun) define(name, "lambda"); - MAP(args, function(name){ define(name, "arg") }); - return MAP(body, walk); - })]; - }; - - function _vardefs(type) { - return function(defs) { - MAP(defs, function(d){ - define(d[0], type); - if (d[1]) reference(d[0]); - }); - }; - }; - - function _breacont(label) { - if (label) - current_scope.labels.refs[label] = true; - }; - - return with_new_scope(function(){ - // process AST - var ret = w.with_walkers({ - "function": _lambda, - "defun": _lambda, - "label": function(name, stat) { current_scope.labels.define(name) }, - "break": _breacont, - "continue": _breacont, - "with": function(expr, block) { - for (var s = current_scope; s; s = s.parent) - s.uses_with = true; - }, - "var": _vardefs("var"), - "const": _vardefs("const"), - "try": function(t, c, f) { - if (c != null) return [ - this[0], - MAP(t, walk), - [ define(c[0], "catch"), MAP(c[1], walk) ], - f != null ? MAP(f, walk) : null - ]; - }, - "name": function(name) { - if (name == "eval") - having_eval.push(current_scope); - reference(name); - } - }, function(){ - return walk(ast); - }); - - // the reason why we need an additional pass here is - // that names can be used prior to their definition. - - // scopes where eval was detected and their parents - // are marked with uses_eval, unless they define the - // "eval" name. - MAP(having_eval, function(scope){ - if (!scope.has("eval")) while (scope) { - scope.uses_eval = true; - scope = scope.parent; - } - }); - - // for referenced names it might be useful to know - // their origin scope. current_scope here is the - // toplevel one. - function fixrefs(scope, i) { - // do children first; order shouldn't matter - for (i = scope.children.length; --i >= 0;) - fixrefs(scope.children[i]); - for (i in scope.refs) if (HOP(scope.refs, i)) { - // find origin scope and propagate the reference to origin - for (var origin = scope.has(i), s = scope; s; s = s.parent) { - s.refs[i] = origin; - if (s === origin) break; - } - } - }; - fixrefs(current_scope); - - return ret; - }); - -}; - -/* -----[ mangle names ]----- */ - -function ast_mangle(ast, options) { - var w = ast_walker(), walk = w.walk, scope; - options = defaults(options, { - mangle : true, - toplevel : false, - defines : null, - except : null, - no_functions : false - }); - - function get_mangled(name, newMangle) { - if (!options.mangle) return name; - if (!options.toplevel && !scope.parent) return name; // don't mangle toplevel - if (options.except && member(name, options.except)) - return name; - if (options.no_functions && HOP(scope.names, name) && - (scope.names[name] == 'defun' || scope.names[name] == 'lambda')) - return name; - return scope.get_mangled(name, newMangle); - }; - - function get_define(name) { - if (options.defines) { - // we always lookup a defined symbol for the current scope FIRST, so declared - // vars trump a DEFINE symbol, but if no such var is found, then match a DEFINE value - if (!scope.has(name)) { - if (HOP(options.defines, name)) { - return options.defines[name]; - } - } - return null; - } - }; - - function _lambda(name, args, body) { - if (!options.no_functions && options.mangle) { - var is_defun = this[0] == "defun", extra; - if (name) { - if (is_defun) name = get_mangled(name); - else if (body.scope.references(name)) { - extra = {}; - if (!(scope.uses_eval || scope.uses_with)) - name = extra[name] = scope.next_mangled(); - else - extra[name] = name; - } - else name = null; - } - } - body = with_scope(body.scope, function(){ - args = MAP(args, function(name){ return get_mangled(name) }); - return MAP(body, walk); - }, extra); - return [ this[0], name, args, body ]; - }; - - function with_scope(s, cont, extra) { - var _scope = scope; - scope = s; - if (extra) for (var i in extra) if (HOP(extra, i)) { - s.set_mangle(i, extra[i]); - } - for (var i in s.names) if (HOP(s.names, i)) { - get_mangled(i, true); - } - var ret = cont(); - ret.scope = s; - scope = _scope; - return ret; - }; - - function _vardefs(defs) { - return [ this[0], MAP(defs, function(d){ - return [ get_mangled(d[0]), walk(d[1]) ]; - }) ]; - }; - - function _breacont(label) { - if (label) return [ this[0], scope.labels.get_mangled(label) ]; - }; - - return w.with_walkers({ - "function": _lambda, - "defun": function() { - // move function declarations to the top when - // they are not in some block. - var ast = _lambda.apply(this, arguments); - switch (w.parent()[0]) { - case "toplevel": - case "function": - case "defun": - return MAP.at_top(ast); - } - return ast; - }, - "label": function(label, stat) { - if (scope.labels.refs[label]) return [ - this[0], - scope.labels.get_mangled(label, true), - walk(stat) - ]; - return walk(stat); - }, - "break": _breacont, - "continue": _breacont, - "var": _vardefs, - "const": _vardefs, - "name": function(name) { - return get_define(name) || [ this[0], get_mangled(name) ]; - }, - "try": function(t, c, f) { - return [ this[0], - MAP(t, walk), - c != null ? [ get_mangled(c[0]), MAP(c[1], walk) ] : null, - f != null ? MAP(f, walk) : null ]; - }, - "toplevel": function(body) { - var self = this; - return with_scope(self.scope, function(){ - return [ self[0], MAP(body, walk) ]; - }); - }, - "directive": function() { - return MAP.at_top(this); - } - }, function() { - return walk(ast_add_scope(ast)); - }); -}; - -/* -----[ - - compress foo["bar"] into foo.bar, - - remove block brackets {} where possible - - join consecutive var declarations - - various optimizations for IFs: - - if (cond) foo(); else bar(); ==> cond?foo():bar(); - - if (cond) foo(); ==> cond&&foo(); - - if (foo) return bar(); else return baz(); ==> return foo?bar():baz(); // also for throw - - if (foo) return bar(); else something(); ==> {if(foo)return bar();something()} - ]----- */ - -var warn = function(){}; - -function best_of(ast1, ast2) { - return gen_code(ast1).length > gen_code(ast2[0] == "stat" ? ast2[1] : ast2).length ? ast2 : ast1; -}; - -function last_stat(b) { - if (b[0] == "block" && b[1] && b[1].length > 0) - return b[1][b[1].length - 1]; - return b; -} - -function aborts(t) { - if (t) switch (last_stat(t)[0]) { - case "return": - case "break": - case "continue": - case "throw": - return true; - } -}; - -function boolean_expr(expr) { - return ( (expr[0] == "unary-prefix" - && member(expr[1], [ "!", "delete" ])) || - - (expr[0] == "binary" - && member(expr[1], [ "in", "instanceof", "==", "!=", "===", "!==", "<", "<=", ">=", ">" ])) || - - (expr[0] == "binary" - && member(expr[1], [ "&&", "||" ]) - && boolean_expr(expr[2]) - && boolean_expr(expr[3])) || - - (expr[0] == "conditional" - && boolean_expr(expr[2]) - && boolean_expr(expr[3])) || - - (expr[0] == "assign" - && expr[1] === true - && boolean_expr(expr[3])) || - - (expr[0] == "seq" - && boolean_expr(expr[expr.length - 1])) - ); -}; - -function empty(b) { - return !b || (b[0] == "block" && (!b[1] || b[1].length == 0)); -}; - -function is_string(node) { - return (node[0] == "string" || - node[0] == "unary-prefix" && node[1] == "typeof" || - node[0] == "binary" && node[1] == "+" && - (is_string(node[2]) || is_string(node[3]))); -}; - -var when_constant = (function(){ - - var $NOT_CONSTANT = {}; - - // this can only evaluate constant expressions. If it finds anything - // not constant, it throws $NOT_CONSTANT. - function evaluate(expr) { - switch (expr[0]) { - case "string": - case "num": - return expr[1]; - case "name": - case "atom": - switch (expr[1]) { - case "true": return true; - case "false": return false; - case "null": return null; - } - break; - case "unary-prefix": - switch (expr[1]) { - case "!": return !evaluate(expr[2]); - case "typeof": return typeof evaluate(expr[2]); - case "~": return ~evaluate(expr[2]); - case "-": return -evaluate(expr[2]); - case "+": return +evaluate(expr[2]); - } - break; - case "binary": - var left = expr[2], right = expr[3]; - switch (expr[1]) { - case "&&" : return evaluate(left) && evaluate(right); - case "||" : return evaluate(left) || evaluate(right); - case "|" : return evaluate(left) | evaluate(right); - case "&" : return evaluate(left) & evaluate(right); - case "^" : return evaluate(left) ^ evaluate(right); - case "+" : return evaluate(left) + evaluate(right); - case "*" : return evaluate(left) * evaluate(right); - case "/" : return evaluate(left) / evaluate(right); - case "%" : return evaluate(left) % evaluate(right); - case "-" : return evaluate(left) - evaluate(right); - case "<<" : return evaluate(left) << evaluate(right); - case ">>" : return evaluate(left) >> evaluate(right); - case ">>>" : return evaluate(left) >>> evaluate(right); - case "==" : return evaluate(left) == evaluate(right); - case "===" : return evaluate(left) === evaluate(right); - case "!=" : return evaluate(left) != evaluate(right); - case "!==" : return evaluate(left) !== evaluate(right); - case "<" : return evaluate(left) < evaluate(right); - case "<=" : return evaluate(left) <= evaluate(right); - case ">" : return evaluate(left) > evaluate(right); - case ">=" : return evaluate(left) >= evaluate(right); - case "in" : return evaluate(left) in evaluate(right); - case "instanceof" : return evaluate(left) instanceof evaluate(right); - } - } - throw $NOT_CONSTANT; - }; - - return function(expr, yes, no) { - try { - var val = evaluate(expr), ast; - switch (typeof val) { - case "string": ast = [ "string", val ]; break; - case "number": ast = [ "num", val ]; break; - case "boolean": ast = [ "name", String(val) ]; break; - default: - if (val === null) { ast = [ "atom", "null" ]; break; } - throw new Error("Can't handle constant of type: " + (typeof val)); - } - return yes.call(expr, ast, val); - } catch(ex) { - if (ex === $NOT_CONSTANT) { - if (expr[0] == "binary" - && (expr[1] == "===" || expr[1] == "!==") - && ((is_string(expr[2]) && is_string(expr[3])) - || (boolean_expr(expr[2]) && boolean_expr(expr[3])))) { - expr[1] = expr[1].substr(0, 2); - } - else if (no && expr[0] == "binary" - && (expr[1] == "||" || expr[1] == "&&")) { - // the whole expression is not constant but the lval may be... - try { - var lval = evaluate(expr[2]); - expr = ((expr[1] == "&&" && (lval ? expr[3] : lval)) || - (expr[1] == "||" && (lval ? lval : expr[3])) || - expr); - } catch(ex2) { - // IGNORE... lval is not constant - } - } - return no ? no.call(expr, expr) : null; - } - else throw ex; - } - }; - -})(); - -function warn_unreachable(ast) { - if (!empty(ast)) - warn("Dropping unreachable code: " + gen_code(ast, true)); -}; - -function prepare_ifs(ast) { - var w = ast_walker(), walk = w.walk; - // In this first pass, we rewrite ifs which abort with no else with an - // if-else. For example: - // - // if (x) { - // blah(); - // return y; - // } - // foobar(); - // - // is rewritten into: - // - // if (x) { - // blah(); - // return y; - // } else { - // foobar(); - // } - function redo_if(statements) { - statements = MAP(statements, walk); - - for (var i = 0; i < statements.length; ++i) { - var fi = statements[i]; - if (fi[0] != "if") continue; - - if (fi[3]) continue; - - var t = fi[2]; - if (!aborts(t)) continue; - - var conditional = walk(fi[1]); - - var e_body = redo_if(statements.slice(i + 1)); - var e = e_body.length == 1 ? e_body[0] : [ "block", e_body ]; - - return statements.slice(0, i).concat([ [ - fi[0], // "if" - conditional, // conditional - t, // then - e // else - ] ]); - } - - return statements; - }; - - function redo_if_lambda(name, args, body) { - body = redo_if(body); - return [ this[0], name, args, body ]; - }; - - function redo_if_block(statements) { - return [ this[0], statements != null ? redo_if(statements) : null ]; - }; - - return w.with_walkers({ - "defun": redo_if_lambda, - "function": redo_if_lambda, - "block": redo_if_block, - "splice": redo_if_block, - "toplevel": function(statements) { - return [ this[0], redo_if(statements) ]; - }, - "try": function(t, c, f) { - return [ - this[0], - redo_if(t), - c != null ? [ c[0], redo_if(c[1]) ] : null, - f != null ? redo_if(f) : null - ]; - } - }, function() { - return walk(ast); - }); -}; - -function for_side_effects(ast, handler) { - var w = ast_walker(), walk = w.walk; - var $stop = {}, $restart = {}; - function stop() { throw $stop }; - function restart() { throw $restart }; - function found(){ return handler.call(this, this, w, stop, restart) }; - function unary(op) { - if (op == "++" || op == "--") - return found.apply(this, arguments); - }; - function binary(op) { - if (op == "&&" || op == "||") - return found.apply(this, arguments); - }; - return w.with_walkers({ - "try": found, - "throw": found, - "return": found, - "new": found, - "switch": found, - "break": found, - "continue": found, - "assign": found, - "call": found, - "if": found, - "for": found, - "for-in": found, - "while": found, - "do": found, - "return": found, - "unary-prefix": unary, - "unary-postfix": unary, - "conditional": found, - "binary": binary, - "defun": found - }, function(){ - while (true) try { - walk(ast); - break; - } catch(ex) { - if (ex === $stop) break; - if (ex === $restart) continue; - throw ex; - } - }); -}; - -function ast_lift_variables(ast) { - var w = ast_walker(), walk = w.walk, scope; - function do_body(body, env) { - var _scope = scope; - scope = env; - body = MAP(body, walk); - var hash = {}, names = MAP(env.names, function(type, name){ - if (type != "var") return MAP.skip; - if (!env.references(name)) return MAP.skip; - hash[name] = true; - return [ name ]; - }); - if (names.length > 0) { - // looking for assignments to any of these variables. - // we can save considerable space by moving the definitions - // in the var declaration. - for_side_effects([ "block", body ], function(ast, walker, stop, restart) { - if (ast[0] == "assign" - && ast[1] === true - && ast[2][0] == "name" - && HOP(hash, ast[2][1])) { - // insert the definition into the var declaration - for (var i = names.length; --i >= 0;) { - if (names[i][0] == ast[2][1]) { - if (names[i][1]) // this name already defined, we must stop - stop(); - names[i][1] = ast[3]; // definition - names.push(names.splice(i, 1)[0]); - break; - } - } - // remove this assignment from the AST. - var p = walker.parent(); - if (p[0] == "seq") { - var a = p[2]; - a.unshift(0, p.length); - p.splice.apply(p, a); - } - else if (p[0] == "stat") { - p.splice(0, p.length, "block"); // empty statement - } - else { - stop(); - } - restart(); - } - stop(); - }); - body.unshift([ "var", names ]); - } - scope = _scope; - return body; - }; - function _vardefs(defs) { - var ret = null; - for (var i = defs.length; --i >= 0;) { - var d = defs[i]; - if (!d[1]) continue; - d = [ "assign", true, [ "name", d[0] ], d[1] ]; - if (ret == null) ret = d; - else ret = [ "seq", d, ret ]; - } - if (ret == null && w.parent()[0] != "for") { - if (w.parent()[0] == "for-in") - return [ "name", defs[0][0] ]; - return MAP.skip; - } - return [ "stat", ret ]; - }; - function _toplevel(body) { - return [ this[0], do_body(body, this.scope) ]; - }; - return w.with_walkers({ - "function": function(name, args, body){ - for (var i = args.length; --i >= 0 && !body.scope.references(args[i]);) - args.pop(); - if (!body.scope.references(name)) name = null; - return [ this[0], name, args, do_body(body, body.scope) ]; - }, - "defun": function(name, args, body){ - if (!scope.references(name)) return MAP.skip; - for (var i = args.length; --i >= 0 && !body.scope.references(args[i]);) - args.pop(); - return [ this[0], name, args, do_body(body, body.scope) ]; - }, - "var": _vardefs, - "toplevel": _toplevel - }, function(){ - return walk(ast_add_scope(ast)); - }); -}; - -function ast_squeeze(ast, options) { - ast = squeeze_1(ast, options); - ast = squeeze_2(ast, options); - return ast; -}; - -function squeeze_1(ast, options) { - options = defaults(options, { - make_seqs : true, - dead_code : true, - no_warnings : false, - keep_comps : true, - unsafe : false - }); - - var w = ast_walker(), walk = w.walk, scope; - - function negate(c) { - var not_c = [ "unary-prefix", "!", c ]; - switch (c[0]) { - case "unary-prefix": - return c[1] == "!" && boolean_expr(c[2]) ? c[2] : not_c; - case "seq": - c = slice(c); - c[c.length - 1] = negate(c[c.length - 1]); - return c; - case "conditional": - return best_of(not_c, [ "conditional", c[1], negate(c[2]), negate(c[3]) ]); - case "binary": - var op = c[1], left = c[2], right = c[3]; - if (!options.keep_comps) switch (op) { - case "<=" : return [ "binary", ">", left, right ]; - case "<" : return [ "binary", ">=", left, right ]; - case ">=" : return [ "binary", "<", left, right ]; - case ">" : return [ "binary", "<=", left, right ]; - } - switch (op) { - case "==" : return [ "binary", "!=", left, right ]; - case "!=" : return [ "binary", "==", left, right ]; - case "===" : return [ "binary", "!==", left, right ]; - case "!==" : return [ "binary", "===", left, right ]; - case "&&" : return best_of(not_c, [ "binary", "||", negate(left), negate(right) ]); - case "||" : return best_of(not_c, [ "binary", "&&", negate(left), negate(right) ]); - } - break; - } - return not_c; - }; - - function make_conditional(c, t, e) { - var make_real_conditional = function() { - if (c[0] == "unary-prefix" && c[1] == "!") { - return e ? [ "conditional", c[2], e, t ] : [ "binary", "||", c[2], t ]; - } else { - return e ? best_of( - [ "conditional", c, t, e ], - [ "conditional", negate(c), e, t ] - ) : [ "binary", "&&", c, t ]; - } - }; - // shortcut the conditional if the expression has a constant value - return when_constant(c, function(ast, val){ - warn_unreachable(val ? e : t); - return (val ? t : e); - }, make_real_conditional); - }; - - function rmblock(block) { - if (block != null && block[0] == "block" && block[1]) { - if (block[1].length == 1) - block = block[1][0]; - else if (block[1].length == 0) - block = [ "block" ]; - } - return block; - }; - - function _lambda(name, args, body) { - return [ this[0], name, args, tighten(body, "lambda") ]; - }; - - // this function does a few things: - // 1. discard useless blocks - // 2. join consecutive var declarations - // 3. remove obviously dead code - // 4. transform consecutive statements using the comma operator - // 5. if block_type == "lambda" and it detects constructs like if(foo) return ... - rewrite like if (!foo) { ... } - function tighten(statements, block_type) { - statements = MAP(statements, walk); - - statements = statements.reduce(function(a, stat){ - if (stat[0] == "block") { - if (stat[1]) { - a.push.apply(a, stat[1]); - } - } else { - a.push(stat); - } - return a; - }, []); - - statements = (function(a, prev){ - statements.forEach(function(cur){ - if (prev && ((cur[0] == "var" && prev[0] == "var") || - (cur[0] == "const" && prev[0] == "const"))) { - prev[1] = prev[1].concat(cur[1]); - } else { - a.push(cur); - prev = cur; - } - }); - return a; - })([]); - - if (options.dead_code) statements = (function(a, has_quit){ - statements.forEach(function(st){ - if (has_quit) { - if (st[0] == "function" || st[0] == "defun") { - a.push(st); - } - else if (st[0] == "var" || st[0] == "const") { - if (!options.no_warnings) - warn("Variables declared in unreachable code"); - st[1] = MAP(st[1], function(def){ - if (def[1] && !options.no_warnings) - warn_unreachable([ "assign", true, [ "name", def[0] ], def[1] ]); - return [ def[0] ]; - }); - a.push(st); - } - else if (!options.no_warnings) - warn_unreachable(st); - } - else { - a.push(st); - if (member(st[0], [ "return", "throw", "break", "continue" ])) - has_quit = true; - } - }); - return a; - })([]); - - if (options.make_seqs) statements = (function(a, prev) { - statements.forEach(function(cur){ - if (prev && prev[0] == "stat" && cur[0] == "stat") { - prev[1] = [ "seq", prev[1], cur[1] ]; - } else { - a.push(cur); - prev = cur; - } - }); - if (a.length >= 2 - && a[a.length-2][0] == "stat" - && (a[a.length-1][0] == "return" || a[a.length-1][0] == "throw") - && a[a.length-1][1]) - { - a.splice(a.length - 2, 2, - [ a[a.length-1][0], - [ "seq", a[a.length-2][1], a[a.length-1][1] ]]); - } - return a; - })([]); - - // this increases jQuery by 1K. Probably not such a good idea after all.. - // part of this is done in prepare_ifs anyway. - // if (block_type == "lambda") statements = (function(i, a, stat){ - // while (i < statements.length) { - // stat = statements[i++]; - // if (stat[0] == "if" && !stat[3]) { - // if (stat[2][0] == "return" && stat[2][1] == null) { - // a.push(make_if(negate(stat[1]), [ "block", statements.slice(i) ])); - // break; - // } - // var last = last_stat(stat[2]); - // if (last[0] == "return" && last[1] == null) { - // a.push(make_if(stat[1], [ "block", stat[2][1].slice(0, -1) ], [ "block", statements.slice(i) ])); - // break; - // } - // } - // a.push(stat); - // } - // return a; - // })(0, []); - - return statements; - }; - - function make_if(c, t, e) { - return when_constant(c, function(ast, val){ - if (val) { - t = walk(t); - warn_unreachable(e); - return t || [ "block" ]; - } else { - e = walk(e); - warn_unreachable(t); - return e || [ "block" ]; - } - }, function() { - return make_real_if(c, t, e); - }); - }; - - function abort_else(c, t, e) { - var ret = [ [ "if", negate(c), e ] ]; - if (t[0] == "block") { - if (t[1]) ret = ret.concat(t[1]); - } else { - ret.push(t); - } - return walk([ "block", ret ]); - }; - - function make_real_if(c, t, e) { - c = walk(c); - t = walk(t); - e = walk(e); - - if (empty(e) && empty(t)) - return [ "stat", c ]; - - if (empty(t)) { - c = negate(c); - t = e; - e = null; - } else if (empty(e)) { - e = null; - } else { - // if we have both else and then, maybe it makes sense to switch them? - (function(){ - var a = gen_code(c); - var n = negate(c); - var b = gen_code(n); - if (b.length < a.length) { - var tmp = t; - t = e; - e = tmp; - c = n; - } - })(); - } - var ret = [ "if", c, t, e ]; - if (t[0] == "if" && empty(t[3]) && empty(e)) { - ret = best_of(ret, walk([ "if", [ "binary", "&&", c, t[1] ], t[2] ])); - } - else if (t[0] == "stat") { - if (e) { - if (e[0] == "stat") - ret = best_of(ret, [ "stat", make_conditional(c, t[1], e[1]) ]); - else if (aborts(e)) - ret = abort_else(c, t, e); - } - else { - ret = best_of(ret, [ "stat", make_conditional(c, t[1]) ]); - } - } - else if (e && t[0] == e[0] && (t[0] == "return" || t[0] == "throw") && t[1] && e[1]) { - ret = best_of(ret, [ t[0], make_conditional(c, t[1], e[1] ) ]); - } - else if (e && aborts(t)) { - ret = [ [ "if", c, t ] ]; - if (e[0] == "block") { - if (e[1]) ret = ret.concat(e[1]); - } - else { - ret.push(e); - } - ret = walk([ "block", ret ]); - } - else if (t && aborts(e)) { - ret = abort_else(c, t, e); - } - return ret; - }; - - function _do_while(cond, body) { - return when_constant(cond, function(cond, val){ - if (!val) { - warn_unreachable(body); - return [ "block" ]; - } else { - return [ "for", null, null, null, walk(body) ]; - } - }); - }; - - return w.with_walkers({ - "sub": function(expr, subscript) { - if (subscript[0] == "string") { - var name = subscript[1]; - if (is_identifier(name)) - return [ "dot", walk(expr), name ]; - else if (/^[1-9][0-9]*$/.test(name) || name === "0") - return [ "sub", walk(expr), [ "num", parseInt(name, 10) ] ]; - } - }, - "if": make_if, - "toplevel": function(body) { - return [ "toplevel", tighten(body) ]; - }, - "switch": function(expr, body) { - var last = body.length - 1; - return [ "switch", walk(expr), MAP(body, function(branch, i){ - var block = tighten(branch[1]); - if (i == last && block.length > 0) { - var node = block[block.length - 1]; - if (node[0] == "break" && !node[1]) - block.pop(); - } - return [ branch[0] ? walk(branch[0]) : null, block ]; - }) ]; - }, - "function": _lambda, - "defun": _lambda, - "block": function(body) { - if (body) return rmblock([ "block", tighten(body) ]); - }, - "binary": function(op, left, right) { - return when_constant([ "binary", op, walk(left), walk(right) ], function yes(c){ - return best_of(walk(c), this); - }, function no() { - return function(){ - if(op != "==" && op != "!=") return; - var l = walk(left), r = walk(right); - if(l && l[0] == "unary-prefix" && l[1] == "!" && l[2][0] == "num") - left = ['num', +!l[2][1]]; - else if (r && r[0] == "unary-prefix" && r[1] == "!" && r[2][0] == "num") - right = ['num', +!r[2][1]]; - return ["binary", op, left, right]; - }() || this; - }); - }, - "conditional": function(c, t, e) { - return make_conditional(walk(c), walk(t), walk(e)); - }, - "try": function(t, c, f) { - return [ - "try", - tighten(t), - c != null ? [ c[0], tighten(c[1]) ] : null, - f != null ? tighten(f) : null - ]; - }, - "unary-prefix": function(op, expr) { - expr = walk(expr); - var ret = [ "unary-prefix", op, expr ]; - if (op == "!") - ret = best_of(ret, negate(expr)); - return when_constant(ret, function(ast, val){ - return walk(ast); // it's either true or false, so minifies to !0 or !1 - }, function() { return ret }); - }, - "name": function(name) { - switch (name) { - case "true": return [ "unary-prefix", "!", [ "num", 0 ]]; - case "false": return [ "unary-prefix", "!", [ "num", 1 ]]; - } - }, - "while": _do_while, - "assign": function(op, lvalue, rvalue) { - lvalue = walk(lvalue); - rvalue = walk(rvalue); - var okOps = [ '+', '-', '/', '*', '%', '>>', '<<', '>>>', '|', '^', '&' ]; - if (op === true && lvalue[0] === "name" && rvalue[0] === "binary" && - ~okOps.indexOf(rvalue[1]) && rvalue[2][0] === "name" && - rvalue[2][1] === lvalue[1]) { - return [ this[0], rvalue[1], lvalue, rvalue[3] ] - } - return [ this[0], op, lvalue, rvalue ]; - }, - "call": function(expr, args) { - expr = walk(expr); - if (options.unsafe && expr[0] == "dot" && expr[1][0] == "string" && expr[2] == "toString") { - return expr[1]; - } - return [ this[0], expr, MAP(args, walk) ]; - }, - "num": function (num) { - if (!isFinite(num)) - return [ "binary", "/", num === 1 / 0 - ? [ "num", 1 ] : num === -1 / 0 - ? [ "unary-prefix", "-", [ "num", 1 ] ] - : [ "num", 0 ], [ "num", 0 ] ]; - - return [ this[0], num ]; - } - }, function() { - return walk(prepare_ifs(walk(prepare_ifs(ast)))); - }); -}; - -function squeeze_2(ast, options) { - var w = ast_walker(), walk = w.walk, scope; - function with_scope(s, cont) { - var save = scope, ret; - scope = s; - ret = cont(); - scope = save; - return ret; - }; - function lambda(name, args, body) { - return [ this[0], name, args, with_scope(body.scope, curry(MAP, body, walk)) ]; - }; - return w.with_walkers({ - "directive": function(dir) { - if (scope.active_directive(dir)) - return [ "block" ]; - scope.directives.push(dir); - }, - "toplevel": function(body) { - return [ this[0], with_scope(this.scope, curry(MAP, body, walk)) ]; - }, - "function": lambda, - "defun": lambda - }, function(){ - return walk(ast_add_scope(ast)); - }); -}; - -/* -----[ re-generate code from the AST ]----- */ - -var DOT_CALL_NO_PARENS = jsp.array_to_hash([ - "name", - "array", - "object", - "string", - "dot", - "sub", - "call", - "regexp", - "defun" -]); - -function make_string(str, ascii_only) { - var dq = 0, sq = 0; - str = str.replace(/[\\\b\f\n\r\t\x22\x27\u2028\u2029\0]/g, function(s){ - switch (s) { - case "\\": return "\\\\"; - case "\b": return "\\b"; - case "\f": return "\\f"; - case "\n": return "\\n"; - case "\r": return "\\r"; - case "\u2028": return "\\u2028"; - case "\u2029": return "\\u2029"; - case '"': ++dq; return '"'; - case "'": ++sq; return "'"; - case "\0": return "\\0"; - } - return s; - }); - if (ascii_only) str = to_ascii(str); - if (dq > sq) return "'" + str.replace(/\x27/g, "\\'") + "'"; - else return '"' + str.replace(/\x22/g, '\\"') + '"'; -}; - -function to_ascii(str) { - return str.replace(/[\u0080-\uffff]/g, function(ch) { - var code = ch.charCodeAt(0).toString(16); - while (code.length < 4) code = "0" + code; - return "\\u" + code; - }); -}; - -var SPLICE_NEEDS_BRACKETS = jsp.array_to_hash([ "if", "while", "do", "for", "for-in", "with" ]); - -function gen_code(ast, options) { - options = defaults(options, { - indent_start : 0, - indent_level : 4, - quote_keys : false, - space_colon : false, - beautify : false, - ascii_only : false, - inline_script: false - }); - var beautify = !!options.beautify; - var indentation = 0, - newline = beautify ? "\n" : "", - space = beautify ? " " : ""; - - function encode_string(str) { - var ret = make_string(str, options.ascii_only); - if (options.inline_script) - ret = ret.replace(/<\x2fscript([>\/\t\n\f\r ])/gi, "<\\/script$1"); - return ret; - }; - - function make_name(name) { - name = name.toString(); - if (options.ascii_only) - name = to_ascii(name); - return name; - }; - - function indent(line) { - if (line == null) - line = ""; - if (beautify) - line = repeat_string(" ", options.indent_start + indentation * options.indent_level) + line; - return line; - }; - - function with_indent(cont, incr) { - if (incr == null) incr = 1; - indentation += incr; - try { return cont.apply(null, slice(arguments, 1)); } - finally { indentation -= incr; } - }; - - function last_char(str) { - str = str.toString(); - return str.charAt(str.length - 1); - }; - - function first_char(str) { - return str.toString().charAt(0); - }; - - function add_spaces(a) { - if (beautify) - return a.join(" "); - var b = []; - for (var i = 0; i < a.length; ++i) { - var next = a[i + 1]; - b.push(a[i]); - if (next && - ((is_identifier_char(last_char(a[i])) && (is_identifier_char(first_char(next)) - || first_char(next) == "\\")) || - (/[\+\-]$/.test(a[i].toString()) && /^[\+\-]/.test(next.toString()) || - last_char(a[i]) == "/" && first_char(next) == "/"))) { - b.push(" "); - } - } - return b.join(""); - }; - - function add_commas(a) { - return a.join("," + space); - }; - - function parenthesize(expr) { - var gen = make(expr); - for (var i = 1; i < arguments.length; ++i) { - var el = arguments[i]; - if ((el instanceof Function && el(expr)) || expr[0] == el) - return "(" + gen + ")"; - } - return gen; - }; - - function best_of(a) { - if (a.length == 1) { - return a[0]; - } - if (a.length == 2) { - var b = a[1]; - a = a[0]; - return a.length <= b.length ? a : b; - } - return best_of([ a[0], best_of(a.slice(1)) ]); - }; - - function needs_parens(expr) { - if (expr[0] == "function" || expr[0] == "object") { - // dot/call on a literal function requires the - // function literal itself to be parenthesized - // only if it's the first "thing" in a - // statement. This means that the parent is - // "stat", but it could also be a "seq" and - // we're the first in this "seq" and the - // parent is "stat", and so on. Messy stuff, - // but it worths the trouble. - var a = slice(w.stack()), self = a.pop(), p = a.pop(); - while (p) { - if (p[0] == "stat") return true; - if (((p[0] == "seq" || p[0] == "call" || p[0] == "dot" || p[0] == "sub" || p[0] == "conditional") && p[1] === self) || - ((p[0] == "binary" || p[0] == "assign" || p[0] == "unary-postfix") && p[2] === self)) { - self = p; - p = a.pop(); - } else { - return false; - } - } - } - return !HOP(DOT_CALL_NO_PARENS, expr[0]); - }; - - function make_num(num) { - var str = num.toString(10), a = [ str.replace(/^0\./, ".").replace('e+', 'e') ], m; - if (Math.floor(num) === num) { - if (num >= 0) { - a.push("0x" + num.toString(16).toLowerCase(), // probably pointless - "0" + num.toString(8)); // same. - } else { - a.push("-0x" + (-num).toString(16).toLowerCase(), // probably pointless - "-0" + (-num).toString(8)); // same. - } - if ((m = /^(.*?)(0+)$/.exec(num))) { - a.push(m[1] + "e" + m[2].length); - } - } else if ((m = /^0?\.(0+)(.*)$/.exec(num))) { - a.push(m[2] + "e-" + (m[1].length + m[2].length), - str.substr(str.indexOf("."))); - } - return best_of(a); - }; - - var w = ast_walker(); - var make = w.walk; - return w.with_walkers({ - "string": encode_string, - "num": make_num, - "name": make_name, - "debugger": function(){ return "debugger;" }, - "toplevel": function(statements) { - return make_block_statements(statements) - .join(newline + newline); - }, - "splice": function(statements) { - var parent = w.parent(); - if (HOP(SPLICE_NEEDS_BRACKETS, parent)) { - // we need block brackets in this case - return make_block.apply(this, arguments); - } else { - return MAP(make_block_statements(statements, true), - function(line, i) { - // the first line is already indented - return i > 0 ? indent(line) : line; - }).join(newline); - } - }, - "block": make_block, - "var": function(defs) { - return "var " + add_commas(MAP(defs, make_1vardef)) + ";"; - }, - "const": function(defs) { - return "const " + add_commas(MAP(defs, make_1vardef)) + ";"; - }, - "try": function(tr, ca, fi) { - var out = [ "try", make_block(tr) ]; - if (ca) out.push("catch", "(" + ca[0] + ")", make_block(ca[1])); - if (fi) out.push("finally", make_block(fi)); - return add_spaces(out); - }, - "throw": function(expr) { - return add_spaces([ "throw", make(expr) ]) + ";"; - }, - "new": function(ctor, args) { - args = args.length > 0 ? "(" + add_commas(MAP(args, function(expr){ - return parenthesize(expr, "seq"); - })) + ")" : ""; - return add_spaces([ "new", parenthesize(ctor, "seq", "binary", "conditional", "assign", function(expr){ - var w = ast_walker(), has_call = {}; - try { - w.with_walkers({ - "call": function() { throw has_call }, - "function": function() { return this } - }, function(){ - w.walk(expr); - }); - } catch(ex) { - if (ex === has_call) - return true; - throw ex; - } - }) + args ]); - }, - "switch": function(expr, body) { - return add_spaces([ "switch", "(" + make(expr) + ")", make_switch_block(body) ]); - }, - "break": function(label) { - var out = "break"; - if (label != null) - out += " " + make_name(label); - return out + ";"; - }, - "continue": function(label) { - var out = "continue"; - if (label != null) - out += " " + make_name(label); - return out + ";"; - }, - "conditional": function(co, th, el) { - return add_spaces([ parenthesize(co, "assign", "seq", "conditional"), "?", - parenthesize(th, "seq"), ":", - parenthesize(el, "seq") ]); - }, - "assign": function(op, lvalue, rvalue) { - if (op && op !== true) op += "="; - else op = "="; - return add_spaces([ make(lvalue), op, parenthesize(rvalue, "seq") ]); - }, - "dot": function(expr) { - var out = make(expr), i = 1; - if (expr[0] == "num") { - if (!/[a-f.]/i.test(out)) - out += "."; - } else if (expr[0] != "function" && needs_parens(expr)) - out = "(" + out + ")"; - while (i < arguments.length) - out += "." + make_name(arguments[i++]); - return out; - }, - "call": function(func, args) { - var f = make(func); - if (f.charAt(0) != "(" && needs_parens(func)) - f = "(" + f + ")"; - return f + "(" + add_commas(MAP(args, function(expr){ - return parenthesize(expr, "seq"); - })) + ")"; - }, - "function": make_function, - "defun": make_function, - "if": function(co, th, el) { - var out = [ "if", "(" + make(co) + ")", el ? make_then(th) : make(th) ]; - if (el) { - out.push("else", make(el)); - } - return add_spaces(out); - }, - "for": function(init, cond, step, block) { - var out = [ "for" ]; - init = (init != null ? make(init) : "").replace(/;*\s*$/, ";" + space); - cond = (cond != null ? make(cond) : "").replace(/;*\s*$/, ";" + space); - step = (step != null ? make(step) : "").replace(/;*\s*$/, ""); - var args = init + cond + step; - if (args == "; ; ") args = ";;"; - out.push("(" + args + ")", make(block)); - return add_spaces(out); - }, - "for-in": function(vvar, key, hash, block) { - return add_spaces([ "for", "(" + - (vvar ? make(vvar).replace(/;+$/, "") : make(key)), - "in", - make(hash) + ")", make(block) ]); - }, - "while": function(condition, block) { - return add_spaces([ "while", "(" + make(condition) + ")", make(block) ]); - }, - "do": function(condition, block) { - return add_spaces([ "do", make(block), "while", "(" + make(condition) + ")" ]) + ";"; - }, - "return": function(expr) { - var out = [ "return" ]; - if (expr != null) out.push(make(expr)); - return add_spaces(out) + ";"; - }, - "binary": function(operator, lvalue, rvalue) { - var left = make(lvalue), right = make(rvalue); - // XXX: I'm pretty sure other cases will bite here. - // we need to be smarter. - // adding parens all the time is the safest bet. - if (member(lvalue[0], [ "assign", "conditional", "seq" ]) || - lvalue[0] == "binary" && PRECEDENCE[operator] > PRECEDENCE[lvalue[1]] || - lvalue[0] == "function" && needs_parens(this)) { - left = "(" + left + ")"; - } - if (member(rvalue[0], [ "assign", "conditional", "seq" ]) || - rvalue[0] == "binary" && PRECEDENCE[operator] >= PRECEDENCE[rvalue[1]] && - !(rvalue[1] == operator && member(operator, [ "&&", "||", "*" ]))) { - right = "(" + right + ")"; - } - else if (!beautify && options.inline_script && (operator == "<" || operator == "<<") - && rvalue[0] == "regexp" && /^script/i.test(rvalue[1])) { - right = " " + right; - } - return add_spaces([ left, operator, right ]); - }, - "unary-prefix": function(operator, expr) { - var val = make(expr); - if (!(expr[0] == "num" || (expr[0] == "unary-prefix" && !HOP(OPERATORS, operator + expr[1])) || !needs_parens(expr))) - val = "(" + val + ")"; - return operator + (jsp.is_alphanumeric_char(operator.charAt(0)) ? " " : "") + val; - }, - "unary-postfix": function(operator, expr) { - var val = make(expr); - if (!(expr[0] == "num" || (expr[0] == "unary-postfix" && !HOP(OPERATORS, operator + expr[1])) || !needs_parens(expr))) - val = "(" + val + ")"; - return val + operator; - }, - "sub": function(expr, subscript) { - var hash = make(expr); - if (needs_parens(expr)) - hash = "(" + hash + ")"; - return hash + "[" + make(subscript) + "]"; - }, - "object": function(props) { - var obj_needs_parens = needs_parens(this); - if (props.length == 0) - return obj_needs_parens ? "({})" : "{}"; - var out = "{" + newline + with_indent(function(){ - return MAP(props, function(p){ - if (p.length == 3) { - // getter/setter. The name is in p[0], the arg.list in p[1][2], the - // body in p[1][3] and type ("get" / "set") in p[2]. - return indent(make_function(p[0], p[1][2], p[1][3], p[2], true)); - } - var key = p[0], val = parenthesize(p[1], "seq"); - if (options.quote_keys) { - key = encode_string(key); - } else if ((typeof key == "number" || !beautify && +key + "" == key) - && parseFloat(key) >= 0) { - key = make_num(+key); - } else if (!is_identifier(key)) { - key = encode_string(key); - } - return indent(add_spaces(beautify && options.space_colon - ? [ key, ":", val ] - : [ key + ":", val ])); - }).join("," + newline); - }) + newline + indent("}"); - return obj_needs_parens ? "(" + out + ")" : out; - }, - "regexp": function(rx, mods) { - if (options.ascii_only) rx = to_ascii(rx); - return "/" + rx + "/" + mods; - }, - "array": function(elements) { - if (elements.length == 0) return "[]"; - return add_spaces([ "[", add_commas(MAP(elements, function(el, i){ - if (!beautify && el[0] == "atom" && el[1] == "undefined") return i === elements.length - 1 ? "," : ""; - return parenthesize(el, "seq"); - })), "]" ]); - }, - "stat": function(stmt) { - return stmt != null - ? make(stmt).replace(/;*\s*$/, ";") - : ";"; - }, - "seq": function() { - return add_commas(MAP(slice(arguments), make)); - }, - "label": function(name, block) { - return add_spaces([ make_name(name), ":", make(block) ]); - }, - "with": function(expr, block) { - return add_spaces([ "with", "(" + make(expr) + ")", make(block) ]); - }, - "atom": function(name) { - return make_name(name); - }, - "directive": function(dir) { - return make_string(dir) + ";"; - } - }, function(){ return make(ast) }); - - // The squeezer replaces "block"-s that contain only a single - // statement with the statement itself; technically, the AST - // is correct, but this can create problems when we output an - // IF having an ELSE clause where the THEN clause ends in an - // IF *without* an ELSE block (then the outer ELSE would refer - // to the inner IF). This function checks for this case and - // adds the block brackets if needed. - function make_then(th) { - if (th == null) return ";"; - if (th[0] == "do") { - // https://github.com/mishoo/UglifyJS/issues/#issue/57 - // IE croaks with "syntax error" on code like this: - // if (foo) do ... while(cond); else ... - // we need block brackets around do/while - return make_block([ th ]); - } - var b = th; - while (true) { - var type = b[0]; - if (type == "if") { - if (!b[3]) - // no else, we must add the block - return make([ "block", [ th ]]); - b = b[3]; - } - else if (type == "while" || type == "do") b = b[2]; - else if (type == "for" || type == "for-in") b = b[4]; - else break; - } - return make(th); - }; - - function make_function(name, args, body, keyword, no_parens) { - var out = keyword || "function"; - if (name) { - out += " " + make_name(name); - } - out += "(" + add_commas(MAP(args, make_name)) + ")"; - out = add_spaces([ out, make_block(body) ]); - return (!no_parens && needs_parens(this)) ? "(" + out + ")" : out; - }; - - function must_has_semicolon(node) { - switch (node[0]) { - case "with": - case "while": - return empty(node[2]) || must_has_semicolon(node[2]); - case "for": - case "for-in": - return empty(node[4]) || must_has_semicolon(node[4]); - case "if": - if (empty(node[2]) && !node[3]) return true; // `if' with empty `then' and no `else' - if (node[3]) { - if (empty(node[3])) return true; // `else' present but empty - return must_has_semicolon(node[3]); // dive into the `else' branch - } - return must_has_semicolon(node[2]); // dive into the `then' branch - case "directive": - return true; - } - }; - - function make_block_statements(statements, noindent) { - for (var a = [], last = statements.length - 1, i = 0; i <= last; ++i) { - var stat = statements[i]; - var code = make(stat); - if (code != ";") { - if (!beautify && i == last && !must_has_semicolon(stat)) { - code = code.replace(/;+\s*$/, ""); - } - a.push(code); - } - } - return noindent ? a : MAP(a, indent); - }; - - function make_switch_block(body) { - var n = body.length; - if (n == 0) return "{}"; - return "{" + newline + MAP(body, function(branch, i){ - var has_body = branch[1].length > 0, code = with_indent(function(){ - return indent(branch[0] - ? add_spaces([ "case", make(branch[0]) + ":" ]) - : "default:"); - }, 0.5) + (has_body ? newline + with_indent(function(){ - return make_block_statements(branch[1]).join(newline); - }) : ""); - if (!beautify && has_body && i < n - 1) - code += ";"; - return code; - }).join(newline) + newline + indent("}"); - }; - - function make_block(statements) { - if (!statements) return ";"; - if (statements.length == 0) return "{}"; - return "{" + newline + with_indent(function(){ - return make_block_statements(statements).join(newline); - }) + newline + indent("}"); - }; - - function make_1vardef(def) { - var name = def[0], val = def[1]; - if (val != null) - name = add_spaces([ make_name(name), "=", parenthesize(val, "seq") ]); - return name; - }; - -}; - -function split_lines(code, max_line_length) { - var splits = [ 0 ]; - jsp.parse(function(){ - var next_token = jsp.tokenizer(code); - var last_split = 0; - var prev_token; - function current_length(tok) { - return tok.pos - last_split; - }; - function split_here(tok) { - last_split = tok.pos; - splits.push(last_split); - }; - function custom(){ - var tok = next_token.apply(this, arguments); - out: { - if (prev_token) { - if (prev_token.type == "keyword") break out; - } - if (current_length(tok) > max_line_length) { - switch (tok.type) { - case "keyword": - case "atom": - case "name": - case "punc": - split_here(tok); - break out; - } - } - } - prev_token = tok; - return tok; - }; - custom.context = function() { - return next_token.context.apply(this, arguments); - }; - return custom; - }()); - return splits.map(function(pos, i){ - return code.substring(pos, splits[i + 1] || code.length); - }).join("\n"); -}; - -/* -----[ Utilities ]----- */ - -function repeat_string(str, i) { - if (i <= 0) return ""; - if (i == 1) return str; - var d = repeat_string(str, i >> 1); - d += d; - if (i & 1) d += str; - return d; -}; - -function defaults(args, defs) { - var ret = {}; - if (args === true) - args = {}; - for (var i in defs) if (HOP(defs, i)) { - ret[i] = (args && HOP(args, i)) ? args[i] : defs[i]; - } - return ret; -}; - -function is_identifier(name) { - return /^[a-z_$][a-z0-9_$]*$/i.test(name) - && name != "this" - && !HOP(jsp.KEYWORDS_ATOM, name) - && !HOP(jsp.RESERVED_WORDS, name) - && !HOP(jsp.KEYWORDS, name); -}; - -function HOP(obj, prop) { - return Object.prototype.hasOwnProperty.call(obj, prop); -}; - -// some utilities - -var MAP; - -(function(){ - MAP = function(a, f, o) { - var ret = [], top = [], i; - function doit() { - var val = f.call(o, a[i], i); - if (val instanceof AtTop) { - val = val.v; - if (val instanceof Splice) { - top.push.apply(top, val.v); - } else { - top.push(val); - } - } - else if (val != skip) { - if (val instanceof Splice) { - ret.push.apply(ret, val.v); - } else { - ret.push(val); - } - } - }; - if (a instanceof Array) for (i = 0; i < a.length; ++i) doit(); - else for (i in a) if (HOP(a, i)) doit(); - return top.concat(ret); - }; - MAP.at_top = function(val) { return new AtTop(val) }; - MAP.splice = function(val) { return new Splice(val) }; - var skip = MAP.skip = {}; - function AtTop(val) { this.v = val }; - function Splice(val) { this.v = val }; -})(); - -/* -----[ Exports ]----- */ - -exports.ast_walker = ast_walker; -exports.ast_mangle = ast_mangle; -exports.ast_squeeze = ast_squeeze; -exports.ast_lift_variables = ast_lift_variables; -exports.gen_code = gen_code; -exports.ast_add_scope = ast_add_scope; -exports.set_logger = function(logger) { warn = logger }; -exports.make_string = make_string; -exports.split_lines = split_lines; -exports.MAP = MAP; - -// keep this last! -exports.ast_squeeze_more = require("./squeeze-more").ast_squeeze_more; - -// Local variables: -// js-indent-level: 4 -// End: diff --git a/install/ui/util/uglifyjs/lib/squeeze-more.js b/install/ui/util/uglifyjs/lib/squeeze-more.js deleted file mode 100644 index a14bc451a..000000000 --- a/install/ui/util/uglifyjs/lib/squeeze-more.js +++ /dev/null @@ -1,78 +0,0 @@ -var jsp = require("./parse-js"), - pro = require("./process"), - slice = jsp.slice, - member = jsp.member, - curry = jsp.curry, - MAP = pro.MAP, - PRECEDENCE = jsp.PRECEDENCE, - OPERATORS = jsp.OPERATORS; - -function ast_squeeze_more(ast) { - var w = pro.ast_walker(), walk = w.walk, scope; - function with_scope(s, cont) { - var save = scope, ret; - scope = s; - ret = cont(); - scope = save; - return ret; - }; - function _lambda(name, args, body) { - return [ this[0], name, args, with_scope(body.scope, curry(MAP, body, walk)) ]; - }; - return w.with_walkers({ - "toplevel": function(body) { - return [ this[0], with_scope(this.scope, curry(MAP, body, walk)) ]; - }, - "function": _lambda, - "defun": _lambda, - "new": function(ctor, args) { - if (ctor[0] == "name") { - if (ctor[1] == "Array" && !scope.has("Array")) { - if (args.length != 1) { - return [ "array", args ]; - } else { - return walk([ "call", [ "name", "Array" ], args ]); - } - } else if (ctor[1] == "Object" && !scope.has("Object")) { - if (!args.length) { - return [ "object", [] ]; - } else { - return walk([ "call", [ "name", "Object" ], args ]); - } - } else if ((ctor[1] == "RegExp" || ctor[1] == "Function" || ctor[1] == "Error") && !scope.has(ctor[1])) { - return walk([ "call", [ "name", ctor[1] ], args]); - } - } - }, - "call": function(expr, args) { - if (expr[0] == "dot" && expr[1][0] == "string" && args.length == 1 - && (args[0][1] > 0 && expr[2] == "substring" || expr[2] == "substr")) { - return [ "call", [ "dot", expr[1], "slice"], args]; - } - if (expr[0] == "dot" && expr[2] == "toString" && args.length == 0) { - // foo.toString() ==> foo+"" - if (expr[1][0] == "string") return expr[1]; - return [ "binary", "+", expr[1], [ "string", "" ]]; - } - if (expr[0] == "name") { - if (expr[1] == "Array" && args.length != 1 && !scope.has("Array")) { - return [ "array", args ]; - } - if (expr[1] == "Object" && !args.length && !scope.has("Object")) { - return [ "object", [] ]; - } - if (expr[1] == "String" && !scope.has("String")) { - return [ "binary", "+", args[0], [ "string", "" ]]; - } - } - } - }, function() { - return walk(pro.ast_add_scope(ast)); - }); -}; - -exports.ast_squeeze_more = ast_squeeze_more; - -// Local variables: -// js-indent-level: 4 -// End: diff --git a/install/ui/util/uglifyjs/ug.js b/install/ui/util/uglifyjs/ug.js deleted file mode 100644 index 1e910782e..000000000 --- a/install/ui/util/uglifyjs/ug.js +++ /dev/null @@ -1 +0,0 @@ -//just empty file to make rhino happy \ No newline at end of file diff --git a/install/ui/util/uglifyjs/uglify b/install/ui/util/uglifyjs/uglify deleted file mode 100755 index dcd3b7336..000000000 --- a/install/ui/util/uglifyjs/uglify +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash - -# Authors: -# Petr Vobornik -# -# Copyright (C) 2012 Red Hat -# see file 'COPYING' for use and warranty information -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# Wrapper for calling uglify.js under rhino - -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" - -# rhino-1.7R4 doesn't have -main option to enable CommonJS support. It was -# replaced by -require option. -RHINO="java -Xss${JAVA_STACK_SIZE:-512k} -classpath /usr/share/java/js.jar org.mozilla.javascript.tools.shell.Main" -if [ `$RHINO --help | grep -e -require | wc -l` -gt 0 ] ; then - $RHINO -require $DIR/uglify-js.js $@ -else - $RHINO -main $DIR/uglify-js.js $DIR/ug.js $@ -fi diff --git a/install/ui/util/uglifyjs/uglify-js.js b/install/ui/util/uglifyjs/uglify-js.js deleted file mode 100644 index 471c07e9f..000000000 --- a/install/ui/util/uglifyjs/uglify-js.js +++ /dev/null @@ -1,86 +0,0 @@ -// Modified version of the orignal uglify-js.js. Modified to be runnable -// under rhino by Petr Vobornik, Red Hat -// writeFile(), read() code written by John Resig. - -function uglify(orig_code, options){ - options || (options = {}); - var jsp = uglify.parser; - var pro = uglify.uglify; - - var ast = jsp.parse(orig_code, options.strict_semicolons); // parse code and get the initial AST - ast = pro.ast_mangle(ast, options.mangle_options); // get a new AST with mangled names - ast = pro.ast_squeeze(ast, options.squeeze_options); // get an AST with compression optimizations - var final_code = pro.gen_code(ast, options.gen_options); // compressed code here - return final_code; -}; - -uglify.parser = require("./lib/parse-js"); -uglify.uglify = require("./lib/process"); -uglify.consolidator = require("./lib/consolidator"); - -module.exports = uglify - - -importPackage(java.io); - -function writeFile( file, stream ) { - var buffer = new PrintWriter( new FileWriter( file ) ); - buffer.print( stream ); - buffer.close(); -} - -function read( file ) { - var f = new File(file); - var reader = new BufferedReader(new FileReader(f)); - var line = null; - var buffer = new java.lang.StringBuffer(f.length()); - while( (line = reader.readLine()) != null) { - buffer.append(line); - buffer.append("\n"); - } - return buffer.toString(); -} - -var options = { - ast: false, - consolidate: false, - mangle: true, - mangle_toplevel: false, - no_mangle_functions: false, - squeeze: true, - make_seqs: true, - dead_code: true, - verbose: false, - show_copyright: true, - out_same_file: false, - max_line_length: 32 * 1024, - unsafe: false, - reserved_names: null, - defines: { }, - lift_vars: false, - codegen_options: { - ascii_only: false, - beautify: false, - indent_level: 4, - indent_start: 0, - quote_keys: false, - space_colon: false, - inline_script: false - }, - make: false, - output: true // stdout -}; - -if (arguments.length < 2) { - print('Invalid input\nUsage: uglify inputFile outputFile'); - quit(); -} - -if (arguments.indexOf('-v')) { - print('Uglifying '+arguments[0] +'\nOutput: '+arguments[1]); -} - -//read input file -var input = read(arguments[0]) + ''; -var output = uglify(input, options); -writeFile(arguments[1], output); \ No newline at end of file