HtmlScriptElement
sealed class HtmlScriptElement : HtmlElement, IHtmlScriptElement, IHtmlElement, IElement, INode, IEventTarget, IMarkupFormattable, IParentNode, IChildNode, INonDocumentTypeChildNode, IElementCssInlineStyle
Represents an HTML script element.
http://www.w3.org/TR/html5/scripting-1.html#execute-the-script-block
using AngleSharp.Dom.Css;
using AngleSharp.Extensions;
using AngleSharp.Html;
using AngleSharp.Network;
using AngleSharp.Services.Scripting;
using System;
using System.Linq;
using System.Threading;
namespace AngleSharp.Dom.Html
{
internal sealed class HtmlScriptElement : HtmlElement, IHtmlScriptElement, IHtmlElement, IElement, INode, IEventTarget, IMarkupFormattable, IParentNode, IChildNode, INonDocumentTypeChildNode, IElementCssInlineStyle
{
private bool _started;
private bool _parserInserted;
private bool _forceAsync;
private Action _runScript;
internal string AlternativeLanguage {
get {
string ownAttribute = GetOwnAttribute(AttributeNames.Language);
if (ownAttribute == null)
return null;
return "text/" + ownAttribute;
}
}
internal IScriptEngine Engine => base.Owner.Options.GetScriptEngine(ScriptLanguage);
public string ScriptLanguage {
get {
string text = Type ?? AlternativeLanguage;
if (!string.IsNullOrEmpty(text))
return text;
return MimeTypes.DefaultJavaScript;
}
}
public string Source {
get {
return GetOwnAttribute(AttributeNames.Src);
}
set {
SetOwnAttribute(AttributeNames.Src, value);
}
}
public string Type {
get {
return GetOwnAttribute(AttributeNames.Type);
}
set {
SetOwnAttribute(AttributeNames.Type, value);
}
}
public string CharacterSet {
get {
return GetOwnAttribute(AttributeNames.Charset);
}
set {
SetOwnAttribute(AttributeNames.Charset, value);
}
}
public string Text {
get {
return TextContent;
}
set {
TextContent = value;
}
}
public string CrossOrigin {
get {
return GetOwnAttribute(AttributeNames.CrossOrigin);
}
set {
SetOwnAttribute(AttributeNames.CrossOrigin, value);
}
}
public bool IsDeferred {
get {
return GetOwnAttribute(AttributeNames.Defer) != null;
}
set {
SetOwnAttribute(AttributeNames.Defer, value ? string.Empty : null);
}
}
public bool IsAsync {
get {
return GetOwnAttribute(AttributeNames.Async) != null;
}
set {
SetOwnAttribute(AttributeNames.Async, value ? string.Empty : null);
}
}
public HtmlScriptElement(Document owner, string prefix = null)
: base(owner, Tags.Script, prefix, NodeFlags.Special | NodeFlags.LiteralText)
{
_forceAsync = false;
_parserInserted = false;
_started = false;
}
internal void SetStarted(bool fragmentCase)
{
_parserInserted = true;
_started = fragmentCase;
}
internal void Run()
{
if (_runScript != null && !this.FireSimpleEvent(EventNames.BeforeScriptExecute, false, true))
_runScript();
}
private void RunFromResponse(IResponse response)
{
ScriptOptions options = CreateOptions();
try {
Engine.Evaluate(response, options);
} catch {
}
FireAfterScriptExecuteEvent();
FireLoadEvent();
}
private void RunFromSource()
{
ScriptOptions options = CreateOptions();
try {
Engine.Evaluate(Text, options);
} catch {
}
FireAfterScriptExecuteEvent();
base.Owner.QueueTask(FireLoadEvent);
}
internal bool Prepare()
{
IConfiguration option = base.Owner.Options;
string ownAttribute = GetOwnAttribute(AttributeNames.Event);
string ownAttribute2 = GetOwnAttribute(AttributeNames.For);
string source = Source;
bool parserInserted = _parserInserted;
if (_started)
return false;
if (parserInserted)
_forceAsync = !IsAsync;
_parserInserted = false;
if (string.IsNullOrEmpty(source) && string.IsNullOrEmpty(Text))
return false;
if (Engine == null)
return false;
if (parserInserted)
_forceAsync = false;
_parserInserted = true;
_started = true;
if (!string.IsNullOrEmpty(ownAttribute) && !string.IsNullOrEmpty(ownAttribute2)) {
ownAttribute = ownAttribute.Trim();
ownAttribute2 = ownAttribute2.Trim();
if (ownAttribute.EndsWith("()"))
ownAttribute = ownAttribute.Substring(0, ownAttribute.Length - 2);
if (!ownAttribute2.Equals(AttributeNames.Window, StringComparison.OrdinalIgnoreCase) || !ownAttribute.Equals("onload", StringComparison.OrdinalIgnoreCase))
return false;
}
if (source != null) {
if (!(source == string.Empty))
return InvokeLoadingScript(this.HyperReference(source));
base.Owner.QueueTask(FireErrorEvent);
} else {
if (_parserInserted && base.Owner.GetStyleSheetDownloads().Any()) {
_runScript = RunFromSource;
return true;
}
RunFromSource();
}
return false;
}
private bool InvokeLoadingScript(Url url)
{
bool result = true;
if ((_parserInserted && IsDeferred && !IsAsync) || !_parserInserted || IsAsync) {
base.Owner.AddScript(this);
result = false;
}
ResourceRequest request = this.CreateRequestFor(url);
CorsSetting setting = CrossOrigin.ToEnum(CorsSetting.None);
OriginBehavior behavior = OriginBehavior.Taint;
this.CreateTask(async delegate(CancellationToken c) {
IResponse response = await base.Owner.Loader.FetchWithCorsAsync(request, setting, behavior, c).ConfigureAwait(false);
if (response != null)
_runScript = delegate {
RunFromResponse(response);
response.Dispose();
};
else
FireErrorEvent();
return response;
});
return result;
}
private void FireLoadEvent()
{
this.FireSimpleEvent(EventNames.Load, false, false);
}
private void FireErrorEvent()
{
this.FireSimpleEvent(EventNames.Error, false, false);
}
private void FireAfterScriptExecuteEvent()
{
this.FireSimpleEvent(EventNames.AfterScriptExecute, true, false);
}
private ScriptOptions CreateOptions()
{
ScriptOptions scriptOptions = new ScriptOptions();
scriptOptions.Context = base.Owner.DefaultView;
scriptOptions.Document = base.Owner;
scriptOptions.Element = this;
scriptOptions.Encoding = TextEncoding.Resolve(CharacterSet);
return scriptOptions;
}
}
}