Example #1
0
        public static bool Analyze(JsStatement statement)
        {
            var obj = new UsesThisVisitor();

            obj.VisitStatement(statement, null);
            return(obj._result);
        }
        public static bool Analyze(JsExpression expression)
        {
            var obj = new UsesThisVisitor();

            obj.VisitExpression(expression, null);
            return(obj._result);
        }
        private JsBlockStatement ProcessAsyncMethod(JsBlockStatement statement, string stateMachineMethodName, string doFinallyBlocksVariableName, JsVariableDeclaration taskCompletionSource, Func <JsExpression, JsExpression> makeSetResult, Func <JsExpression, JsExpression> makeSetException, Func <JsExpression> getTask, Func <JsExpression, JsExpression, JsExpression> bindToContext)
        {
            _stateMachineMethodName      = stateMachineMethodName;
            _doFinallyBlocksVariableName = doFinallyBlocksVariableName;
            _makeSetResult = taskCompletionSource != null ? makeSetResult : null;
            _needDoFinallyBlocksVariable = new HasAwaitInsideTryWithFinallyVisitor().Analyze(statement);

            var result      = Process(statement, isIteratorBlock: false, isAsync: true);
            var hoistResult = VariableHoistingVisitor.Process(result);

            string catchVariable = _allocateTempVariable();

            JsStatement body;

            if (taskCompletionSource != null && (statement.Statements.Count == 0 || IsNextStatementReachable(statement.Statements[statement.Statements.Count - 1])))                    // If we return the task, and if we risk falling out of the original method, we need to add a setResult call.
            {
                body = JsStatement.Block(hoistResult.Item1.Statements.Concat(new JsStatement[] { makeSetResult(null) }));
            }
            else
            {
                body = hoistResult.Item1;
            }

            if (taskCompletionSource != null)
            {
                body = JsStatement.Try(body, JsStatement.Catch(catchVariable, JsStatement.Block(makeSetException(JsExpression.Identifier(catchVariable)))), null);
            }

            IEnumerable <JsVariableDeclaration> declarations = new[] { JsStatement.Declaration(_stateVariableName, JsExpression.Number(0)) };

            if (taskCompletionSource != null)
            {
                declarations = declarations.Concat(new[] { taskCompletionSource });
            }
            declarations = declarations.Concat(hoistResult.Item2.Select(v => JsStatement.Declaration(v, null)));

            if (_needDoFinallyBlocksVariable)
            {
                body = JsStatement.Block(new[] { JsStatement.Var(_doFinallyBlocksVariableName, JsExpression.True) }.Concat(body is JsBlockStatement ? ((JsBlockStatement)body).Statements : (IEnumerable <JsStatement>) new[] { body }));
            }

            var stateMachine      = JsExpression.FunctionDefinition(new string[0], body);
            var boundStateMachine = UsesThisVisitor.Analyze(stateMachine.Body) ? bindToContext(stateMachine, JsExpression.This) : stateMachine;

            IEnumerable <JsStatement> stmts = new JsStatement[] { JsStatement.Var(declarations),
                                                                  JsStatement.Var(stateMachineMethodName, boundStateMachine),
                                                                  JsExpression.Invocation(JsExpression.Identifier(stateMachineMethodName)) };

            if (taskCompletionSource != null)
            {
                stmts = stmts.Concat(new[] { JsStatement.Return(getTask()) });
            }

            return(JsStatement.Block(stmts));
        }