From 2de58cd3772fbe9138db9368e0015dcc063f8cbf Mon Sep 17 00:00:00 2001 From: Marko Lahma Date: Sat, 15 Jun 2024 20:58:50 +0300 Subject: [PATCH] Support creating NamespaceReference against empty namespace (#1892) --- Jint.Tests/Runtime/Domain/Shape.cs | 5 +++++ Jint.Tests/Runtime/InteropTests.cs | 16 ++++++++++++++++ Jint/Options.cs | 3 +-- Jint/Runtime/Interop/NamespaceReference.cs | 15 ++++++++++----- 4 files changed, 32 insertions(+), 7 deletions(-) diff --git a/Jint.Tests/Runtime/Domain/Shape.cs b/Jint.Tests/Runtime/Domain/Shape.cs index 40cbd30781..2c053bbe83 100644 --- a/Jint.Tests/Runtime/Domain/Shape.cs +++ b/Jint.Tests/Runtime/Domain/Shape.cs @@ -1,5 +1,10 @@ using Jint.Tests.Runtime.Domain; +public class ShapeWithoutNameSpace : Shapes.Shape +{ + public override double Perimeter() => 42; +} + namespace Shapes { public abstract class Shape diff --git a/Jint.Tests/Runtime/InteropTests.cs b/Jint.Tests/Runtime/InteropTests.cs index 2c3a062524..ff32087f26 100644 --- a/Jint.Tests/Runtime/InteropTests.cs +++ b/Jint.Tests/Runtime/InteropTests.cs @@ -1302,6 +1302,22 @@ public void ShouldImportNamespace() "); } + [Fact] + public void ShouldImportEmptyNamespace() + { + RunTest(""" + var nullSpace = importNamespace(null); + var c1 = new nullSpace.ShapeWithoutNameSpace(); + assert(c1.Perimeter() === 42); + var undefinedSpace = importNamespace(undefined); + var c2 = new undefinedSpace.ShapeWithoutNameSpace(); + assert(c2.Perimeter() === 42); + var defaultSpace = importNamespace(); + var c3 = new defaultSpace.ShapeWithoutNameSpace(); + assert(c3.Perimeter() === 42); + """); + } + [Fact] public void ShouldConstructReferenceTypeWithParameters() { diff --git a/Jint/Options.cs b/Jint/Options.cs index 9eb1d6584e..b0775768e3 100644 --- a/Jint/Options.cs +++ b/Jint/Options.cs @@ -126,8 +126,7 @@ internal void Apply(Engine engine) engine.Realm.GlobalObject.SetProperty("importNamespace", new PropertyDescriptor(new ClrFunction( engine, "importNamespace", - (thisObj, arguments) => - new NamespaceReference(engine, TypeConverter.ToString(arguments.At(0)))), + (_, arguments) => new NamespaceReference(engine, arguments.At(0).IsNullOrUndefined() ? null : TypeConverter.ToString(arguments.At(0)))), PropertyFlag.AllForbidden)); engine.Realm.GlobalObject.SetProperty("clrHelper", new PropertyDescriptor(ObjectWrapper.Create(engine, new ClrHelper(Interop)), PropertyFlag.AllForbidden)); diff --git a/Jint/Runtime/Interop/NamespaceReference.cs b/Jint/Runtime/Interop/NamespaceReference.cs index efaab337f8..c14c898bc8 100644 --- a/Jint/Runtime/Interop/NamespaceReference.cs +++ b/Jint/Runtime/Interop/NamespaceReference.cs @@ -18,9 +18,9 @@ namespace Jint.Runtime.Interop [RequiresUnreferencedCode("Dynamic loading")] public class NamespaceReference : ObjectInstance, ICallable { - private readonly string _path; + private readonly string? _path; - public NamespaceReference(Engine engine, string path) : base(engine) + public NamespaceReference(Engine engine, string? path) : base(engine) { _path = path; } @@ -75,7 +75,9 @@ JsValue ICallable.Call(JsValue thisObject, JsValue[] arguments) public override JsValue Get(JsValue property, JsValue receiver) { - var newPath = _path + "." + property; + var newPath = string.IsNullOrEmpty(_path) + ? property.ToString() + : $"{_path}.{property}"; return GetPath(newPath); } @@ -123,8 +125,11 @@ public JsValue GetPath(string path) } var lastPeriodPos = path.LastIndexOf('.'); - var trimPath = path.Substring(0, lastPeriodPos); - type = GetType(assembly, trimPath); + if (lastPeriodPos != -1) + { + var trimPath = path.Substring(0, lastPeriodPos); + type = GetType(assembly, trimPath); + } if (type != null) { foreach (Type nType in GetAllNestedTypes(type))