From df39df364a92c8812e5e73f1d2013ebae7c6954f Mon Sep 17 00:00:00 2001
From: Artyom Sovetnikov <2056864+elringus@users.noreply.github.com>
Date: Tue, 28 May 2024 20:15:57 +0300
Subject: [PATCH] fix serialization context (#156)
---
.../Bootsharp.Common.Test.csproj | 10 +--
.../Bootsharp.Common.Test/SerializerTest.cs | 16 ++--
src/cs/Bootsharp.Common.Test/TypesTest.cs | 9 ---
src/cs/Bootsharp.Common/Interop/Serializer.cs | 6 +-
.../Bootsharp.Generate.Test.csproj | 12 +--
.../Bootsharp.Inject.Test.csproj | 10 +--
.../Bootsharp.Inject/Bootsharp.Inject.csproj | 2 +-
.../Bootsharp.Publish.Test.csproj | 16 ++--
.../Emit/DependenciesTest.cs | 2 +-
.../Emit/InterfacesTest.cs | 4 +-
.../Emit/InteropTest.cs | 20 ++---
.../Emit/SerializerTest.cs | 64 +--------------
.../Pack/BindingTest.cs | 8 +-
.../Pack/DeclarationTest.cs | 14 ++--
src/cs/Bootsharp.Publish.Test/TaskTest.cs | 5 ++
.../Bootsharp.Publish.csproj | 4 +-
.../Common/Global/GlobalInspection.cs | 36 +++++++++
.../Common/Global/GlobalSerialization.cs | 55 +++++++++++++
.../GlobalText.cs} | 4 +-
.../GlobalType.cs} | 80 +------------------
.../SolutionInspector/SolutionInspection.cs | 2 +-
.../Common/TypeConverter/TypeConverter.cs | 3 +
.../Emit/InteropGenerator.cs | 44 +++++-----
.../Emit/SerializerGenerator.cs | 32 --------
.../Pack/BindingGenerator/BindingGenerator.cs | 24 +++---
src/cs/Directory.Build.props | 2 +-
src/js/package.json | 10 +--
src/js/test/cs/Test/Functions.cs | 41 ++++++++++
src/js/test/spec/interop.spec.ts | 48 +++++++++--
29 files changed, 300 insertions(+), 283 deletions(-)
create mode 100644 src/cs/Bootsharp.Publish/Common/Global/GlobalInspection.cs
create mode 100644 src/cs/Bootsharp.Publish/Common/Global/GlobalSerialization.cs
rename src/cs/Bootsharp.Publish/Common/{TextUtilities.cs => Global/GlobalText.cs} (87%)
rename src/cs/Bootsharp.Publish/Common/{TypeUtilities.cs => Global/GlobalType.cs} (65%)
diff --git a/src/cs/Bootsharp.Common.Test/Bootsharp.Common.Test.csproj b/src/cs/Bootsharp.Common.Test/Bootsharp.Common.Test.csproj
index 0a66cd84..6bb47b48 100644
--- a/src/cs/Bootsharp.Common.Test/Bootsharp.Common.Test.csproj
+++ b/src/cs/Bootsharp.Common.Test/Bootsharp.Common.Test.csproj
@@ -11,17 +11,17 @@
-
-
-
+
+
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
-
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
-
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
diff --git a/src/cs/Bootsharp.Common.Test/SerializerTest.cs b/src/cs/Bootsharp.Common.Test/SerializerTest.cs
index 386215bf..fd26c9c7 100644
--- a/src/cs/Bootsharp.Common.Test/SerializerTest.cs
+++ b/src/cs/Bootsharp.Common.Test/SerializerTest.cs
@@ -21,7 +21,7 @@ public void WhenInfoResolverNotAssignedThrowsError ()
TypeInfoResolver = null
};
Assert.Contains("Serializer info resolver is not assigned",
- Assert.Throws(() => Serialize("")).Message);
+ Assert.Throws(() => Serialize("", null)).Message);
}
[Fact]
@@ -31,20 +31,20 @@ public void WhenTypeInfoNotAvailableThrowsError ()
TypeInfoResolver = new MockResolver()
};
Assert.Contains("Failed to resolve serializer info",
- Assert.Throws(() => Serialize("")).Message);
+ Assert.Throws(() => Serialize("", null)).Message);
}
[Fact]
public void CanSerialize ()
{
Assert.Equal("""{"items":[{"id":"foo"},{"id":"bar"}]}""",
- Serialize(new MockRecord(new MockItem[] { new("foo"), new("bar") })));
+ Serialize(new MockRecord(new MockItem[] { new("foo"), new("bar") }), typeof(MockRecord)));
}
[Fact]
public void SerializesNullAsNull ()
{
- Assert.Equal("null", Serialize(null));
+ Assert.Equal("null", Serialize(null, null));
}
[Fact]
@@ -77,8 +77,8 @@ public void WhenDeserializationFailsErrorIsThrown ()
[Fact]
public void RespectsOptions ()
{
- Assert.Equal("{\"enum\":0}", Serialize(new MockItemWithEnum(MockEnum.Foo)));
- Assert.Equal("{\"enum\":null}", Serialize(new MockItemWithEnum(null)));
+ Assert.Equal("{\"enum\":0}", Serialize(new MockItemWithEnum(MockEnum.Foo), typeof(MockItemWithEnum)));
+ Assert.Equal("{\"enum\":null}", Serialize(new MockItemWithEnum(null), typeof(MockItemWithEnum)));
Assert.Equal(MockEnum.Foo, Deserialize("{\"enum\":0}").Enum);
Assert.Null((Deserialize("{\"enum\":null}")).Enum);
Options = new JsonSerializerOptions(JsonSerializerDefaults.Web) {
@@ -86,8 +86,8 @@ public void RespectsOptions ()
Converters = { new JsonStringEnumConverter() },
TypeInfoResolver = new DefaultJsonTypeInfoResolver()
};
- Assert.Equal("{\"enum\":\"Foo\"}", Serialize(new MockItemWithEnum(MockEnum.Foo)));
- Assert.Equal("{}", Serialize(new MockItemWithEnum(null)));
+ Assert.Equal("{\"enum\":\"Foo\"}", Serialize(new MockItemWithEnum(MockEnum.Foo), typeof(MockItemWithEnum)));
+ Assert.Equal("{}", Serialize(new MockItemWithEnum(null), typeof(MockItemWithEnum)));
Assert.Equal(MockEnum.Foo, (Deserialize("{\"enum\":\"Foo\"}")).Enum);
Assert.Null((Deserialize("{}")).Enum);
}
diff --git a/src/cs/Bootsharp.Common.Test/TypesTest.cs b/src/cs/Bootsharp.Common.Test/TypesTest.cs
index f706a478..e60a911f 100644
--- a/src/cs/Bootsharp.Common.Test/TypesTest.cs
+++ b/src/cs/Bootsharp.Common.Test/TypesTest.cs
@@ -11,15 +11,6 @@ public class TypesTest
private readonly CustomAttributeData export = GetMockExportAttribute();
private readonly CustomAttributeData import = GetMockImportAttribute();
- [Fact]
- public void Records ()
- {
- // TODO: Remove when coverlet bug is resolved: https://github.com/coverlet-coverage/coverlet/issues/1561
- _ = new MockItem("") with { Id = "foo" };
- _ = new MockItemWithEnum(default) with { Enum = MockEnum.Bar };
- _ = new MockRecord(default) with { Items = new[] { new MockItem("") } };
- }
-
[Fact]
public void TypesAreAssigned ()
{
diff --git a/src/cs/Bootsharp.Common/Interop/Serializer.cs b/src/cs/Bootsharp.Common/Interop/Serializer.cs
index 74d628dd..a15b5a5a 100644
--- a/src/cs/Bootsharp.Common/Interop/Serializer.cs
+++ b/src/cs/Bootsharp.Common/Interop/Serializer.cs
@@ -17,12 +17,12 @@ public static class Serializer
};
///
- /// Serializes specified object to JSON string.
+ /// Serializes specified object to JSON string using specified serialization context type.
///
- public static string Serialize (object? @object)
+ public static string Serialize (object? @object, Type type)
{
if (@object is null) return "null";
- return JsonSerializer.Serialize(@object, GetInfo(@object.GetType()));
+ return JsonSerializer.Serialize(@object, GetInfo(type));
}
///
diff --git a/src/cs/Bootsharp.Generate.Test/Bootsharp.Generate.Test.csproj b/src/cs/Bootsharp.Generate.Test/Bootsharp.Generate.Test.csproj
index 742b45f6..00022940 100644
--- a/src/cs/Bootsharp.Generate.Test/Bootsharp.Generate.Test.csproj
+++ b/src/cs/Bootsharp.Generate.Test/Bootsharp.Generate.Test.csproj
@@ -16,19 +16,19 @@
-
+
-
-
-
+
+
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
-
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
-
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
diff --git a/src/cs/Bootsharp.Inject.Test/Bootsharp.Inject.Test.csproj b/src/cs/Bootsharp.Inject.Test/Bootsharp.Inject.Test.csproj
index e0e26eb3..f409c828 100644
--- a/src/cs/Bootsharp.Inject.Test/Bootsharp.Inject.Test.csproj
+++ b/src/cs/Bootsharp.Inject.Test/Bootsharp.Inject.Test.csproj
@@ -13,17 +13,17 @@
-
-
-
+
+
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
-
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
-
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
diff --git a/src/cs/Bootsharp.Inject/Bootsharp.Inject.csproj b/src/cs/Bootsharp.Inject/Bootsharp.Inject.csproj
index 8af681c1..adac40d0 100644
--- a/src/cs/Bootsharp.Inject/Bootsharp.Inject.csproj
+++ b/src/cs/Bootsharp.Inject/Bootsharp.Inject.csproj
@@ -13,7 +13,7 @@
-
+
diff --git a/src/cs/Bootsharp.Publish.Test/Bootsharp.Publish.Test.csproj b/src/cs/Bootsharp.Publish.Test/Bootsharp.Publish.Test.csproj
index 09eb9248..30a8a5b8 100644
--- a/src/cs/Bootsharp.Publish.Test/Bootsharp.Publish.Test.csproj
+++ b/src/cs/Bootsharp.Publish.Test/Bootsharp.Publish.Test.csproj
@@ -11,20 +11,20 @@
-
-
-
-
-
-
+
+
+
+
+
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
-
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
-
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
diff --git a/src/cs/Bootsharp.Publish.Test/Emit/DependenciesTest.cs b/src/cs/Bootsharp.Publish.Test/Emit/DependenciesTest.cs
index a542fb74..f1e7bb15 100644
--- a/src/cs/Bootsharp.Publish.Test/Emit/DependenciesTest.cs
+++ b/src/cs/Bootsharp.Publish.Test/Emit/DependenciesTest.cs
@@ -72,7 +72,7 @@ public class Class
Added(All, "Bootsharp.Generated.Imports.JSImportedInstancedA");
Added(All, "Bootsharp.Generated.Imports.JSImportedInstancedB");
// Export interop instances are not generated in C#; they're authored by user.
- Assert.DoesNotContain("Bootsharp.Generated.Exports.JSExportedInstanced", TestedContent);
+ DoesNotContain("Bootsharp.Generated.Exports.JSExportedInstanced");
}
[Fact]
diff --git a/src/cs/Bootsharp.Publish.Test/Emit/InterfacesTest.cs b/src/cs/Bootsharp.Publish.Test/Emit/InterfacesTest.cs
index b1e78d6a..df90858c 100644
--- a/src/cs/Bootsharp.Publish.Test/Emit/InterfacesTest.cs
+++ b/src/cs/Bootsharp.Publish.Test/Emit/InterfacesTest.cs
@@ -146,7 +146,7 @@ public class JSImported(global::System.Int32 _id) : global::IImported
}
}
""");
- Assert.DoesNotContain("JSExported", TestedContent); // Exported instances are authored by user and registered on initial interop.
+ DoesNotContain("JSExported"); // Exported instances are authored by user and registered on initial interop.
}
[Fact]
@@ -297,6 +297,6 @@ public class Class
}
"""));
Execute();
- Assert.DoesNotContain("Foo", TestedContent, StringComparison.OrdinalIgnoreCase);
+ DoesNotContain("Foo");
}
}
diff --git a/src/cs/Bootsharp.Publish.Test/Emit/InteropTest.cs b/src/cs/Bootsharp.Publish.Test/Emit/InteropTest.cs
index f49c8b07..f1c8ffe3 100644
--- a/src/cs/Bootsharp.Publish.Test/Emit/InteropTest.cs
+++ b/src/cs/Bootsharp.Publish.Test/Emit/InteropTest.cs
@@ -26,8 +26,8 @@ internal static void RegisterProxies ()
public void GeneratesDisposeInstanceBindings ()
{
Execute();
- Contains("JSExport] internal static void DisposeExportedInstance (global::System.Int32 id) => global::Bootsharp.Instances.Dispose(id);");
- Contains("""JSImport("disposeInstance", "Bootsharp")] internal static partial void DisposeImportedInstance (global::System.Int32 id);""");
+ Contains("JSExport] internal static void DisposeExportedInstance (int id) => global::Bootsharp.Instances.Dispose(id);");
+ Contains("""JSImport("disposeInstance", "Bootsharp")] internal static partial void DisposeImportedInstance (int id);""");
}
[Fact]
@@ -158,7 +158,7 @@ public class Class
}
"""));
Execute();
- Assert.DoesNotContain("Foo", TestedContent, StringComparison.OrdinalIgnoreCase);
+ DoesNotContain("Foo");
}
[Fact]
@@ -206,17 +206,17 @@ public class Class
}
"""));
Execute();
- Contains("""Proxies.Set("Space.Class.FunA", (global::Space.Record a) => Deserialize(Space_Class_FunA(Serialize(a))));""");
- Contains("""Proxies.Set("Space.Class.FunB", async (global::Space.Record?[]? a) => Deserialize(await Space_Class_FunB(Serialize(a))));""");
- Contains("JSExport] internal static global::System.String Space_Class_InvA (global::System.String a) => Serialize(global::Space.Class.InvA(Deserialize(a)));");
- Contains("JSExport] internal static async global::System.Threading.Tasks.Task Space_Class_InvB (global::System.String? a) => Serialize(await global::Space.Class.InvB(Deserialize(a)));");
+ Contains("""Proxies.Set("Space.Class.FunA", (global::Space.Record a) => Deserialize(Space_Class_FunA(Serialize(a, typeof(global::Space.Record)))));""");
+ Contains("""Proxies.Set("Space.Class.FunB", async (global::Space.Record?[]? a) => Deserialize(await Space_Class_FunB(Serialize(a, typeof(global::Space.Record[])))));""");
+ Contains("JSExport] internal static global::System.String Space_Class_InvA (global::System.String a) => Serialize(global::Space.Class.InvA(Deserialize(a)), typeof(global::Space.Record));");
+ Contains("JSExport] internal static async global::System.Threading.Tasks.Task Space_Class_InvB (global::System.String? a) => Serialize(await global::Space.Class.InvB(Deserialize(a)), typeof(global::Space.Record[]));");
Contains("""JSImport("Space.Class.funASerialized", "Bootsharp")] internal static partial global::System.String Space_Class_FunA (global::System.String a);""");
Contains("""JSImport("Space.Class.funBSerialized", "Bootsharp")] internal static partial global::System.Threading.Tasks.Task Space_Class_FunB (global::System.String? a);""");
// TODO: Remove when resolved: https://github.com/elringus/bootsharp/issues/138
- Contains("""Proxies.Set("Space.Class.FunAsyncBytes", async () => Deserialize(await Space_Class_FunAsyncBytes()));""");
- Contains("JSExport] internal static async global::System.Threading.Tasks.Task Space_Class_InvAsyncBytes () => Serialize(await global::Space.Class.InvAsyncBytes());");
- Contains("""JSImport("Space.Class.funAsyncBytesSerialized", "Bootsharp")] internal static partial global::System.Threading.Tasks.Task Space_Class_FunAsyncBytes ();""");
+ Contains("""Proxies.Set("Space.Class.FunAsyncBytes", async () => await Space_Class_FunAsyncBytes());""");
+ Contains("JSExport] [return: JSMarshalAs>] internal static async global::System.Threading.Tasks.Task