Ejemplo n.º 1
0
        public JsStatement VisitGotoStateStatement(JsGotoStateStatement statement, object data)
        {
            var   result = new List <JsStatement>();
            State targetState;

            if (statement.TargetState == null)
            {
                if (!_labelStates.TryGetValue(statement.TargetLabel, out targetState))
                {
                    throw new InvalidOperationException("The label " + statement.TargetLabel + " does not exist.");
                }
            }
            else
            {
                targetState = statement.TargetState.Value;
            }

            var remaining = statement.CurrentState.FinallyStack;

            for (int i = 0, n = remaining.Count() - targetState.FinallyStack.Count(); i < n; i++)
            {
                var current = remaining.Peek();
                remaining = remaining.Pop();
                result.Add(new JsExpressionStatement(JsExpression.Assign(JsExpression.Identifier(_stateVariableName), JsExpression.Number(remaining.IsEmpty ? -1 : remaining.Peek().Item1))));
                result.Add(new JsExpressionStatement(JsExpression.Invocation(JsExpression.Member(JsExpression.Identifier(current.Item2), "call"), JsExpression.This)));
            }

            result.Add(MakeSetNextStateStatement(targetState.StateValue));
            result.Add(targetState.StateValue == -1 ? (JsStatement) new JsBreakStatement(targetState.LoopLabelName) : new JsContinueStatement(targetState.LoopLabelName));
            return(new JsBlockStatement(result, mergeWithParent: true));
        }
 public void FunctionIsParenthesizedWhenInvokedDirectly()
 {
     AssertCorrect(JsExpression.Invocation(
                       JsExpression.FunctionDefinition(new string[0], JsBlockStatement.EmptyStatement, null)
                       ),
                   "(function() {\r\n})()");
 }
Ejemplo n.º 3
0
        private JsExpression GetScriptType(IType type, TypeContext context, Func <ITypeParameter, JsExpression> resolveTypeParameter)
        {
            string contextName = GetTypeContextShortName(context);

            if (type is ParameterizedType)
            {
                var pt = (ParameterizedType)type;
                return(JsExpression.Invocation(JsExpression.Identifier(contextName + "_$InstantiateGenericType"), new[] { new JsTypeReferenceExpression(Common.CreateMockTypeDefinition(type.Name, Common.CreateMockAssembly())) }.Concat(pt.TypeArguments.Select(a => GetScriptType(a, TypeContext.GenericArgument, resolveTypeParameter)))));
            }
            else if (type.TypeParameterCount > 0)
            {
                // This handles open generic types ( typeof(C<,>) )
                return(new JsTypeReferenceExpression(Common.CreateMockTypeDefinition(contextName + "_" + type.GetDefinition().Name, Common.CreateMockAssembly())));
            }
            else if (type.Kind == TypeKind.Array)
            {
                return(JsExpression.Invocation(JsExpression.Identifier(contextName + "_$Array"), GetScriptType(((ArrayType)type).ElementType, TypeContext.GenericArgument, resolveTypeParameter)));
            }
            else if (type.Kind == TypeKind.Anonymous)
            {
                return(JsExpression.Identifier(contextName + "_$Anonymous"));
            }
            else if (type is ITypeDefinition)
            {
                return(new JsTypeReferenceExpression(Common.CreateMockTypeDefinition(contextName + "_" + type.Name, Common.CreateMockAssembly())));
            }
            else if (type is ITypeParameter)
            {
                return(resolveTypeParameter((ITypeParameter)type));
            }
            else
            {
                throw new ArgumentException("Unsupported type + " + type);
            }
        }
Ejemplo n.º 4
0
        private JsExpression CreateInitEnumCall(JsEnum type, string ctorName)
        {
            var values = new List <JsObjectLiteralProperty>();

            foreach (var v in type.CSharpTypeDefinition.Fields)
            {
                if (v.ConstantValue != null)
                {
                    var sem = _metadataImporter.GetFieldSemantics(v);
                    if (sem.Type == FieldScriptSemantics.ImplType.Field)
                    {
                        values.Add(new JsObjectLiteralProperty(sem.Name, JsExpression.Number(Convert.ToDouble(v.ConstantValue))));
                    }
                    else if (sem.Type == FieldScriptSemantics.ImplType.Constant && sem.Name != null)
                    {
                        values.Add(new JsObjectLiteralProperty(sem.Name, sem.Value is string?JsExpression.String((string)sem.Value) : JsExpression.Number(Convert.ToDouble(sem.Value))));
                    }
                }
                else
                {
                    _errorReporter.Region = v.Region;
                    _errorReporter.InternalError("Enum field " + v.FullName + " is not constant.");
                }
            }

            var args = new List <JsExpression> {
                JsExpression.Identifier(ctorName), _linker.CurrentAssemblyExpression, JsExpression.ObjectLiteral(values)
            };

            if (MetadataUtils.IsNamedValues(type.CSharpTypeDefinition, _attributeStore))
            {
                args.Add(JsExpression.True);
            }
            return(JsExpression.Invocation(JsExpression.Member(_systemScript, InitEnum), args));
        }
        private JsExpression CreateDefaultConstructorInvocation(IMethod defaultConstructor, JsExpression typeRef)
        {
            var sem = _metadataImporter.GetConstructorSemantics(defaultConstructor);

            switch (sem.Type)
            {
            case ConstructorScriptSemantics.ImplType.UnnamedConstructor:                      // default behavior is good enough.
            case ConstructorScriptSemantics.ImplType.NotUsableFromScript:                     // Can't be invoked so we don't need to create it.
                return(null);

            case ConstructorScriptSemantics.ImplType.NamedConstructor:
                return(JsExpression.New(JsExpression.Member(typeRef, sem.Name)));

            case ConstructorScriptSemantics.ImplType.StaticMethod:
                return(JsExpression.Invocation(JsExpression.Member(typeRef, sem.Name)));

            case ConstructorScriptSemantics.ImplType.InlineCode:
                var prevRegion = _errorReporter.Region;
                try {
                    _errorReporter.Region = defaultConstructor.Region;
                    return(InlineCodeMethodCompiler.CompileInlineCodeMethodInvocation(defaultConstructor, sem.LiteralCode, null, EmptyList <JsExpression> .Instance, r => r.Resolve(_compilation), _runtimeLibrary.GetScriptType, false, s => _errorReporter.Message(7525, s)));
                }
                finally {
                    _errorReporter.Region = prevRegion;
                }

            case ConstructorScriptSemantics.ImplType.Json:
                return(JsExpression.ObjectLiteral());

            default:
                throw new Exception("Invalid constructor implementation type: " + sem.Type);
            }
        }
Ejemplo n.º 6
0
        private JsExpression GenerateStructCloneMethod(ITypeDefinition type, string typevarName, bool hasCreateInstance)
        {
            var stmts = new List <JsStatement>()
            {
                JsStatement.Var("r", hasCreateInstance ? (JsExpression)JsExpression.Invocation(JsExpression.Member(JsExpression.Identifier(typevarName), "createInstance")) : JsExpression.New(JsExpression.Identifier(typevarName)))
            };
            var o = JsExpression.Identifier("o");
            var r = JsExpression.Identifier("r");

            foreach (var f in type.Fields.Where(f => !f.IsStatic))
            {
                var sem = _metadataImporter.GetFieldSemantics(f);
                if (sem.Type == FieldScriptSemantics.ImplType.Field)
                {
                    var          def   = f.ReturnType.GetDefinition();
                    JsExpression value = JsExpression.Member(o, sem.Name);
                    if (def != null && def.Kind == TypeKind.Struct && _metadataImporter.GetTypeSemantics(def).Type == TypeScriptSemantics.ImplType.MutableValueType)
                    {
                        value = _runtimeLibrary.CloneValueType(value, f.ReturnType, new DefaultRuntimeContext(type, _metadataImporter, _errorReporter, _namer));
                    }
                    stmts.Add(JsExpression.Assign(JsExpression.Member(r, sem.Name), value));
                }
            }

            foreach (var p in type.Properties.Where(p => !p.IsStatic))
            {
                var sem = _metadataImporter.GetPropertySemantics(p);

                if ((sem.Type == PropertyScriptSemantics.ImplType.GetAndSetMethods && MetadataUtils.IsAutoProperty(p) == true) || sem.Type == PropertyScriptSemantics.ImplType.Field)
                {
                    var          def       = p.ReturnType.GetDefinition();
                    var          fieldName = sem.Type == PropertyScriptSemantics.ImplType.GetAndSetMethods ? _metadataImporter.GetAutoPropertyBackingFieldName(p) : sem.FieldName;
                    JsExpression value     = JsExpression.Member(o, fieldName);
                    if (def != null && def.Kind == TypeKind.Struct && _metadataImporter.GetTypeSemantics(def).Type == TypeScriptSemantics.ImplType.MutableValueType)
                    {
                        value = _runtimeLibrary.CloneValueType(value, p.ReturnType, new DefaultRuntimeContext(type, _metadataImporter, _errorReporter, _namer));
                    }
                    stmts.Add(JsExpression.Assign(JsExpression.Member(r, fieldName), value));
                }
            }

            foreach (var e in type.Events.Where(e => !e.IsStatic && MetadataUtils.IsAutoEvent(e) == true))
            {
                var sem = _metadataImporter.GetEventSemantics(e);

                if (sem.Type == EventScriptSemantics.ImplType.AddAndRemoveMethods)
                {
                    var          def       = e.ReturnType.GetDefinition();
                    var          fieldName = _metadataImporter.GetAutoEventBackingFieldName(e);
                    JsExpression value     = JsExpression.Member(o, fieldName);
                    if (def != null && def.Kind == TypeKind.Struct && _metadataImporter.GetTypeSemantics(def).Type == TypeScriptSemantics.ImplType.MutableValueType)
                    {
                        value = _runtimeLibrary.CloneValueType(value, e.ReturnType, new DefaultRuntimeContext(type, _metadataImporter, _errorReporter, _namer));
                    }
                    stmts.Add(JsExpression.Assign(JsExpression.Member(r, fieldName), value));
                }
            }
            stmts.Add(JsStatement.Return(r));
            return(JsExpression.FunctionDefinition(new[] { "o" }, JsStatement.Block(stmts)));
        }
        public JsExpression TypeIs(JsExpression expression, IType sourceType, IType targetType, IRuntimeContext context)
        {
            var importedCheck = CompileImportedTypeCheckCode(targetType, ref expression, context, true);

            if (importedCheck != null)
            {
                return(importedCheck);
            }

            var def = targetType.GetDefinition();

            if (def != null && (!MetadataUtils.DoesTypeObeyTypeSystem(def) || (MetadataUtils.IsSerializable(def) && string.IsNullOrEmpty(MetadataUtils.GetSerializableTypeCheckCode(def)))))
            {
                _errorReporter.Message(Messages._7701, targetType.FullName);
                return(JsExpression.Null);
            }

            var jsTarget = GetCastTarget(sourceType, targetType, context);

            if (jsTarget == null || IsSystemObjectReference(jsTarget))
            {
                return(ReferenceNotEquals(expression, JsExpression.Null, context));
            }
            return(JsExpression.Invocation(JsExpression.Member(CreateTypeReferenceExpression(_systemScript), "isInstanceOfType"), expression, jsTarget));
        }
Ejemplo n.º 8
0
        private JsExpression GenerateStructEqualsMethod(ITypeDefinition type, string typeVariableName)
        {
            var o     = JsExpression.Identifier("o");
            var parts = new List <JsExpression>();

            foreach (var f in type.Fields.Where(f => !f.IsStatic))
            {
                var expr = GenerateFieldCompare(f, o);
                if (expr != null)
                {
                    parts.Add(expr);
                }
            }

            JsExpression typeCompare = JsExpression.Invocation(JsExpression.Member(_systemScript, "isInstanceOfType"), o, JsExpression.Identifier(typeVariableName));

            if (parts.Count == 0)
            {
                return(JsExpression.FunctionDefinition(new[] { "o" }, JsStatement.Return(typeCompare)));
            }
            else
            {
                return(JsExpression.FunctionDefinition(new[] { "o" }, JsStatement.Block(
                                                           JsStatement.If(JsExpression.LogicalNot(typeCompare),
                                                                          JsStatement.Return(JsExpression.False),
                                                                          null
                                                                          ),
                                                           JsStatement.Return(parts.Aggregate((old, p) => old == null ? p : JsExpression.LogicalAnd(old, p)))
                                                           )));
            }
        }
        public JsExpression Downcast(JsExpression expression, IType sourceType, IType targetType, IRuntimeContext context)
        {
            if (_omitDowncasts)
            {
                return(expression);
            }

            if (sourceType.Kind == TypeKind.Dynamic && targetType.IsKnownType(KnownTypeCode.Boolean))
            {
                return(JsExpression.LogicalNot(JsExpression.LogicalNot(expression)));
            }

            JsExpression jsTarget = CompileImportedTypeCheckCode(targetType, ref expression, context, false);

            if (jsTarget == null)
            {
                jsTarget = GetCastTarget(sourceType, targetType, context);
            }

            if (jsTarget == null || IsSystemObjectReference(jsTarget))
            {
                return(expression);
            }
            return(JsExpression.Invocation(JsExpression.Member(CreateTypeReferenceExpression(_systemScript), "cast"), expression, jsTarget));
        }
        public JsExpression CallBase(IMethod method, IEnumerable <JsExpression> thisAndArguments, IRuntimeContext context)
        {
            var impl = GetMethodSemantics(method);

            JsExpression jsMethod = JsExpression.Member(JsExpression.Member(GetScriptType(method.DeclaringType, TypeContext.GetScriptType, context), "prototype"), impl.Name);

            if (method is SpecializedMethod && !impl.IgnoreGenericArguments)
            {
                jsMethod = InstantiateGenericMethod(jsMethod, ((SpecializedMethod)method).TypeArguments, context);
            }

            if (impl.ExpandParams)
            {
                var args = thisAndArguments.ToList();
                if (args[args.Count - 1] is JsArrayLiteralExpression)
                {
                    return(JsExpression.Invocation(JsExpression.Member(jsMethod, "call"), args.Take(args.Count - 1).Concat(((JsArrayLiteralExpression)args[args.Count - 1]).Elements)));
                }
                else
                {
                    return(JsExpression.Invocation(JsExpression.Member(jsMethod, "apply"), args[0], args.Count == 2 ? args[1] : JsExpression.Invocation(JsExpression.Member(JsExpression.ArrayLiteral(args.Skip(1).Take(args.Count - 2)), "concat"), args[args.Count - 1])));
                }
            }
            else
            {
                return(JsExpression.Invocation(JsExpression.Member(jsMethod, "call"), thisAndArguments));
            }
        }
        private bool HandleAwaitStatement(JsAwaitStatement stmt, StackEntry location, ImmutableStack <StackEntry> stack, ImmutableStack <Tuple <string, State> > breakStack, ImmutableStack <Tuple <string, State> > continueStack, State currentState, State returnState, IList <JsStatement> currentBlock)
        {
            var  stateAfter       = GetStateAfterStatement(location, stack, currentState.FinallyStack, returnState).Item1;
            bool createDummyState = false;

            if (stateAfter.StateValue == returnState.StateValue)
            {
                stateAfter       = CreateNewStateValue(currentState.FinallyStack);
                createDummyState = true;                        // We must never return to our parent state after an await because
            }

            currentBlock.Add(new JsSetNextStateStatement(stateAfter.StateValue));
            currentBlock.Add(JsExpression.Invocation(JsExpression.Member(stmt.Awaiter, stmt.OnCompletedMethodName), JsExpression.Identifier(_stateMachineMethodName)));
            if (_needDoFinallyBlocksVariable)
            {
                currentBlock.Add(JsExpression.Assign(JsExpression.Identifier(_doFinallyBlocksVariableName), JsExpression.False));
            }
            currentBlock.Add(JsStatement.Return());

            if (!stack.IsEmpty || location.Index < location.Block.Statements.Count - 1)
            {
                Enqueue(PushFollowing(stack, location), breakStack, continueStack, stateAfter, returnState);
            }
            if (createDummyState)
            {
                Enqueue(ImmutableStack <StackEntry> .Empty.Push(new StackEntry(JsStatement.Block(JsStatement.BlockMerged(new JsStatement[0])), 0)), breakStack, continueStack, stateAfter, returnState);
            }

            return(false);
        }
        protected void AssertCorrect(string orig, string expected, MethodType methodType = MethodType.Normal)
        {
            int tempIndex = 0, stateIndex = 0, loopLabelIndex = 0;
            var stmt = JsBlockStatement.MakeBlock(JavaScriptParser.Parser.ParseStatement(orig));
            JsBlockStatement result;

            if (methodType == MethodType.Iterator)
            {
                int finallyHandlerIndex = 0;
                result = StateMachineRewriter.RewriteIteratorBlock(stmt, e => e.NodeType != ExpressionNodeType.Identifier, () => "$tmp" + (++tempIndex).ToString(CultureInfo.InvariantCulture), () => "$state" + (++stateIndex).ToString(CultureInfo.InvariantCulture), () => string.Format("$loop" + (++loopLabelIndex).ToString(CultureInfo.InvariantCulture)), () => string.Format("$finally" + (++finallyHandlerIndex).ToString(CultureInfo.InvariantCulture)), v => JsExpression.Invocation(JsExpression.Identifier("setCurrent"), v), sm => {
                    var body = new List <JsStatement>();
                    if (sm.Variables.Count > 0)
                    {
                        body.Add(new JsVariableDeclarationStatement(sm.Variables));
                    }
                    body.AddRange(sm.FinallyHandlers.Select(h => new JsExpressionStatement(JsExpression.Assign(JsExpression.Identifier(h.Item1), h.Item2))));
                    if (sm.Disposer != null)
                    {
                        body.Add(new JsExpressionStatement(JsExpression.Assign(JsExpression.Identifier("dispose"), new JsFunctionDefinitionExpression(new string[0], sm.Disposer))));
                    }
                    body.Add(sm.MainBlock);
                    return(new JsBlockStatement(body));
                });
            }
            else if (methodType == MethodType.AsyncTask || methodType == MethodType.AsyncVoid)
            {
                result = StateMachineRewriter.RewriteAsyncMethod(stmt,
                                                                 e => e.NodeType != ExpressionNodeType.Identifier,
                                                                 () => "$tmp" + (++tempIndex).ToString(CultureInfo.InvariantCulture),
                                                                 () => "$state" + (++stateIndex).ToString(CultureInfo.InvariantCulture),
                                                                 () => string.Format("$loop" + (++loopLabelIndex).ToString(CultureInfo.InvariantCulture)),
                                                                 "$sm",
                                                                 "$doFinally",
                                                                 methodType == MethodType.AsyncTask ? new JsVariableDeclaration("$tcs", JsExpression.New(JsExpression.Identifier("TaskCompletionSource"))) : null,
                                                                 expr => { if (methodType != MethodType.AsyncTask)
                                                                           {
                                                                               throw new InvalidOperationException("Should not set result in async void method");
                                                                           }
                                                                           return(JsExpression.Invocation(JsExpression.Member(JsExpression.Identifier("$tcs"), "setResult"), expr ?? JsExpression.String("<<null>>"))); },
                                                                 expr => { if (methodType != MethodType.AsyncTask)
                                                                           {
                                                                               throw new InvalidOperationException("Should not set exception in async void method");
                                                                           }
                                                                           return(JsExpression.Invocation(JsExpression.Member(JsExpression.Identifier("$tcs"), "setException"), expr)); },
                                                                 () => { if (methodType != MethodType.AsyncTask)
                                                                         {
                                                                             throw new InvalidOperationException("Should not get task async void method");
                                                                         }
                                                                         return(JsExpression.Invocation(JsExpression.Member(JsExpression.Identifier("$tcs"), "getTask"))); },
                                                                 (sm, ctx) => JsExpression.Invocation(JsExpression.Identifier("$Bind"), sm, ctx));
            }
            else
            {
                result = StateMachineRewriter.RewriteNormalMethod(stmt, e => e.NodeType != ExpressionNodeType.Identifier, () => "$tmp" + (++tempIndex).ToString(CultureInfo.InvariantCulture), () => "$state" + (++stateIndex).ToString(CultureInfo.InvariantCulture), () => string.Format("$loop" + (++loopLabelIndex).ToString(CultureInfo.InvariantCulture)));
            }
            var actual = OutputFormatter.Format(result);

            Assert.That(actual.Replace("\r\n", "\n"), Is.EqualTo(expected.Replace("\r\n", "\n")), "Expected:\n" + expected + "\n\nActual:\n" + actual);
        }
 public void IncrementIsParenthesizedWhenUsedAsInvocationMethod()
 {
     AssertCorrect(JsExpression.Invocation(
                       JsExpression.Unary(ExpressionNodeType.PostfixMinusMinus,
                                          JsExpression.Identifier("x")
                                          ),
                       new JsExpression[0]
                       ),
                   "(x--)()");
 }
Ejemplo n.º 14
0
        public JsExpression TypeIs(JsExpression expression, IType sourceType, IType targetType)
        {
            var jsTarget = GetCastTarget(sourceType, targetType);

            if (jsTarget == null || IsSystemObjectReference(jsTarget))
            {
                return(ReferenceNotEquals(expression, JsExpression.Null));
            }
            return(JsExpression.Invocation(JsExpression.MemberAccess(_createTypeReferenceExpression(KnownTypeReference.Type), "isInstanceOfType"), expression, jsTarget));
        }
 public void IncrementIsParenthesizedWhenBeingUsedAsInvocationTarget()
 {
     AssertCorrect(JsExpression.Invocation(
                       JsExpression.Unary(ExpressionNodeType.PostfixPlusPlus,
                                          JsExpression.Identifier("X")
                                          ),
                       new[] { JsExpression.Number(1) }
                       ),
                   "(X++)(1)");
 }
Ejemplo n.º 16
0
        public JsExpression TryDowncast(JsExpression expression, IType sourceType, IType targetType)
        {
            var jsTarget = GetCastTarget(sourceType, targetType);

            if (jsTarget == null || IsSystemObjectReference(jsTarget))
            {
                return(expression);
            }
            return(JsExpression.Invocation(JsExpression.MemberAccess(_createTypeReferenceExpression(KnownTypeReference.Type), "safeCast"), expression, jsTarget));
        }
        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));
        }
 public void ChainedFunctionCallsAreNotParenthtesized()
 {
     AssertCorrect(JsExpression.Invocation(
                       JsExpression.Invocation(
                           JsExpression.Identifier("x"),
                           new[] { JsExpression.Number(1) }
                           ),
                       new[] { JsExpression.Number(2) }
                       ),
                   "x(1)(2)");
 }
Ejemplo n.º 19
0
        public JsExpression CallBase(IType baseType, string methodName, IList <IType> typeArguments, IEnumerable <JsExpression> thisAndArguments)
        {
            JsExpression method = JsExpression.MemberAccess(JsExpression.MemberAccess(GetScriptType(baseType, TypeContext.BindBaseCall), "prototype"), methodName);

            if (typeArguments != null && typeArguments.Count > 0)
            {
                method = InstantiateGenericMethod(method, typeArguments);
            }

            return(JsExpression.Invocation(JsExpression.MemberAccess(method, "call"), thisAndArguments));
        }
Ejemplo n.º 20
0
        public JsExpression BindBaseCall(IType baseType, string methodName, IList <IType> typeArguments, JsExpression @this)
        {
            JsExpression method = JsExpression.MemberAccess(JsExpression.MemberAccess(GetScriptType(baseType, TypeContext.BindBaseCall), "prototype"), methodName);

            if (typeArguments != null && typeArguments.Count > 0)
            {
                method = InstantiateGenericMethod(method, typeArguments);
            }

            return(JsExpression.Invocation(JsExpression.MemberAccess(_createTypeReferenceExpression(KnownTypeReference.Delegate), "mkdel"), @this, method));
        }
 public void InvocationIsNotParenthesizedWhenUsedAsMemberAccessTarget()
 {
     AssertCorrect(JsExpression.Member(
                       JsExpression.Invocation(
                           JsExpression.Number(1),
                           new[] { JsExpression.Number(2) }
                           ),
                       "Member"
                       ),
                   "1(2).Member");
 }
 public void MemberAccessIsNotParenthesizedWhenUsedAsInvocationTarget()
 {
     AssertCorrect(JsExpression.Invocation(
                       JsExpression.Member(
                           JsExpression.Identifier("x"),
                           "Member"
                           ),
                       new JsExpression[0]
                       ),
                   "x.Member()");
 }
 public JsExpression CloneDelegate(JsExpression source, IType sourceType, IType targetType, IRuntimeContext context)
 {
     if (Equals(sourceType, targetType))
     {
         // The user does something like "D d1 = F(); var d2 = new D(d1)". Assume he does this for a reason and create a clone of the delegate.
         return(JsExpression.Invocation(JsExpression.Member(CreateTypeReferenceExpression(_systemScript), "delegateClone"), source));
     }
     else
     {
         return(source);                 // The clone is just to convert the delegate to a different type. The risk of anyone comparing the references is small, so just return the original as delegates are immutable anyway.
     }
 }
Ejemplo n.º 24
0
        private JsExpression CreateInitInterfaceCall(JsClass type, string ctorName, IList <JsExpression> interfaces)
        {
            var args = new List <JsExpression> {
                JsExpression.Identifier(ctorName), _linker.CurrentAssemblyExpression, CreateInstanceMembers(type, null)
            };

            if (interfaces.Count > 0)
            {
                args.Add(JsExpression.ArrayLiteral(interfaces));
            }
            return(JsExpression.Invocation(JsExpression.Member(_systemScript, InitInterface), args));
        }
Ejemplo n.º 25
0
        private JsType ConvertType(JsClass type)
        {
            if (type.InstanceMethods.Any(m => m.Name == "runTests"))
            {
                _errorReporter.Region = type.CSharpTypeDefinition.Region;
                _errorReporter.Message(MessageSeverity.Error, 7019, string.Format("The type {0} cannot define a method named 'runTests' because it has a [TestFixtureAttribute].", type.CSharpTypeDefinition.FullName));
                return(type);
            }

            var instanceMethods = new List <JsMethod>();
            var tests           = new List <Tuple <string, string, bool, int?, JsFunctionDefinitionExpression> >();

            foreach (var method in type.InstanceMethods)
            {
                var testAttr = _attributeStore.AttributesFor(method.CSharpMember).GetAttribute <TestAttribute>();
                if (testAttr != null)
                {
                    if (!method.CSharpMember.IsPublic || !method.CSharpMember.ReturnType.IsKnownType(KnownTypeCode.Void) || ((IMethod)method.CSharpMember).Parameters.Count > 0 || ((IMethod)method.CSharpMember).TypeParameters.Count > 0)
                    {
                        _errorReporter.Region = method.CSharpMember.Region;
                        _errorReporter.Message(MessageSeverity.Error, 7020, string.Format("Method {0}: Methods decorated with a [TestAttribute] must be public, non-generic, parameterless instance methods that return void.", method.CSharpMember.FullName));
                    }

                    tests.Add(Tuple.Create(testAttr.Description ?? method.CSharpMember.Name, testAttr.Category, testAttr.IsAsync, testAttr.ExpectedAssertionCount >= 0 ? (int?)testAttr.ExpectedAssertionCount : null, method.Definition));
                }
                else
                {
                    instanceMethods.Add(method);
                }
            }

            var testInvocations = new List <JsExpression>();

            foreach (var category in tests.GroupBy(t => t.Item2).Select(g => new { Category = g.Key, Tests = g.Select(x => new { Description = x.Item1, IsAsync = x.Item3, ExpectedAssertionCount = x.Item4, Function = x.Item5 }) }).OrderBy(x => x.Category))
            {
                if (category.Category != null)
                {
                    testInvocations.Add(JsExpression.Invocation(JsExpression.Member(JsExpression.Identifier("QUnit"), "module"), JsExpression.String(category.Category)));
                }
                testInvocations.AddRange(category.Tests.Select(t => JsExpression.Invocation(JsExpression.Identifier(t.IsAsync ? "asyncTest" : "test"), t.ExpectedAssertionCount != null ? new JsExpression[] { JsExpression.String(t.Description), JsExpression.Number(t.ExpectedAssertionCount.Value), _runtimeLibrary.Bind(t.Function, JsExpression.This, this) } : new JsExpression[] { JsExpression.String(t.Description), _runtimeLibrary.Bind(t.Function, JsExpression.This, this) })));
            }

            instanceMethods.Add(new JsMethod(null, "runTests", null, JsExpression.FunctionDefinition(new string[0], JsStatement.Block(testInvocations.Select(t => (JsStatement)t)))));

            var result = type.Clone();

            result.InstanceMethods.Clear();
            foreach (var m in instanceMethods)
            {
                result.InstanceMethods.Add(m);
            }
            return(result);
        }
 public void NewExpressionIsParenthesizedWhenBeingUsedAsInvocationTarget()
 {
     // Just to get rid of ambiguities
     AssertCorrect(JsExpression.Invocation(
                       JsExpression.New(
                           JsExpression.Identifier("X"),
                           new JsExpression[0]
                           ),
                       new[] { JsExpression.Number(1) }
                       ),
                   "(new X())(1)");
 }
        public JsExpression BindBaseCall(IMethod method, JsExpression @this, IRuntimeContext context)
        {
            var impl = GetMethodSemantics(method);

            JsExpression jsMethod = JsExpression.Member(JsExpression.Member(GetScriptType(method.DeclaringType, TypeContext.GetScriptType, context), "prototype"), impl.Name);

            if (method is SpecializedMethod && !impl.IgnoreGenericArguments)
            {
                jsMethod = InstantiateGenericMethod(jsMethod, ((SpecializedMethod)method).TypeArguments, context);
            }

            return(JsExpression.Invocation(JsExpression.Member(CreateTypeReferenceExpression(_systemScript), "mkdel"), @this, jsMethod));
        }
        public JsExpression CreateArray(IType elementType, IEnumerable <JsExpression> size, IRuntimeContext context)
        {
            var sizeList = (size is IList <JsExpression>) ? (IList <JsExpression>)size : size.ToList();

            if (sizeList.Count == 1)
            {
                return(JsExpression.New(CreateTypeReferenceExpression(KnownTypeReference.Array), sizeList));
            }
            else
            {
                return(JsExpression.Invocation(JsExpression.Member(CreateTypeReferenceExpression(_systemScript), "multidimArray"), new[] { Default(elementType, context) }.Concat(sizeList)));
            }
        }
        public JsExpression FromNullable(JsExpression expression, IRuntimeContext context)
        {
            if (_omitNullableChecks)
            {
                return(expression);
            }

            if (expression.NodeType == ExpressionNodeType.LogicalNot)
            {
                return(expression);                     // This is a little hacky. The problem we want to solve is that 'bool b = myDynamic' should compile to !!myDynamic, but the actual call is unbox(convert(myDynamic, bool)), where convert() will return the !!. Anyway, in JS, the !expression will never be null anyway.
            }
            return(JsExpression.Invocation(JsExpression.Member(CreateTypeReferenceExpression(_systemScript), "unbox"), expression));
        }
Ejemplo n.º 30
0
        private JsExpression CreateRegisterEnumCall(ITypeDefinition type, string name, JsExpression ctor)
        {
            var args = new List <JsExpression> {
                GetRoot(type), JsExpression.String(name), ctor
            };
            var metadata = GetMetadataDescriptor(type, false);

            if (metadata != null)
            {
                args.Add(metadata);
            }
            return(JsExpression.Invocation(JsExpression.Member(_systemScript, RegisterEnum), args));
        }