Ejemplo n.º 1
0
        public void ImportingTypesFromModulesWorks()
        {
            var t1 = Common.CreateMockTypeDefinition("SomeNamespace.InnerNamespace.Type1", Common.CreateMockAssembly(new Expression <Func <Attribute> >[] { () => new ModuleNameAttribute("module1") }));
            var t2 = Common.CreateMockTypeDefinition("SomeNamespace.InnerNamespace.Type2", Common.CreateMockAssembly(new Expression <Func <Attribute> >[] { () => new ModuleNameAttribute("module2") }));
            var t3 = Common.CreateMockTypeDefinition("SomeNamespace.Type3", Common.CreateMockAssembly(new Expression <Func <Attribute> >[] { () => new ModuleNameAttribute("module1") }));
            var t4 = Common.CreateMockTypeDefinition("Type4", Common.CreateMockAssembly(new Expression <Func <Attribute> >[] { () => new ModuleNameAttribute("module3") }));

            var actual = Process(new JsStatement[] {
                JsExpression.Add(JsExpression.Member(new JsTypeReferenceExpression(t1), "a"), JsExpression.Member(new JsTypeReferenceExpression(t2), "b")),
                JsExpression.Add(JsExpression.Member(new JsTypeReferenceExpression(t3), "c"), JsExpression.Member(new JsTypeReferenceExpression(t4), "d")),
                JsExpression.Add(JsExpression.Member(new JsTypeReferenceExpression(t1), "e"), JsExpression.Member(new JsTypeReferenceExpression(t4), "f")),
            }, new[] { Common.CreateMockAssembly(), t1.ParentAssembly, t2.ParentAssembly, t3.ParentAssembly, t4.ParentAssembly });

            AssertCorrect(actual,
                          @"'use strict';
require('mscorlib');
var $module1 = require('module1');
var $module2 = require('module2');
var $module3 = require('module3');
var $asm = {};
$module1.SomeNamespace.InnerNamespace.Type1.a + $module2.SomeNamespace.InnerNamespace.Type2.b;
$module1.SomeNamespace.Type3.c + $module3.Type4.d;
$module1.SomeNamespace.InnerNamespace.Type1.e + $module3.Type4.f;
");
        }
Ejemplo n.º 2
0
        public void GeneratedModuleAliasesAreValidAndDoNotClashWithEachOtherOrUsedSymbols()
        {
            var t1 = Common.CreateMockTypeDefinition("Type1", Common.CreateMockAssembly(new Expression <Func <Attribute> >[] { () => new ModuleNameAttribute("mymodule") }));
            var t2 = Common.CreateMockTypeDefinition("Type2", Common.CreateMockAssembly(new Expression <Func <Attribute> >[] { () => new ModuleNameAttribute("mymodule+") }));
            var t3 = Common.CreateMockTypeDefinition("Type3", Common.CreateMockAssembly(new Expression <Func <Attribute> >[] { () => new ModuleNameAttribute("mymodule-") }));
            var t4 = Common.CreateMockTypeDefinition("Type4", Common.CreateMockAssembly(new Expression <Func <Attribute> >[] { () => new ModuleNameAttribute("+") }));
            var t5 = Common.CreateMockTypeDefinition("Type5", Common.CreateMockAssembly(new Expression <Func <Attribute> >[] { () => new ModuleNameAttribute("-") }));

            var actual = Process(new JsStatement[] {
                JsExpression.Member(new JsTypeReferenceExpression(t1), "a"),
                JsExpression.Member(new JsTypeReferenceExpression(t2), "b"),
                JsExpression.Member(new JsTypeReferenceExpression(t3), "c"),
                JsExpression.Member(new JsTypeReferenceExpression(t4), "d"),
                JsExpression.Member(new JsTypeReferenceExpression(t5), "e"),
                JsStatement.Var("mymodule", null),
            }, new[] { Common.CreateMockAssembly(), t1.ParentAssembly, t2.ParentAssembly, t3.ParentAssembly, t4.ParentAssembly, t5.ParentAssembly }, namer: new MockNamer(prefixWithDollar: false));

            AssertCorrect(actual,
                          @"'use strict';
require('mscorlib');
var _2 = require('-');
var _ = require('+');
var mymodule2 = require('mymodule');
var mymodule4 = require('mymodule-');
var mymodule3 = require('mymodule+');
var $asm = {};
mymodule2.Type1.a;
mymodule3.Type2.b;
mymodule4.Type3.c;
_.Type4.d;
_2.Type5.e;
var mymodule;
");
        }
Ejemplo n.º 3
0
        public void AsyncModuleWithReferencesWorks()
        {
            var asm = Common.CreateMockAssembly(new Expression <Func <Attribute> >[] { () => new AsyncModuleAttribute() });
            var t1  = Common.CreateMockTypeDefinition("SomeNamespace.InnerNamespace.Type1", Common.CreateMockAssembly(new Expression <Func <Attribute> >[] { () => new ModuleNameAttribute("module1") }));
            var t2  = Common.CreateMockTypeDefinition("SomeNamespace.InnerNamespace.Type2", Common.CreateMockAssembly(new Expression <Func <Attribute> >[] { () => new ModuleNameAttribute("module2") }));
            var t3  = Common.CreateMockTypeDefinition("SomeNamespace.Type3", Common.CreateMockAssembly(new Expression <Func <Attribute> >[] { () => new ModuleNameAttribute("module1") }));
            var t4  = Common.CreateMockTypeDefinition("Type4", Common.CreateMockAssembly(new Expression <Func <Attribute> >[] { () => new ModuleNameAttribute("module3") }));

            var actual = Process(new JsStatement[] {
                JsExpression.Add(JsExpression.Member(new JsTypeReferenceExpression(t1), "a"), JsExpression.Member(new JsTypeReferenceExpression(t2), "b")),
                JsExpression.Add(JsExpression.Member(new JsTypeReferenceExpression(t3), "c"), JsExpression.Member(new JsTypeReferenceExpression(t4), "d")),
                JsExpression.Add(JsExpression.Member(new JsTypeReferenceExpression(t1), "e"), JsExpression.Member(new JsTypeReferenceExpression(t4), "f")),
            }, new[] { asm, t1.ParentAssembly, t2.ParentAssembly, t3.ParentAssembly, t4.ParentAssembly });

            AssertCorrect(actual,
                          @"define(['mscorlib', 'module1', 'module2', 'module3'], function($_, $module1, $module2, $module3) {
	'use strict';
	var exports = {};
	$module1.SomeNamespace.InnerNamespace.Type1.a + $module2.SomeNamespace.InnerNamespace.Type2.b;
	$module1.SomeNamespace.Type3.c + $module3.Type4.d;
	$module1.SomeNamespace.InnerNamespace.Type1.e + $module3.Type4.f;
	return exports;
});
");
        }
Ejemplo n.º 4
0
        public void ModuleNameAttributeCanBeSpecifiedOnType()
        {
            var c1 = Common.CreateMockTypeDefinition("C1", Common.CreateMockAssembly());
            var c2 = Common.CreateMockTypeDefinition("C2", Common.CreateMockAssembly(), attributes: new Expression <Func <Attribute> >[] { () => new ModuleNameAttribute("my-module") });
            var c3 = Common.CreateMockTypeDefinition("C3", Common.CreateMockAssembly(), attributes: new Expression <Func <Attribute> >[] { () => new ModuleNameAttribute("") });
            var c4 = Common.CreateMockTypeDefinition("C4", Common.CreateMockAssembly(), attributes: new Expression <Func <Attribute> >[] { () => new ModuleNameAttribute(null) });

            var actual = Process(new JsStatement[] {
                JsExpression.Member(new JsTypeReferenceExpression(c1), "a"),
                JsExpression.Member(new JsTypeReferenceExpression(c2), "b"),
                JsExpression.Member(new JsTypeReferenceExpression(c3), "c"),
                JsExpression.Member(new JsTypeReferenceExpression(c4), "d"),
            }, new[] { Common.CreateMockAssembly(), c1.ParentAssembly, c2.ParentAssembly, c3.ParentAssembly, c4.ParentAssembly });

            AssertCorrect(actual,
                          @"'use strict';
require('mscorlib');
var $mymodule = require('my-module');
var $asm = {};
C1.a;
$mymodule.C2.b;
C3.c;
C4.d;
");
        }
Ejemplo n.º 5
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));
        }
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)));
        }
Ejemplo n.º 7
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));
        }
Ejemplo n.º 8
0
        public void AsyncModuleWithReferencesWorks()
        {
            var asm = CreateMockAssembly();
            var t1  = CreateMockType("SomeNamespace.InnerNamespace.Type1", asm);
            var t2  = CreateMockType("SomeNamespace.InnerNamespace.Type2", asm);
            var t3  = CreateMockType("SomeNamespace.Type3", asm);
            var t4  = CreateMockType("Type4", asm);
            var md  = new MockScriptSharpMetadataImporter {
                GetModuleName = t => t.Name == "Type1" || t.Name == "Type3" ? "module1" : (t.Name == "Type2" ? "module2" : "module3"), IsAsyncModule = true
            };

            var actual = Process(new JsStatement[] {
                new JsExpressionStatement(JsExpression.Add(JsExpression.Member(new JsTypeReferenceExpression(t1), "a"), JsExpression.Member(new JsTypeReferenceExpression(t2), "b"))),
                new JsExpressionStatement(JsExpression.Add(JsExpression.Member(new JsTypeReferenceExpression(t3), "c"), JsExpression.Member(new JsTypeReferenceExpression(t4), "d"))),
                new JsExpressionStatement(JsExpression.Add(JsExpression.Member(new JsTypeReferenceExpression(t1), "e"), JsExpression.Member(new JsTypeReferenceExpression(t4), "f"))),
            }, metadata: md);

            AssertCorrect(actual,
                          @"define(['mscorlib', 'module1', 'module2', 'module3'], function($_, $module1, $module2, $module3) {
	var exports = {};
	$module1.SomeNamespace.InnerNamespace.Type1.a + $module2.SomeNamespace.InnerNamespace.Type2.b;
	$module1.SomeNamespace.Type3.c + $module3.Type4.d;
	$module1.SomeNamespace.InnerNamespace.Type1.e + $module3.Type4.f;
	return exports;
});
");
        }
Ejemplo n.º 9
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)))
                                                           )));
            }
        }
Ejemplo n.º 10
0
        public void ImportingTypesFromModulesWorks()
        {
            var asm = CreateMockAssembly();
            var t1  = CreateMockType("SomeNamespace.InnerNamespace.Type1", asm);
            var t2  = CreateMockType("SomeNamespace.InnerNamespace.Type2", asm);
            var t3  = CreateMockType("SomeNamespace.Type3", asm);
            var t4  = CreateMockType("Type4", asm);
            var md  = new MockScriptSharpMetadataImporter {
                GetModuleName = t => t.Name == "Type1" || t.Name == "Type3" ? "module1" : (t.Name == "Type2" ? "module2" : "module3")
            };

            var actual = Process(new JsStatement[] {
                new JsExpressionStatement(JsExpression.Add(JsExpression.Member(new JsTypeReferenceExpression(t1), "a"), JsExpression.Member(new JsTypeReferenceExpression(t2), "b"))),
                new JsExpressionStatement(JsExpression.Add(JsExpression.Member(new JsTypeReferenceExpression(t3), "c"), JsExpression.Member(new JsTypeReferenceExpression(t4), "d"))),
                new JsExpressionStatement(JsExpression.Add(JsExpression.Member(new JsTypeReferenceExpression(t1), "e"), JsExpression.Member(new JsTypeReferenceExpression(t4), "f"))),
            }, metadata: md);

            AssertCorrect(actual,
                          @"require('mscorlib');
var $module1 = require('module1');
var $module2 = require('module2');
var $module3 = require('module3');
$module1.SomeNamespace.InnerNamespace.Type1.a + $module2.SomeNamespace.InnerNamespace.Type2.b;
$module1.SomeNamespace.Type3.c + $module3.Type4.d;
$module1.SomeNamespace.InnerNamespace.Type1.e + $module3.Type4.f;
");
        }
Ejemplo n.º 11
0
        public void ModuleNameOnAssemblyCanBeOverriddenOnType()
        {
            var asm = Common.CreateMockAssembly(new Expression <Func <Attribute> >[] { () => new ModuleNameAttribute("my-module") });
            var c1  = Common.CreateMockTypeDefinition("C1", asm, attributes: new Expression <Func <Attribute> >[] { () => new ModuleNameAttribute("other-module") });
            var c2  = Common.CreateMockTypeDefinition("C2", asm, attributes: new Expression <Func <Attribute> >[] { () => new ModuleNameAttribute("") });
            var c3  = Common.CreateMockTypeDefinition("C3", asm, attributes: new Expression <Func <Attribute> >[] { () => new ModuleNameAttribute(null) });

            var actual = Process(new JsStatement[] {
                JsExpression.Member(new JsTypeReferenceExpression(c1), "a"),
                JsExpression.Member(new JsTypeReferenceExpression(c2), "b"),
                JsExpression.Member(new JsTypeReferenceExpression(c3), "c"),
            }, new[] { Common.CreateMockAssembly(), asm }, metadata: new MockMetadataImporter {
                GetTypeSemantics = t => TypeScriptSemantics.NormalType(t.Name.Replace("+", "_"))
            });

            AssertCorrect(actual,
                          @"'use strict';
require('mscorlib');
var $othermodule = require('other-module');
var $asm = {};
$othermodule.C1.a;
C2.b;
C3.c;
");
        }
Ejemplo n.º 12
0
        public void ClassWithSameNameAsVariable1()
        {
            var someAsm = Common.CreateMockAssembly();
            var actual  = Process(new JsStatement[] {
                JsStatement.Function("f", new[] { "x" }, JsStatement.Block(
                                         JsStatement.Var("y", JsExpression.Number(0)),
                                         JsExpression.Binary(ExpressionNodeType.Add, JsExpression.Member(new JsTypeReferenceExpression(Common.CreateMockTypeDefinition("x", someAsm)), "a"), JsExpression.Identifier("x")),
                                         JsExpression.Binary(ExpressionNodeType.Add, JsExpression.Member(new JsTypeReferenceExpression(Common.CreateMockTypeDefinition("y", someAsm)), "a"), JsExpression.Identifier("y"))
                                         )),
                JsExpression.FunctionDefinition(new[] { "x" }, JsStatement.Block(
                                                    JsStatement.Var("y", JsExpression.Number(0)),
                                                    JsExpression.Binary(ExpressionNodeType.Add, JsExpression.Member(new JsTypeReferenceExpression(Common.CreateMockTypeDefinition("x", someAsm)), "a"), JsExpression.Identifier("x")),
                                                    JsExpression.Binary(ExpressionNodeType.Add, JsExpression.Member(new JsTypeReferenceExpression(Common.CreateMockTypeDefinition("y", someAsm)), "a"), JsExpression.Identifier("y"))
                                                    ))
            }, new[] { Common.CreateMockAssembly(), someAsm }, new MockMetadataImporter {
                GetTypeSemantics = t => TypeScriptSemantics.NormalType(t.Name)
            }, namer: new Namer());

            AssertCorrect(actual,
                          @"(function() {
	'use strict';
	var $asm = {};
	function f(x1) {
		var y1 = 0;
		x.a + x1;
		y.a + y1;
	}
	(function(x1) {
		var y1 = 0;
		x.a + x1;
		y.a + y1;
	});
})();
");
        }
        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);
        }
Ejemplo n.º 14
0
        public JsFunctionDefinitionExpression CompileAutoEventRemover(IEvent @event, EventScriptSemantics impl, string backingFieldName)
        {
            try {
                string valueName = _namer.GetVariableName(@event.RemoveAccessor.Parameters[0].Name, new HashSet <string>(@event.DeclaringTypeDefinition.TypeParameters.Select(p => _namer.GetTypeParameterName(p))));
                CreateCompilationContext(null, null, @event.DeclaringTypeDefinition, null);

                JsExpression target;
                string[]     args;
                if (@event.IsStatic)
                {
                    target = _runtimeLibrary.InstantiateType(Utils.SelfParameterize(@event.DeclaringTypeDefinition), _statementCompiler);
                    args   = new[] { valueName };
                }
                else if (impl.RemoveMethod.Type == MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument)
                {
                    target = JsExpression.Identifier(_namer.ThisAlias);
                    args   = new[] { _namer.ThisAlias, valueName };
                }
                else
                {
                    target = JsExpression.This;
                    args   = new[] { valueName };
                }

                var bfAccessor  = JsExpression.Member(target, backingFieldName);
                var combineCall = _statementCompiler.CompileDelegateRemoveCall(@event.RemoveAccessor.Region, bfAccessor, JsExpression.Identifier(valueName));
                return(JsExpression.FunctionDefinition(args, JsStatement.Block(JsExpression.Assign(bfAccessor, combineCall))));
            }
            catch (Exception ex) {
                _errorReporter.Region = @event.Region;
                _errorReporter.InternalError(ex);
                return(JsExpression.FunctionDefinition(new string[0], JsStatement.EmptyBlock));
            }
        }
        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.º 16
0
        public void RenamedVariableClashWithImplicitGlobal()
        {
            var someAsm = Common.CreateMockAssembly();
            var actual  = Process(new JsStatement[] {
                JsStatement.Function("f", new[] { "x" }, JsStatement.Block(
                                         JsExpression.FunctionDefinition(new string[0],
                                                                         JsExpression.Member(new JsTypeReferenceExpression(Common.CreateMockTypeDefinition("x", someAsm)), "a")
                                                                         ),
                                         JsExpression.FunctionDefinition(new string[0], JsStatement.Block(
                                                                             JsExpression.Add(JsExpression.Identifier("x"), JsExpression.Identifier("x1"))
                                                                             ))
                                         ))
            }, new[] { Common.CreateMockAssembly(), someAsm }, new MockMetadataImporter {
                GetTypeSemantics = t => TypeScriptSemantics.NormalType(t.Name)
            }, namer: new Namer());

            AssertCorrect(actual,
                          @"(function() {
	'use strict';
	var $asm = {};
	function f(x2) {
		(function() {
			x.a;
		});
		(function() {
			x2 + x1;
		});
	}
})();
");
        }
        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));
        }
        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));
            }
        }
        public JsExpression GetMember(IMember member, IRuntimeContext context)
        {
            var owner = member is IMethod && ((IMethod)member).IsAccessor ? ((IMethod)member).AccessorOwner : null;

            int index = FindIndexInReflectableMembers(owner ?? member);

            if (index >= 0)
            {
                JsExpression result = JsExpression.Index(
                    JsExpression.Member(
                        JsExpression.Member(
                            TypeOf(member.DeclaringType, context),
                            "__metadata"),
                        "members"),
                    JsExpression.Number(index));
                if (owner != null)
                {
                    if (owner is IProperty)
                    {
                        if (ReferenceEquals(member, ((IProperty)owner).Getter))
                        {
                            result = JsExpression.MemberAccess(result, "getter");
                        }
                        else if (ReferenceEquals(member, ((IProperty)owner).Setter))
                        {
                            result = JsExpression.MemberAccess(result, "setter");
                        }
                        else
                        {
                            throw new ArgumentException("Invalid member " + member);
                        }
                    }
                    else if (owner is IEvent)
                    {
                        if (ReferenceEquals(member, ((IEvent)owner).AddAccessor))
                        {
                            result = JsExpression.MemberAccess(result, "adder");
                        }
                        else if (ReferenceEquals(member, ((IEvent)owner).RemoveAccessor))
                        {
                            result = JsExpression.MemberAccess(result, "remover");
                        }
                        else
                        {
                            throw new ArgumentException("Invalid member " + member);
                        }
                    }
                    else
                    {
                        throw new ArgumentException("Invalid owner " + owner);
                    }
                }
                return(result);
            }
            else
            {
                return(MetadataUtils.ConstructMemberInfo(member, _compilation, _metadataImporter, _namer, this, _errorReporter, t => TypeOf(t, context), includeDeclaringType: true));
            }
        }
        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.Member(_createTypeReferenceExpression(KnownTypeReference.Type), "safeCast"), expression, jsTarget));
        }
        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.Member(_createTypeReferenceExpression(KnownTypeReference.Type), "isInstanceOfType"), expression, jsTarget));
        }
Ejemplo n.º 23
0
        private TypeOOPEmulationPhase CreateInitTypeCalls(JsType type)
        {
            bool generateCall = true;

            if (type is JsClass && MetadataUtils.IsJsGeneric(type.CSharpTypeDefinition, _metadataImporter))
            {
                generateCall = false;
            }
            if (string.IsNullOrEmpty(_metadataImporter.GetTypeSemantics(type.CSharpTypeDefinition).Name))
            {
                generateCall = false;
            }
            if (MetadataUtils.IsResources(type.CSharpTypeDefinition, _attributeStore))
            {
                generateCall = false;
            }
            if (MetadataUtils.IsMixin(type.CSharpTypeDefinition, _attributeStore))
            {
                generateCall = false;
            }

            var statements = new List <JsStatement>();

            if (generateCall)
            {
                string name        = _metadataImporter.GetTypeSemantics(type.CSharpTypeDefinition).Name;
                string typevarName = _namer.GetTypeVariableName(name);
                if (type.CSharpTypeDefinition.Kind == TypeKind.Enum)
                {
                    statements.Add(CreateInitEnumCall((JsEnum)type, typevarName));
                }
                else
                {
                    var c = (JsClass)type;
                    if (type.CSharpTypeDefinition.Kind == TypeKind.Interface)
                    {
                        statements.Add(CreateInitInterfaceCall(c, typevarName, GetImplementedInterfaces(type.CSharpTypeDefinition.GetDefinition()).ToList()));
                    }
                    else
                    {
                        statements.Add(CreateInitClassCall(c, typevarName, GetBaseClass(type.CSharpTypeDefinition), GetImplementedInterfaces(type.CSharpTypeDefinition).ToList()));
                        if (c.NamedConstructors.Count > 0)
                        {
                            statements.Add(AssignNamedConstructorPrototypes(c, JsExpression.Identifier(_namer.GetTypeVariableName(name))));
                        }
                        if (c.CSharpTypeDefinition.Kind == TypeKind.Struct)
                        {
                            statements.Add(JsExpression.Assign(JsExpression.Member(JsExpression.Identifier(_namer.GetTypeVariableName(name)), "__class"), JsExpression.False));
                        }
                    }
                }
            }

            return(new TypeOOPEmulationPhase(type.CSharpTypeDefinition.GetAllBaseTypeDefinitions().Where(t => !t.Equals(type.CSharpTypeDefinition)), statements));
        }
        public JsExpression BindBaseCall(IType baseType, string methodName, IList <IType> typeArguments, JsExpression @this)
        {
            JsExpression method = JsExpression.Member(JsExpression.Member(GetScriptType(baseType, TypeContext.BindBaseCall), "prototype"), methodName);

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

            return(JsExpression.Invocation(JsExpression.Member(_createTypeReferenceExpression(KnownTypeReference.Delegate), "mkdel"), @this, method));
        }
Ejemplo n.º 25
0
        private JsExpression MakeNestedMemberAccess(string full)
        {
            var          parts  = full.Split('.');
            JsExpression result = JsExpression.Identifier(parts[0]);

            for (int i = 1; i < parts.Length; i++)
            {
                result = JsExpression.Member(result, parts[i]);
            }
            return(result);
        }
 public void NewExpressionIsParenthesizedWhenItIsTheTargetOfAMemberAccess()
 {
     AssertCorrect(JsExpression.Member(
                       JsExpression.New(
                           JsExpression.Number(1),
                           new[] { JsExpression.Number(2) }
                           ),
                       "Member"
                       ),
                   "(new 1(2)).Member");
 }
 public void MemberAccessIsNotParenthesizedWhenUsedAsInvocationTarget()
 {
     AssertCorrect(JsExpression.Invocation(
                       JsExpression.Member(
                           JsExpression.Identifier("x"),
                           "Member"
                           ),
                       new JsExpression[0]
                       ),
                   "x.Member()");
 }
        public JsExpression CallBase(IType baseType, string methodName, IList <IType> typeArguments, IEnumerable <JsExpression> thisAndArguments)
        {
            JsExpression method = JsExpression.Member(JsExpression.Member(GetScriptType(baseType, TypeContext.BindBaseCall), "prototype"), methodName);

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

            return(JsExpression.Invocation(JsExpression.Member(method, "call"), thisAndArguments));
        }
 public void InvocationIsNotParenthesizedWhenUsedAsMemberAccessTarget()
 {
     AssertCorrect(JsExpression.Member(
                       JsExpression.Invocation(
                           JsExpression.Number(1),
                           new[] { JsExpression.Number(2) }
                           ),
                       "Member"
                       ),
                   "1(2).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.º 31
0
        public JsExpression CreateObject(JsExpression containingType, IMethodSymbol constructor, params JsExpression[] arguments)
        {
            var constructorReference = containingType.Member("prototype").Member(constructor.GetMemberName());

            if (constructor.IsBuiltIn())
            {
                // If the constructor is built-in, then we don't want it invoked at all, since it's just a shim for the built-in
                // version.  Therefore, just call the types constructor passing in the arguments as usual for a normal JS new.
                return Js.New(containingType, arguments);
            }
            else
            {
                // Object creation gets transformed into:
                // new T(T.prototype.ctor, arg1, arg2, arg3...)
                return constructorReference.Member(SpecialNames.New).Invoke(arguments);
            }
        }
Ejemplo n.º 32
0
        public JsExpression GetPropertyValue(JsExpression target, IPropertySymbol property, bool isSetter, bool isBaseReference)
        {
            bool isExported = property.IsExported();
            var propertyName = property.GetMemberName();

            JsExpression inline;
            if (!isSetter && TryInline(property.GetMethod, target, new JsExpression[0], out inline))
            {
                return inline;
            }

            if (!isExported || IsMinimizedAutoProperty(property))
            {
                return target.Member(propertyName);
            }
            else
            {
                bool isExtension = property.IsExtension();
                if (isExtension || isBaseReference)
                    return InvokeMethodAs(property.GetMethod, target);
                else if (property.GetMethod != null)
                    return target.Member(property.GetMethod.GetMemberName()).Invoke();
                else 
                    return target.Member("get_" + property.GetMemberName()).Invoke();
            }
        }
Ejemplo n.º 33
0
        public JsExpression MemberReference(JsExpression @this, ISymbol symbol, bool isSetter = false, bool isBaseReference = false)
        {
            switch (symbol.Kind)
            {
                case SymbolKind.Field:
                {
                    var field = (IFieldSymbol)symbol;
                    var result = (JsExpression)@this.Member(field.GetMemberName());

                    if (field.Type is IArrayTypeSymbol && !field.IsExported())
                    {
                        result = MakeArray(result, (IArrayTypeSymbol)field.Type);
                    }

                    return result;
                }
                case SymbolKind.Event:
                {
                    var field = (IEventSymbol)symbol;
                    return @this.Member(field.GetBackingFieldName());
                }
                case SymbolKind.Property:
                {
                    var property = (IPropertySymbol)symbol;
                    if (property.ContainingType.IsGenericType && Equals(property.ContainingType.ConstructedFrom, Context.Instance.NullableType))
                    {
                        property = property.OriginalDefinition;
                        if (Equals(property, Context.Instance.NullableHasValue))
                        {
                            return @this.NotEqualTo(Js.Null()).Parenthetical();
                        }
                        else if (Equals(property, Context.Instance.NullableValue))
                        {
                            return Js.Reference(SpecialNames.NullableGetValue).Invoke(@this);
                        }
                    }

                    return GetPropertyValue(@this, property, isSetter, isBaseReference);
                }
                case SymbolKind.Parameter:
                    return transformer.ReferenceDeclarationInScope(symbol).GetReference();
                case SymbolKind.NamedType:
                    var namedTypeSymbol = (INamedTypeSymbol)symbol;
                    var type = Type(namedTypeSymbol);
                    if (!(type is JsInvocationExpression) && namedTypeSymbol.IsExported())
                        type = type.Invoke();
                    return type;
                case SymbolKind.Local:
                    var declaration = transformer.ReferenceDeclarationInScope(symbol);
                    return !isSetter ? declaration.GetReference() : declaration.SetReference();
                case SymbolKind.Method:
                {
                    var method = (IMethodSymbol)symbol;
                    var containingSymbol = symbol.ContainingType;
                    var name = method.GetMemberName();
                    var target = method.IsStatic ? Type(containingSymbol) : @this;
                    if (Equals(method.ContainingType, containingSymbol))
                    {
                        return target.Member(name);
                    }
                    else if (containingSymbol.IsSubclassOf(method.ContainingType))
                    {
                        return target.Member(name);
                    }
                    else 
                    {
                        throw new Exception();
                    }
                }
                case SymbolKind.Namespace:
                    return Js.Reference(symbol.Name);
                case SymbolKind.Label:
                    return Js.Reference(symbol.Name);
                case SymbolKind.TypeParameter:
                    return Js.Reference(symbol.Name);
                default:
                    throw new InvalidOperationException("Unexpected node: " + symbol);
            }
        }
Ejemplo n.º 34
0
        public bool TryCharUnaryExpression(SyntaxKind type, TypeInfo operandType, JsExpression operand, out JsExpression result)
        {
            if (Equals(operandType.Type, Context.Instance.Char))
            {
                switch (type)
                {
                    case SyntaxKind.PostDecrementExpression:
                    case SyntaxKind.PostIncrementExpression:
                    {
                        var old = Js.Variable("$old", operand);

                        var op = type == SyntaxKind.PostDecrementExpression ? JsBinaryOperator.Subtract : JsBinaryOperator.Add;
                        result = Js.Binary(
                            op, 
                            old.GetReference().Member("charCodeAt").Invoke(Js.Primitive(0)),
                            Js.Primitive(1)
                        );
                        result = operand.Assign(Js.Reference("String").Member("fromCharCode").Invoke(result));

                        var block = new JsBlockStatement();
                        block.Local(old);
                        block.Express(result);
                        block.Return(old.GetReference());
                        result = Wrap(block);

                        return true;
                    }
                    case SyntaxKind.PreDecrementExpression:
                    case SyntaxKind.PreIncrementExpression:
                    {
                        var op = type == SyntaxKind.PreDecrementExpression ? JsBinaryOperator.Subtract : JsBinaryOperator.Add;
                        result = Js.Binary(
                            op, 
                            operand.Member("charCodeAt").Invoke(Js.Primitive(0)),
                            Js.Primitive(1)
                        );
                        result = operand.Assign(Js.Reference("String").Member("fromCharCode").Invoke(result));
                        return true;
                    }
                }
            }
            result = null;
            return false;
        }
Ejemplo n.º 35
0
 public bool TryCharBinaryExpression(SyntaxKind type, TypeInfo leftSymbol, TypeInfo rightSymbol, JsExpression left, JsExpression right, out JsExpression result)
 {
     if (Equals(leftSymbol.Type, Context.Instance.Char) || Equals(rightSymbol.Type, Context.Instance.Char))
     {
         switch (type)
         {
             case SyntaxKind.SubtractExpression:
             case SyntaxKind.AddExpression:
             case SyntaxKind.MultiplyExpression:
             case SyntaxKind.DivideExpression:
             case SyntaxKind.ModuloExpression:
             case SyntaxKind.BitwiseAndExpression:
             case SyntaxKind.BitwiseOrExpression:
             case SyntaxKind.LessThanExpression:
             case SyntaxKind.LessThanOrEqualExpression:
             case SyntaxKind.GreaterThanExpression:
             case SyntaxKind.GreaterThanOrEqualExpression:
             case SyntaxKind.LeftShiftExpression:
             case SyntaxKind.RightShiftExpression:
             case SyntaxKind.ExclusiveOrExpression:
             case SyntaxKind.AddAssignmentExpression:
             case SyntaxKind.SubtractAssignmentExpression:
             case SyntaxKind.MultiplyAssignmentExpression:
             case SyntaxKind.DivideAssignmentExpression:
             case SyntaxKind.ModuloAssignmentExpression:
                 result = Js.Binary(
                     ToBinaryOperator(type).Value,
                     !Equals(leftSymbol.Type, Context.Instance.Char) || Equals(rightSymbol.Type, Context.Instance.String) ? left : left.Member("charCodeAt").Invoke(Js.Primitive(0)),
                     !Equals(rightSymbol.Type, Context.Instance.Char) || Equals(leftSymbol.Type, Context.Instance.String) ? right : right.Member("charCodeAt").Invoke(Js.Primitive(0))
                 );
                 switch (type)
                 {
                     case SyntaxKind.AddAssignmentExpression:
                     case SyntaxKind.SubtractAssignmentExpression:
                     case SyntaxKind.MultiplyAssignmentExpression:
                     case SyntaxKind.DivideAssignmentExpression:
                     case SyntaxKind.ModuloAssignmentExpression:
                         result = left.Assign(Js.Reference("String").Member("fromCharCode").Invoke(result));
                         break;
                 }
                 return true;
         }                
     }
     result = null;
     return false;
 }
Ejemplo n.º 36
0
 public JsInvocationExpression Get(JsExpression target, IPropertySymbol property, params JsExpression[] arguments)
 {
     return target.Member(property.GetMethod.GetMemberName()).Invoke(arguments);
 }
Ejemplo n.º 37
0
 public JsExpressionStatement CreatePrototype(JsExpression type, JsExpression baseType)
 {
     return type.Member("prototype").Assign(Js.New(baseType)).Express();
 }
Ejemplo n.º 38
0
 public JsInvocationExpression Invoke(JsExpression target, IMethodSymbol method, params JsExpression[] arguments)
 {
     return target.Member(method.GetMemberName()).Invoke(arguments);
 }
Ejemplo n.º 39
0
 public JsStatement MapInterfaceMethod(JsExpression assignee, IMethodSymbol interfaceMethod, JsExpression implementation)
 {
     return assignee.Member(interfaceMethod.GetMemberName()).Assign(implementation).Express();
 }