ImportLinkRelation
using AngleSharp.Dom;
using AngleSharp.Dom.Html;
using AngleSharp.Extensions;
using AngleSharp.Network;
using AngleSharp.Network.RequestProcessors;
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++) {
if (_list[i].Relation.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 _isasync;
public IDocument Import => (base.Processor as DocumentRequestProcessor)?.ChildDocument;
public bool IsAsync => _isasync;
public ImportLinkRelation(HtmlLinkElement link)
: base(link, DocumentRequestProcessor.Create(link))
{
}
public override Task LoadAsync()
{
HtmlLinkElement link = base.Link;
Document owner = link.Owner;
ImportList orCreateValue = ImportLists.GetOrCreateValue(owner);
Url url = base.Url;
IRequestProcessor processor = base.Processor;
ImportEntry importEntry = new ImportEntry {
Relation = this,
IsCycle = CheckCycle(owner, url)
};
orCreateValue.Add(importEntry);
if (!importEntry.IsCycle) {
ResourceRequest request = link.CreateRequestFor(url);
_isasync = link.HasAttribute(AttributeNames.Async);
return processor?.ProcessAsync(request);
}
return null;
}
private static bool CheckCycle(IDocument document, Url location)
{
IDocument importAncestor = document.ImportAncestor;
ImportList value = null;
while (importAncestor != null && ImportLists.TryGetValue(importAncestor, out value)) {
if (value.Contains(location))
return true;
importAncestor = importAncestor.ImportAncestor;
}
return false;
}
}
}