From 05aa209bd0bab55b0d85d356b22b73600c148c28 Mon Sep 17 00:00:00 2001 From: Igor Kiselev Date: Fri, 22 Jul 2016 12:49:58 -0700 Subject: [PATCH 01/10] Detecting circular reference for TypeScript updated. --- JSIL/DefinitelyTypedAssemblyEmitter.cs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/JSIL/DefinitelyTypedAssemblyEmitter.cs b/JSIL/DefinitelyTypedAssemblyEmitter.cs index 7d56cbb8d..2757483b7 100644 --- a/JSIL/DefinitelyTypedAssemblyEmitter.cs +++ b/JSIL/DefinitelyTypedAssemblyEmitter.cs @@ -626,7 +626,7 @@ public static bool WriteTypeReference (this JavascriptFormatter formatter, TypeR * It could be improved, by we really need generic variance support or support of: type T = something & I (see Microsoft/TypeScript#6230) */ - var fixedMode = (replaceMode != ReplaceMode.Instance && context == definition) ? ReplaceMode.Instance : replaceMode; + var fixedMode = (replaceMode != ReplaceMode.Instance && IsCircularRef(definition, context)) ? ReplaceMode.Instance : replaceMode; formatter.TRSuffix(fixedMode); } else { @@ -639,6 +639,27 @@ public static bool WriteTypeReference (this JavascriptFormatter formatter, TypeR return true; } + public static bool IsCircularRef (TypeReference type, TypeDefinition context) { + if (type is GenericParameter) { + return false; + } + if (type is ArrayType) { + return IsCircularRef(((ArrayType) type).ElementType, context); + } + if (type is GenericInstanceType) { + var gt = (GenericInstanceType) type; + foreach (var genericArgument in gt.GenericArguments) { + if (IsCircularRef(genericArgument, context)) { + return true; + } + } + } + if (type.Resolve() == context) { + return true; + }; + return false; + } + public static void CommaSeparatedList (this JavascriptFormatter formatter, IEnumerable list, Action process) { bool first = true; foreach (var item in list) { From 4595943b11af30d7736de050a1210bb18214756b Mon Sep 17 00:00:00 2001 From: Igor Kiselev Date: Fri, 22 Jul 2016 14:40:32 -0700 Subject: [PATCH 02/10] Improved circular ref detection --- JSIL/DefinitelyTypedAssemblyEmitter.cs | 35 ++++++++++++++++++++------ 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/JSIL/DefinitelyTypedAssemblyEmitter.cs b/JSIL/DefinitelyTypedAssemblyEmitter.cs index 2757483b7..84b1ec751 100644 --- a/JSIL/DefinitelyTypedAssemblyEmitter.cs +++ b/JSIL/DefinitelyTypedAssemblyEmitter.cs @@ -626,7 +626,7 @@ public static bool WriteTypeReference (this JavascriptFormatter formatter, TypeR * It could be improved, by we really need generic variance support or support of: type T = something & I (see Microsoft/TypeScript#6230) */ - var fixedMode = (replaceMode != ReplaceMode.Instance && IsCircularRef(definition, context)) ? ReplaceMode.Instance : replaceMode; + var fixedMode = (replaceMode != ReplaceMode.Instance && IsCircularRef(definition, context, null)) ? ReplaceMode.Instance : replaceMode; formatter.TRSuffix(fixedMode); } else { @@ -639,24 +639,45 @@ public static bool WriteTypeReference (this JavascriptFormatter formatter, TypeR return true; } - public static bool IsCircularRef (TypeReference type, TypeDefinition context) { + public static bool IsCircularRef (TypeReference type, TypeDefinition context, List checkedList) { + if (checkedList == null) { + checkedList = new List(); + } + if (type is GenericParameter) { return false; } if (type is ArrayType) { - return IsCircularRef(((ArrayType) type).ElementType, context); + return IsCircularRef(((ArrayType) type).ElementType, context, checkedList); } if (type is GenericInstanceType) { var gt = (GenericInstanceType) type; foreach (var genericArgument in gt.GenericArguments) { - if (IsCircularRef(genericArgument, context)) { + if (IsCircularRef(genericArgument, context, checkedList)) { + return true; + } + } + } + + var resolvedType = type.Resolve(); + if (resolvedType != null) { + if (checkedList.Contains(resolvedType)) { + return false; + } + checkedList.Add(resolvedType); + + if (resolvedType == context) { + return true; + } + if (resolvedType.BaseType != null && IsCircularRef(resolvedType.BaseType, context, checkedList)) { + return true; + } + foreach (var typeReference in resolvedType.Interfaces) { + if (IsCircularRef(typeReference, context, checkedList)) { return true; } } } - if (type.Resolve() == context) { - return true; - }; return false; } From 027dbda4a43ef8e6e5e6be91693ee780ccf73151 Mon Sep 17 00:00:00 2001 From: Igor Kiselev Date: Fri, 22 Jul 2016 15:04:10 -0700 Subject: [PATCH 03/10] Added null check for CircularRef check. --- JSIL/DefinitelyTypedAssemblyEmitter.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/JSIL/DefinitelyTypedAssemblyEmitter.cs b/JSIL/DefinitelyTypedAssemblyEmitter.cs index 84b1ec751..2932eb293 100644 --- a/JSIL/DefinitelyTypedAssemblyEmitter.cs +++ b/JSIL/DefinitelyTypedAssemblyEmitter.cs @@ -640,12 +640,13 @@ public static bool WriteTypeReference (this JavascriptFormatter formatter, TypeR } public static bool IsCircularRef (TypeReference type, TypeDefinition context, List checkedList) { - if (checkedList == null) { - checkedList = new List(); + if (type is GenericParameter || context == null || type == null) + { + return false; } - if (type is GenericParameter) { - return false; + if (checkedList == null) { + checkedList = new List(); } if (type is ArrayType) { return IsCircularRef(((ArrayType) type).ElementType, context, checkedList); @@ -669,7 +670,7 @@ public static bool IsCircularRef (TypeReference type, TypeDefinition context, Li if (resolvedType == context) { return true; } - if (resolvedType.BaseType != null && IsCircularRef(resolvedType.BaseType, context, checkedList)) { + if (IsCircularRef(resolvedType.BaseType, context, checkedList)) { return true; } foreach (var typeReference in resolvedType.Interfaces) { From aa43bc2618629a23b5df0db12dbbf8174d2fbf9c Mon Sep 17 00:00:00 2001 From: Igor Kiselev Date: Mon, 25 Jul 2016 13:26:56 -0700 Subject: [PATCH 04/10] Added module for TypeScript interop helper functions. --- .../DefinitelyTyped/module.JSIL.TypeScriptInterop.d.ts | 5 +++++ .../DefinitelyTyped/module.JSIL.TypeScriptInterop.js | 5 +++++ JSIL/JSIL.csproj | 8 ++++++++ 3 files changed, 18 insertions(+) create mode 100644 JSIL/JS Libraries/DefinitelyTyped/module.JSIL.TypeScriptInterop.d.ts create mode 100644 JSIL/JS Libraries/DefinitelyTyped/module.JSIL.TypeScriptInterop.js diff --git a/JSIL/JS Libraries/DefinitelyTyped/module.JSIL.TypeScriptInterop.d.ts b/JSIL/JS Libraries/DefinitelyTyped/module.JSIL.TypeScriptInterop.d.ts new file mode 100644 index 000000000..a5584526d --- /dev/null +++ b/JSIL/JS Libraries/DefinitelyTyped/module.JSIL.TypeScriptInterop.d.ts @@ -0,0 +1,5 @@ +import * as jsilCore from "./module.JSIL.Core"; + +type NetString = typeof jsilCore.System.String.$Undefined; + +export function AsNetString(input: string): NetString \ No newline at end of file diff --git a/JSIL/JS Libraries/DefinitelyTyped/module.JSIL.TypeScriptInterop.js b/JSIL/JS Libraries/DefinitelyTyped/module.JSIL.TypeScriptInterop.js new file mode 100644 index 000000000..f3cde5925 --- /dev/null +++ b/JSIL/JS Libraries/DefinitelyTyped/module.JSIL.TypeScriptInterop.js @@ -0,0 +1,5 @@ +JSIL.AsNetString = function (input) { + return input; +} + +module.exports = JSIL; \ No newline at end of file diff --git a/JSIL/JSIL.csproj b/JSIL/JSIL.csproj index 0a1dea55b..cb794007a 100644 --- a/JSIL/JSIL.csproj +++ b/JSIL/JSIL.csproj @@ -168,6 +168,9 @@ + + PreserveNewest + @@ -183,5 +186,10 @@ PreserveNewest + + + PreserveNewest + + \ No newline at end of file From 3d3b36a2d4dbef9da98b7418c4fea14199344ad7 Mon Sep 17 00:00:00 2001 From: Igor Kiselev Date: Tue, 26 Jul 2016 22:23:27 -0700 Subject: [PATCH 05/10] Nullable types support. --- JSIL/DefinitelyTypedAssemblyEmitter.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/JSIL/DefinitelyTypedAssemblyEmitter.cs b/JSIL/DefinitelyTypedAssemblyEmitter.cs index 2932eb293..39396e861 100644 --- a/JSIL/DefinitelyTypedAssemblyEmitter.cs +++ b/JSIL/DefinitelyTypedAssemblyEmitter.cs @@ -575,7 +575,10 @@ public static bool WriteTypeReference (this JavascriptFormatter formatter, TypeR } } else if (typeReference is GenericInstanceType) { var genericType = (GenericInstanceType) typeReference; - if (formatter.WriteTypeReference(genericType.ElementType, context, replaceMode)) /*TODO*/ { + if (genericType.Resolve().FullName == "System.Nullable`1") { + formatter.WriteTypeReference(genericType.GenericArguments[0], context, replaceMode); + } + else if (formatter.WriteTypeReference(genericType.ElementType, context, replaceMode)) /*TODO*/ { formatter.WriteRaw("<"); formatter.CommaSeparatedList(genericType.GenericArguments, genericArgument => { formatter.WriteTypeReference(genericArgument, context, ReplaceMode.Instance); From 0dc363bf4dd135b35bfed67d6d95d5f76a3d00f3 Mon Sep 17 00:00:00 2001 From: Igor Kiselev Date: Wed, 27 Jul 2016 13:54:53 -0700 Subject: [PATCH 06/10] All interfaces could be used as System.Object --- JSIL/DefinitelyTypedAssemblyEmitter.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/JSIL/DefinitelyTypedAssemblyEmitter.cs b/JSIL/DefinitelyTypedAssemblyEmitter.cs index 39396e861..48b6b26f9 100644 --- a/JSIL/DefinitelyTypedAssemblyEmitter.cs +++ b/JSIL/DefinitelyTypedAssemblyEmitter.cs @@ -158,6 +158,13 @@ private void EmitClassInOutType (TypeDefinition typedef) { Formatter.WriteTypeReference(iface, typedef, JavascriptFormatterHelper.ReplaceMode.In, false); } + if (typedef.IsInterface) { + Formatter.Space(); + Formatter.WriteRaw("|"); + Formatter.Space(); + Formatter.WriteTypeReference(typedef.Module.TypeSystem.Object, typedef, JavascriptFormatterHelper.ReplaceMode.In, false); + } + Formatter.Semicolon(); /*Out*/ @@ -185,6 +192,14 @@ private void EmitClassInOutType (TypeDefinition typedef) { Formatter.WriteTypeReference(iface, typedef, JavascriptFormatterHelper.ReplaceMode.Out, false); } + if (typedef.IsInterface) + { + Formatter.Space(); + Formatter.WriteRaw("&"); + Formatter.Space(); + Formatter.WriteTypeReference(typedef.Module.TypeSystem.Object, typedef, JavascriptFormatterHelper.ReplaceMode.Out, false); + } + Formatter.Semicolon(); } From 2a2349522a31486fcbb8729a3b8ccf6db081a1e8 Mon Sep 17 00:00:00 2001 From: Igor Kiselev Date: Wed, 27 Jul 2016 16:57:40 -0700 Subject: [PATCH 07/10] Include generic suffix for interface methods --- JSIL/DefinitelyTypedAssemblyEmitter.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/JSIL/DefinitelyTypedAssemblyEmitter.cs b/JSIL/DefinitelyTypedAssemblyEmitter.cs index 48b6b26f9..c5009d54e 100644 --- a/JSIL/DefinitelyTypedAssemblyEmitter.cs +++ b/JSIL/DefinitelyTypedAssemblyEmitter.cs @@ -245,7 +245,10 @@ private void EmitClassStatic (TypeDefinition typedef) { } if (typedef.IsInterface) { - var instanceMethods = typedef.Methods.Where(it => it.IsPublic && !Translator.ShouldSkipMember(it)).GroupBy(method => method.Name).OrderBy(group => group.Key); + var instanceMethods = typedef.Methods + .Where(it => it.IsPublic && !Translator.ShouldSkipMember(it)) + .GroupBy(method => method.Name + (method.HasGenericParameters ? "`" + method.GenericParameters.Count : string.Empty)) + .OrderBy(group => group.Key); foreach (var instanceMethodGroup in instanceMethods) { EmitInterfaceMethodGroup(instanceMethodGroup.Key, instanceMethodGroup); From 3a4e135bf02be4d16836f9bdda1326fb3a23e320 Mon Sep 17 00:00:00 2001 From: Igor Kiselev Date: Wed, 27 Jul 2016 17:43:03 -0700 Subject: [PATCH 08/10] Fixed InterfaceMethod.prototype.$MakeCallMethod error. Added AsIntXX() helpers. --- JSIL.Libraries/Sources/JSIL.Core.js | 2 +- .../DefinitelyTyped/internals/JSIL.Core.d.ts | 10 -------- .../module.JSIL.TypeScriptInterop.d.ts | 10 +++++--- .../module.JSIL.TypeScriptInterop.js | 24 +++++++++++++++++++ 4 files changed, 32 insertions(+), 14 deletions(-) diff --git a/JSIL.Libraries/Sources/JSIL.Core.js b/JSIL.Libraries/Sources/JSIL.Core.js index 773d5ff9c..d4894c167 100644 --- a/JSIL.Libraries/Sources/JSIL.Core.js +++ b/JSIL.Libraries/Sources/JSIL.Core.js @@ -8492,7 +8492,7 @@ JSIL.InterfaceMethod.prototype.$MakeCallMethod = function () { var target = thisObject[key]; var targetFunctionArgs = Array.prototype.slice.call(arguments, 2); if (genericArgs) { - resolvedTarget = target.apply(thisObject, genericArgs); + var resolvedTarget = target.apply(thisObject, genericArgs); return resolvedTarget(targetFunctionArgs); } else { return target.apply(thisObject, targetFunctionArgs); diff --git a/JSIL/JS Libraries/DefinitelyTyped/internals/JSIL.Core.d.ts b/JSIL/JS Libraries/DefinitelyTyped/internals/JSIL.Core.d.ts index ef22ac0cb..3bf87242f 100644 --- a/JSIL/JS Libraries/DefinitelyTyped/internals/JSIL.Core.d.ts +++ b/JSIL/JS Libraries/DefinitelyTyped/internals/JSIL.Core.d.ts @@ -48,7 +48,6 @@ export declare namespace $private{ type TIn = Instance; type TOut = Instance & number; interface Static extends Type { - new (arg: number): TOut; } type Factory = Static; } @@ -59,7 +58,6 @@ export declare namespace $private{ type TIn = Instance; type TOut = Instance & number; interface Static extends Type { - new (arg: number): TOut; } type Factory = Static; } @@ -70,7 +68,6 @@ export declare namespace $private{ type TIn = Instance; type TOut = Instance & number; interface Static extends Type { - new (arg: number): TOut; } type Factory = Static; } @@ -81,7 +78,6 @@ export declare namespace $private{ type TIn = Instance; type TOut = Instance & number; interface Static extends Type { - new (arg: number): TOut; } type Factory = Static; } @@ -92,7 +88,6 @@ export declare namespace $private{ type TIn = Instance; type TOut = Instance & number; interface Static extends Type { - new (arg: number): TOut; } type Factory = Static; } @@ -103,7 +98,6 @@ export declare namespace $private{ type TIn = Instance; type TOut = Instance & number; interface Static extends Type { - new (arg: number): TOut; } type Factory = Static; } @@ -112,7 +106,6 @@ export declare namespace $private{ type TIn = Instance; type TOut = Instance; interface Static extends Type { - new (arg: number): TOut; } type Factory = Static; } @@ -121,7 +114,6 @@ export declare namespace $private{ type TIn = Instance; type TOut = Instance; interface Static extends Type { - new(arg: number): TOut; } type Factory = Static; } @@ -130,7 +122,6 @@ export declare namespace $private{ type TIn = Instance; type TOut = Instance; interface Static extends Type { - new(arg: number): TOut; } type Factory = Static; } @@ -141,7 +132,6 @@ export declare namespace $private{ type TIn = Instance; type TOut = Instance & string; interface Static extends Type { - new (arg: number): TOut; } type Factory = Static; } diff --git a/JSIL/JS Libraries/DefinitelyTyped/module.JSIL.TypeScriptInterop.d.ts b/JSIL/JS Libraries/DefinitelyTyped/module.JSIL.TypeScriptInterop.d.ts index a5584526d..b9a6173f2 100644 --- a/JSIL/JS Libraries/DefinitelyTyped/module.JSIL.TypeScriptInterop.d.ts +++ b/JSIL/JS Libraries/DefinitelyTyped/module.JSIL.TypeScriptInterop.d.ts @@ -1,5 +1,9 @@ import * as jsilCore from "./module.JSIL.Core"; -type NetString = typeof jsilCore.System.String.$Undefined; - -export function AsNetString(input: string): NetString \ No newline at end of file +export function AsNetString(input: string): typeof jsilCore.System.String.$Undefined; +export function AsInt32(input: number): typeof jsilCore.System.Int32.$Undefined; +export function AsUInt32(input: number): typeof jsilCore.System.UInt32.$Undefined; +export function AsInt16(input: number): typeof jsilCore.System.Int16.$Undefined; +export function AsUInt16(input: number): typeof jsilCore.System.UInt16.$Undefined; +export function AsByte(input: number): typeof jsilCore.System.Byte.$Undefined; +export function AsSByte(input: number): typeof jsilCore.System.SByte.$Undefined; \ No newline at end of file diff --git a/JSIL/JS Libraries/DefinitelyTyped/module.JSIL.TypeScriptInterop.js b/JSIL/JS Libraries/DefinitelyTyped/module.JSIL.TypeScriptInterop.js index f3cde5925..c28c73813 100644 --- a/JSIL/JS Libraries/DefinitelyTyped/module.JSIL.TypeScriptInterop.js +++ b/JSIL/JS Libraries/DefinitelyTyped/module.JSIL.TypeScriptInterop.js @@ -2,4 +2,28 @@ JSIL.AsNetString = function (input) { return input; } +JSIL.AsInt32 = function (input) { + return input | 0; +} + +JSIL.AsUInt32 = function (input) { + return input >>> 0; +} + +JSIL.AsInt16 = function (input) { + return (input | 0) && 0xFFFF; +} + +JSIL.AsUInt16 = function (input) { + return (input >>> 0) && 0xFFFF; +} + +JSIL.AsSByte = function (input) { + return (input | 0) && 0xFF; +} + +JSIL.AsByte = function (input) { + return (input >>> 0) && 0xFF; +} + module.exports = JSIL; \ No newline at end of file From 35b244ceda2425aef80c03c66c74ac88d3dcc5ef Mon Sep 17 00:00:00 2001 From: Igor Kiselev Date: Mon, 8 Aug 2016 17:00:52 -0700 Subject: [PATCH 09/10] d.ts generators doesn't write type references for ignored assemblies --- JSIL/AssemblyTranslator.cs | 22 ++-------------------- JSIL/DefinitelyTypedAssemblyEmitter.cs | 7 ++++++- 2 files changed, 8 insertions(+), 21 deletions(-) diff --git a/JSIL/AssemblyTranslator.cs b/JSIL/AssemblyTranslator.cs index 9af9e54a5..b2c4877bd 100644 --- a/JSIL/AssemblyTranslator.cs +++ b/JSIL/AssemblyTranslator.cs @@ -284,12 +284,7 @@ protected ParallelOptions GetParallelOptions () { } protected bool IsIgnored (string assemblyName) { - foreach (var ia in Configuration.Assemblies.Ignored) { - if (Regex.IsMatch(assemblyName, ia, RegexOptions.IgnoreCase)) - return true; - } - - return false; + return Configuration.IsIgnoredAssembly(assemblyName); } protected string ResolveRedirectedName (string assemblyName) { @@ -841,20 +836,7 @@ private void GetMethodsToAnalyze (AssemblyDefinition assembly, ConcurrentBag assemblies) { if (assemblies != null) { foreach (var referenceOverride in assemblies) { - if (!Translator.IsIgnoredAssembly(referenceOverride.Value)) { + if (!Translator.Configuration.IsIgnoredAssembly(referenceOverride.Value)) { Formatter.WriteRaw(string.Format("import {{$private as {0}}} from \"./{1}\"", referenceOverride.Key.IDString, referenceOverride.Value)); Formatter.Semicolon(); } @@ -625,6 +625,11 @@ public static bool WriteTypeReference (this JavascriptFormatter formatter, TypeR } else if (targetAssembly == formatter.Assembly.FullName) { assemblyRef = string.Empty; } else { + if (formatter.Configuration.IsIgnoredAssembly(targetAssembly)) { + formatter.WriteRaw("Object"); // TODO. Think what type use for ignored assemblies. + return false; + } + assemblyRef = formatter.Manifest.Entries.FirstOrDefault(item => item.Value == targetAssembly).Key; } if (definition != null && assemblyRef != null) { From 0923e48e65f7a7c7f7ba54f00395c602b0ad9f1c Mon Sep 17 00:00:00 2001 From: Igor Kiselev Date: Tue, 9 Aug 2016 12:51:52 -0700 Subject: [PATCH 10/10] Build fix (added missed change) --- JSIL/Configuration.cs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/JSIL/Configuration.cs b/JSIL/Configuration.cs index c90bd24a8..f5c4120c5 100644 --- a/JSIL/Configuration.cs +++ b/JSIL/Configuration.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Text.RegularExpressions; namespace JSIL.Translator { [Serializable] @@ -154,7 +155,7 @@ public virtual void MergeInto (Configuration result) { if (UseThreads.HasValue) result.UseThreads = UseThreads; if (UseDefaultProxies.HasValue) - result.UseDefaultProxies = UseDefaultProxies; + result.UseDefaultProxies = UseDefaultProxies; if (FrameworkVersion.HasValue) result.FrameworkVersion = FrameworkVersion; @@ -191,4 +192,16 @@ public virtual void MergeInto (Configuration result) { CodeGenerator.MergeInto(result.CodeGenerator); } } + + public static class ConfigurationHelper { + public static bool IsIgnoredAssembly (this Configuration configurain, string assemblyName) { + foreach (var sa in configurain.Assemblies.Ignored) { + if (Regex.IsMatch(assemblyName, sa, RegexOptions.IgnoreCase)) { + return true; + } + } + + return false; + } + } }