internal void SetAssumedGlobals(JsSettings settings)
        {
            if (settings != null)
            {
                // start off with any known globals
                m_assumedGlobals = settings.KnownGlobalCollection == null ? new HashSet <string>() : new HashSet <string>(settings.KnownGlobalCollection);

                // chek to see if there are any debug lookups
                foreach (var debugLookup in settings.DebugLookupCollection)
                {
                    m_assumedGlobals.Add(debugLookup.SubstringUpToFirst('.'));
                }

                // and the root name of any resource strings is also an assumed global
                foreach (var resourceStrings in settings.ResourceStrings)
                {
                    if (!resourceStrings.Name.IsNullOrWhiteSpace())
                    {
                        m_assumedGlobals.Add(resourceStrings.Name.SubstringUpToFirst('.'));
                    }
                }
            }
            else
            {
                // empty set
                m_assumedGlobals = new HashSet <string>();
            }
        }
        private static void ResolveLookups(JsActivationObject scope, JsSettings settings)
        {
            // resolve each lookup this scope contains
            foreach (var lookup in scope.ScopeLookups)
            {
                ResolveLookup(scope, lookup, settings);
            }

            // and recurse
            foreach (var childScope in scope.ChildScopes)
            {
                ResolveLookups(childScope, settings);
            }

            // mark any variables defined in this scope that don't have any references
            // so we can throw warnings later. We can't rely on the reference count because
            // we might remove references while optimizing code -- if we throw an error when
            // the count gets to zero, then we would be reporting errors that don't exist.
            // but we DO know right now what isn't referenced at all.
            foreach (var field in scope.NameTable.Values)
            {
                if (field.RefCount == 0)
                {
                    field.HasNoReferences = true;
                }
            }
        }
        protected JsActivationObject(JsActivationObject parent, JsSettings codeSettings)
        {
            m_isKnownAtCompileTime = true;
            m_useStrict            = false;
            m_settings             = codeSettings;

            Parent      = parent;
            NameTable   = new Dictionary <string, JsVariableField>();
            ChildScopes = new List <JsActivationObject>();

            // if our parent is a scope....
            if (parent != null)
            {
                // add us to the parent's list of child scopes
                parent.ChildScopes.Add(this);

                // if the parent is strict, so are we
                UseStrict = parent.UseStrict;
            }

            // create the two lists of declared items for this scope
            ScopeLookups           = new HashSet <JsLookup>();
            VarDeclaredNames       = new HashSet <IJsNameDeclaration>();
            LexicallyDeclaredNames = new HashSet <IJsNameDeclaration>();

            GhostedCatchParameters = new HashSet <JsParameterDeclaration>();
            GhostedFunctions       = new HashSet <JsFunctionObject>();
        }
示例#4
0
        public JsBlockScope(JsActivationObject parent, JsContext context, JsSettings settings)
            : base(parent, settings)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            m_context = context.Clone();
        }
        private JsResolutionVisitor(JsActivationObject rootScope, JsSettings settings)
        {
            // create the lexical and variable scope stacks and push the root scope onto them
            m_lexicalStack = new Stack <JsActivationObject>();
            m_lexicalStack.Push(rootScope);

            m_variableStack = new Stack <JsActivationObject>();
            m_variableStack.Push(rootScope);

            m_settings = settings;
        }
示例#6
0
        /// <summary>
        /// Instantiate a new CodeSettings object with the same settings as the current object.
        /// </summary>
        /// <returns>a copy CodeSettings object</returns>
        public JsSettings Clone()
        {
            // create a new settings object and set all the properties using this settings object
            var newSettings = new JsSettings()
            {
                // set the field, not the property. Setting the property will set a bunch of
                // other properties, which may not represent their actual values.
                m_minify = this.m_minify,

                AllowEmbeddedAspNetBlocks = this.AllowEmbeddedAspNetBlocks,
                AlwaysEscapeNonAscii      = this.AlwaysEscapeNonAscii,
                CollapseToLiteral         = this.CollapseToLiteral,
                ConstStatementsMozilla    = this.ConstStatementsMozilla,
                DebugLookupList           = this.DebugLookupList,
                EvalLiteralExpressions    = this.EvalLiteralExpressions,
                EvalTreatment             = this.EvalTreatment,
                Format = this.Format,
                IgnoreConditionalCompilation = this.IgnoreConditionalCompilation,
                IgnoreAllErrors           = this.IgnoreAllErrors,
                IgnoreErrorList           = this.IgnoreErrorList,
                IgnorePreprocessorDefines = this.IgnorePreprocessorDefines,
                IndentSize                    = this.IndentSize,
                InlineSafeStrings             = this.InlineSafeStrings,
                KillSwitch                    = this.KillSwitch,
                KnownGlobalNamesList          = this.KnownGlobalNamesList,
                LineBreakThreshold            = this.LineBreakThreshold,
                LocalRenaming                 = this.LocalRenaming,
                MacSafariQuirks               = this.MacSafariQuirks,
                ManualRenamesProperties       = this.ManualRenamesProperties,
                NoAutoRenameList              = this.NoAutoRenameList,
                OutputMode                    = this.OutputMode,
                PreprocessOnly                = this.PreprocessOnly,
                PreprocessorDefineList        = this.PreprocessorDefineList,
                PreserveFunctionNames         = this.PreserveFunctionNames,
                PreserveImportantComments     = this.PreserveImportantComments,
                QuoteObjectLiteralProperties  = this.QuoteObjectLiteralProperties,
                RemoveFunctionExpressionNames = this.RemoveFunctionExpressionNames,
                RemoveUnneededCode            = this.RemoveUnneededCode,
                RenamePairs                   = this.RenamePairs,
                ReorderScopeDeclarations      = this.ReorderScopeDeclarations,
                SourceMode                    = this.SourceMode,
                StrictMode                    = this.StrictMode,
                StripDebugStatements          = this.StripDebugStatements,
                TermSemicolons                = this.TermSemicolons,
                BlocksStartOnSameLine         = this.BlocksStartOnSameLine,
                ErrorIfNotInlineSafe          = this.ErrorIfNotInlineSafe,
                SymbolsMap                    = this.SymbolsMap,
            };

            // set the resource strings if there are any
            newSettings.AddResourceStrings(this.ResourceStrings);

            return(newSettings);
        }
示例#7
0
        internal JsFunctionScope(JsActivationObject parent, bool isExpression, JsSettings settings, JsFunctionObject funcObj)
            : base(parent, settings)
        {
            m_refScopes = new HashSet <JsActivationObject>();
            if (isExpression)
            {
                // parent scopes automatically reference enclosed function expressions
                AddReference(Parent);
            }

            FunctionObject = funcObj;
        }
        internal JsGlobalScope(JsSettings settings)
            : base(null, settings)
        {
            // define the Global object's properties, and methods
            m_globalProperties = new HashSet <string>(new[] {
                "Infinity", "NaN", "undefined", "window", "Image", "JSON", "Map", "Math", "Set", "WeakMap", "XMLHttpRequest", "DOMParser",
                "applicationCache", "clientInformation", "clipboardData", "closed", "console", "document", "event", "external", "frameElement", "frames", "history", "length", "localStorage", "location", "name", "navigator", "opener", "parent", "screen", "self", "sessionStorage", "status", "top"
            });

            m_globalFunctions = new HashSet <string>(new[] {
                "decodeURI", "decodeURIComponent", "encodeURI", "encodeURIComponent", "escape", "eval", "importScripts", "isNaN", "isFinite", "parseFloat", "parseInt", "unescape", "ActiveXObject", "Array", "Boolean", "Date", "Error", "EvalError", "EventSource", "File", "FileList", "FileReader", "Function", "GeckoActiveXObject", "HTMLElement", "Number", "Object", "Proxy", "RangeError", "ReferenceError", "RegExp", "SharedWorker", "String", "SyntaxError", "TypeError", "URIError", "WebSocket", "Worker",
                "addEventListener", "alert", "attachEvent", "blur", "clearInterval", "clearTimeout", "close", "confirm", "createPopup", "detachEvent", "dispatchEvent", "execScript", "focus", "getComputedStyle", "getSelection", "moveBy", "moveTo", "navigate", "open", "postMessage", "prompt", "removeEventListener", "resizeBy", "resizeTo", "scroll", "scrollBy", "scrollTo", "setActive", "setInterval", "setTimeout", "showModalDialog", "showModelessDialog"
            });
        }
示例#9
0
        /// <summary>
        /// Minifies the CSS stylesheet passes to it using the given settings, returning the minified results
        /// The ErrorList property will be set with any errors found during the minification process.
        /// </summary>
        /// <param name="source">CSS Source</param>
        /// <param name="settings">CSS minification settings</param>
        /// <param name="scriptSettings">JS minification settings to use for expression-minification</param>
        /// <returns>Minified StyleSheet</returns>
        public string MinifyStyleSheet(string source, CssSettings settings, JsSettings scriptSettings)
        {
            // initialize some values, including the error list (which shoudl start off empty)
            string minifiedResults = string.Empty;

            m_errorList = new List <MinifierError>();

            // create the parser object and if we specified some settings,
            // use it to set the Parser's settings object
            CssParser parser = new CssParser();

            parser.FileContext = FileName;

            if (settings != null)
            {
                parser.Settings = settings;
            }

            if (scriptSettings != null)
            {
                parser.JSSettings = scriptSettings;
            }

            // hook the error handler
            parser.CssError += new EventHandler <CssErrorEventArgs>(OnCssError);

            // try parsing the source and return the results
            try
            {
                minifiedResults = parser.Parse(source);
            }
            catch (Exception e)
            {
                m_errorList.Add(new MinifierError(
                                    true,
                                    0,
                                    null,
                                    null,
                                    null,
                                    this.FileName,
                                    0,
                                    0,
                                    0,
                                    0,
                                    e.Message));
                throw;
            }
            return(minifiedResults);
        }
        public static void Apply(JsAstNode node, JsActivationObject scope, JsSettings settings)
        {
            if (node != null && scope != null)
            {
                // create the visitor and run it. This will create all the child
                // scopes and populate all the scopes with the var-decl, lex-decl,
                // and lookup references within them.
                var visitor = new JsResolutionVisitor(scope, settings);
                node.Accept(visitor);

                // now that all the scopes are created and they all know what decls
                // they contains, create all the fields
                CreateFields(scope);

                // now that all the fields have been created in all the scopes,
                // let's go through and resolve all the references
                ResolveLookups(scope, settings);

                // now that everything is declared and resolved as per the language specs,
                // we need to go back and add ghosted fields for older versions of IE that
                // incorrectly implement catch-variables and named function expressions.
                AddGhostedFields(scope);
            }
        }
示例#11
0
 internal JsCatchScope(JsActivationObject parent, JsContext catchContext, JsSettings settings, JsParameterDeclaration catchParameter)
     : base(parent, catchContext, settings)
 {
     CatchParameter = catchParameter;
 }
        private static void ResolveLookup(JsActivationObject scope, JsLookup lookup, JsSettings settings)
        {
            // resolve lookup via the lexical scope
            lookup.VariableField = scope.FindReference(lookup.Name);
            if (lookup.VariableField.FieldType == JsFieldType.UndefinedGlobal)
            {
                // couldn't find it.
                // if the lookup isn't generated and isn't the object of a typeof operator,
                // then we want to throw an error.
                if (!lookup.IsGenerated)
                {
                    var parentUnaryOp = lookup.Parent as JsUnaryOperator;
                    if (parentUnaryOp != null && parentUnaryOp.OperatorToken == JsToken.TypeOf)
                    {
                        // this undefined lookup is the target of a typeof operator.
                        // I think it's safe to assume we're going to use it. Don't throw an error
                        // and instead add it to the "known" expected globals of the global scope
                        MakeExpectedGlobal(lookup.VariableField);
                    }
                    else
                    {
                        // report this undefined reference
                        lookup.Context.ReportUndefined(lookup);

                        // possibly undefined global (but definitely not local).
                        // see if this is a function or a variable.
                        var callNode   = lookup.Parent as JsCallNode;
                        var isFunction = callNode != null && callNode.Function == lookup;
                        lookup.Context.HandleError((isFunction ? JsError.UndeclaredFunction : JsError.UndeclaredVariable), false);
                    }
                }
            }
            else if (lookup.VariableField.FieldType == JsFieldType.Predefined)
            {
                if (string.CompareOrdinal(lookup.Name, "window") == 0)
                {
                    // it's the global window object
                    // see if it's the child of a member or call-brackets node
                    var member = lookup.Parent as JsMember;
                    if (member != null)
                    {
                        // we have window.XXXX. Add XXXX to the known globals if it
                        // isn't already a known item.
                        scope.AddGlobal(member.Name);
                    }
                    else
                    {
                        var callNode = lookup.Parent as JsCallNode;
                        if (callNode != null && callNode.InBrackets &&
                            callNode.Arguments.Count == 1 &&
                            callNode.Arguments[0] is JsConstantWrapper &&
                            callNode.Arguments[0].FindPrimitiveType() == JsPrimitiveType.String)
                        {
                            // we have window["XXXX"]. See if XXXX is a valid identifier.
                            // TODO: we could get rid of the ConstantWrapper restriction and use an Evaluate visitor
                            // to evaluate the argument, since we know for sure that it's a string.
                            var identifier = callNode.Arguments[0].ToString();
                            if (JsScanner.IsValidIdentifier(identifier))
                            {
                                // Add XXXX to the known globals if it isn't already a known item.
                                scope.AddGlobal(identifier);
                            }
                        }
                    }
                }
                else if (settings.EvalTreatment != JsEvalTreatment.Ignore &&
                         string.CompareOrdinal(lookup.Name, "eval") == 0)
                {
                    // it's an eval -- but are we calling it?
                    // TODO: what if we are assigning it to a variable? Should we track that variable and see if we call it?
                    // What about passing it as a parameter to a function? track that as well in case the function calls it?
                    var parentCall = lookup.Parent as JsCallNode;
                    if (parentCall != null && parentCall.Function == lookup)
                    {
                        scope.IsKnownAtCompileTime = false;
                    }
                }
            }

            // add the reference
            lookup.VariableField.AddReference(lookup);

            // we are actually referencing this field, so it's no longer a placeholder field if it
            // happens to have been one.
            lookup.VariableField.IsPlaceholder = false;
        }
示例#13
0
 public JsWithScope(JsActivationObject parent, JsContext context, JsSettings settings)
     : base(parent, context, settings)
 {
     IsInWithScope = true;
 }
示例#14
0
        /// <summary>
        /// Crunched JS string passed to it, returning crunched string.
        /// The ErrorList property will be set with any errors found during the minification process.
        /// </summary>
        /// <param name="source">source Javascript</param>
        /// <param name="codeSettings">code minification settings</param>
        /// <returns>minified Javascript</returns>
        public string MinifyJavaScript(string source, JsSettings codeSettings)
        {
            // default is an empty string
            var crunched = string.Empty;

            // reset the errors builder
            m_errorList = new List <MinifierError>();

            // create the parser from the source string.
            // pass null for the assumed globals array
            var parser = new JsParser(source);

            // file context is a property on the parser
            parser.FileContext = FileName;

            // hook the engine error event
            parser.CompilerError += OnJavaScriptError;

            try
            {
                var preprocessOnly = codeSettings != null && codeSettings.PreprocessOnly;
                var sb             = new StringBuilder();
                using (var stringWriter = new StringWriter(sb, CultureInfo.InvariantCulture))
                {
                    if (preprocessOnly)
                    {
                        parser.EchoWriter = stringWriter;
                    }

                    // parse the input
                    var scriptBlock = parser.Parse(codeSettings);
                    if (scriptBlock != null && !preprocessOnly)
                    {
                        // we'll return the crunched code
                        if (codeSettings != null && codeSettings.Format == JsFormat.JSON)
                        {
                            // we're going to use a different output visitor -- one
                            // that specifically returns valid JSON.
                            if (!JsonOutputVisitor.Apply(stringWriter, scriptBlock))
                            {
                                m_errorList.Add(new MinifierError(
                                                    true,
                                                    0,
                                                    null,
                                                    null,
                                                    null,
                                                    this.FileName,
                                                    0,
                                                    0,
                                                    0,
                                                    0,
                                                    JScript.InvalidJSONOutput));
                            }
                        }
                        else
                        {
                            // just use the normal output visitor
                            JsOutputVisitor.Apply(stringWriter, scriptBlock, codeSettings);
                        }
                    }
                }

                crunched = sb.ToString();
            }
            catch (Exception e)
            {
                m_errorList.Add(new MinifierError(
                                    true,
                                    0,
                                    null,
                                    null,
                                    null,
                                    this.FileName,
                                    0,
                                    0,
                                    0,
                                    0,
                                    e.Message));
                throw;
            }

            return(crunched);
        }