|
@@ -1,186 +1,291 @@
|
|
|
-using System.Reflection;
|
|
|
+namespace Jint.Tests.Runtime;
|
|
|
|
|
|
-namespace Jint.Tests.Runtime
|
|
|
+using Jint.Runtime.Interop;
|
|
|
+
|
|
|
+public class InteropExplicitTypeTests
|
|
|
{
|
|
|
- public class InteropExplicitTypeTests
|
|
|
+ public interface I1
|
|
|
+ {
|
|
|
+ string Name { get; }
|
|
|
+ }
|
|
|
+
|
|
|
+ public class Super
|
|
|
+ {
|
|
|
+ public string Name { get; } = "Super";
|
|
|
+ }
|
|
|
+
|
|
|
+ public class CI1 : Super, I1
|
|
|
{
|
|
|
- public interface I1
|
|
|
+ public new string Name { get; } = "CI1";
|
|
|
+
|
|
|
+ string I1.Name { get; } = "CI1 as I1";
|
|
|
+ }
|
|
|
+
|
|
|
+ public class Indexer<T>
|
|
|
+ {
|
|
|
+ private readonly T t;
|
|
|
+ public Indexer(T t)
|
|
|
{
|
|
|
- string Name { get; }
|
|
|
+ this.t = t;
|
|
|
}
|
|
|
-
|
|
|
- public class Super
|
|
|
+ public T this[int index]
|
|
|
{
|
|
|
- public string Name { get; } = "Super";
|
|
|
+ get { return t; }
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- public class CI1 : Super, I1
|
|
|
+ public class InterfaceHolder
|
|
|
+ {
|
|
|
+ public InterfaceHolder()
|
|
|
{
|
|
|
- public new string Name { get; } = "CI1";
|
|
|
+ var ci1 = new CI1();
|
|
|
+ this.ci1 = ci1;
|
|
|
+ this.i1 = ci1;
|
|
|
+ this.super = ci1;
|
|
|
|
|
|
- string I1.Name { get; } = "CI1 as I1";
|
|
|
+ this.IndexerCI1 = new Indexer<CI1>(ci1);
|
|
|
+ this.IndexerI1 = new Indexer<I1>(ci1);
|
|
|
+ this.IndexerSuper = new Indexer<Super>(ci1);
|
|
|
}
|
|
|
|
|
|
- public class Indexer<T>
|
|
|
- {
|
|
|
- private readonly T t;
|
|
|
- public Indexer(T t)
|
|
|
- {
|
|
|
- this.t = t;
|
|
|
- }
|
|
|
- public T this[int index]
|
|
|
- {
|
|
|
- get { return t; }
|
|
|
- }
|
|
|
- }
|
|
|
+ public readonly CI1 ci1;
|
|
|
+ public readonly I1 i1;
|
|
|
+ public readonly Super super;
|
|
|
|
|
|
- public class InterfaceHolder
|
|
|
- {
|
|
|
- public InterfaceHolder()
|
|
|
- {
|
|
|
- var ci1 = new CI1();
|
|
|
- this.ci1 = ci1;
|
|
|
- this.i1 = ci1;
|
|
|
- this.super = ci1;
|
|
|
+ public CI1 CI1 { get => ci1; }
|
|
|
+ public I1 I1 { get => i1; }
|
|
|
+ public Super Super { get => super; }
|
|
|
|
|
|
- this.IndexerCI1 = new Indexer<CI1>(ci1);
|
|
|
- this.IndexerI1 = new Indexer<I1>(ci1);
|
|
|
- this.IndexerSuper = new Indexer<Super>(ci1);
|
|
|
- }
|
|
|
+ public CI1 GetCI1() => ci1;
|
|
|
+ public I1 GetI1() => i1;
|
|
|
+ public Super GetSuper() => super;
|
|
|
|
|
|
- public readonly CI1 ci1;
|
|
|
- public readonly I1 i1;
|
|
|
- public readonly Super super;
|
|
|
+ public Indexer<CI1> IndexerCI1 { get; }
|
|
|
+ public Indexer<I1> IndexerI1 { get; }
|
|
|
+ public Indexer<Super> IndexerSuper { get; }
|
|
|
|
|
|
- public CI1 CI1 { get => ci1; }
|
|
|
- public I1 I1 { get => i1; }
|
|
|
- public Super Super { get => super; }
|
|
|
+ }
|
|
|
|
|
|
- public CI1 GetCI1() => ci1;
|
|
|
- public I1 GetI1() => i1;
|
|
|
- public Super GetSuper() => super;
|
|
|
+ private readonly Engine _engine;
|
|
|
+ private readonly InterfaceHolder holder;
|
|
|
|
|
|
- public Indexer<CI1> IndexerCI1 { get; }
|
|
|
- public Indexer<I1> IndexerI1 { get; }
|
|
|
- public Indexer<Super> IndexerSuper { get; }
|
|
|
+ public InteropExplicitTypeTests()
|
|
|
+ {
|
|
|
+ holder = new InterfaceHolder();
|
|
|
+ _engine = new Engine(cfg => cfg.AllowClr(
|
|
|
+ typeof(CI1).Assembly,
|
|
|
+ typeof(Console).Assembly,
|
|
|
+ typeof(File).Assembly))
|
|
|
+ .SetValue("log", new Action<object>(Console.WriteLine))
|
|
|
+ .SetValue("assert", new Action<bool>(Assert.True))
|
|
|
+ .SetValue("equal", new Action<object, object>(Assert.Equal))
|
|
|
+ .SetValue("holder", holder)
|
|
|
+ ;
|
|
|
+ }
|
|
|
+ [Fact]
|
|
|
+ public void EqualTest()
|
|
|
+ {
|
|
|
+ Assert.Equal(_engine.Evaluate("holder.I1"), _engine.Evaluate("holder.i1"));
|
|
|
+ Assert.NotEqual(_engine.Evaluate("holder.I1"), _engine.Evaluate("holder.ci1"));
|
|
|
|
|
|
- }
|
|
|
+ Assert.Equal(_engine.Evaluate("holder.Super"), _engine.Evaluate("holder.super"));
|
|
|
+ Assert.NotEqual(_engine.Evaluate("holder.Super"), _engine.Evaluate("holder.ci1"));
|
|
|
+ }
|
|
|
|
|
|
- private readonly Engine _engine;
|
|
|
- private readonly InterfaceHolder holder;
|
|
|
+ [Fact]
|
|
|
+ public void ExplicitInterfaceFromField()
|
|
|
+ {
|
|
|
+ Assert.Equal(holder.i1.Name, _engine.Evaluate("holder.i1.Name"));
|
|
|
+ Assert.NotEqual(holder.i1.Name, _engine.Evaluate("holder.ci1.Name"));
|
|
|
+ }
|
|
|
|
|
|
- public InteropExplicitTypeTests()
|
|
|
- {
|
|
|
- holder = new InterfaceHolder();
|
|
|
- _engine = new Engine(cfg => cfg.AllowClr(
|
|
|
- typeof(Console).GetTypeInfo().Assembly,
|
|
|
- typeof(File).GetTypeInfo().Assembly))
|
|
|
- .SetValue("log", new Action<object>(Console.WriteLine))
|
|
|
- .SetValue("assert", new Action<bool>(Assert.True))
|
|
|
- .SetValue("equal", new Action<object, object>(Assert.Equal))
|
|
|
- .SetValue("holder", holder)
|
|
|
- ;
|
|
|
- }
|
|
|
- [Fact]
|
|
|
- public void EqualTest()
|
|
|
- {
|
|
|
- Assert.Equal(_engine.Evaluate("holder.I1"), _engine.Evaluate("holder.i1"));
|
|
|
- Assert.NotEqual(_engine.Evaluate("holder.I1"), _engine.Evaluate("holder.ci1"));
|
|
|
+ [Fact]
|
|
|
+ public void ExplicitInterfaceFromProperty()
|
|
|
+ {
|
|
|
+ Assert.Equal(holder.I1.Name, _engine.Evaluate("holder.I1.Name"));
|
|
|
+ Assert.NotEqual(holder.I1.Name, _engine.Evaluate("holder.CI1.Name"));
|
|
|
+ }
|
|
|
|
|
|
- Assert.Equal(_engine.Evaluate("holder.Super"), _engine.Evaluate("holder.super"));
|
|
|
- Assert.NotEqual(_engine.Evaluate("holder.Super"), _engine.Evaluate("holder.ci1"));
|
|
|
- }
|
|
|
+ [Fact]
|
|
|
+ public void ExplicitInterfaceFromMethod()
|
|
|
+ {
|
|
|
+ Assert.Equal(holder.GetI1().Name, _engine.Evaluate("holder.GetI1().Name"));
|
|
|
+ Assert.NotEqual(holder.GetI1().Name, _engine.Evaluate("holder.GetCI1().Name"));
|
|
|
+ }
|
|
|
|
|
|
- [Fact]
|
|
|
- public void ExplicitInterfaceFromField()
|
|
|
- {
|
|
|
- Assert.Equal(holder.i1.Name, _engine.Evaluate("holder.i1.Name"));
|
|
|
- Assert.NotEqual(holder.i1.Name, _engine.Evaluate("holder.ci1.Name"));
|
|
|
- }
|
|
|
+ [Fact]
|
|
|
+ public void ExplicitInterfaceFromIndexer()
|
|
|
+ {
|
|
|
+ Assert.Equal(holder.IndexerI1[0].Name, _engine.Evaluate("holder.IndexerI1[0].Name"));
|
|
|
+ }
|
|
|
|
|
|
- [Fact]
|
|
|
- public void ExplicitInterfaceFromProperty()
|
|
|
- {
|
|
|
- Assert.Equal(holder.I1.Name, _engine.Evaluate("holder.I1.Name"));
|
|
|
- Assert.NotEqual(holder.I1.Name, _engine.Evaluate("holder.CI1.Name"));
|
|
|
- }
|
|
|
|
|
|
- [Fact]
|
|
|
- public void ExplicitInterfaceFromMethod()
|
|
|
- {
|
|
|
- Assert.Equal(holder.GetI1().Name, _engine.Evaluate("holder.GetI1().Name"));
|
|
|
- Assert.NotEqual(holder.GetI1().Name, _engine.Evaluate("holder.GetCI1().Name"));
|
|
|
- }
|
|
|
+ [Fact]
|
|
|
+ public void SuperClassFromField()
|
|
|
+ {
|
|
|
+ Assert.Equal(holder.super.Name, _engine.Evaluate("holder.super.Name"));
|
|
|
+ Assert.NotEqual(holder.super.Name, _engine.Evaluate("holder.ci1.Name"));
|
|
|
+ }
|
|
|
|
|
|
- [Fact]
|
|
|
- public void ExplicitInterfaceFromIndexer()
|
|
|
- {
|
|
|
- Assert.Equal(holder.IndexerI1[0].Name, _engine.Evaluate("holder.IndexerI1[0].Name"));
|
|
|
- }
|
|
|
+ [Fact]
|
|
|
+ public void SuperClassFromProperty()
|
|
|
+ {
|
|
|
+ Assert.Equal(holder.Super.Name, _engine.Evaluate("holder.Super.Name"));
|
|
|
+ Assert.NotEqual(holder.Super.Name, _engine.Evaluate("holder.CI1.Name"));
|
|
|
+ }
|
|
|
|
|
|
+ [Fact]
|
|
|
+ public void SuperClassFromMethod()
|
|
|
+ {
|
|
|
+ Assert.Equal(holder.GetSuper().Name, _engine.Evaluate("holder.GetSuper().Name"));
|
|
|
+ Assert.NotEqual(holder.GetSuper().Name, _engine.Evaluate("holder.GetCI1().Name"));
|
|
|
+ }
|
|
|
|
|
|
- [Fact]
|
|
|
- public void SuperClassFromField()
|
|
|
- {
|
|
|
- Assert.Equal(holder.super.Name, _engine.Evaluate("holder.super.Name"));
|
|
|
- Assert.NotEqual(holder.super.Name, _engine.Evaluate("holder.ci1.Name"));
|
|
|
- }
|
|
|
+ [Fact]
|
|
|
+ public void SuperClassFromIndexer()
|
|
|
+ {
|
|
|
+ Assert.Equal(holder.IndexerSuper[0].Name, _engine.Evaluate("holder.IndexerSuper[0].Name"));
|
|
|
+ }
|
|
|
|
|
|
- [Fact]
|
|
|
- public void SuperClassFromProperty()
|
|
|
+ public struct NullabeStruct : I1
|
|
|
+ {
|
|
|
+ public NullabeStruct()
|
|
|
{
|
|
|
- Assert.Equal(holder.Super.Name, _engine.Evaluate("holder.Super.Name"));
|
|
|
- Assert.NotEqual(holder.Super.Name, _engine.Evaluate("holder.CI1.Name"));
|
|
|
}
|
|
|
+ public string name = "NullabeStruct";
|
|
|
+
|
|
|
+ public string Name { get => name; }
|
|
|
+
|
|
|
+ string I1.Name { get => "NullabeStruct as I1"; }
|
|
|
+ }
|
|
|
+
|
|
|
+ public class NullableHolder
|
|
|
+ {
|
|
|
+ public I1 I1 { get; set; }
|
|
|
+ public NullabeStruct? NullabeStruct { get; set; }
|
|
|
+ }
|
|
|
+
|
|
|
+ [Fact]
|
|
|
+ public void TypedObjectWrapperForNullableType()
|
|
|
+ {
|
|
|
+ var nullableHolder = new NullableHolder();
|
|
|
+ _engine.SetValue("nullableHolder", nullableHolder);
|
|
|
+ _engine.SetValue("nullabeStruct", new NullabeStruct());
|
|
|
+
|
|
|
+ Assert.Equal(_engine.Evaluate("nullableHolder.NullabeStruct"), Native.JsValue.Null);
|
|
|
+ _engine.Evaluate("nullableHolder.NullabeStruct = nullabeStruct");
|
|
|
+ Assert.Equal(_engine.Evaluate("nullableHolder.NullabeStruct.Name"), nullableHolder.NullabeStruct?.Name);
|
|
|
+ }
|
|
|
+
|
|
|
+ [Fact]
|
|
|
+ public void ClrHelperUnwrap()
|
|
|
+ {
|
|
|
+ Assert.NotEqual(holder.CI1.Name, _engine.Evaluate("holder.I1.Name"));
|
|
|
+ Assert.Equal(holder.CI1.Name, _engine.Evaluate("clrHelper.unwrap(holder.I1).Name"));
|
|
|
+ }
|
|
|
+
|
|
|
+ [Fact]
|
|
|
+ public void ClrHelperWrap()
|
|
|
+ {
|
|
|
+ _engine.Execute("Jint = importNamespace('Jint');");
|
|
|
+ Assert.NotEqual(holder.I1.Name, _engine.Evaluate("holder.CI1.Name"));
|
|
|
+ Assert.Equal(holder.I1.Name, _engine.Evaluate("clrHelper.wrap(holder.CI1, Jint.Tests.Runtime.InteropExplicitTypeTests.I1).Name"));
|
|
|
+ }
|
|
|
|
|
|
- [Fact]
|
|
|
- public void SuperClassFromMethod()
|
|
|
+ [Fact]
|
|
|
+ public void ClrHelperTypeOf()
|
|
|
+ {
|
|
|
+ Action<Engine> runner = engine =>
|
|
|
{
|
|
|
- Assert.Equal(holder.GetSuper().Name, _engine.Evaluate("holder.GetSuper().Name"));
|
|
|
- Assert.NotEqual(holder.GetSuper().Name, _engine.Evaluate("holder.GetCI1().Name"));
|
|
|
- }
|
|
|
+ engine.SetValue("clrobj", new object());
|
|
|
+ Assert.Equal(engine.Evaluate("System.Object"), engine.Evaluate("clrHelper.typeOf(clrobj)"));
|
|
|
+ };
|
|
|
|
|
|
- [Fact]
|
|
|
- public void SuperClassFromIndexer()
|
|
|
+ runner.Invoke(new Engine(cfg =>
|
|
|
{
|
|
|
- Assert.Equal(holder.IndexerSuper[0].Name, _engine.Evaluate("holder.IndexerSuper[0].Name"));
|
|
|
- }
|
|
|
+ cfg.AllowClr();
|
|
|
+ cfg.Interop.AllowGetType = true;
|
|
|
+ }));
|
|
|
|
|
|
- public struct NullabeStruct: I1
|
|
|
+ var ex = Assert.Throws<InvalidOperationException>(() =>
|
|
|
{
|
|
|
- public NullabeStruct()
|
|
|
+ runner.Invoke(new Engine(cfg =>
|
|
|
{
|
|
|
- }
|
|
|
- public string name = "NullabeStruct";
|
|
|
+ cfg.AllowClr();
|
|
|
+ }));
|
|
|
+ });
|
|
|
+ Assert.Equal("Invalid when Engine.Options.Interop.AllowGetType == false", ex.Message);
|
|
|
+ }
|
|
|
+
|
|
|
+ [Fact]
|
|
|
+ public void ClrHelperTypeOfForNestedType()
|
|
|
+ {
|
|
|
+ var engine = new Engine(cfg =>
|
|
|
+ {
|
|
|
+ cfg.AllowClr(GetType().Assembly);
|
|
|
+ cfg.Interop.AllowGetType = true;
|
|
|
+ });
|
|
|
|
|
|
- public string Name { get => name; }
|
|
|
+ engine.SetValue("holder", holder);
|
|
|
+ engine.Execute("Jint = importNamespace('Jint');");
|
|
|
+ Assert.Equal(engine.Evaluate("Jint.Tests.Runtime.InteropExplicitTypeTests.CI1"), engine.Evaluate("clrHelper.typeOf(holder.CI1)"));
|
|
|
+ Assert.Equal(engine.Evaluate("Jint.Tests.Runtime.InteropExplicitTypeTests.I1"), engine.Evaluate("clrHelper.typeOf(holder.I1)"));
|
|
|
+ }
|
|
|
|
|
|
- string I1.Name { get => "NullabeStruct as I1"; }
|
|
|
- }
|
|
|
+ public class TypeHolder
|
|
|
+ {
|
|
|
+ public static Type Type => typeof(TypeHolder);
|
|
|
+ }
|
|
|
+
|
|
|
+ [Fact]
|
|
|
+ public void ClrHelperTypeToObject()
|
|
|
+ {
|
|
|
+ Action<Engine> runner = engine =>
|
|
|
+ {
|
|
|
+ engine.SetValue("TypeHolder", typeof(TypeHolder));
|
|
|
+ Assert.True(engine.Evaluate("TypeHolder") is TypeReference);
|
|
|
+ Assert.True(engine.Evaluate("clrHelper.typeToObject(TypeHolder)") is ObjectWrapper);
|
|
|
+ };
|
|
|
|
|
|
- public class NullableHolder
|
|
|
+ runner.Invoke(new Engine(cfg =>
|
|
|
{
|
|
|
- public I1? I1 { get; set; }
|
|
|
- public NullabeStruct? NullabeStruct { get; set; }
|
|
|
- }
|
|
|
+ cfg.AllowClr();
|
|
|
+ cfg.Interop.AllowGetType = true;
|
|
|
+ }));
|
|
|
|
|
|
- [Fact]
|
|
|
- public void TestNullable()
|
|
|
+ var ex = Assert.Throws<InvalidOperationException>(() =>
|
|
|
{
|
|
|
- var nullableHolder = new NullableHolder();
|
|
|
- _engine.SetValue("nullableHolder", nullableHolder);
|
|
|
- _engine.SetValue("nullabeStruct", new NullabeStruct());
|
|
|
+ runner.Invoke(new Engine(cfg =>
|
|
|
+ {
|
|
|
+ cfg.AllowClr();
|
|
|
+ }));
|
|
|
+ });
|
|
|
+ Assert.Equal("Invalid when Engine.Options.Interop.AllowGetType == false", ex.Message);
|
|
|
+ }
|
|
|
|
|
|
- Assert.Equal(_engine.Evaluate("nullableHolder.NullabeStruct"), Native.JsValue.Null);
|
|
|
- _engine.Evaluate("nullableHolder.NullabeStruct = nullabeStruct");
|
|
|
- Assert.Equal(_engine.Evaluate("nullableHolder.NullabeStruct.Name"), nullableHolder.NullabeStruct?.Name);
|
|
|
- }
|
|
|
+ [Fact]
|
|
|
+ public void ClrHelperObjectToType()
|
|
|
+ {
|
|
|
+ Action<Engine> runner = engine =>
|
|
|
+ {
|
|
|
+ engine.SetValue("TypeHolder", typeof(TypeHolder));
|
|
|
+ Assert.True(engine.Evaluate("TypeHolder.Type") is ObjectWrapper);
|
|
|
+ Assert.True(engine.Evaluate("clrHelper.objectToType(TypeHolder.Type)") is TypeReference);
|
|
|
+ };
|
|
|
|
|
|
- [Fact]
|
|
|
- public void TestUnwrapClr()
|
|
|
+ runner.Invoke(new Engine(cfg =>
|
|
|
{
|
|
|
- Assert.NotEqual(holder.CI1.Name, _engine.Evaluate("holder.I1.Name"));
|
|
|
- Assert.Equal(holder.CI1.Name, _engine.Evaluate("unwrapClr(holder.I1).Name"));
|
|
|
- }
|
|
|
+ cfg.AllowClr();
|
|
|
+ cfg.Interop.AllowGetType = true;
|
|
|
+ }));
|
|
|
+
|
|
|
+ var ex = Assert.Throws<InvalidOperationException>(() =>
|
|
|
+ {
|
|
|
+ runner.Invoke(new Engine(cfg =>
|
|
|
+ {
|
|
|
+ cfg.AllowClr();
|
|
|
+ }));
|
|
|
+ });
|
|
|
+ Assert.Equal("Invalid when Engine.Options.Interop.AllowGetType == false", ex.Message);
|
|
|
}
|
|
|
}
|