From cac9d8a0d1ee5f15e6f59804897668e98b0ae534 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20K=C5=82ys?= Date: Tue, 22 Sep 2026 10:41:52 +0200 Subject: [PATCH 1/3] Preserve canonical DOM identity through SameObject getters --- .../SameObjectIdentityTests.cs | 31 +++++++++++++++++++ src/AngleSharp.Js/EngineInstance.cs | 7 +++++ 2 files changed, 38 insertions(+) create mode 100644 src/AngleSharp.Js.Tests/SameObjectIdentityTests.cs diff --git a/src/AngleSharp.Js.Tests/SameObjectIdentityTests.cs b/src/AngleSharp.Js.Tests/SameObjectIdentityTests.cs new file mode 100644 index 0000000..9fdfff1 --- /dev/null +++ b/src/AngleSharp.Js.Tests/SameObjectIdentityTests.cs @@ -0,0 +1,31 @@ +namespace AngleSharp.Js.Tests +{ + using AngleSharp.Dom; + using AngleSharp.Scripting; + using Jint; + using NUnit.Framework; + using System.Threading.Tasks; + + [TestFixture] + public class SameObjectIdentityTests + { + [Test] + public async Task MutationTargetUsesTheCanonicalNodeAndItsConcretePrototype() + { + using var context = BrowsingContext.New(Configuration.Default.WithJs()); + var document = await context.OpenAsync(response => response.Content("test")).ConfigureAwait(false); + IMutationRecord record = null; + var observer = new MutationObserver((records, _) => record = records[0]); + observer.Connect(document.Body, attributes: true); + document.Body.SetAttribute("data-value", "changed"); + observer.Disconnect(); + Assert.IsNotNull(record); + var engine = context.GetService().GetOrCreateJint(document); + engine.SetValue("observedRecord", record); + engine.Execute("document.body.marker = 'retained'"); + Assert.AreEqual("target", engine.Evaluate("observedRecord.target.id").ToString()); + Assert.IsTrue(engine.Evaluate("observedRecord.target === document.body").AsBoolean()); + Assert.AreEqual("retained", engine.Evaluate("observedRecord.target.marker").ToString()); + } + } +} diff --git a/src/AngleSharp.Js/EngineInstance.cs b/src/AngleSharp.Js/EngineInstance.cs index 00b67e5..d9ef5a2 100644 --- a/src/AngleSharp.Js/EngineInstance.cs +++ b/src/AngleSharp.Js/EngineInstance.cs @@ -122,6 +122,13 @@ public JsValue GetSameObject(Object owner, MethodInfo getter) return JsValue.Null; } + // Nodes and windows already have a canonical proxy. Preserve its identity, + // concrete prototype and script-owned properties across SameObject getters. + if (current is INode || current is IWindow) + { + return GetDomNode(current); + } + var cache = _sameObjects.GetValue(owner, _ => new SameObjectCache()); return cache.GetOrUpdate(getter, current, () => CreateInstance(current, getter.ReturnType)); } From 47b8e9de2a479643c55b1679cf749109321c9789 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20K=C5=82ys?= Date: Tue, 22 Sep 2026 11:37:26 +0200 Subject: [PATCH 2/3] Document pending SameObject identity fix --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e0b7d77..8a8136f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ Released on Saturday, September 5 2026. - Added support for the `DomReturnType` attribute - Added support for the `DomSameObject` attribute - Added iterable integration for `IEnumerable` instances +- Unreleased fix: preserve canonical DOM node identity and concrete prototypes through `DomSameObject` getters (#140) # 1.0.1 From c4c8f7afb7054b9d11ac73fc26badb014962bb2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20K=C5=82ys?= Date: Tue, 22 Sep 2026 13:00:57 +0200 Subject: [PATCH 3/3] Document DOM identity fix under version 1.1.1 --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a8136f..a0691b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# 1.1.1 + +- Fixed canonical DOM node identity and concrete prototypes through `DomSameObject` getters (#140) + # 1.1.0 Released on Saturday, September 5 2026. @@ -6,7 +10,6 @@ Released on Saturday, September 5 2026. - Added support for the `DomReturnType` attribute - Added support for the `DomSameObject` attribute - Added iterable integration for `IEnumerable` instances -- Unreleased fix: preserve canonical DOM node identity and concrete prototypes through `DomSameObject` getters (#140) # 1.0.1