Skip to content

feat: implement attribute, class list, dataset, and style views for H… - #19

Merged
ziflex merged 6 commits into
mainfrom
feat/assign-prop
May 22, 2026
Merged

feat: implement attribute, class list, dataset, and style views for H…#19
ziflex merged 6 commits into
mainfrom
feat/assign-prop

Conversation

@ziflex

@ziflex ziflex commented May 16, 2026

Copy link
Copy Markdown
Member

This pull request introduces a significant refactor to how HTML element capabilities are resolved and accessed in the codebase, especially for CDP-backed elements. The main theme is to move away from direct interface implementation on elements and instead use provider methods to resolve capabilities like attributes, styles, and wait targets. This change enables a more flexible and extensible architecture for element capabilities, and is reflected in both the implementation and the documentation. Additionally, new view types are introduced for attribute, class, and dataset collections, supporting dynamic assignment and mutation. The documentation and tests are updated accordingly.

The most important changes are:

Capability Resolution Refactor

  • CDP-backed HTMLElement no longer directly implements interfaces such as AttributeTarget, StyleTarget, or WaitTarget. Instead, it provides provider methods (e.g., AsAttributeTarget, AsStyleTarget, AsWaitTarget) which return the appropriate capability object. This enables more flexible capability resolution and easier extension in the future. [1] [2] [3] [4] [5]
  • New provider element types and test helpers are added to validate that capability resolvers use provider methods rather than direct interface implementation. [1] [2] [3]

Attribute, Class, and Dataset View Implementations

  • Introduced new view types for attributes (attributeView), classes (classListView), and dataset (datasetView) that provide snapshot-based, mutable map-like interfaces to these collections. These support assignment and mutation patterns in a way that is consistent with browser behavior. [1] [2] [3] [4]

Documentation Updates

  • Updated the README.md to document the new assignment and mutation behavior for CDP-backed elements, including examples for mutating attributes, style, classes, and dataset properties directly through assignment. [1] [2] [3]

Helper and Test Adjustments

  • Refactored helper functions (snapshotElementHTML) to use the new capability provider pattern for accessing content and attributes, ensuring compatibility with the new architecture. [1] [2]
  • Updated capability tests to check for the absence of direct interface implementation and the correct use of provider-based resolution.

These changes modernize the capability model for HTML elements, improve testability and extensibility, and provide a more ergonomic and powerful API for mutating DOM state in Ferret scripts.

Copilot AI review requested due to automatic review settings May 16, 2026 01:48

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a write-through assignment surface for CDP-backed HTMLElement values, enabling direct property assignment (e.g. el.text = "...") and map-like nested assignment through attributes, style, classes, and dataset views that both snapshot reads and write through to the live DOM.

Changes:

  • Implement HTMLElement.Set (KeyWritable) for a limited set of writable element properties (text, html, value, checked, disabled, selected) and expose new dot-access keys (classes, dataset) for CDP elements.
  • Introduce elementMapView plus attribute/style/classList/dataset view wrappers that snapshot on read while writing through on assignment.
  • Add CDP JS templates for dataset and classList access/mutation, improve style templates for kebab-case vs camelCase, and update README + add integration/unit tests.

Reviewed changes

Copilot reviewed 17 out of 17 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/modules/web/html/dynamic/element/assignment/views.fql Integration fixture validating snapshot vs write-through semantics for views.
tests/modules/web/html/dynamic/element/assignment/invalid_class.fail.fql Negative fixture for invalid class assignment type.
tests/modules/web/html/dynamic/element/assignment/direct.fql Integration fixture validating direct element property assignment writes through.
modules/web/html/README.md Documents new CDP-only write-through assignment surface and examples.
modules/web/html/drivers/read_only_contract_test.go Updates driver contract test to assert only CDP elements are KeyWritable.
modules/web/html/drivers/cdp/templates/value.go Adds templates for textContent and generic DOM property get/set.
modules/web/html/drivers/cdp/templates/styles.go Enhances style get/set/remove to support kebab-case property names.
modules/web/html/drivers/cdp/templates/dataset.go Adds dataset snapshot/get + set/remove property templates.
modules/web/html/drivers/cdp/templates/classes.go Adds classList snapshot/get + toggle template.
modules/web/html/drivers/cdp/dom/view_keys.go Adds dataset key normalization helper.
modules/web/html/drivers/cdp/dom/style_view.go Adds style view wrapper around a snapshot with write-through mutations.
modules/web/html/drivers/cdp/dom/element_value.go Adds CDP HTMLElement writable property handling and view exposure.
modules/web/html/drivers/cdp/dom/element_map_view.go Adds generic snapshot+write-through map wrapper used by views.
modules/web/html/drivers/cdp/dom/element_map_view_test.go Unit test for elementMapView snapshot/write-through behavior.
modules/web/html/drivers/cdp/dom/dataset_view.go Adds dataset view wrapper around dataset snapshot with write-through mutations.
modules/web/html/drivers/cdp/dom/class_list_view.go Adds class list view wrapper with write-through toggling.
modules/web/html/drivers/cdp/dom/attribute_view.go Adds attribute view wrapper around attribute snapshot with write-through mutations.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +20 to +24
elementMapView: newElementMapView(
snapshot,
func(ctx context.Context, key, value runtime.Value) (runtime.Value, bool, error) {
name := runtime.ToString(key)
if value == runtime.None {
Comment on lines +26 to +30
elementMapView: newElementMapView(
snapshot,
func(ctx context.Context, key, value runtime.Value) (runtime.Value, bool, error) {
name := datasetPropertyName(key)
if value == runtime.None {
Copilot AI review requested due to automatic review settings May 19, 2026 14:52

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 34 out of 34 changed files in this pull request and generated 4 comments.

Comment on lines +20 to +30
elementMapView: newElementMapView(
snapshot,
func(ctx context.Context, key, value runtime.Value) (runtime.Value, bool, error) {
name := datasetPropertyName(key)
if value == runtime.None {
return runtime.None, true, dataset.RemoveDatasetProperty(ctx, name)
}

next := runtime.ToString(value)

return next, false, dataset.SetDatasetProperty(ctx, name, next)
upperNext := false

for _, r := range name {
if r == '-' || r == '_' {
Comment thread modules/web/html/README.md Outdated
| `HTMLPage` | `response`, `mainFrame`, `document`, `frames`, `url`, `URL`, `cookies`, `title`, `isClosed`, plus document properties through the main frame. |
| `HTMLDocument` | `url`, `URL`, `name`, `title`, `parent`, `body`, `head`, `innerHTML`, `innerText`, plus node properties. |
| `HTMLElement` | `innerText`, `innerHTML`, `value`, `attributes`, `style`, `previousElementSibling`, `nextElementSibling`, `parentElement`, plus node properties. |
| `HTMLElement` | `innerText`, `innerHTML`, `textContent` (CDP), `value`, `checked` (CDP), `disabled` (CDP), `selected` (CDP), `attributes`, `style`, `classes` (CDP), `dataset` (CDP), `previousElementSibling`, `nextElementSibling`, `parentElement`, plus node properties. |
Comment on lines +333 to +335
button.textContent = "Continue"
button.innerHTML = "<strong>Continue</strong>"
button.disabled = FALSE
Copilot AI review requested due to automatic review settings May 19, 2026 20:04

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 45 out of 45 changed files in this pull request and generated 2 comments.

upperNext := false

for _, r := range name {
if r == '-' || r == '_' {
Comment on lines +327 to +335
CDP-backed elements can also be mutated with normal assignment. Top-level assignment supports content/value properties plus `attributes`, `style`, `classes`, and `dataset`; nested assignment writes through snapshot views returned by those collection properties. A captured view keeps its read snapshot while writes through that view update the browser:

```fql
LET page = DOCUMENT($url, { driver: "cdp" })
LET button = ELEMENT(page, "button[type=submit]")

button.textContent = "Continue"
button.innerHTML = "<strong>Continue</strong>"
button.disabled = FALSE

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 46 out of 46 changed files in this pull request and generated no new comments.

@ziflex
ziflex merged commit 8f8e8b9 into main May 22, 2026
33 checks passed
@ziflex
ziflex deleted the feat/assign-prop branch May 22, 2026 12:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants