Skip to content

AmbiguousMatchException with AngleSharp 1.7.0: multiple [DomName] attributes on geometry types break the prototype binder #136

Description

@robsonfelix

Summary

AngleSharp.Js 1.0.0 throws System.Reflection.AmbiguousMatchException: Multiple custom attributes of the same type 'AngleSharp.Attributes.DomNameAttribute' found. on any script execution when used with AngleSharp 1.7.0. The same code works with AngleSharp 1.5.2 and 1.6.0.

The package's dependency range (AngleSharp >= 1.5.0 && < 2.0.0) allows 1.7.0, so a plain dotnet add package of both latest stables produces a broken combination.

Repro

using AngleSharp;
using AngleSharp.Js;

var context = BrowsingContext.New(Configuration.Default.WithJs());
var document = await context.OpenAsync(res => res.Content("<html><body></body></html>"));
var result = document.ExecuteScript("2 + 3"); // throws AmbiguousMatchException
<PackageReference Include="AngleSharp" Version="1.7.0" />
<PackageReference Include="AngleSharp.Js" Version="1.0.0" />
  • AngleSharp 1.7.0 → throws (with or without AngleSharp.Css in the mix)
  • AngleSharp 1.6.0 → works
  • AngleSharp 1.5.2 → works

TFM: net10.0, Windows (nothing platform-specific in the stack).

Root cause

AngleSharp 1.7.0 introduced geometry types that carry multiple [DomName] attributes (aliases). Scanning the core assembly:

[3] AngleSharp.Dom.Geometry.DomMatrix
[2] AngleSharp.Dom.Geometry.DomPoint
[2] AngleSharp.Dom.Geometry.DomRect
[3] AngleSharp.Dom.Geometry.IDomMatrix
[2] AngleSharp.Dom.Geometry.IDomPoint
[2] AngleSharp.Dom.Geometry.IDomRect

AngleSharp.Js.ReflectionExtensions.GetOfficialName resolves the DOM name via the singular GetCustomAttribute<DomNameAttribute>(), which throws AmbiguousMatchException when more than one attribute is present. Because PrototypeTypeCache.CreateDefiningTypes walks every exported type of the assembly, the first script evaluation dies even though the script never touches the geometry API.

Stack (inner exception)

System.Reflection.AmbiguousMatchException: Multiple custom attributes of the same type 'AngleSharp.Attributes.DomNameAttribute' found.
   at AngleSharp.Js.ReflectionExtensions.GetOfficialName(Type currentType, Type baseType)
   at AngleSharp.Js.Cache.PrototypeTypeCache.CreateDefiningTypes(Assembly assembly)
   at AngleSharp.Js.Cache.PrototypeTypeCache.GetDefiningTypes(Assembly assembly)
   at AngleSharp.Js.Cache.PrototypeTypeCache.GetDomPrototypeType(Type type, IEnumerable`1 libs)
   at AngleSharp.Js.PrototypeCache.Canonicalize(Type type)
   at AngleSharp.Js.EngineInstance.GetDomPrototype(Type type)
   at AngleSharp.Js.DomNodeInstance..ctor(EngineInstance engine, Object value)
   at AngleSharp.Js.EngineInstance..ctor(IWindow window, IDictionary`2 assignments, IEnumerable`1 libs, JsScriptingOptions options)
   at AngleSharp.Scripting.JsScriptingService.GetOrCreateInstance(IDocument document)
   at AngleSharp.Scripting.JsScriptingService.EvaluateScript(IDocument document, String source, String type, String sourceUrl)

Suggested fix

In GetOfficialName (and any other single-attribute lookups in the binder), use GetCustomAttributes<DomNameAttribute>() and treat the first as the official name — ideally registering the remaining names as aliases, matching how the multi-[DomName] convention is used elsewhere (e.g. DOMMatrix/WebKitCSSMatrix/SVGMatrix).

Happy to provide more detail if useful — thanks for the 1.0 release!

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions