private bool m_useStrict; //= false;

        #endregion Fields

        #region Constructors

        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>();
        }
        public MinifierParser()
        {
            // initialize with default values
            JSSettings = new JsSettings();
            CssSettings = new CssSettings();

            // see if this is running under the Mono runtime (on UNIX)
            m_isMono = Type.GetType("Mono.Runtime") != null;
        }
        private JsContext m_context; // = null;

        #endregion Fields

        #region Constructors

        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;
        }
        public static void Apply(TextWriter writer, JsAstNode node, JsSettings settings)
        {
            if (node != null)
            {
                var outputVisitor = new JsOutputVisitor(writer, settings);
                node.Accept(outputVisitor);

                // if there is a symbol map that we are tracking, tell it that we have ended an output run
                // and pass it offsets to the last line and column positions.
                settings.IfNotNull(s => s.SymbolsMap.IfNotNull(m => m.EndOutputRun(outputVisitor.m_lineCount, outputVisitor.m_lineLength)));
            }
        }
        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;
        }
示例#7
0
 public ProjectView(UnrealProject uproject, JsSettings s)
 {
     SelectedUproject = uproject;
     settings         = s;
     InitializeComponent();
     gr.DataContext = this;
     if (SelectedUproject.JsUnrealProject.Plugins != null)
     {
         Plugins.ItemsSource = SelectedUproject.JsUnrealProject.Plugins;
     }
     Modules.ItemsSource = SelectedUproject.JsUnrealProject.Modules;
 }
        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
        private void LoadSettings()
        {
            if (File.Exists(appdatapath))
            {
                settings = JsonConvert.DeserializeObject <JsSettings>(File.ReadAllText(appdatapath));
                return;
            }

            settings = new JsSettings {
                AutomaticallyRecompile = false, DeleteDerivedFiles = true, IncludeSavedFolder = false
            };
            if (!Directory.Exists(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "/UnrealHelpers/ModuleManager"))
            {
                Directory.CreateDirectory(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "/UnrealHelpers/ModuleManager");
            }
            File.WriteAllText(appdatapath, JsonConvert.SerializeObject(settings));
        }
 public MinifierParser(JsSettings scriptSettings, CssSettings cssSettings)
 {
     // apply the switches to these two settings objects
     JSSettings = scriptSettings ?? new JsSettings();
     CssSettings = cssSettings ?? new CssSettings();
 }
        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>();
            }
        }
示例#12
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;
        }
示例#13
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;
        }
        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;
                }
            }
        }
 private JsOutputVisitor(TextWriter writer, JsSettings settings)
 {
     m_outputStream = writer;
     m_settings = settings ?? new JsSettings();
     m_onNewLine = true;
 }
示例#16
0
        /// <summary>
        /// Parse the source code using the given settings, getting back an abstract syntax tree Block node as the root
        /// representing the list of statements in the source code.
        /// </summary>
        /// <param name="settings">code settings to use to process the source code</param>
        /// <returns>root Block node representing the top-level statements</returns>
        public JsBlock Parse(JsSettings settings)
        {
            // initialize the scanner with our settings
            // make sure the RawTokens setting is OFF or we won't be able to create our AST
            InitializeScanner(settings);

            // make sure we initialize the global scope's strict mode to our flag, whether or not it
            // is true. This means if the setting is false, we will RESET the flag to false if we are
            // reusing the scope and a previous Parse call had code that set it to strict with a
            // program directive.
            GlobalScope.UseStrict = m_settings.StrictMode;

            // make sure the global scope knows about our known global names
            GlobalScope.SetAssumedGlobals(m_settings);

            // start of a new module
            m_newModule = true;

            var timePoints = m_timingPoints = new long[9];
            var timeIndex = timePoints.Length;
            var stopWatch = new Stopwatch();
            stopWatch.Start();

            JsBlock scriptBlock = null;
            JsBlock returnBlock = null;
            try
            {
                switch (m_settings.SourceMode)
                {
                    case JsSourceMode.Program:
                        // simply parse a block of statements
                        returnBlock = scriptBlock = ParseStatements();
                        break;

                    case JsSourceMode.Expression:
                        // create a block, get the first token, add in the parse of a single expression,
                        // and we'll go fron there.
                        returnBlock = scriptBlock = new JsBlock(CurrentPositionContext(), this);
                        GetNextToken();
                        try
                        {
                            var expr = ParseExpression();
                            if (expr != null)
                            {
                                scriptBlock.Append(expr);
                                scriptBlock.UpdateWith(expr.Context);
                            }
                        }
                        catch (EndOfStreamException)
                        {
                            Debug.WriteLine("EOF");
                        }
                        break;

                    case JsSourceMode.EventHandler:
                        // we're going to create the global block, add in a function expression with a single
                        // parameter named "event", and then we're going to parse the input as the body of that
                        // function expression. We're going to resolve the global block, but only return the body
                        // of the function.
                        scriptBlock = new JsBlock(null, this);

                        var parameters = new JsAstNodeList(null, this);
                        parameters.Append(new JsParameterDeclaration(null, this)
                            {
                                Name = "event",
                                RenameNotAllowed = true
                            });

                        var funcExpression = new JsFunctionObject(null, this)
                            {
                                FunctionType = JsFunctionType.Expression,
                                ParameterDeclarations = parameters
                            };
                        scriptBlock.Append(funcExpression);
                        funcExpression.Body = returnBlock = ParseStatements();
                        break;

                    default:
                        Debug.Fail("Unexpected source mode enumeration");
                        return null;
                }
            }
            catch (RecoveryTokenException)
            {
                // this should never happen but let's make SURE we don't expose our
                // private exception object to the outside world
                m_currentToken.HandleError(JsError.ApplicationError, true);
            }

            timePoints[--timeIndex] = stopWatch.ElapsedTicks;

            if (scriptBlock != null)
            {
                // resolve everything
                JsResolutionVisitor.Apply(scriptBlock, GlobalScope, m_settings);
            }

            timePoints[--timeIndex] = stopWatch.ElapsedTicks;

            if (scriptBlock != null && Settings.MinifyCode && !Settings.PreprocessOnly)
            {
                // this visitor doesn't just reorder scopes. It also combines the adjacent var variables,
                // unnests blocks, identifies prologue directives, and sets the strict mode on scopes.
                JsReorderScopeVisitor.Apply(scriptBlock, this);
                timePoints[--timeIndex] = stopWatch.ElapsedTicks;

                // analyze the entire node tree (needed for hypercrunch)
                // root to leaf (top down)
                var analyzeVisitor = new JsAnalyzeNodeVisitor(this);
                scriptBlock.Accept(analyzeVisitor);
                timePoints[--timeIndex] = stopWatch.ElapsedTicks;

                // analyze the scope chain (also needed for hypercrunch)
                // root to leaf (top down)
                GlobalScope.AnalyzeScope();
                timePoints[--timeIndex] = stopWatch.ElapsedTicks;

                // if we want to crunch any names....
                if (m_settings.LocalRenaming != JsLocalRenaming.KeepAll
                    && m_settings.IsModificationAllowed(JsTreeModifications.LocalRenaming))
                {
                    // then do a top-down traversal of the scope tree. For each field that had not
                    // already been crunched (globals and outers will already be crunched), crunch
                    // the name with a crunch iterator that does not use any names in the verboten set.
                    GlobalScope.AutoRenameFields();
                }

                timePoints[--timeIndex] = stopWatch.ElapsedTicks;

                // if we want to evaluate literal expressions, do so now
                if (m_settings.EvalLiteralExpressions)
                {
                    var visitor = new JsEvaluateLiteralVisitor(this);
                    scriptBlock.Accept(visitor);
                }

                timePoints[--timeIndex] = stopWatch.ElapsedTicks;

                // make the final cleanup pass
                JsFinalPassVisitor.Apply(scriptBlock, this);
                timePoints[--timeIndex] = stopWatch.ElapsedTicks;

                // we want to walk all the scopes to make sure that any generated
                // variables that haven't been crunched have been assigned valid
                // variable names that don't collide with any existing variables.
                GlobalScope.ValidateGeneratedNames();
                timePoints[--timeIndex] = stopWatch.ElapsedTicks;
            }

            if (returnBlock != null && returnBlock.Parent != null)
            {
                returnBlock.Parent = null;
            }

            return returnBlock;
        }
        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;
        }
示例#18
0
 public JsWithScope(JsActivationObject parent, JsContext context, JsSettings settings)
     : base(parent, context, settings)
 {
     IsInWithScope = true;
 }
示例#19
0
        private void InitializeScanner(JsSettings settings)
        {
            // save the settings
            // if we are passed null, just create a default settings object
            m_settings = settings = settings ?? new JsSettings();

            // if the settings list is not null, use it to initialize a new list
            // with the same settings. If it is null, initialize an empty list
            // because we already determined that we want to strip debug statements,
            // and the scanner might add items to the list as it scans the source.
            DebugLookups = new HashSet<string>(m_settings.DebugLookupCollection);

            // pass our list to the scanner -- it might add more as we encounter special comments
            m_scanner.DebugLookupCollection = DebugLookups;

            m_scanner.AllowEmbeddedAspNetBlocks = m_settings.AllowEmbeddedAspNetBlocks;
            m_scanner.IgnoreConditionalCompilation = m_settings.IgnoreConditionalCompilation;

            // set any defines
            m_scanner.UsePreprocessorDefines = !m_settings.IgnorePreprocessorDefines;
            if (m_scanner.UsePreprocessorDefines)
            {
                m_scanner.SetPreprocessorDefines(m_settings.PreprocessorValues);
            }

            // if we want to strip debug statements, let's also strip ///#DEBUG comment
            // blocks for legacy reasons. ///#DEBUG will get stripped ONLY is this
            // flag is true AND the name "DEBUG" is not in the preprocessor defines.
            // Alternately, we will keep those blocks in the output is this flag is
            // set to false OR we define "DEBUG" in the preprocessor defines.
            m_scanner.StripDebugCommentBlocks = m_settings.StripDebugStatements;
        }
示例#20
0
        public void PreprocessOnly(JsSettings settings, TextWriter outputStream)
        {
            if (outputStream != null)
            {
                EchoWriter = outputStream;
                Parse(settings);
                EchoWriter = null;

                if (m_settings.TermSemicolons)
                {
                    // if we want to make sure this file has a terminating semicolon, start a new line
                    // (to make sure any single-line comments are terminated) and output a semicolon
                    // followed by another line break.
                    outputStream.WriteLine();
                    outputStream.WriteLine(';');
                }
            }
        }
示例#21
0
        public string PreprocessOnly(JsSettings settings)
        {
            // create an empty string builder
            using (var outputStream = new StringWriter(CultureInfo.InvariantCulture))
            {
                // output to the string builder
                PreprocessOnly(settings, outputStream);

                // return the resulting text
                return outputStream.ToString();
            }
        }
示例#22
0
 public JsBlock ParseExpression(JsSettings settings)
 {
     // we need to make sure the settings object has the expression source mode property set,
     // but let's not modify the settings object passed in. So clone it, set the property on the
     // clone, and use that object for parsing.
     settings = settings == null ? new JsSettings() : settings.Clone();
     settings.SourceMode = JsSourceMode.Expression;
     return Parse(settings);
 }
 internal JsCatchScope(JsActivationObject parent, JsContext catchContext, JsSettings settings, JsParameterDeclaration catchParameter)
     : base(parent, catchContext, settings)
 {
     CatchParameter = catchParameter;
 }
        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);
            }
        }