Skip to content

Commit 4195e5d

Browse files
committed
Added document Then method
1 parent 191d6fc commit 4195e5d

3 files changed

Lines changed: 134 additions & 23 deletions

File tree

src/AngleSharp.Js.Tests/FireEventTests.cs

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
namespace AngleSharp.Js.Tests
22
{
3+
using AngleSharp.Dom;
34
using AngleSharp.Dom.Events;
4-
using Jint;
55
using NUnit.Framework;
66
using System.Threading.Tasks;
77

@@ -208,6 +208,55 @@ public async Task SetTimeoutWithNormalFunction()
208208
Assert.IsTrue(result);
209209
}
210210

211+
[Test]
212+
public async Task DomContentLoadedEventIsFired_Issue50()
213+
{
214+
//TODO Check this as well on the window level - currently works
215+
//only against document (se AngleSharp#789)
216+
var cfg = Configuration.Default.WithJs();
217+
var html = @"<!doctype html>
218+
<html>
219+
<body>
220+
<script>
221+
document.addEventListener('DOMContentLoaded', function() {
222+
var element = document.createElement('div');
223+
element.textContent = 'Success!';
224+
document.body.appendChild(element);
225+
});
226+
</script>
227+
</body>";
228+
await BrowsingContext.New(cfg).OpenAsync(m => m.Content(html))
229+
.Then(document =>
230+
{
231+
var div = document.QuerySelector("div");
232+
Assert.AreEqual("Success!", div?.TextContent);
233+
});
234+
}
235+
236+
[Test]
237+
public async Task DocumentLoadEventIsFired_Issue42()
238+
{
239+
var cfg = Configuration.Default.WithJs();
240+
var html = @"<!doctype html>
241+
<html>
242+
<body>
243+
<script>
244+
window.onload = function() {
245+
var element = document.createElement('div');
246+
element.textContent = 'Success!';
247+
document.body.appendChild(element);
248+
};
249+
</script>
250+
</body>";
251+
var context = BrowsingContext.New(cfg);
252+
await context.OpenAsync(m => m.Content(html))
253+
.Then(document =>
254+
{
255+
var div = document.QuerySelector("div");
256+
Assert.AreEqual("Success!", div?.TextContent);
257+
});
258+
}
259+
211260
[Test]
212261
public async Task SetTimeoutWithStringAsFunction()
213262
{
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
namespace AngleSharp.Dom
2+
{
3+
using AngleSharp.Browser;
4+
using AngleSharp.Js;
5+
using System;
6+
using System.Threading.Tasks;
7+
8+
/// <summary>
9+
/// A set of extensions for interacting with the document.
10+
/// </summary>
11+
public static class JsDocumentExtensions
12+
{
13+
/// <summary>
14+
/// Enqueues the given action as a normal task to the document,
15+
/// thus ensuring it runs after any script-related actions.
16+
/// </summary>
17+
/// <param name="document">The document to extend.</param>
18+
/// <param name="action">The action on the document to perform.</param>
19+
/// <returns>A task that is finished when the enqueued task completed.</returns>
20+
public static Task<IDocument> Then(this IDocument document, Action<IDocument> action)
21+
{
22+
var context = document.Context;
23+
var evts = context.GetService<IEventLoop>();
24+
var tcs = new TaskCompletionSource<Boolean>();
25+
evts.Enqueue(cancel =>
26+
{
27+
try
28+
{
29+
action?.Invoke(document);
30+
tcs.SetResult(true);
31+
}
32+
catch (Exception ex)
33+
{
34+
tcs.SetException(ex);
35+
}
36+
}, TaskPriority.Normal);
37+
return tcs.Task.ContinueWith(_ => document);
38+
}
39+
40+
/// <summary>
41+
/// Enqueues the given JavaScript code as a normal task to the document,
42+
/// thus ensuring it runs after any script-related actions.
43+
/// </summary>
44+
/// <param name="document">The document to extend.</param>
45+
/// <param name="jsSource">The JavaScript action to perform.</param>
46+
/// <returns>A task that is finished when the enqueued task completed.</returns>
47+
public static Task<IDocument> Then(this IDocument document, String jsSource) =>
48+
document.Then(current => current.ExecuteScript(jsSource));
49+
50+
/// <summary>
51+
/// Enqueues the given action as a normal task to the document,
52+
/// thus ensuring it runs after any script-related actions.
53+
/// </summary>
54+
/// <param name="documentTask">The soon available document.</param>
55+
/// <param name="action">The action on the document to perform.</param>
56+
/// <returns>A task that is finished when the enqueued task completed.</returns>
57+
public static async Task<IDocument> Then(this Task<IDocument> documentTask, Action<IDocument> action)
58+
{
59+
var document = await documentTask.ConfigureAwait(false);
60+
return await document.Then(action).ConfigureAwait(false);
61+
}
62+
63+
/// <summary>
64+
/// Enqueues the given JavaScript code as a normal task to the document,
65+
/// thus ensuring it runs after any script-related actions.
66+
/// </summary>
67+
/// <param name="documentTask">The soon available document.</param>
68+
/// <param name="jsSource">The JavaScript action to perform.</param>
69+
/// <returns>A task that is finished when the enqueued task completed.</returns>
70+
public static Task<IDocument> Then(this Task<IDocument> documentTask, String jsSource) =>
71+
documentTask.Then(document => document.ExecuteScript(jsSource));
72+
}
73+
}

src/AngleSharp.Js/JsScriptingService.cs

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -42,37 +42,27 @@ public JsScriptingService()
4242
/// <summary>
4343
/// Gets the external assignments.
4444
/// </summary>
45-
public IDictionary<String, Object> External
46-
{
47-
get { return _external; }
48-
}
45+
public IDictionary<String, Object> External => _external;
4946

5047
/// <summary>
5148
/// Gets the engine's mime-type.
5249
/// </summary>
53-
public String Type
54-
{
55-
get { return MimeTypeNames.DefaultJavaScript; }
56-
}
50+
public String Type => MimeTypeNames.DefaultJavaScript;
5751

5852
#endregion
5953

6054
#region Methods
6155

62-
Boolean IScriptingService.SupportsType(String mimeType)
63-
{
64-
return MimeTypeNames.IsJavaScript(mimeType);
65-
}
56+
Boolean IScriptingService.SupportsType(String mimeType) =>
57+
MimeTypeNames.IsJavaScript(mimeType);
6658

6759
/// <summary>
6860
/// Gets the associated Jint engine or creates it.
6961
/// </summary>
7062
/// <param name="document">The current document.</param>
7163
/// <returns>The engine object.</returns>
72-
public Engine GetOrCreateJint(IDocument document)
73-
{
74-
return GetOrCreateInstance(document).Jint;
75-
}
64+
public Engine GetOrCreateJint(IDocument document) =>
65+
GetOrCreateInstance(document).Jint;
7666

7767
/// <summary>
7868
/// Evaluates the response asynchronously.
@@ -82,7 +72,9 @@ public Engine GetOrCreateJint(IDocument document)
8272
/// <param name="cancel">The cancellation token to transport.</param>
8373
public async Task EvaluateScriptAsync(IResponse response, ScriptOptions options, CancellationToken cancel)
8474
{
85-
using (var reader = new StreamReader(response.Content, options.Encoding ?? Encoding.UTF8, true))
75+
var encoding = options.Encoding ?? Encoding.UTF8;
76+
77+
using (var reader = new StreamReader(response.Content, encoding, true))
8678
{
8779
var content = await reader.ReadToEndAsync().ConfigureAwait(false);
8880
EvaluateScript(options.Document, content);
@@ -97,9 +89,7 @@ public async Task EvaluateScriptAsync(IResponse response, ScriptOptions options,
9789
/// <returns>The result of the evaluation.</returns>
9890
public Object EvaluateScript(IDocument document, String source)
9991
{
100-
if (document == null)
101-
throw new ArgumentNullException(nameof(document));
102-
92+
document = document ?? throw new ArgumentNullException(nameof(document));
10393
return GetOrCreateInstance(document).RunScript(source).FromJsValue();
10494
}
10595

@@ -109,10 +99,9 @@ public Object EvaluateScript(IDocument document, String source)
10999

110100
internal EngineInstance GetOrCreateInstance(IDocument document)
111101
{
112-
var instance = default(EngineInstance);
113102
var objectContext = document.DefaultView;
114103

115-
if (!_contexts.TryGetValue(objectContext, out instance))
104+
if (!_contexts.TryGetValue(objectContext, out var instance))
116105
{
117106
instance = new EngineInstance(objectContext, _external);
118107
_contexts.Add(objectContext, instance);

0 commit comments

Comments
 (0)