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; "); }
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; "); }
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; }); "); }
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; "); }
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)); }
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))); }
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)); }
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; }); "); }
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 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; "); }
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; "); }
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); }
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); } }
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)); }
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)); }
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. } }
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); } }
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(); } }
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); } }
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; }
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; }
public JsInvocationExpression Get(JsExpression target, IPropertySymbol property, params JsExpression[] arguments) { return target.Member(property.GetMethod.GetMemberName()).Invoke(arguments); }
public JsExpressionStatement CreatePrototype(JsExpression type, JsExpression baseType) { return type.Member("prototype").Assign(Js.New(baseType)).Express(); }
public JsInvocationExpression Invoke(JsExpression target, IMethodSymbol method, params JsExpression[] arguments) { return target.Member(method.GetMemberName()).Invoke(arguments); }
public JsStatement MapInterfaceMethod(JsExpression assignee, IMethodSymbol interfaceMethod, JsExpression implementation) { return assignee.Member(interfaceMethod.GetMemberName()).Assign(implementation).Express(); }