Example #1
0
        public void EnterPseudoScope(ast.Node n)
        {
            SymbolScope currentScope = m_PseudoScopes.Peek();

            n.PseudoScope = new SymbolScope(currentScope.Compiler, n, Accessibility.Private);

            currentScope.InnerScopes.Add(n.PseudoScope);
            n.PseudoScope.OuterScope = currentScope;

            m_PseudoScopes.Push(n.PseudoScope);
        }
Example #2
0
        public void EnterScope(SymbolScope Scope)
        {
            System.Diagnostics.Debug.Assert(Scope.OuterScope == m_CurrentScope);

            m_CurrentScope = Scope;

            m_SymbolAllocator.EnterScope();
            m_MemberAllocator.EnterScope();

            // Obfuscate symbols?
            if (!Compiler.NoObfuscate)
            {
                Scope.ObfuscateSymbols(this);
            }
        }
Example #3
0
        public bool OnEnterNode(MiniME.ast.Node n)
        {
            // Descending into an inner scope
            if (n.Scope != null)
            {
                System.Diagnostics.Debug.Assert(n.Scope.OuterScope == currentScope);
                currentScope = n.Scope;
            }

            // Is is a "var <name>=<literal_int_or_double>", inside a function
            if (currentScope.OuterScope!=null && n.GetType() == typeof(ast.StatementVariableDeclaration))
            {
                var vardecl = (ast.StatementVariableDeclaration)n;
                foreach (var v in vardecl.Variables)
                {
                    // Must have initial value
                    if (v.InitialValue == null)
                        continue;

                    // Must evaluate to a constant
                    object val = v.InitialValue.RootNode.EvalConstLiteral();
                    if (val==null)
                        continue;

                    // Must be a number
                    if (val.GetType() != typeof(long) && val.GetType() != typeof(DoubleLiteral))
                        continue;

                    // Find the symbol in the current scope
                    Symbol s = currentScope.Symbols.FindLocalSymbol(v.Name);
                    System.Diagnostics.Debug.Assert(s != null);

                    // Store the constant value for this symbol
                    if (s.ConstValue == null && s.ConstAllowed)
                    {
                        s.ConstValue = val;
                    }
                    else
                    {
                        s.ConstAllowed = false;
                        s.ConstValue = null;
                    }
                }
            }

            return true;
        }
Example #4
0
        public bool OnEnterNode(MiniME.ast.Node n)
        {
            if (n.Scope != null)
            {
                currentScope = n.Scope;
            }

            if (n.PseudoScope!=null)
            {
                currentPseudoScope=n.PseudoScope;
                DetectMultipleDeclarations();
            }

            // Check 'if' statement
            var ifStatement = n as ast.StatementIfElse;
            if (ifStatement != null)
            {
                CheckControlCondition(ifStatement, ifStatement.Condition);
            }

            // Check 'while' statement
            var whileStatement = n as ast.StatementWhile;
            if (whileStatement != null)
            {
                CheckControlCondition(whileStatement, whileStatement.Condition);
            }

            // Check 'do' statement
            var doStatement = n as ast.StatementDoWhile;
            if (doStatement != null)
            {
                CheckControlCondition(doStatement, doStatement.Condition);
            }

            // Check 'for' statement
            var forStatement = n as ast.StatementFor;
            if (forStatement != null)
            {
                CheckControlCondition(forStatement, forStatement.Condition);
            }

            // Check for variable used outself declaring pseudo scope
            var ident = n as ast.ExprNodeIdentifier;
            if (ident!=null && ident.Lhs == null)
            {
                var symbol=currentScope.FindLocalSymbol(ident.Name);
                if (symbol!=null)
                {
                    // Now walk the pseudo scopes and make sure that it's defined in the current scope too
                    // (and not in a child scope)

                    var scope = currentPseudoScope;
                    bool bFound=false;
                    while (scope != null && !bFound)
                    {
                        // Check scope
                        if (scope.FindLocalSymbol(ident.Name) != null)
                        {
                            bFound = true;
                            break;
                        }

                        // Are we finished on the actual local scope
                        if (scope.Node!=null && scope.Node.Scope != null)
                            break;

                        // Get next outer scope
                        scope = scope.OuterScope;
                    }

                    if (!bFound)
                    {
                        currentScope.Compiler.RecordWarning(n.Bookmark, "symbol `{0}` used outside declaring pseudo scope", ident.Name);
                        foreach (var decl in symbol.Declarations)
                        {
                            currentScope.Compiler.RecordWarning(decl, n.Bookmark, "see also declaration of `{0}`", ident.Name);
                        }
                    }
                }
            }

            return true;
        }
Example #5
0
 // Constructor
 public VisitorLint(SymbolScope rootScope, SymbolScope rootPseudoScope)
 {
     currentScope = rootScope;
     currentPseudoScope = rootPseudoScope;
     DetectMultipleDeclarations();
 }
Example #6
0
 // Constructor
 public VisitorScopeBuilder(SymbolScope rootScope, SymbolScope rootPseudoScope)
 {
     m_Scopes.Push(rootScope);
     m_PseudoScopes.Push(rootPseudoScope);
 }
Example #7
0
 public void OnLeaveNode(MiniME.ast.Node n)
 {
     if (n.Scope != null)
     {
         currentScope = n.Scope.OuterScope;
     }
 }
Example #8
0
 public VisitorConstDetectorPass1(SymbolScope rootScope)
 {
     currentScope = rootScope;
 }
Example #9
0
        public bool OnEnterNode(MiniME.ast.Node n)
        {
            // Descending into an inner scope
            if (n.Scope != null)
            {
                System.Diagnostics.Debug.Assert(n.Scope.OuterScope == currentScope);
                currentScope = n.Scope;
            }

            // Look for assignments to property
            if (n.GetType() == typeof(ast.ExprNodeAssignment))
            {
                // Is it an assignment
                var assignOp = (ast.ExprNodeAssignment)n;
                RejectConstVariable(assignOp.Lhs);
            }

            // Look for increment/decrement operators
            if (n.GetType() == typeof(ast.ExprNodeUnary))
            {
                var oneOp = (ast.ExprNodeUnary)n;
                if (oneOp.Op == Token.increment || oneOp.Op == Token.decrement)
                {
                    RejectConstVariable(oneOp.Rhs);
                }
            }

            // Postfix too
            if (n.GetType() == typeof(ast.ExprNodePostfix))
            {
                var oneOp = (ast.ExprNodePostfix)n;
                if (oneOp.Op == Token.increment || oneOp.Op == Token.decrement)
                {
                    RejectConstVariable(oneOp.Lhs);
                }
            }

            return true;
        }
 // Constructor
 public VisitorSymbolDeclaration(SymbolScope rootScope, SymbolScope rootPseudoScope)
 {
     currentScope       = rootScope;
     currentPseudoScope = rootPseudoScope;
 }
Example #11
0
        public void EnterScope(SymbolScope Scope)
        {
            System.Diagnostics.Debug.Assert(Scope.OuterScope == m_CurrentScope);

            m_CurrentScope = Scope;

            m_SymbolAllocator.EnterScope();
            m_MemberAllocator.EnterScope();

            // Obfuscate symbols?
            if (!Compiler.NoObfuscate)
                Scope.ObfuscateSymbols(this);
        }
Example #12
0
 // Constructor
 public VisitorLint(SymbolScope rootScope, SymbolScope rootPseudoScope)
 {
     currentScope       = rootScope;
     currentPseudoScope = rootPseudoScope;
     DetectMultipleDeclarations();
 }
Example #13
0
 public VisitorConstDetectorPass1(SymbolScope rootScope)
 {
     currentScope = rootScope;
 }
 public VisitorCombineVarDecl(SymbolScope rootScope)
 {
 }
Example #15
0
        public bool OnEnterNode(ast.Node n)
        {
            // New actual scope (function body or catch clause)
            if (n.GetType() == typeof(ast.ExprNodeFunction) || n.GetType() == typeof(ast.CatchClause))
            {
                SymbolScope currentScope = m_Scopes.Peek();

                n.Scope = new SymbolScope(currentScope.Compiler, n, Accessibility.Private);

                // Add this function to the parent function's list of nested functions
                currentScope.InnerScopes.Add(n.Scope);
                n.Scope.OuterScope = currentScope;

                // Enter scope
                m_Scopes.Push(n.Scope);

                // Also create a pseudo scope
                EnterPseudoScope(n);

                return(true);
            }

            // New pseudo scope (statement body or braced code block)
            if (n.GetType() == typeof(ast.CodeBlock) || n.GetType() == typeof(ast.StatementBlock) || n.GetType() == typeof(ast.StatementFor) || n.GetType() == typeof(ast.StatementForIn))
            {
                // Create pseudo scope
                EnterPseudoScope(n);
                return(true);
            }

            // Is it an evil?
            if (n.GetType() == typeof(ast.StatementWith))
            {
                m_Scopes.Peek().Compiler.RecordWarning(n.Bookmark, "use of `with` statement prevents local symbol obfuscation of all containing scopes");
                m_Scopes.Peek().DefaultAccessibility = Accessibility.Public;
                return(true);
            }

            // More evil
            if (n.GetType() == typeof(ast.ExprNodeIdentifier))
            {
                var m = (ast.ExprNodeIdentifier)n;
                if (m.Lhs == null && m.Name == "eval")
                {
                    m_Scopes.Peek().Compiler.RecordWarning(n.Bookmark, "use of `eval` prevents local symbol obfuscation of all containing scopes");
                    m_Scopes.Peek().DefaultAccessibility = Accessibility.Public;
                }
                return(true);
            }

            // Private member declaration?
            if (n.GetType() == typeof(ast.StatementAccessibility))
            {
                var p = (ast.StatementAccessibility)n;
                foreach (var s in p.Specs)
                {
                    m_Scopes.Peek().AddAccessibilitySpec(p.Bookmark, s);
                }
            }

            // Try to guess name of function by assignment in variable declaration
            var decl = n as ast.StatementVariableDeclaration;

            if (decl != null)
            {
                foreach (var i in decl.Variables)
                {
                    if (i.InitialValue != null)
                    {
                        var fn = i.InitialValue.RootNode as ast.ExprNodeFunction;
                        if (fn != null)
                        {
                            fn.AssignedToName = i.Name;
                        }
                    }
                }
            }

            // Try to guess name of function by assignment
            var assignment = n as ast.ExprNodeAssignment;

            if (assignment != null)
            {
                var fn = assignment.Rhs as ast.ExprNodeFunction;
                if (fn != null)
                {
                    var id = assignment.Lhs as ast.ExprNodeIdentifier;
                    if (id != null)
                    {
                        fn.AssignedToName = id.Name;
                    }
                }
            }

            // Try to guess name of function in object literal
            var objLiteral = n as ast.ExprNodeObjectLiteral;

            if (objLiteral != null)
            {
                foreach (var i in objLiteral.Values)
                {
                    var fn = i.Value as ast.ExprNodeFunction;
                    if (fn != null)
                    {
                        var id = i.Key as ast.ExprNodeIdentifier;
                        if (id != null)
                        {
                            fn.AssignedToName = id.Name;
                        }
                    }
                }
            }

            return(true);
        }
Example #16
0
 // Constructor
 public VisitorSymbolDeclaration(SymbolScope rootScope, SymbolScope rootPseudoScope)
 {
     currentScope = rootScope;
     currentPseudoScope = rootPseudoScope;
 }
Example #17
0
        public bool OnEnterNode(MiniME.ast.Node n)
        {
            // Define name of function in outer scope, before descending
            if (n.GetType() == typeof(ast.ExprNodeFunction))
            {
                var fn = (ast.ExprNodeFunction)n;

                // Define a symbol for the new function
                if (!String.IsNullOrEmpty(fn.Name))
                {
                    DefineLocalSymbol(fn.Name, fn.Bookmark);
                    currentScope.ProcessAccessibilitySpecs(fn.Name, fn.Bookmark);
                }
            }

            // Descending into an inner scope
            if (n.Scope != null)
            {
                System.Diagnostics.Debug.Assert(n.Scope.OuterScope == currentScope);
                currentScope = n.Scope;
            }

            // Descending into an inner pseudo scope
            if (n.PseudoScope != null)
            {
                System.Diagnostics.Debug.Assert(n.PseudoScope.OuterScope == currentPseudoScope);
                currentPseudoScope = n.PseudoScope;
            }

            // Define catch clause exception variables in the inner scope
            if (n.GetType() == typeof(ast.CatchClause))
            {
                var cc = (ast.CatchClause)n;
                DefineLocalSymbol(cc.ExceptionVariable, n.Bookmark);
                return true;
            }

            // Define variables in the current scope
            if (n.GetType() == typeof(ast.StatementVariableDeclaration))
            {
                var vardecl = (ast.StatementVariableDeclaration)n;
                foreach (var v in vardecl.Variables)
                {
                    DefineLocalSymbol(v.Name, v.Bookmark);
                    currentScope.ProcessAccessibilitySpecs(v.Name, v.Bookmark);

                    if (v.InitialValue!=null && v.InitialValue.RootNode.GetType()==typeof(ast.ExprNodeObjectLiteral))
                    {
                        // Get the object literal
                        var literal=(ast.ExprNodeObjectLiteral)v.InitialValue.RootNode;

                        // Create a fake/temp identifier node while we process accessibility specs
                        var target = new ast.ExprNodeIdentifier(null, v.Name);

                        // Process all keys that are identifiers
                        foreach (var x in literal.Values)
                        {
                            var identifierKey=x.Key as ast.ExprNodeIdentifier;
                            if (identifierKey!=null && identifierKey.Lhs==null)
                            {
                                currentScope.ProcessAccessibilitySpecs(target, identifierKey.Name, identifierKey.Bookmark);
                            }
                        }
                    }
                }

                return true;
            }

            // Define parameters in the current scope
            if (n.GetType() == typeof(ast.Parameter))
            {
                var p = (ast.Parameter)n;
                DefineLocalSymbol(p.Name, p.Bookmark);
                currentScope.ProcessAccessibilitySpecs(p.Name, p.Bookmark);
                return true;
            }

            // Automatic declaration of private member?
            // We're looking for an assignment to a matching private spec
            if (n.GetType() == typeof(ast.StatementExpression))
            {
                var exprstmt = (ast.StatementExpression)n;
                if (exprstmt.Expression.RootNode.GetType()==typeof(ast.ExprNodeAssignment))
                {
                    var assignOp = (ast.ExprNodeAssignment)exprstmt.Expression.RootNode;
                    if (assignOp.Op == Token.assign)
                    {
                        // Lhs must be an identifier member
                        // eg: target.member=<expr>
                        if (assignOp.Lhs.GetType()==typeof(ast.ExprNodeIdentifier))
                        {
                            var identifier=(ast.ExprNodeIdentifier)assignOp.Lhs;
                            if (identifier.Lhs!=null)
                            {
                                // For member specs, the identifier must have a lhs
                                if (identifier.Lhs.GetType() != typeof(ast.ExprNodeIdentifier))
                                    return false;

                                currentScope.ProcessAccessibilitySpecs((ast.ExprNodeIdentifier)identifier.Lhs, identifier.Name, identifier.Bookmark);
                            }
                        }

                        // Assignment of an object literal
                        // eg: target={member:value,member:value};
                        if (assignOp.Lhs.GetType() == typeof(ast.ExprNodeIdentifier) &&
                            assignOp.Rhs.GetType() == typeof(ast.ExprNodeObjectLiteral))
                        {
                            var target = (ast.ExprNodeIdentifier)assignOp.Lhs;
                            var literal=(ast.ExprNodeObjectLiteral)assignOp.Rhs;

                            if (target.Lhs == null)
                            {
                                foreach (var x in literal.Values)
                                {
                                    var identifierKey=x.Key as ast.ExprNodeIdentifier;
                                    if (identifierKey!=null && identifierKey.Lhs==null)
                                    {
                                        currentScope.ProcessAccessibilitySpecs(target, identifierKey.Name, identifierKey.Bookmark);
                                    }
                                }

                            }
                        }
                        /*
                        if (assignOp.Rhs.GetType() == typeof(ast.ExprNodeObjectLiteral))
                        {
                            var literal=ast.ExprNode
                        }
                         */
                    }
                }
            }

            // Normally accessibility specs are already processed in the scope builder, but this
            // is a special case for declaring external symbols.  We need to pick up the explicit
            // symbol declaration and add it to the pseudo scope to avoid incorrect warnings.
            // Use case is declaring `x` as an external global var by:
            //
            //			// public:x
            //
            if (n.GetType() == typeof(ast.StatementAccessibility))
            {
                var p = (ast.StatementAccessibility)n;
                foreach (var s in p.Specs)
                {
                    if (!s.IsWildcard() && !s.IsMemberSpec())
                        currentPseudoScope.Symbols.DefineSymbol(s.GetExplicitName(), n.Bookmark);
                }
            }
            return true;
        }
Example #18
0
 public void LeaveScope()
 {
     m_SymbolAllocator.LeaveScope();
     m_MemberAllocator.LeaveScope();
     m_CurrentScope = m_CurrentScope.OuterScope;
 }
Example #19
0
 // Constructor
 public VisitorSymbolUsage(SymbolScope rootScope)
 {
     currentScope = rootScope;
 }
Example #20
0
        /// <summary>
        /// Parses all loaded scripts as javascript and compiles them to a string.
        /// </summary>
        /// <returns>A string containing the minified javascript.</returns>
        public string CompileJavascriptToString()
        {
            // Create a symbol allocator
            SymbolAllocator SymbolAllocator = new SymbolAllocator(this);

            // Don't let the symbol allocator use any reserved words or common Javascript bits
            // We only go up to three letters - symbol allocation of more than 3 letters is
            // highly unlikely.
            // (based on list here: http://www.quackit.com/javascript/javascript_reserved_words.cfm)
            string[] words = new string[] { "if", "in", "do", "for", "new", "var", "int", "try", "NaN", "ref", "sun", "top" };
            foreach (var s in words)
            {
                SymbolAllocator.ClaimSymbol(s);
            }

            // Create a member allocator
            SymbolAllocator MemberAllocator = new SymbolAllocator(this);

            // Render
            RenderContext r = new RenderContext(this, SymbolAllocator, MemberAllocator);

            // Process all files
            bool bNeedSemicolon = false;
            foreach (var file in m_files)
            {
                Console.WriteLine("Processing {0}...", System.IO.Path.GetFileName(file.filename));

                // Create a tokenizer and parser
                Warnings = new List<Warning>();
                WarningsEnabledStack = new Stack<bool>();
                Tokenizer t = new Tokenizer(this, file.content, file.filename, file.warnings);
                Parser p = new Parser(t);

                // Create the global statement block
                var code = new ast.CodeBlock(null, TriState.No);

                // Parse the file into a namespace
                p.ParseStatements(code);

                // Ensure everything processed
                if (t.more)
                {
                    throw new CompileError("Unexpected end of file", t);
                }

                // Dump the abstract syntax tree
                if (DumpAST)
                    code.Dump(0);

                // Create the root symbol scope and build scopes for all
                // constained function scopes
                SymbolScope rootScope = new SymbolScope(this, null, Accessibility.Public);
                SymbolScope rootPseudoScope = new SymbolScope(this, null, Accessibility.Public);
                code.Visit(new VisitorScopeBuilder(rootScope, rootPseudoScope));

                // Combine consecutive var declarations into a single one
                code.Visit(new VisitorCombineVarDecl(rootScope));

                // Find all variable declarations
                code.Visit(new VisitorSymbolDeclaration(rootScope, rootPseudoScope));

                // Do lint stuff
                code.Visit(new VisitorLint(rootScope, rootPseudoScope));

                // Try to eliminate const declarations
                if (DetectConsts && !NoObfuscate)
                {
                    code.Visit(new VisitorConstDetectorPass1(rootScope));
                    code.Visit(new VisitorConstDetectorPass2(rootScope));
                    code.Visit(new VisitorConstDetectorPass3(rootScope));
                }

                // Simplify expressions
                code.Visit(new VisitorSimplifyExpressions());

                // If obfuscation is allowed, find all in-scope symbols and then
                // count the frequency of their use.
                if (!NoObfuscate)
                {
                    code.Visit(new VisitorSymbolUsage(rootScope));
                }

                // Process all symbol scopes, applying default accessibility levels
                // and determining the "rank" of each symbol
                rootScope.Prepare();

                // Dump scopes to stdout
                if (DumpScopes)
                    rootScope.Dump(0);

                // Tell the global scope to claim all locally defined symbols
                // so they're not re-used (and therefore hidden) by the
                // symbol allocation
                rootScope.ClaimSymbols(SymbolAllocator);

                // Create a credit comment on the first file
                if (!NoCredit && file==m_files[0])
                {
                    int iInsertPos = 0;
                    while (iInsertPos < code.Content.Count && code.Content[iInsertPos].GetType() == typeof(ast.StatementComment))
                        iInsertPos++;
                    code.Content.Insert(iInsertPos, new ast.StatementComment(null, "// Minified by MiniME from toptensoftware.com"));
                }

                if (bNeedSemicolon)
                {
                    r.Append(";");
                }

                // Render it
                r.EnterScope(rootScope);
                bNeedSemicolon=code.Render(r);
                r.LeaveScope();

                // Display warnings
                Warnings.Sort(delegate(Warning w1, Warning w2)
                {
                    int Compare = w1.Order.file.FileName.CompareTo(w2.Order.file.FileName);
                    if (Compare == 0)
                        Compare = w1.Order.position - w2.Order.position;
                    if (Compare == 0)
                        Compare = w1.OriginalOrder - w2.OriginalOrder;
                    return Compare;
                });
                foreach (var w in Warnings)
                {
                    Console.WriteLine("{0}: {1}", w.Bookmark, w.Message);
                }

            }

            // return the final script
            string strResult = r.GetGeneratedOutput();
            return strResult;
        }
Example #21
0
        public bool OnEnterNode(MiniME.ast.Node n)
        {
            // Descending into an inner scope
            if (n.Scope != null)
            {
                System.Diagnostics.Debug.Assert(n.Scope.OuterScope == currentScope);
                currentScope = n.Scope;
            }

            // Is it a variable declaration
            if (n.GetType() == typeof(ast.StatementVariableDeclaration))
            {
                var vardecl = (ast.StatementVariableDeclaration)n;

                for (int i = vardecl.Variables.Count - 1; i >= 0; i-- )
                {
                    var v = vardecl.Variables[i];

                    // Find the symbol (must exist in current scope)
                    var s = currentScope.Symbols.FindLocalSymbol(v.Name);
                    System.Diagnostics.Debug.Assert(s != null);

                    // Is it a const?
                    if (s.ConstValue != null)
                    {
                        // Yes!  Remove it
                        vardecl.Variables.RemoveAt(i);
                    }
                }
            }

            return true;
        }
Example #22
0
 // Constructor
 public VisitorSymbolUsage(SymbolScope rootScope)
 {
     currentScope = rootScope;
 }
Example #23
0
        public bool OnEnterNode(MiniME.ast.Node n)
        {
            // Define name of function in outer scope, before descending
            if (n.GetType() == typeof(ast.ExprNodeFunction))
            {
                var fn = (ast.ExprNodeFunction)n;

                // Define a symbol for the new function
                if (!String.IsNullOrEmpty(fn.Name))
                {
                    currentScope.Symbols.UseSymbol(fn.Name);
                }
            }

            // Descending into an inner scope
            if (n.Scope != null)
            {
                System.Diagnostics.Debug.Assert(n.Scope.OuterScope == currentScope);
                currentScope = n.Scope;
            }

            // Identifier?
            if (n.GetType() == typeof(ast.ExprNodeIdentifier))
            {
                var m = (ast.ExprNodeIdentifier)n;
                if (m.Lhs == null)
                {
                    currentScope.Symbols.UseSymbol(m.Name);
                }
                else
                {
                    currentScope.Members.UseSymbol(m.Name);
                }
            }

            // Use catch clause exception variables in the inner scope
            if (n.GetType() == typeof(ast.CatchClause))
            {
                var cc = (ast.CatchClause)n;
                currentScope.Symbols.UseSymbol(cc.ExceptionVariable);
                return true;
            }

            // Use variables in the current scope
            if (n.GetType() == typeof(ast.StatementVariableDeclaration))
            {
                var vardecl = (ast.StatementVariableDeclaration)n;
                foreach (var v in vardecl.Variables)
                {
                    currentScope.Symbols.UseSymbol(v.Name);
                }
                return true;
            }

            // Use parameters in the current scope
            if (n.GetType() == typeof(ast.Parameter))
            {
                var p = (ast.Parameter)n;
                currentScope.Symbols.UseSymbol(p.Name);
                return true;
            }

            // Look for assignment to undefined variable
            if (n.GetType() == typeof(ast.ExprNodeAssignment))
            {
                var rtlOp = (ast.ExprNodeAssignment)n;
                if (rtlOp.Op == Token.assign)
                {
                    if (rtlOp.Lhs.GetType() == typeof(ast.ExprNodeIdentifier))
                    {
                        var identifier = (ast.ExprNodeIdentifier)rtlOp.Lhs;
                        if (identifier.Lhs == null)
                        {
                            // Assignment to an identifier
                            if (currentScope.FindSymbol(identifier.Name) == null)
                            {
                                currentScope.Compiler.RecordWarning(identifier.Bookmark, "assignment to undeclared variable `{0}` introduces new global variable", identifier.Name);
                            }
                        }
                    }
                }
            }

            return true;
        }
Example #24
0
        // Compile all loaded script to a string
        public string CompileJavascriptToString()
        {
            // Create a symbol allocator
            SymbolAllocator SymbolAllocator = new SymbolAllocator(this);

            // Don't let the symbol allocator use any reserved words or common Javascript bits
            // We only go up to three letters - symbol allocation of more than 3 letters is
            // highly unlikely.
            // (based on list here: http://www.quackit.com/javascript/javascript_reserved_words.cfm)
            string[] words = new string[] { "if", "in", "do", "for", "new", "var", "int", "try", "NaN", "ref", "sun", "top" };
            foreach (var s in words)
            {
                SymbolAllocator.ClaimSymbol(s);
            }

            // Create a member allocator
            SymbolAllocator MemberAllocator = new SymbolAllocator(this);

            // Render
            RenderContext r = new RenderContext(this, SymbolAllocator, MemberAllocator);

            // Process all files
            bool bNeedSemicolon = false;

            foreach (var file in m_files)
            {
                Console.WriteLine("Processing {0}...", System.IO.Path.GetFileName(file.filename));

                // Create a tokenizer and parser
                Warnings             = new List <Warning>();
                WarningsEnabledStack = new Stack <bool>();
                Tokenizer t = new Tokenizer(this, file.content, file.filename, file.warnings);
                Parser    p = new Parser(t);

                // Create the global statement block
                var code = new ast.CodeBlock(null, TriState.No);

                // Parse the file into a namespace
                p.ParseStatements(code);

                // Ensure everything processed
                if (t.more)
                {
                    throw new CompileError("Unexpected end of file", t);
                }


                // Dump the abstract syntax tree
                if (DumpAST)
                {
                    code.Dump(0);
                }

                // Create the root symbol scope and build scopes for all
                // constained function scopes
                SymbolScope rootScope       = new SymbolScope(this, null, Accessibility.Public);
                SymbolScope rootPseudoScope = new SymbolScope(this, null, Accessibility.Public);
                code.Visit(new VisitorScopeBuilder(rootScope, rootPseudoScope));

                // Combine consecutive var declarations into a single one
                code.Visit(new VisitorCombineVarDecl(rootScope));

                // Find all variable declarations
                code.Visit(new VisitorSymbolDeclaration(rootScope, rootPseudoScope));

                // Do lint stuff
                code.Visit(new VisitorLint(rootScope, rootPseudoScope));

                // Try to eliminate const declarations
                if (DetectConsts && !NoObfuscate)
                {
                    code.Visit(new VisitorConstDetectorPass1(rootScope));
                    code.Visit(new VisitorConstDetectorPass2(rootScope));
                    code.Visit(new VisitorConstDetectorPass3(rootScope));
                }

                // Simplify expressions
                code.Visit(new VisitorSimplifyExpressions());

                // If obfuscation is allowed, find all in-scope symbols and then
                // count the frequency of their use.
                if (!NoObfuscate)
                {
                    code.Visit(new VisitorSymbolUsage(rootScope));
                }

                // Process all symbol scopes, applying default accessibility levels
                // and determining the "rank" of each symbol
                rootScope.Prepare();

                // Dump scopes to stdout
                if (DumpScopes)
                {
                    rootScope.Dump(0);
                }

                // Tell the global scope to claim all locally defined symbols
                // so they're not re-used (and therefore hidden) by the
                // symbol allocation
                rootScope.ClaimSymbols(SymbolAllocator);

                // Create a credit comment on the first file
                if (!NoCredit && file == m_files[0])
                {
                    int iInsertPos = 0;
                    while (iInsertPos < code.Content.Count && code.Content[iInsertPos].GetType() == typeof(ast.StatementComment))
                    {
                        iInsertPos++;
                    }
                    code.Content.Insert(iInsertPos, new ast.StatementComment(null, "// Minified by MiniME from toptensoftware.com"));
                }

                if (bNeedSemicolon)
                {
                    r.Append(";");
                }

                // Render it
                r.EnterScope(rootScope);
                bNeedSemicolon = code.Render(r);
                r.LeaveScope();

                // Display warnings
                Warnings.Sort(delegate(Warning w1, Warning w2)
                {
                    int Compare = w1.Order.file.FileName.CompareTo(w2.Order.file.FileName);
                    if (Compare == 0)
                    {
                        Compare = w1.Order.position - w2.Order.position;
                    }
                    if (Compare == 0)
                    {
                        Compare = w1.OriginalOrder - w2.OriginalOrder;
                    }
                    return(Compare);
                });
                foreach (var w in Warnings)
                {
                    Console.WriteLine("{0}: {1}", w.Bookmark, w.Message);
                }
            }

            // return the final script
            string strResult = r.GetGeneratedOutput();

            return(strResult);
        }
Example #25
0
 public VisitorCombineVarDecl(SymbolScope rootScope)
 {
 }
Example #26
0
 // Constructor
 public VisitorScopeBuilder(SymbolScope rootScope, SymbolScope rootPseudoScope)
 {
     m_Scopes.Push(rootScope);
     m_PseudoScopes.Push(rootPseudoScope);
 }