From 4c5a573d188f5bfd40fb7826dbc2138cfdc764ee Mon Sep 17 00:00:00 2001 From: Marko Lahma Date: Mon, 27 Jul 2026 11:33:30 +0300 Subject: [PATCH 1/4] docs: add scripting integration guide Closes #30 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- docs/README.md | 2 +- docs/general/01-Basics.md | 172 +++++++++++++++++++++++++++++++------- 2 files changed, 143 insertions(+), 31 deletions(-) diff --git a/docs/README.md b/docs/README.md index 20d21e3..b642d95 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2,4 +2,4 @@ We have more detailed information regarding the following subjects: -- [API Documentation](tutorials/01-API.md) +- [Scripting with AngleSharp.Js](general/01-Basics.md) diff --git a/docs/general/01-Basics.md b/docs/general/01-Basics.md index e498cb7..fe7ea66 100644 --- a/docs/general/01-Basics.md +++ b/docs/general/01-Basics.md @@ -1,60 +1,172 @@ --- -title: "Getting Started" +title: "Scripting with AngleSharp.Js" section: "AngleSharp.Js" --- -# Getting Started +# Scripting with AngleSharp.Js -## Requirements +AngleSharp.Js runs JavaScript against an AngleSharp document. It integrates the +[Jint](https://github.com/sebastienros/jint) interpreter with AngleSharp, so scripts can +read and change the same DOM that your .NET code uses. This is useful when processing pages +whose behavior depends on script execution, evaluating a snippet in a document context, or +hosting JavaScript APIs alongside your application. -AngleSharp.Js comes currently in two flavors: on Windows for .NET 4.6 and in general targetting .NET Standard 2.0 platforms. +## Install and configure -Most of the features of the library do not require .NET 4.6, which means you could create your own fork and modify it to work with previous versions of the .NET-Framework. - -You need to have AngleSharp installed already. This could be done via NuGet: +Install the package: ```ps1 -Install-Package AngleSharp +Install-Package AngleSharp.Js ``` -## Getting AngleSharp.Js over NuGet +Add `WithJs()` to the AngleSharp configuration. Add `WithEventLoop()` when scripts, events, +or resource callbacks must run in the browser-like task queue. Add a loader when the document +needs to fetch external scripts or other resources. -The simplest way of integrating AngleSharp.Js to your project is by using NuGet. You can install AngleSharp.Js by opening the package manager console (PM) and typing in the following statement: +```cs +var configuration = Configuration.Default + .WithDefaultLoader(new LoaderOptions + { + IsResourceLoadingEnabled = true, + }) + .WithJs() + .WithEventLoop(); -```ps1 -Install-Package AngleSharp.Js +var context = BrowsingContext.New(configuration); +var document = await context.OpenAsync("https://example.com"); + +await document.WaitUntilAvailable(); ``` -You can also use the graphical library package manager ("Manage NuGet Packages for Solution"). Searching for "AngleSharp.Js" in the official NuGet online feed will find this library. +`WithJs()` registers the JavaScript scripting service, support for inline event attributes +such as `onclick`, a navigation handler for `javascript:` URLs, and a default `navigator` +when the configuration does not already provide one. -## Setting up AngleSharp.Js +### Configure the execution stack -To use AngleSharp.Js you need to add it to your `Configuration` coming from AngleSharp itself. +`JsScriptingOptions.MaxCallStackDepth` defaults to 10,000. It makes deep JavaScript recursion +fail with a JavaScript error rather than exhausting the process stack. Leave it positive unless +you explicitly accept the risk of an uncatchable `StackOverflowException`. -If you just want a configuration *that works* you should use the following code: +```cs +var configuration = Configuration.Default + .WithJs(new JsScriptingOptions + { + MaxCallStackDepth = 5000, + }); +``` + +## Execute JavaScript + +HTML `")); +``` + +JavaScript can call delegates and access the public members of objects exposed this way. For +advanced integration, `GetOrCreateJint(document)` returns the document's Jint `Engine`, which +lets host code inspect JavaScript values or invoke JavaScript functions directly. + +### Capture `console.log` + +`console.log` forwards its arguments to an `IConsoleLogger` registered for the browsing +context. Provide one with `WithConsoleLogger`: + +```cs +var configuration = Configuration.Default .WithJs() - .WithConsoleLogger(ctx => new MyConsoleLogger(ctx)); + .WithConsoleLogger(_ => new ApplicationConsoleLogger()); ``` -in the previous example `MyConsoleLogger` refers to a class implementing the `IConsoleLogger` interface. Examples of classes implementing this interface are available in our [samples repository](https://github.com/AngleSharp/AngleSharp.Samples). +Implement `IConsoleLogger.Log(Object[] values)` to send the values to your application's +logging system. Without a logger, calls to `console.log` do not produce output. + +## DOM APIs and integration points + +AngleSharp.Js exposes AngleSharp DOM interfaces to JavaScript dynamically. The available +surface therefore follows the AngleSharp services registered in the browsing context. For +example, adding CSS support also makes its AngleSharp DOM types available to scripts. + +In addition to the DOM provided by AngleSharp, the package supplies: + +- `console.log`, `atob`, `btoa`, `DOMParser`, `Image`, `screen`, and `XMLHttpRequest`. +- `javascript:` URL navigation. +- Inline event-handler attributes and DOM event callbacks. +- ES modules and import maps through Jint's module loader. + +To replace the supplied behavior, register your own compatible AngleSharp service before +calling `WithJs()`. In particular, `WithJs()` preserves an existing `INavigator`, and the +`WithEventLoop` overloads accept either an existing `IEventLoop` or a factory for one. + +## Supported behavior and limitations + +AngleSharp.Js is a DOM and scripting integration, not a browser runtime. Script behavior +depends on the installed Jint and AngleSharp versions, plus the services that your +configuration supplies. Test the browser APIs your application relies on instead of assuming +complete browser parity. + +Notable limitations include: + +- Layout is not calculated unless you add appropriate AngleSharp rendering services. The + package's fallback `scroll*`, `client*`, and `offset*` element properties return `0`. +- The default `navigator` is intentionally minimal. Its platform is empty, registration + methods are no-ops, and its user-agent value is a fixed compatibility string. +- Network-backed features such as external scripts and `XMLHttpRequest` require suitable + AngleSharp requesters and resource loading configuration. +- The JavaScript engine executes application-provided or page-provided code in your process. + Treat untrusted scripts as untrusted code and apply the constraints appropriate to your + application. From 9c58742dac1ee69a9d67a86475ec82c0d7613530 Mon Sep 17 00:00:00 2001 From: Marko Lahma Date: Mon, 27 Jul 2026 11:36:32 +0300 Subject: [PATCH 2/4] docs: clarify browser facade limits Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- docs/general/01-Basics.md | 46 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/docs/general/01-Basics.md b/docs/general/01-Basics.md index fe7ea66..0bb1527 100644 --- a/docs/general/01-Basics.md +++ b/docs/general/01-Basics.md @@ -41,6 +41,20 @@ await document.WaitUntilAvailable(); such as `onclick`, a navigation handler for `javascript:` URLs, and a default `navigator` when the configuration does not already provide one. +### Customize the event loop + +`WithEventLoop()` creates a dedicated `JsEventLoop` for each browsing context. To select the +stack size of its worker thread, use the factory overload: + +```cs +var configuration = Configuration.Default + .WithJs() + .WithEventLoop(_ => new JsEventLoop(32 * 1024 * 1024)); +``` + +You can instead provide an `IEventLoop` implementation when the host application owns +scheduling. Use the factory overload when each browsing context needs an independent loop. + ### Configure the execution stack `JsScriptingOptions.MaxCallStackDepth` defaults to 10,000. It makes deep JavaScript recursion @@ -135,6 +149,18 @@ var configuration = Configuration.Default Implement `IConsoleLogger.Log(Object[] values)` to send the values to your application's logging system. Without a logger, calls to `console.log` do not produce output. +For example, a minimal logger can forward values to `System.Diagnostics`: + +```cs +sealed class ApplicationConsoleLogger : IConsoleLogger +{ + public void Log(Object[] values) + { + Debug.WriteLine(String.Join(" ", values)); + } +} +``` + ## DOM APIs and integration points AngleSharp.Js exposes AngleSharp DOM interfaces to JavaScript dynamically. The available @@ -148,6 +174,20 @@ In addition to the DOM provided by AngleSharp, the package supplies: - Inline event-handler attributes and DOM event callbacks. - ES modules and import maps through Jint's module loader. +### Built-in browser facades + +The additional browser-like APIs are deliberately small. Use this table when deciding whether +they meet a script's needs: + +| API | Available behavior | +| --- | --- | +| `DOMParser` | `parseFromString` creates a document through the configured `IDocumentFactory`. The requested MIME type must be supported by that configuration. | +| `Image` | Creates an AngleSharp `` element; optional width and height become its display dimensions. | +| `window.postMessage` | Queues a `message` event on the current window. It requires an event loop; it does not transfer objects or deliver to another browsing context. | +| `XMLHttpRequest` | Supports `open`, `send`, request headers, status, text responses, and lifecycle events through the configured document loader. | +| `console` | Supports `console.log` only. | +| `screen` | Exposes fixed 1920-by-1080 dimensions and 24-bit color depth for compatibility. | + To replace the supplied behavior, register your own compatible AngleSharp service before calling `WithJs()`. In particular, `WithJs()` preserves an existing `INavigator`, and the `WithEventLoop` overloads accept either an existing `IEventLoop` or a factory for one. @@ -161,12 +201,14 @@ complete browser parity. Notable limitations include: -- Layout is not calculated unless you add appropriate AngleSharp rendering services. The - package's fallback `scroll*`, `client*`, and `offset*` element properties return `0`. +- The package does not calculate layout. Its `scroll*`, `client*`, and `offset*` element + properties return `0`. - The default `navigator` is intentionally minimal. Its platform is empty, registration methods are no-ops, and its user-agent value is a fixed compatibility string. - Network-backed features such as external scripts and `XMLHttpRequest` require suitable AngleSharp requesters and resource loading configuration. +- `XMLHttpRequest` currently provides text responses only. Its `response`, `responseXML`, and + `upload` properties are unavailable, and `responseType` always has its empty value. - The JavaScript engine executes application-provided or page-provided code in your process. Treat untrusted scripts as untrusted code and apply the constraints appropriate to your application. From 6714582fcff72103cf3dab027c3e7dbdac3f8004 Mon Sep 17 00:00:00 2001 From: Marko Lahma Date: Mon, 27 Jul 2026 11:41:47 +0300 Subject: [PATCH 3/4] docs: clarify integration behavior Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- docs/general/01-Basics.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/docs/general/01-Basics.md b/docs/general/01-Basics.md index 0bb1527..1fbd388 100644 --- a/docs/general/01-Basics.md +++ b/docs/general/01-Basics.md @@ -101,6 +101,9 @@ With an event loop configured, use the document extensions to control when work | `WhenStable()` | Wait until the work already in the event loop has completed. | | `WaitUntilAvailable()` | Wait for document completion and then for the event loop to stabilize. | +These methods do not wait for asynchronous I/O that a script starts after the marker has been +queued. For example, await an event dispatched by the script after an `XMLHttpRequest` finishes. + For example, wait for scripts that change the document before reading the result: ```cs @@ -135,6 +138,9 @@ JavaScript can call delegates and access the public members of objects exposed t advanced integration, `GetOrCreateJint(document)` returns the document's Jint `Engine`, which lets host code inspect JavaScript values or invoke JavaScript functions directly. +Registering a `JsScriptingService` directly does not add the auxiliary integration that +`WithJs()` supplies: inline event-handler attributes and `javascript:` URL navigation. + ### Capture `console.log` `console.log` forwards its arguments to an `IConsoleLogger` registered for the browsing @@ -183,7 +189,7 @@ they meet a script's needs: | --- | --- | | `DOMParser` | `parseFromString` creates a document through the configured `IDocumentFactory`. The requested MIME type must be supported by that configuration. | | `Image` | Creates an AngleSharp `` element; optional width and height become its display dimensions. | -| `window.postMessage` | Queues a `message` event on the current window. It requires an event loop; it does not transfer objects or deliver to another browsing context. | +| `window.postMessage` | Queues a `message` event on the current window. It requires an event loop; it does not transfer objects, deliver to another browsing context, or enforce `targetOrigin`. | | `XMLHttpRequest` | Supports `open`, `send`, request headers, status, text responses, and lifecycle events through the configured document loader. | | `console` | Supports `console.log` only. | | `screen` | Exposes fixed 1920-by-1080 dimensions and 24-bit color depth for compatibility. | @@ -208,7 +214,8 @@ Notable limitations include: - Network-backed features such as external scripts and `XMLHttpRequest` require suitable AngleSharp requesters and resource loading configuration. - `XMLHttpRequest` currently provides text responses only. Its `response`, `responseXML`, and - `upload` properties are unavailable, and `responseType` always has its empty value. + `upload` properties are unavailable, `responseType` always has its empty value, and its + `timeout` and `withCredentials` settings do not affect requests. - The JavaScript engine executes application-provided or page-provided code in your process. Treat untrusted scripts as untrusted code and apply the constraints appropriate to your application. From 4139242b70630adb6270e776dc074f43c982a848 Mon Sep 17 00:00:00 2001 From: Marko Lahma Date: Mon, 27 Jul 2026 11:43:56 +0300 Subject: [PATCH 4/4] docs: retain getting started title Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- docs/README.md | 2 +- docs/general/01-Basics.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/README.md b/docs/README.md index b642d95..29d9695 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2,4 +2,4 @@ We have more detailed information regarding the following subjects: -- [Scripting with AngleSharp.Js](general/01-Basics.md) +- [Getting Started](general/01-Basics.md) diff --git a/docs/general/01-Basics.md b/docs/general/01-Basics.md index 1fbd388..106a181 100644 --- a/docs/general/01-Basics.md +++ b/docs/general/01-Basics.md @@ -1,8 +1,8 @@ --- -title: "Scripting with AngleSharp.Js" +title: "Getting Started" section: "AngleSharp.Js" --- -# Scripting with AngleSharp.Js +# Getting Started AngleSharp.Js runs JavaScript against an AngleSharp document. It integrates the [Jint](https://github.com/sebastienros/jint) interpreter with AngleSharp, so scripts can