AngleSharp by AngleSharp

<PackageReference Include="AngleSharp" Version="0.13.0-alpha-760" />

 ImportLinkRelation

using AngleSharp.Dom; using AngleSharp.Html.Dom; using AngleSharp.Io; using AngleSharp.Io.Processors; using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Threading.Tasks; namespace AngleSharp.Html.LinkRels { internal class ImportLinkRelation : BaseLinkRelation { private sealed class ImportList { private readonly List<ImportEntry> _list; public ImportList() { _list = new List<ImportEntry>(); } public bool Contains(Url location) { for (int i = 0; i < _list.Count; i++) { Url url = _list[i].Relation.Url; if (url != null && url.Equals(location)) return true; } return false; } public void Add(ImportEntry item) { _list.Add(item); } public void Remove(ImportEntry item) { _list.Remove(item); } } private struct ImportEntry { public ImportLinkRelation Relation; public bool IsCycle; } private static readonly ConditionalWeakTable<IDocument, ImportList> ImportLists = new ConditionalWeakTable<IDocument, ImportList>(); private bool _async; public IDocument Import => (base.Processor as DocumentRequestProcessor)?.ChildDocument; public bool IsAsync => _async; public ImportLinkRelation(IHtmlLinkElement link) : base(link, new DocumentRequestProcessor(link?.Owner.Context)) { } public override Task LoadAsync() { IHtmlLinkElement link = base.Link; IDocument owner = link.Owner; ImportList orCreateValue = ImportLists.GetOrCreateValue(owner); Url url = base.Url; IRequestProcessor processor = base.Processor; ImportEntry importEntry = new ImportEntry { Relation = this, IsCycle = (url != null && CheckCycle(owner, url)) }; orCreateValue.Add(importEntry); if (url != null && !importEntry.IsCycle) { ResourceRequest request = link.CreateRequestFor(url); _async = link.HasAttribute(AttributeNames.Async); return processor?.ProcessAsync(request); } return Task.CompletedTask; } private static bool CheckCycle(IDocument document, Url location) { IDocument importAncestor = document.ImportAncestor; ImportList value; while (importAncestor != null && ImportLists.TryGetValue(importAncestor, out value)) { if (value.Contains(location)) return true; importAncestor = importAncestor.ImportAncestor; } return false; } } }