public static void Apply(JsBlock block, JsParser parser)
        {
            // create a new instance of the visitor and apply it to the block
            var visitor = new JsReorderScopeVisitor(parser);

            block.Accept(visitor);

            // if there were any module directive prologues we need to promote, do them first
            var insertAt = 0;

            if (visitor.m_moduleDirectives != null)
            {
                foreach (var directivePrologue in visitor.m_moduleDirectives)
                {
                    insertAt = RelocateDirectivePrologue(block, insertAt, directivePrologue);
                }
            }

            // Make sure that we skip over any remaining comments and directive prologues.
            // we do NOT want to insert anything between the start of the scope and any directive prologues.
            while (insertAt < block.Count &&
                   (block[insertAt] is JsDirectivePrologue || block[insertAt] is JsImportantComment))
            {
                ++insertAt;
            }

            // first, we want to move all function declarations to the top of this block
            if (visitor.m_functionDeclarations != null)
            {
                foreach (var funcDecl in visitor.m_functionDeclarations)
                {
                    insertAt = RelocateFunction(block, insertAt, funcDecl);
                }
            }

            // special case: if there is only one var statement in the entire scope,
            // then just leave it alone because we will only add bytes by moving it around,
            // or be byte-neutral at best (no initializers and not in a for-statement).
            if (visitor.m_varStatements != null && visitor.m_varStatements.Count > 1)
            {
                // then we want to move all variable declarations after to the top (after the functions)
                foreach (var varStatement in visitor.m_varStatements)
                {
                    insertAt = RelocateVar(block, insertAt, varStatement);
                }
            }

            // then we want to do the same thing for all child functions (declarations AND other)
            if (visitor.m_functionDeclarations != null)
            {
                foreach (var funcDecl in visitor.m_functionDeclarations)
                {
                    Apply(funcDecl.Body, parser);
                }
            }

            if (visitor.m_functionExpressions != null)
            {
                foreach (var funcExpr in visitor.m_functionExpressions)
                {
                    Apply(funcExpr.Body, parser);
                }
            }
        }
        public static void Apply(JsBlock block, JsParser parser)
        {
            // create a new instance of the visitor and apply it to the block
            var visitor = new JsReorderScopeVisitor(parser);
            block.Accept(visitor);

            // if there were any module directive prologues we need to promote, do them first
            var insertAt = 0;
            if (visitor.m_moduleDirectives != null)
            {
                foreach (var directivePrologue in visitor.m_moduleDirectives)
                {
                    insertAt = RelocateDirectivePrologue(block, insertAt, directivePrologue);
                }
            }

            // Make sure that we skip over any remaining comments and directive prologues.
            // we do NOT want to insert anything between the start of the scope and any directive prologues.
            while (insertAt < block.Count
                && (block[insertAt] is JsDirectivePrologue || block[insertAt] is JsImportantComment))
            {
                ++insertAt;
            }

            // first, we want to move all function declarations to the top of this block
            if (visitor.m_functionDeclarations != null)
            {
                foreach (var funcDecl in visitor.m_functionDeclarations)
                {
                    insertAt = RelocateFunction(block, insertAt, funcDecl);
                }
            }

            // special case: if there is only one var statement in the entire scope,
            // then just leave it alone because we will only add bytes by moving it around,
            // or be byte-neutral at best (no initializers and not in a for-statement).
            if (visitor.m_varStatements != null && visitor.m_varStatements.Count > 1)
            {
                // then we want to move all variable declarations after to the top (after the functions)
                foreach (var varStatement in visitor.m_varStatements)
                {
                    insertAt = RelocateVar(block, insertAt, varStatement);
                }
            }

            // then we want to do the same thing for all child functions (declarations AND other)
            if (visitor.m_functionDeclarations != null)
            {
                foreach (var funcDecl in visitor.m_functionDeclarations)
                {
                    Apply(funcDecl.Body, parser);
                }
            }

            if (visitor.m_functionExpressions != null)
            {
                foreach (var funcExpr in visitor.m_functionExpressions)
                {
                    Apply(funcExpr.Body, parser);
                }
            }
        }