Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: gost-dom/browser
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v0.5.0
Choose a base ref
...
head repository: gost-dom/browser
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v0.5.1
Choose a head ref

Commits on Mar 18, 2025

  1. Fix broken test, and include in CI build

    The code generator test suite didn't actually execute in CI builds,
    allowing a bad state in source control.
    stroiman committed Mar 18, 2025
    Copy the full SHA
    ae6854f View commit details
  2. Update go modules

    stroiman committed Mar 18, 2025
    Copy the full SHA
    d020f83 View commit details
  3. test(codegen): Control output package scope

    When testing generated code, the tests verify the intended output, but
    for qualified names, the correct output is only generated when the
    target package path is known.
    stroiman committed Mar 18, 2025
    Copy the full SHA
    a595d88 View commit details
  4. Copy the full SHA
    723a65e View commit details
  5. build: Run codegen test _after_ code gen

    Useful when working locally that all generated code isn't removed when
    code generator tests fail.
    stroiman committed Mar 18, 2025
    Copy the full SHA
    ee42788 View commit details
  6. refactor: Rename Name->OutputFile

    The word Name wasn't unambiguous in the context.
    stroiman committed Mar 18, 2025
    Copy the full SHA
    367efa5 View commit details
  7. work: Generate a struct instead of interface

    For the MutationRecord, a simple struct is the sensible type in the
    public API.
    stroiman committed Mar 18, 2025
    Copy the full SHA
    c225870 View commit details
  8. work: Create skeleton mutation.Observer type

    stroiman committed Mar 18, 2025
    Copy the full SHA
    350d082 View commit details
  9. Copy the full SHA
    ce39020 View commit details
  10. Copy the full SHA
    b9231ff View commit details
  11. test: Convert XHR tests to naked go tests

    stroiman committed Mar 18, 2025
    Copy the full SHA
    390898e View commit details

Commits on Mar 19, 2025

  1. refactor(codegen): Move inteface method generation

    Move the code to generate an IdlInterfaceOperation, making it a valid
    Generator by itself.
    stroiman committed Mar 19, 2025
    Copy the full SHA
    6193d83 View commit details
  2. refactor(codegen): Restructor generator

    The old structure made sense in the previous larger function, but being
    extracted, it makes more sense to exit early
    stroiman committed Mar 19, 2025
    Copy the full SHA
    a82426a View commit details
  3. refactor(codegen): Join idl argument with overrides

    Makes it simpler to identify custom rules, particularly when looking at
    the _next_ argument.
    stroiman committed Mar 19, 2025
    Copy the full SHA
    900415f View commit details

Commits on Mar 20, 2025

  1. docs: Update feature list doc

    Clarify a few details, and link to relevant GH issues.
    stroiman committed Mar 20, 2025
    Copy the full SHA
    715c0a0 View commit details
  2. work(dom): MutationObserver listens to Append

    A very crude implementation, not respecting options.
    stroiman committed Mar 20, 2025
    Copy the full SHA
    ff7270f View commit details
  3. Copy the full SHA
    8dd4c1d View commit details
  4. work(codegen): Don't emit variadic argument names

    When combined with non-variadic arguments, this results in invalid code.
    Either all interface arguments have names, or none! None is most
    consistent with the code.
    stroiman committed Mar 20, 2025
    Copy the full SHA
    bdf7c23 View commit details
  5. work: Change Observer.observe signature

    This combines two functions into one with variadic arguments, and
    returns an error for the case when the combination of arguments are
    invalid.
    
    This is particularly necessary necessary change because no arguments at
    all is not a valid, so the previous `Observe` call didn't make sense at
    all.
    stroiman committed Mar 20, 2025
    Copy the full SHA
    cced3c0 View commit details
  6. work: Validate MutationObserver.Observe options

    The API require at least _one_ of the values, ChildList, Attributes, or
    CharacterData be set to true. This check is handled in the
    implementation
    stroiman committed Mar 20, 2025
    Copy the full SHA
    69ac3c0 View commit details
  7. Copy the full SHA
    014a730 View commit details
  8. Copy the full SHA
    55602e6 View commit details
  9. Copy the full SHA
    5825cc6 View commit details
  10. work: Move mutation observer to internal

    The mutation API is still in development, so in order to avoid
    non-breaking changes, it's moved to internal package.
    stroiman committed Mar 20, 2025
    Copy the full SHA
    8cce494 View commit details
  11. chore: Add 'changes' make target

    Simple helper for reporting changes to the public API since the last
    rechable release
    
    Reachable release means that it takes the branch into consideration.
    A branch from a previous release would use that as source, instead of
    the latest published version
    stroiman committed Mar 20, 2025
    Copy the full SHA
    69a88ba View commit details
  12. work: Unexport dom/Logger

    This has only internal use, so avoid adding it as an exported name
    stroiman committed Mar 20, 2025
    Copy the full SHA
    0505faf View commit details
  13. refactor: Introduce a BrowsingContext interface

    This allows some types to depend on a context, but not the entire Window
    API, e.g., XHR can receive a window object containing current URL (used
    to interpret local relative/absolute URLs), as well as the http client,
    and logger to use going forward.
    
    The clock is still an explicit argument, as the XHR need to have more
    low level access to the clock than we want to expose on the Window
    interface.
    stroiman committed Mar 20, 2025
    Copy the full SHA
    73cbc02 View commit details
  14. feat: Browser-scoped logger

    Add support for each browser to have it's own logger, allowing test code
    to have higher control of logging, but using individual settings in a
    test-by-test case.
    stroiman committed Mar 20, 2025
    Copy the full SHA
    a401acc View commit details
  15. test: Replace "TODO" in tests with project tasks

    The TODO tests served as a poor man's task list. The github project is
    used extensively now instead.
    stroiman committed Mar 20, 2025
    Copy the full SHA
    c9d7de9 View commit details
  16. test: Remove skipped tests

    The features are already covered by other tests
    stroiman committed Mar 20, 2025
    Copy the full SHA
    6d9b1fd View commit details
  17. Reuse option type

    stroiman committed Mar 20, 2025
    Copy the full SHA
    9f5150b View commit details
  18. Copy the full SHA
    861d0b3 View commit details
  19. Copy the full SHA
    b669690 View commit details
  20. Copy the full SHA
    3b1ec50 View commit details
  21. work: Add verification node logging

    stroiman committed Mar 20, 2025
    Copy the full SHA
    f989606 View commit details
  22. build: Change automated github release creation

    stroiman committed Mar 20, 2025
    Copy the full SHA
    8b9e81d View commit details
  23. build: Skip gorelease step

    This doesn't follow the intended versioning.
    stroiman committed Mar 20, 2025
    Copy the full SHA
    70bd329 View commit details
  24. chore(release): 0.5.1

    stroiman committed Mar 20, 2025
    Copy the full SHA
    9275eb2 View commit details
Showing with 1,527 additions and 738 deletions.
  1. +0 −18 .github/release.yml
  2. +35 −0 .github/workflows/create-github-release.yml
  3. +3 −0 .github/workflows/release.yml
  4. +7 −0 CHANGELOG.md
  5. +11 −1 Makefile
  6. +35 −7 browser.go
  7. +31 −1 browser_test.go
  8. +6 −7 docs/Features.md
  9. +8 −0 dom/document.go
  10. +0 −4 dom/element_test.go
  11. +19 −8 dom/event/event_target.go
  12. +76 −1 dom/node.go
  13. +3 −3 dom/parent_node_generated.go
  14. +5 −1 html/history.go
  15. +8 −0 html/html_element.go
  16. +1 −1 html/html_script_element.go
  17. +35 −22 html/window.go
  18. +5 −1 internal/code-gen/Makefile
  19. +31 −0 internal/code-gen/codegentest/renderer.go
  20. +14 −1 internal/code-gen/customrules/customrules.go
  21. +7 −7 internal/code-gen/go.mod
  22. +14 −10 internal/code-gen/go.sum
  23. +1 −0 internal/code-gen/html-elements/combined_generators.go
  24. +4 −1 internal/code-gen/html-elements/dom_generator_test.go
  25. +14 −0 internal/code-gen/html-elements/dom_interfaces_generator.go
  26. +41 −0 internal/code-gen/html-elements/dom_interfaces_generator_test.go
  27. +70 −16 internal/code-gen/html-elements/element_generator.go
  28. +1 −1 internal/code-gen/html-elements/generator.go
  29. +12 −1 internal/code-gen/html-elements/helpers_test.go
  30. +2 −2 internal/code-gen/html-elements/html_generators_test.go
  31. +79 −48 internal/code-gen/html-elements/idl_interface.go
  32. +2 −2 internal/code-gen/html-elements/idl_type.go
  33. +1 −0 internal/code-gen/script-wrappers/v8_generators.go
  34. +109 −0 internal/dom/mutation/observer.go
  35. +163 −0 internal/dom/mutation/observer_test.go
  36. +16 −0 internal/dom/mutation/options.go
  37. +26 −0 internal/gosterror/errors.go
  38. +28 −19 internal/html/xml_http_request.go
  39. +176 −231 internal/html/xml_http_request_test.go
  40. +11 −0 internal/interfaces/dom-interfaces/mutation_observer_generated.go
  41. +11 −0 internal/interfaces/dom-interfaces/mutation_observer_init.go
  42. +17 −0 internal/interfaces/dom-interfaces/mutation_record_generated.go
  43. +3 −0 internal/interfaces/dom-interfaces/package.go
  44. +12 −5 internal/interfaces/package.go
  45. +24 −9 internal/log/log.go
  46. +2 −0 internal/testing/gomega-matchers/gomega-matchers.go
  47. +23 −24 release
  48. +9 −9 scripting/v8host/dom_token_list_generated.go
  49. +34 −34 scripting/v8host/element_generated.go
  50. +6 −0 scripting/v8host/es_wrapper.go
  51. +7 −7 scripting/v8host/event_generated.go
  52. +7 −7 scripting/v8host/history_generated.go
  53. +2 −2 scripting/v8host/html_anchor_element_generated.go
  54. +1 −1 scripting/v8host/html_element_generated.go
  55. +24 −24 scripting/v8host/html_form_element_generated.go
  56. +21 −21 scripting/v8host/html_hyperlink_element_utils_generated.go
  57. +3 −3 scripting/v8host/html_input_element_generated.go
  58. +1 −1 scripting/v8host/html_or_svgelement.go
  59. +8 −8 scripting/v8host/html_or_svgelement_generated.go
  60. +9 −9 scripting/v8host/html_template_element_generated.go
  61. +15 −15 scripting/v8host/node_generated.go
  62. +5 −5 scripting/v8host/parent_node_generated.go
  63. +4 −4 scripting/v8host/pointerevents4_generated.go
  64. +26 −9 scripting/v8host/script_host.go
  65. +16 −19 scripting/v8host/script_host_test.go
  66. +10 −10 scripting/v8host/uievents_generated.go
  67. +23 −23 scripting/v8host/url_generated.go
  68. +34 −34 scripting/v8host/window_generated.go
  69. +19 −19 scripting/v8host/xhr_generated.go
  70. +1 −1 scripting/v8host/xml_http_request.go
  71. +40 −0 testing/gomega-matchers/formatters.go
  72. +0 −13 testing/gomega-matchers/html_matchers.go
  73. +0 −8 url/url_test.go
18 changes: 0 additions & 18 deletions .github/release.yml

This file was deleted.

35 changes: 35 additions & 0 deletions .github/workflows/create-github-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Create a "github" release based on new tags. The actual release is created by
# the 'release' workflow, which creates a tag if successful
name: Create Release

on:
push:
tags:
- 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10

jobs:
build:
name: Create Release
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Changelog
uses: Bullrich/generate-release-changelog@master
id: Changelog
env:
REPO: ${{ github.repository }}
- name: Create Release
id: create_release
uses: actions/create-release@latest
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
with:
tag_name: ${{ github.ref }}
release_name: Release ${{ github.ref }}
body: |
${{ steps.Changelog.outputs.changelog }}
draft: false
prerelease: false
3 changes: 3 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Builds and verifies the project.
# Create a changelog based on commit messages, commits, and tags
# Calculates the new version based on conventional commit.
name: Release

on:
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
# Changelog - Gost-DOM


## [0.5.1](https://github.com/gost-dom/browser/compare/v0.5.0...v0.5.1) (2025-03-20)


### Features

* Browser-scoped logger ([a401acc](https://github.com/gost-dom/browser/commit/a401accf677b1da49a16b1a9e6782dcedb1518d0))

## [0.5.0](https://github.com/gost-dom/browser/compare/v0.4.1...v0.5.0) (2025-03-16)


12 changes: 11 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -7,6 +7,12 @@ GOW_FLAGS := $(RAW)
# Expects an existing stable version of `gow`.
GOW := gow $(GOW_FLAGS)

.PHONY: changes
changes:
echo "Changes since \c"
git tag --merged | sort -V | tail -1
gorelease -base=`git tag --merged | sort -V | tail -1`

.PHONY: main
main: codegen-watch

@@ -15,6 +21,7 @@ codegen-clean:
rm -f scripting/*_generated.go
rm -f scripting/**/*_generated.go
rm -f dom/*_generated.go
rm -f internal/**/*_generated.go
rm -f html/*_generated.go

.PHONY: codegen-watch codegen-run
@@ -26,6 +33,9 @@ codegen-watch: codegen-clean

.PHONY: codegen codegen-build codegen-build-watch

codegen-test:
$(MAKE) -C internal/code-gen test

codegen-build:
$(MAKE) -C internal/code-gen build

@@ -69,5 +79,5 @@ test-goja:
ci-build:
go build -v ./...

ci: codegen ci-build test
ci: codegen ci-build test codegen-test
git diff --quiet HEAD
42 changes: 35 additions & 7 deletions browser.go
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ package browser

import (
"fmt"
"log/slog"
"net/http"

"github.com/gost-dom/browser/html"
@@ -11,15 +12,35 @@ import (
"github.com/gost-dom/browser/scripting/v8host"
)

type browserConfig struct {
client http.Client
logger *slog.Logger
}

type BrowserOption func(*browserConfig)

func WithLogger(l *slog.Logger) BrowserOption { return func(b *browserConfig) { b.logger = l } }
func WithHandler(h http.Handler) BrowserOption {
return func(b *browserConfig) { b.client = NewHttpClientFromHandler(h) }
}

// Pretty stupid right now, but should _probably_ allow handling multiple
// windows/tabs. This used to be the case for _some_ identity providers, but I'm
// not sure if that even work anymore because of browser security.
type Browser struct {
Client http.Client
ScriptHost ScriptHost
Logger log.Logger
windows []Window
}

func (b *Browser) NewWindow() Window {
window := html.NewWindow(b.createOptions(""))
b.windows = append(b.windows, window)
return window

}

// Open will open a new [html.Window], loading the specified location. If the
// server does not respons with a 200 status code, an error is returned.
//
@@ -58,21 +79,27 @@ func NewFromHandler(handler http.Handler) *Browser {
}

// New initialises a new [Browser] with the default script engine.
func New() *Browser {
return &Browser{
ScriptHost: v8host.New(),
Client: NewHttpClient(),
func New(options ...BrowserOption) *Browser {
config := &browserConfig{client: NewHttpClient()}
for _, o := range options {
o(config)
}
result := &Browser{
Client: config.client,
Logger: config.logger,
ScriptHost: v8host.New(v8host.WithLogger(config.logger)),
}
return result
}

// NewBrowser should not be called. Call New instead.
// Deprecated: NewBrowser should not be called. Call New instead.
//
// This method will selfdestruct in 10 commits
func NewBrowser() *Browser {
return New()
}

// NewBrowserFromHandler should not be called, call, NewFromHandler instead.
// Deprecated: NewBrowserFromHandler should not be called, call, NewFromHandler instead.
//
// This method will selfdestruct in 10 commits
func NewBrowserFromHandler(handler http.Handler) *Browser {
@@ -84,11 +111,12 @@ func (b *Browser) createOptions(location string) WindowOptions {
ScriptHost: b.ScriptHost,
HttpClient: b.Client,
BaseLocation: location,
Logger: b.Logger,
}
}

func (b *Browser) Close() {
log.Debug("Browser: Close()")
log.Debug(b.Logger, "Browser: Close()")
for _, win := range b.windows {
win.Close()
}
32 changes: 31 additions & 1 deletion browser_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package browser_test

import (
"bytes"
"fmt"
"log/slog"
"net/http"
"testing"

@@ -135,7 +137,7 @@ func (s *CookiesTestSuite) TestCookiesArePersistedInSameBrowser() {

func (s *CookiesTestSuite) TestCookiesAreNotReusedInNewBrowser() {
Expect := gomega.NewWithT(s.T()).Expect
browser := NewBrowserFromHandler(http.HandlerFunc(cookieHandler))
browser := New(WithHandler(http.HandlerFunc(cookieHandler)))
win, err := browser.Open("http://localhost/")
Expect(err).ToNot(HaveOccurred())
el := win.Document().GetElementById("gost")
@@ -153,6 +155,34 @@ func TestCookies(t *testing.T) {
suite.Run(t, new(CookiesTestSuite))
}

func TestLogOutput(t *testing.T) {
var b bytes.Buffer
Expect := gomega.NewWithT(t).Expect
logger := slog.New(slog.NewTextHandler(&b, &slog.HandlerOptions{
Level: slog.LevelDebug,
}))
browser := New(
WithHandler(http.HandlerFunc(cookieHandler)),
WithLogger(logger),
)
win, err := browser.Open("http://localhost/")
Expect(err).ToNot(HaveOccurred())
win.Run("console.log('foo bar')")
Expect(b.String()).To(ContainSubstring("foo bar"))
// Expect(b.String()).ToNot(ContainSubstring("Dispatch event"))

b.Reset()
win.DispatchEvent(event.NewCustomEvent("dummy", event.CustomEventInit{}))
Expect(b.String()).To(ContainSubstring(`msg="Dispatch event"`))

b.Reset()
win.Document().Body().AppendChild(win.Document().CreateElement("div"))
win.Document().Body().DispatchEvent(event.NewCustomEvent("dummy", event.CustomEventInit{}))
Expect(b.String()).To(ContainSubstring(`msg=Node.AppendChild`))
Expect(b.String()).To(ContainSubstring(`msg="Dispatch event"`))
b.Reset()
}

func cookieHandler(w http.ResponseWriter, r *http.Request) {
var gost string
if c, _ := r.Cookie("gost"); c != nil {
13 changes: 6 additions & 7 deletions docs/Features.md
Original file line number Diff line number Diff line change
@@ -21,11 +21,9 @@ Opening windows with isolated script context, sharing a cookie store.
The browser supports plain JavaScript, either as content in a `<script>`
element, or `<script src="">`.

### Script loading

- `async` or `defer` attributes are ignored, and the script is executed when
mounted in the DOM.
- ESM is not supported.
- ESM is not supported, [#64](https://github.com/gost-dom/browser/issues/64).
- WASM is not supported.

### Script runtime
@@ -55,9 +53,10 @@ implementations to be build independently.

### DOM API

- Only supports HTML documents. XML and XHTML documents, as well as namespaces are not supported.
- Only supports HTML documents. No support for XML or XHTML documents, as well as namespaces.
- `Element.outerHTML` and `innerHTML` output is not properly escaped.
- No support for shadow DOM.
- MutationObserver - [In progress](https://github.com/gost-dom/browser/issues/65)

### HTML API

@@ -88,12 +87,12 @@ Specific HTML elements have specific behaviour.

The list of supported user interaction is yet quite limited

- `HTMLElement.click()` - implemented on `dom.Element`, due to some weirdness in
- `HTMLElemet.click()` - implemented on `dom.Element`, due to some weirdness in
the specs.

### URL API

- Doesn't support object URLs
- Doesn't support object URLs https://github.com/gost-dom/browser/issues/69

### XHR API

@@ -111,4 +110,4 @@ be directed back to Go code, see [Getting started](./Getting-started.md)

### History

- Updating history does not cause the browser to navigate
- Setting attributes on `window.history` has no effect, i.e., it doesn't navigate.
8 changes: 8 additions & 0 deletions dom/document.go
Original file line number Diff line number Diff line change
@@ -2,8 +2,10 @@ package dom

import (
"io"
"log/slog"

"github.com/gost-dom/browser/dom/event"
"github.com/gost-dom/browser/internal/log"
"golang.org/x/net/html"
)

@@ -44,6 +46,7 @@ type elementConstructor func(doc *document) Element

type document struct {
rootNode
logger *slog.Logger
activeElement Element
ownerWindow DocumentParentWindow
}
@@ -58,9 +61,14 @@ func NewDocument(window DocumentParentWindow) Document {
// What about disconnected documents, e.g. `new Document()` in the browser?
result.SetParentTarget(window)
result.SetSelf(result)
if logger, isLogSource := window.(log.LogSource); isLogSource {
result.logger = logger.Logger()
}
return result
}

func (d document) Logger() *slog.Logger { return d.logger }

func (d document) ActiveElement() Element {
if d.activeElement == nil {
return d.Body()
4 changes: 0 additions & 4 deletions dom/element_test.go
Original file line number Diff line number Diff line change
@@ -158,10 +158,6 @@ func (s *ElementTestSuite) TestTextContent() {
s.Assert().Equal(NodeTypeText, d.ChildNodes().Item(0).NodeType())
}

func (s *ElementTestSuite) TestSetTextContentRemovesChildren() {
s.T().Skip("Not implemented")
}

func TestElement(t *testing.T) {
t.Parallel()
suite.Run(t, new(ElementTestSuite))
27 changes: 19 additions & 8 deletions dom/event/event_target.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package event

import (
"log/slog"
"slices"

"github.com/gost-dom/browser/internal/log"
@@ -56,9 +57,7 @@ func NewEventTarget() EventTarget {
return &res
}

func (t *eventTarget) SetParentTarget(parent EventTarget) {
t.parentTarget = parent
}
func (t *eventTarget) SetParentTarget(parent EventTarget) { t.parentTarget = parent }

func SetEventTargetSelf(t EventTarget) {
t.setSelf(t)
@@ -91,7 +90,7 @@ func (e *eventTarget) AddEventListener(
options ...func(*EventListener),
) {
listener := e.createListener(handler, options)
log.Debug("AddEventListener", "EventType", eventType)
log.Debug(e.logger(), "AddEventListener", "EventType", eventType)
// TODO: Handle options
// - once
// - passive. Defaults to false,
@@ -134,7 +133,7 @@ func (e *eventTarget) SetCatchAllHandler(handler EventHandler) {
}

func (e *eventTarget) DispatchEvent(event *Event) bool {
log.Debug("Dispatch event", "EventType", event.Type)
log.Debug(e.logger(), "Dispatch event", "EventType", event.Type)
event.target = e.self
event.stopped = false
event.cancelled = false
@@ -162,15 +161,20 @@ func (e *eventTarget) dispatchEvent(event *Event, capture bool) {
defer func() { event.currentTarget = nil }()
if e.catchAllHandler != nil && !capture {
if err := e.catchAllHandler.HandleEvent(event); err != nil {
log.Debug("Error occurred", "error", err.Error())
log.Debug(e.logger(), "Error occurred", "error", err.Error())
e.dispatchError(err)
}
}

listeners := e.lmap[event.Type]
for i := 0; i < len(listeners); i++ {
l := listeners[i]
log.Debug("eventTarget.dispatchEvent: Calling event handler", "type", event.Type)
log.Debug(
e.logger(),
"eventTarget.dispatchEvent: Calling event handler",
"type",
event.Type,
)
if l.Capture == capture {
if err := l.Handler.HandleEvent(event); err != nil {
e.handleError(err)
@@ -185,7 +189,7 @@ func (e *eventTarget) dispatchEvent(event *Event, capture bool) {
}

func (e *eventTarget) handleError(err error) {
log.Error(
log.Error(e.logger(),
"eventTarget.dispatchEvent: Error occurred in event handler",
"error",
err.Error(),
@@ -215,3 +219,10 @@ func (e *eventTarget) dispatchError(err error) {
e.parentTarget.dispatchError(err)
}
}

func (e *eventTarget) logger() *slog.Logger {
if source, ok := e.self.(log.LogSource); ok {
return source.Logger()
}
return nil
}
77 changes: 76 additions & 1 deletion dom/node.go
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@ package dom
import (
"errors"
"fmt"
"log/slog"
"slices"
"strconv"
"strings"
@@ -109,9 +110,25 @@ func (t NodeType) String() string {

type GetRootNodeOptions bool

type Closer interface {
Close()
}

type ChangeEvent struct {
// The original target of the change.
Target Node
AddedNodes NodeList
RemovedNodes NodeList
}

type observer interface {
Process(ChangeEvent)
}

type Node interface {
entity.ObjectIder
event.EventTarget
Logger() log.Logger
AppendChild(node Node) (Node, error)
GetRootNode(options ...GetRootNodeOptions) Node
ChildNodes() NodeList
@@ -145,6 +162,8 @@ type Node interface {
// overriding behaviour in super-classes. This is not a behaviour that Go has.
SetSelf(node Node)

Observe(observer) Closer

getSelf() Node
setParent(Node)
setOwnerDocument(owner Document)
@@ -153,6 +172,7 @@ type Node interface {
cloneChildren() []Node
createHtmlNode() *html.Node
nodeDocument() Document
notify(ChangeEvent)
}

type node struct {
@@ -162,6 +182,7 @@ type node struct {
childNodes NodeList
parent Node
document Document
observers []observer
}

func newNode(ownerDocument Document) node {
@@ -193,6 +214,7 @@ func (n *node) cloneChildren() []Node {
//
// [MDN docs for appendChild]: https://developer.mozilla.org/en-US/docs/Web/API/Node/appendChild
func (n *node) AppendChild(node Node) (Node, error) {
log.Debug(n.Logger(), "Node.AppendChild", "target", n.String(), "child", node.NodeName())
_, err := n.self.InsertBefore(node, nil)
return node, err
}
@@ -221,11 +243,32 @@ func (n *node) InsertBefore(newChild Node, referenceNode Node) (Node, error) {

func (n *node) ChildNodes() NodeList { return n.childNodes }

func (n *node) Observe(observer observer) Closer {
if slices.Contains(n.observers, observer) {
panic("Observer already added to this node")
}
n.observers = append(n.observers, observer)
return observerCloser{n, observer}
}

func (n *node) removeObserver(o observer) {
n.observers = slices.DeleteFunc(n.observers, func(x observer) bool { return o == x })
}

type observerCloser struct {
n *node
o observer
}

func (c observerCloser) Close() {
c.n.removeObserver(c.o)
}

// func (n *node) CloneNode(deep bool) Node { return nil }

func (n *node) GetRootNode(options ...GetRootNodeOptions) Node {
if len(options) > 1 {
log.Warn("Node.GetRootNode: composed not yet implemented")
log.Warn(n.Logger(), "Node.GetRootNode: composed not yet implemented")
}
if n.parent == nil {
return n.self
@@ -305,6 +348,7 @@ func (n *node) RemoveChild(node Node) (Node, error) {
)
}
n.childNodes.setNodes(slices.Delete(n.childNodes.All(), idx, idx+1))
n.notify(n.removedNodeEvent(node))
return node, nil
}

@@ -378,6 +422,7 @@ func (n *node) insertBefore(newNode Node, referenceNode Node) (Node, error) {
n.childNodes.setNodes(slices.Insert(n.childNodes.All(), i, newNode))
}
removeNodeFromParent(newNode)
n.notify(n.addedNodeEvent(newNode))
return newNode, nil
}

@@ -494,3 +539,33 @@ func (n *node) RenderChildren(builder *strings.Builder) {
}

func (n *node) String() string { return n.self.NodeName() }

func (n *node) notify(event ChangeEvent) {
for _, o := range n.observers {
o.Process(event)
}
if n.parent != nil {
n.parent.notify(event)
}
}

func (n *node) addedNodeEvent(newNode ...Node) ChangeEvent {
return ChangeEvent{
Target: n.self,
AddedNodes: &nodeList{nodes: newNode},
}
}

func (n *node) removedNodeEvent(nodes ...Node) ChangeEvent {
return ChangeEvent{
Target: n.self,
RemovedNodes: &nodeList{nodes: nodes},
}
}

func (n *node) Logger() *slog.Logger {
if docLogger, ok := n.document.(log.LogSource); ok {
return docLogger.Logger()
}
return nil
}
6 changes: 3 additions & 3 deletions dom/parent_node_generated.go
Original file line number Diff line number Diff line change
@@ -14,23 +14,23 @@ type ParentNode interface {
See also: https://developer.mozilla.org/en-US/docs/Web/API/Element
*/
Prepend(nodes ...Node) error
Prepend(...Node) error
/*
Note that the IDL operation accepts either string or node values. This interface
requires an explicit a [Node]. Use [Document.CreateText] to convert a string to
a Node.
See also: https://developer.mozilla.org/en-US/docs/Web/API/Element
*/
Append(nodes ...Node) error
Append(...Node) error
/*
Note that the IDL operation accepts either string or node values. This interface
requires an explicit a [Node]. Use [Document.CreateText] to convert a string to
a Node.
See also: https://developer.mozilla.org/en-US/docs/Web/API/Element
*/
ReplaceChildren(nodes ...Node) error
ReplaceChildren(...Node) error
QuerySelector(string) (Element, error)
QuerySelectorAll(string) (NodeList, error)
}
6 changes: 5 additions & 1 deletion html/history.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package html

import (
"log/slog"

"github.com/gost-dom/browser/dom/event"
"github.com/gost-dom/browser/internal/log"
)
@@ -123,7 +125,7 @@ func (h History) currentIdx() int {
//
// [replaceState on the History API]: https://developer.mozilla.org/en-US/docs/Web/API/History/replaceState
func (h *History) PushState(state HistoryState, href string) error {
log.Info("History.PushState", "href", href)
log.Info(h.logger(), "History.PushState", "href", href)
newHref := h.window.setBaseLocation(href)
h.pushHistoryEntry(historyEntry{state: state, href: newHref, remote: false})
return nil
@@ -147,6 +149,8 @@ func (h History) State() HistoryState {
return h.entries[h.currentIdx()].state
}

func (h *History) logger() *slog.Logger { return h.window.Logger() }

type popStateEvent struct {
event.Event
state HistoryState
8 changes: 8 additions & 0 deletions html/html_element.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package html

import (
"log/slog"
"strconv"
"strings"

@@ -106,3 +107,10 @@ func (e *htmlElement) SetAutofocus(val bool) {
e.RemoveAttribute("autofocus")
}
}

func (e *htmlElement) logger() *slog.Logger {
if win := e.window(); win != nil {
return win.Logger()
}
return nil
}
2 changes: 1 addition & 1 deletion html/html_script_element.go
Original file line number Diff line number Diff line change
@@ -30,7 +30,7 @@ func (e *htmlScriptElement) Connected() {
}
if resp.StatusCode != 200 {
body, _ := io.ReadAll(resp.Body)
log.Error("Error from server", "body", string(body), "src", src)
log.Error(e.logger(), "Error from server", "body", string(body), "src", src)
panic("Bad response")
}

57 changes: 35 additions & 22 deletions html/window.go
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@ package html
import (
"errors"
"io"
"log/slog"
"net/http"
netURL "net/url"
"strings"
@@ -25,6 +26,13 @@ type Clock interface {
Advance(time.Duration) error
}

// Describes a current browser context
type BrowsingContext interface {
Logger() *slog.Logger
HTTPClient() http.Client
LocationHREF() string
}

type ScriptContext interface {
// Run a script, and convert the result to a Go type. Only use this if you
// need the return value, otherwise call Run.
@@ -33,15 +41,16 @@ type ScriptContext interface {
// returned.
Eval(script string) (any, error)
// Run a script. This is should be used instead of eval when the return value
// is not needed, as eval could generate an error if the value cannot be
// converted to a go-type.
// is not needed, as eval returns an error when the return value cannot be
// converted to a go type.
Run(script string) error
Clock() Clock
Close()
}

type Window interface {
event.EventTarget
BrowsingContext
entity.ObjectIder
Document() dom.Document
Close()
@@ -53,7 +62,6 @@ type Window interface {
ScriptContext() ScriptContext
Location() Location
History() *History
HTTPClient() http.Client
ParseFragment(ownerDocument dom.Document, reader io.Reader) (dom.DocumentFragment, error)
// unexported

@@ -70,6 +78,7 @@ type window struct {
httpClient http.Client
baseLocation string
domParser domParser
logger *slog.Logger
}

func newWindow(windowOptions ...WindowOption) *window {
@@ -82,6 +91,7 @@ func newWindow(windowOptions ...WindowOption) *window {
httpClient: options.HttpClient,
baseLocation: options.BaseLocation,
scriptEngineFactory: options.ScriptHost,
logger: options.Logger,
history: new(History),
}
if win.baseLocation == "" {
@@ -187,20 +197,6 @@ func (w *window) parseReader(reader io.Reader) error {

func (w *window) HTTPClient() http.Client { return w.httpClient }

type WindowOptions struct {
ScriptHost
HttpClient http.Client
BaseLocation string
}

type WindowOption interface {
Apply(options *WindowOptions)
}

type WindowOptionFunc func(*WindowOptions)

func (f WindowOptionFunc) Apply(options *WindowOptions) { f(options) }

func WindowOptionLocation(location string) WindowOptionFunc {
return func(options *WindowOptions) {
options.BaseLocation = location
@@ -228,7 +224,7 @@ func (w *window) handleResponse(resp *http.Response) error {
}

func (w *window) Navigate(href string) error {
log.Info("Window.navigate:", "href", href)
log.Info(w.Logger(), "Window.navigate:", "href", href)
w.History().pushLoad(href)
w.initScriptEngine()
w.baseLocation = href
@@ -247,7 +243,7 @@ func (w *window) Navigate(href string) error {
// reload is used internally to load a page into the browser, but without
// affecting the history
func (w *window) reload(href string) error {
log.Debug("Window.reload:", "href", href)
log.Debug(w.Logger(), "Window.reload:", "href", href)
w.initScriptEngine()
w.baseLocation = href
if href == "about:blank" {
@@ -300,9 +296,9 @@ func (w *window) Location() Location {
return newLocation(u)
}

func (w *window) Clock() Clock {
return w.scriptContext.Clock()
}
func (w *window) Clock() Clock { return w.scriptContext.Clock() }

func (w *window) LocationHREF() string { return w.baseLocation }

func (w *window) Close() {
if w.scriptContext != nil {
@@ -321,3 +317,20 @@ func (w *window) resolveHref(href string) *url.URL {
}
return r
}

func (w *window) Logger() log.Logger { return w.logger }

type WindowOptions struct {
ScriptHost
HttpClient http.Client
BaseLocation string
Logger *slog.Logger
}

type WindowOption interface {
Apply(options *WindowOptions)
}

type WindowOptionFunc func(*WindowOptions)

func (f WindowOptionFunc) Apply(options *WindowOptions) { f(options) }
6 changes: 5 additions & 1 deletion internal/code-gen/Makefile
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
test:
test-watch:
gow -c test ./...


build:
go build .

test:
go test ./...

build-watch:
gow -s -S "Build done" build
31 changes: 31 additions & 0 deletions internal/code-gen/codegentest/renderer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package codegentest

import (
"bytes"
"io"
"testing"

"github.com/dave/jennifer/jen"
"github.com/gost-dom/generators"
)

type Renderer interface {
Render(io.Writer) error
}

func RenderString(t testing.TB, renderer Renderer) string {
t.Helper()
var b bytes.Buffer
err := renderer.Render(&b)
if err != nil {
t.Errorf("RenderString: Render returned: %s", err.Error())
}
return b.String()
}

func RenderInPackage(t testing.TB, packagePath string, gen generators.Generator) string {
t.Helper()
file := jen.NewFilePath(packagePath)
file.Add(gen.Generate())
return RenderString(t, file)
}
15 changes: 14 additions & 1 deletion internal/code-gen/customrules/customrules.go
Original file line number Diff line number Diff line change
@@ -48,8 +48,11 @@ type ArgumentRules map[string]ArgumentRule
type ArgumentRule struct {
Type idl.Type
Variadic bool
Ignore bool
}

func (r ArgumentRule) OverridesType() bool { return r.Type != idl.Type{} }

type AttributeTypeRule struct {
Name string
Package string
@@ -97,6 +100,16 @@ var rules = CustomRules{
"querySelector": parentNodeQueryOperation,
"querySelectorAll": parentNodeQueryOperation,
}},
"MutationObserver": {Operations: OperationRules{
"observe": {
HasError: true,
Arguments: ArgumentRules{
"options": {
Type: idl.Type{Name: "func(*MutationObserverInit)"},
Variadic: true,
},
}},
}},
},
"html": {
"Location": {Operations: OperationRules{
@@ -116,7 +129,7 @@ var rules = CustomRules{
"requestSubmit": {HasError: true},
}},
"HTMLOrSVGElement": {Operations: OperationRules{
"focus": {Arguments: ArgumentRules{"options": {}}},
"focus": {Arguments: ArgumentRules{"options": {Ignore: true}}},
}},
},
"xhr": {
14 changes: 7 additions & 7 deletions internal/code-gen/go.mod
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@ require (
github.com/dave/jennifer v1.7.1
github.com/gost-dom/generators v0.0.0-20250307100108-99a074201466
github.com/gost-dom/webref v0.5.1
github.com/onsi/ginkgo/v2 v2.22.2
github.com/onsi/ginkgo/v2 v2.23.0
github.com/onsi/gomega v1.36.2
github.com/stretchr/testify v1.10.0
)
@@ -15,12 +15,12 @@ require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/pprof v0.0.0-20250208200701-d0013a598941 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/net v0.35.0 // indirect
golang.org/x/sys v0.30.0 // indirect
golang.org/x/text v0.22.0 // indirect
golang.org/x/tools v0.30.0 // indirect
golang.org/x/net v0.37.0 // indirect
golang.org/x/sys v0.31.0 // indirect
golang.org/x/text v0.23.0 // indirect
golang.org/x/tools v0.31.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
24 changes: 14 additions & 10 deletions internal/code-gen/go.sum
Original file line number Diff line number Diff line change
@@ -8,24 +8,20 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/pprof v0.0.0-20250208200701-d0013a598941 h1:43XjGa6toxLpeksjcxs1jIoIyr+vUfOqY2c6HB4bpoc=
github.com/google/pprof v0.0.0-20250208200701-d0013a598941/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/gost-dom/generators v0.0.0-20250130162306-db4af89dffce h1:6UQtdNhXNHBwoS9GNVcId3EllEzquJqLXwhw1iUfD+M=
github.com/gost-dom/generators v0.0.0-20250130162306-db4af89dffce/go.mod h1:KYCKK6byuCYZRyl0VrTX4F+x5kVzggRY6LcO1pectPI=
github.com/gost-dom/generators v0.0.0-20250302122505-693e3cffa93b h1:erAhurZ7nUOzsUSvYt1APvT3O+ruPvaqOA6I1R3h764=
github.com/gost-dom/generators v0.0.0-20250302122505-693e3cffa93b/go.mod h1:KYCKK6byuCYZRyl0VrTX4F+x5kVzggRY6LcO1pectPI=
github.com/gost-dom/generators v0.0.0-20250307095432-972502145b9b h1:n5DBMUO+rP6qe3AXkW+KCJYi647Fmx9tFHCKLshmvoU=
github.com/gost-dom/generators v0.0.0-20250307095432-972502145b9b/go.mod h1:KYCKK6byuCYZRyl0VrTX4F+x5kVzggRY6LcO1pectPI=
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
github.com/gost-dom/generators v0.0.0-20250307100108-99a074201466 h1:1QvUd3RPIt976H9QN3ExJ1z6UCG5ybVJ9w7alUCxsAo=
github.com/gost-dom/generators v0.0.0-20250307100108-99a074201466/go.mod h1:KYCKK6byuCYZRyl0VrTX4F+x5kVzggRY6LcO1pectPI=
github.com/gost-dom/webref v0.3.0 h1:l5x01q7v66gprGLESGvtPuQyffMEVOQz/HLkcXXSKCs=
github.com/gost-dom/webref v0.3.0/go.mod h1:eNon8FDGv/xEaMoHveVdXOgfsnuiKREWEglnMM063Gk=
github.com/gost-dom/webref v0.5.0 h1:dHSIcSCDYhKJwtbEucSqe0/J2GJo7OZPb6RALAEfk1g=
github.com/gost-dom/webref v0.5.0/go.mod h1:dDG6ljKAixLvdbSHD/FeyKbaFB5a9GiV9aHvSM5QmqE=
github.com/gost-dom/webref v0.5.1 h1:sXaLrWo++JMxDx1mI+awYFUUJi2l3weUPXIqlaTCWSk=
github.com/gost-dom/webref v0.5.1/go.mod h1:dDG6ljKAixLvdbSHD/FeyKbaFB5a9GiV9aHvSM5QmqE=
github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU=
github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk=
github.com/onsi/ginkgo/v2 v2.23.0 h1:FA1xjp8ieYDzlgS5ABTpdUDB7wtngggONc8a7ku2NqQ=
github.com/onsi/ginkgo/v2 v2.23.0/go.mod h1:zXTP6xIp3U8aVuXN8ENK9IXRaTjFnpVB9mGmaSRvxnM=
github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8=
github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@@ -34,12 +30,20 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY=
golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY=
golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU=
golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ=
google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk=
google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
1 change: 1 addition & 0 deletions internal/code-gen/html-elements/combined_generators.go
Original file line number Diff line number Diff line change
@@ -8,4 +8,5 @@ var PackageConfigs = PackageGeneratorSpecs{
"dom": DOMPackageConfig,
"html": HTMLPackageConfig,
"urlinterfaces": URLPackageConfig,
"dominterfaces": DOMInterfacesPackageConfig,
}
5 changes: 4 additions & 1 deletion internal/code-gen/html-elements/dom_generator_test.go
Original file line number Diff line number Diff line change
@@ -3,6 +3,8 @@ package htmlelements_test
import (
"testing"

"github.com/gost-dom/code-gen/codegentest"
"github.com/gost-dom/code-gen/packagenames"
. "github.com/gost-dom/generators/testing/matchers"
"github.com/onsi/gomega"
. "github.com/onsi/gomega"
@@ -28,7 +30,8 @@ func (s *DomSuite) TestGenerateHTMLCollection() {
func (s *DomSuite) TestGenerateParentNode() {
generator, err := getIdlInterfaceGenerator("dom", "ParentNode")
s.Expect(err).ToNot(HaveOccurred())
s.Expect(generator).To(HaveRendered(ContainSubstring("Append(nodes ...Node) error\n")))
output := codegentest.RenderInPackage(s.T(), packagenames.Dom, generator)
s.Expect(output).To(ContainSubstring("Append(...Node) error\n"))
}

func TestGeneratedDomTypes(t *testing.T) {
14 changes: 14 additions & 0 deletions internal/code-gen/html-elements/dom_interfaces_generator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package htmlelements

var DOMInterfacesPackageConfig = GeneratorConfig{
"mutation_observer": {
InterfaceName: "MutationObserver",
SpecName: "dom",
GenerateInterface: true,
},
"mutation_record": {
InterfaceName: "MutationRecord",
SpecName: "dom",
GenerateReadonlyStruct: true,
},
}
41 changes: 41 additions & 0 deletions internal/code-gen/html-elements/dom_interfaces_generator_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package htmlelements_test

import (
"testing"

. "github.com/gost-dom/code-gen/internal/gomega-matchers"
. "github.com/gost-dom/generators/testing/matchers"
)

func TestGenerateStructOfReadOnlyProperties(t *testing.T) {
t.Parallel()

expect := newGomega(t)
g, err := getFileGenerator("dominterfaces", "mutation_record")
expect(err).ToNot(HaveOccurred())
expect(g).To(HaveRendered(`type MutationRecord struct {
Type string
Target dom.Node
AddedNodes dom.NodeList
RemovedNodes dom.NodeList
PreviousSibling dom.Node
NextSibling dom.Node
AttributeName string
AttributeNamespace string
OldValue string
}`))
}

func TestGenerationOfExplicitVariadicArgument(t *testing.T) {
t.Parallel()

expect := newGomega(t)

g, err := getFileGenerator("dominterfaces", "mutation_observer")
expect(err).ToNot(HaveOccurred())
expect(g).To(HaveRenderedSubstring("type MutationObserver interface {\n"))
expect(
g,
).To(HaveRenderedSubstring("\n\tObserve(dom.Node, ...func(*MutationObserverInit)) error\n"))

}
86 changes: 70 additions & 16 deletions internal/code-gen/html-elements/element_generator.go
Original file line number Diff line number Diff line change
@@ -5,7 +5,10 @@ import (
"fmt"
"strings"

"github.com/dave/jennifer/jen"
"github.com/gost-dom/code-gen/customrules"
"github.com/gost-dom/code-gen/internal"
"github.com/gost-dom/generators"
g "github.com/gost-dom/generators"
"github.com/gost-dom/webref/idl"
)
@@ -33,12 +36,13 @@ type HTMLGeneratorReq struct {
// specifies what to generate. So there's a kind of pipline here
// Read(intfName, specName) -> Generate(GenStruct, GenCon...) -> Generator

InterfaceName string
SpecName string
GenerateStruct bool
GenerateConstructor bool
GenerateInterface bool
GenerateAttributes bool
InterfaceName string
SpecName string
GenerateStruct bool
GenerateConstructor bool
GenerateInterface bool
GenerateReadonlyStruct bool
GenerateAttributes bool
}

/* -------- baseGenerator -------- */
@@ -61,6 +65,48 @@ func CreateGenerator(req HTMLGeneratorReq) (baseGenerator, error) {
}, err
}

func (gen baseGenerator) Generate() *jen.Statement {
list := generators.StatementList()

if gen.req.GenerateInterface {
list.Append(gen.GenerateInterface())
}

if gen.req.GenerateReadonlyStruct {
list.Append(gen.GenerateReadonlyStruct())
}

return list.Generate()
}

func (gen baseGenerator) GenerateReadonlyStruct() g.Generator {
idlInterfaceName := gen.idlType.Name
if len(gen.idlType.Operations) > 0 {
panic(
fmt.Sprintf(
"baseGenerator.CreateReadonlyStruct: IDL interface has operations; expected only readonly attributes. Interface: %s",
idlInterfaceName,
))
}
result := g.Struct{
Name: g.NewType(idlInterfaceName),
}
for _, a := range gen.idlType.Attributes {
if !a.Readonly {
panic(
fmt.Sprintf(
"baseGenerator.CreateReadonlyStruct: IDL interface has writeable attributes. Interface: %s. Attribute: %s",
idlInterfaceName,
a.Name,
),
)
}
field := internal.UpperCaseFirstLetter(string(a.Name))
result.Field(g.Id(field), IdlType(a.Type))
}
return result
}

func (gen baseGenerator) GenerateInterface() g.Generator {
idlInterface := gen.idlType
attributes := make([]IdlInterfaceAttribute, 0)
@@ -99,14 +145,22 @@ func (gen baseGenerator) GenerateInterface() g.Generator {
}
}
operationRule := gen.rules.Operations[o.Name]
getArg := func(name string) (res customrules.ArgumentRule) {
if operationRule.Arguments != nil {
res = operationRule.Arguments[name]
}
return
}
arguments := make([]IdlInterfaceOperationArgument, len(o.Arguments))
for i, arg := range o.Arguments {
arguments[i] = IdlInterfaceOperationArgument{
Argument: arg,
Rules: getArg(arg.Name),
}
}
operations = append(
operations,
IdlInterfaceOperation{
o,
IdlType(o.ReturnType),
operationRule.ReturnType,
operationRule.HasError,
},
IdlInterfaceOperation{o, arguments, IdlType(o.ReturnType), operationRule},
)
}
result.Attributes = attributes
@@ -196,9 +250,9 @@ func (gen htmlElementGenerator) GenerateAttributes() g.Generator {
}

type FileGeneratorSpec struct {
Name string
Package string
Generator g.Generator
OutputFile string
Package string
Generator g.Generator
}

// GeneratorConfig contains the configuration for which generated files should contain
@@ -219,7 +273,7 @@ func createGenerators(
result[index] = FileGeneratorSpec{
k,
packageName,
generator.GenerateInterface(),
generator,
}
errs[index] = err
index++
2 changes: 1 addition & 1 deletion internal/code-gen/html-elements/generator.go
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ func writeFile(s FileGeneratorSpec) error {
jf := jen.NewFilePath(s.Package)
jf.HeaderComment("This file is generated. Do not edit.")
jf.Add(s.Generator.Generate())
outputFileName := fmt.Sprintf("%s_generated.go", s.Name)
outputFileName := fmt.Sprintf("%s_generated.go", s.OutputFile)
if writer, err := os.Create(outputFileName); err != nil {
return err
} else {
13 changes: 12 additions & 1 deletion internal/code-gen/html-elements/helpers_test.go
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ package htmlelements_test

import (
"bytes"
"errors"
"fmt"
"testing"

@@ -19,6 +20,16 @@ func newGomega(t *testing.T) expect { return gomega.NewWithT(t).Expect }

type BaseGenerator interface{ GenerateInterface() generator }

func getFileGenerator(packageName, targetFile string) (generators.Generator, error) {
packageSpecs, _ := htmlelements.GetPackageGeneratorSpecs(packageName)
for outputFile, spec := range packageSpecs {
if outputFile == targetFile {
return htmlelements.CreateGenerator(spec)
}
}
return nil, errors.New("Unknown package")
}

func getIdlInterfaceGenerator(
packageName string,
interfaceName string,
@@ -27,7 +38,7 @@ func getIdlInterfaceGenerator(
for _, v := range packageSpecs {
if v.InterfaceName == interfaceName {
g, err := htmlelements.CreateGenerator(v)
return g.GenerateInterface(), err
return g, err
}
}
return nil, fmt.Errorf(
4 changes: 2 additions & 2 deletions internal/code-gen/html-elements/html_generators_test.go
Original file line number Diff line number Diff line change
@@ -57,12 +57,12 @@ func TestGenerateNoFocusOptions(t *testing.T) {
// Verify that the focusoptions are not generated
expect := exp(t)
expect(getIdlInterfaceGenerator("html", "HTMLOrSVGElement")).To(HaveRenderedSubstring(
"\tFocus() bool\n"), "Focus doesn't have options")
"\tFocus()\n"), "Focus doesn't have options")
}

func TestGenerateEventHandlerFunction(t *testing.T) {
expect := exp(t)
expect(getIdlInterfaceGenerator("html", "HTMLOrSVGElement")).To(HaveRenderedSubstring(
"\tBlur() bool\n"), "Blur returns a bool")
"\tBlur()\n"), "Blur returns a bool")

}
127 changes: 79 additions & 48 deletions internal/code-gen/html-elements/idl_interface.go
Original file line number Diff line number Diff line change
@@ -54,47 +54,7 @@ func (i IdlInterface) Generate() *jen.Statement {
}
}
for _, o := range i.Operations {
if o.Stringifier && o.Name == "" {
continue
}
name := o.Name
opRules := i.Rules.Operations[name]
if !o.Static {
args := make([]generators.Generator, len(o.Arguments))
for i, a := range o.Arguments {
argRules, hasArgRules := opRules.Arguments[a.Name]
if hasArgRules {
args[i] = IdlType(argRules.Type)
} else {
args[i] = IdlType(a.Type)
}
if a.Variadic {
args[i] = generators.Raw(
jen.Id(a.Name).Add(jen.Op("...").Add(args[i].Generate())),
)
}

if i < len(o.Arguments)-1 {
nextArg := o.Arguments[i+1]
if nextArg.Optional {
fields = append(fields, generators.Raw(
jen.Id(UpperCaseFirstLetter(name)).
Params(generators.ToJenCodes(args[0:i+1])...).
Add(o.ReturnParams())))
name = name + UpperCaseFirstLetter(nextArg.Name)
}
}
}

if opRules.DocComments != "" {
fields = append(fields, generators.Raw(jen.Comment(opRules.DocComments)))
}
fields = append(fields, generators.Raw(
jen.Id(UpperCaseFirstLetter(name)).
Params(generators.ToJenCodes(args)...).
Add(o.ReturnParams()),
))
}
fields = append(fields, o)
}
return jen.Type().Add(jen.Id(i.Name)).Interface(generators.ToJenCodes(fields)...)
}
@@ -123,11 +83,68 @@ func (t OutputType) Generate() *jen.Statement {
return t.Default.Generate()
}

// Represents an operation specified on an IDL interface. The type is itself a
// [generators.Generator] for generating the method, potentially multiple
// methods if the method is overloaded in the source.
type IdlInterfaceOperation struct {
idl.Operation
ReturnType IdlType
ReturnOverride *typerule.TypeRule
HasError bool
IdlOperation idl.Operation
Arguments []IdlInterfaceOperationArgument
ReturnType IdlType
Rules customrules.OperationRule
}

func (o IdlInterfaceOperation) Stringifier() bool { return o.IdlOperation.Stringifier }
func (o IdlInterfaceOperation) Name() string { return o.IdlOperation.Name }
func (o IdlInterfaceOperation) Static() bool { return o.IdlOperation.Static }

func (o IdlInterfaceOperation) Generate() *jen.Statement {
if o.Stringifier() && o.Name() == "" {
return nil
}
name := o.Name()
opRules := o.Rules
result := generators.StatementList()
if !o.Static() {
args := make([]generators.Generator, 0, len(o.Arguments))
for i, a := range o.Arguments {
if a.Ignore() {
continue
}
var arg generators.Generator = IdlType(a.Type())
if a.Rules.OverridesType() {
arg = IdlType(a.Rules.Type)
}
if a.Variadic() {
arg = generators.Raw(jen.Op("...").Add(arg.Generate()))
}
args = append(args, arg)

if i < len(o.Arguments)-1 {
nextArg := o.Arguments[i+1]
if nextArg.Optional() {
result.Append(generators.Raw(
jen.Id(UpperCaseFirstLetter(name)).
Params(generators.ToJenCodes(args)...).
Add(o.ReturnParams())))
name = name + UpperCaseFirstLetter(nextArg.Name())
}
}
}

if opRules.DocComments != "" {
result.Append(generators.Raw(jen.Comment(opRules.DocComments)))
}
result.Append(generators.Raw(
jen.Id(UpperCaseFirstLetter(name)).
Params(generators.ToJenCodes(args)...).
Add(o.ReturnParams()),
))
}
return result.Generate()
}

func (o IdlInterfaceOperation) HasError() bool {
return o.Rules.HasError
}

// ReturnParams return multiple parameters for an operation's return types.
@@ -136,15 +153,15 @@ type IdlInterfaceOperation struct {
// true, an error return type will be added as well.
func (o IdlInterfaceOperation) ReturnParams() *jen.Statement {
result := make([]generators.Generator, 1, 3)
if o.ReturnOverride != nil {
result[0] = o.ReturnOverride
if o.Rules.ReturnType != nil {
result[0] = o.Rules.ReturnType
} else {
s := o.ReturnType
result[0] = s
if s.Nullable && !s.Nillable() {
result = append(result, generators.Id("bool"))
}
if o.HasError {
if o.HasError() {
result = append(result, generators.Id("error"))
}
}
@@ -154,3 +171,17 @@ func (o IdlInterfaceOperation) ReturnParams() *jen.Statement {
/* -------- IdlInterfaceInclude -------- */

type IdlInterfaceInclude struct{ idl.Interface }

type IdlInterfaceOperationArgument struct {
Argument idl.Argument
Rules customrules.ArgumentRule
}

func (a IdlInterfaceOperationArgument) Name() string { return a.Argument.Name }
func (a IdlInterfaceOperationArgument) Type() idl.Type { return a.Argument.Type }
func (a IdlInterfaceOperationArgument) Variadic() bool {
return a.Argument.Variadic || a.Rules.Variadic
}

func (a IdlInterfaceOperationArgument) Optional() bool { return a.Argument.Optional && !a.Variadic() }
func (a IdlInterfaceOperationArgument) Ignore() bool { return a.Rules.Ignore }
4 changes: 2 additions & 2 deletions internal/code-gen/html-elements/idl_type.go
Original file line number Diff line number Diff line change
@@ -22,8 +22,8 @@ func (s IdlType) Generate() *jen.Statement {
switch string(s.Name) {
case "boolean":
return jen.Id("bool")
case "DOMTokenList":
return jen.Qual(packagenames.Dom, "DOMTokenList")
case "DOMTokenList", "NodeList", "Node":
return jen.Qual(packagenames.Dom, s.Name)
case "undefined":
return nil
default:
1 change: 1 addition & 0 deletions internal/code-gen/script-wrappers/v8_generators.go
Original file line number Diff line number Diff line change
@@ -134,6 +134,7 @@ func CreateV8FunctionTemplateCallbackBody(
) JenGenerator {
naming := V8NamingStrategy{data}
debug := g.NewValuePackage("Debug", packagenames.Log).Call(
g.NewValue(naming.Receiver()).Field("logger").Call(g.Id("info")),
g.Lit(fmt.Sprintf("V8 Function call: %s.%s", data.Name(), op.Name)))
if op.NotImplemented {
errMsg := fmt.Sprintf(
109 changes: 109 additions & 0 deletions internal/dom/mutation/observer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package mutation

import (
"github.com/gost-dom/browser/dom"
"github.com/gost-dom/browser/internal/gosterror"
dominterfaces "github.com/gost-dom/browser/internal/interfaces/dom-interfaces"
)

type Record = dominterfaces.MutationRecord

type Callback interface {
HandleMutation([]Record, *Observer)
}

type CallbackFunc func([]Record, *Observer)

func (f CallbackFunc) HandleMutation(r []Record, o *Observer) { f(r, o) }

type RecordCallbackFunc func([]Record)

func (f RecordCallbackFunc) HandleMutation(r []Record, _ *Observer) { f(r) }

type Observer struct {
Callback Callback
pending []Record
closer dom.Closer
options Options
target dom.Node
}

func NewObserver(cb Callback) *Observer {
return &Observer{Callback: cb}
}

// Start observing for changes for a specific dom node.
//
// Panics if the observer does not have a handler.
func (o *Observer) Observe(node dom.Node, options ...func(*Options)) error {
o.assertCanObserve()

o.options = Options{}
for _, opt := range options {
opt(&o.options)
}
valid := o.options.ChildList || o.options.Attributes || o.options.CharacterData
if !valid {
return gosterror.NewTypeError(
"MutationObserver.observe: One of 'childList', 'attributes', 'characterData' must not be false",
)
}

o.target = node
o.closer = node.Observe(o)
return nil
}

func (o Observer) assertCanObserve() {
if o.Callback == nil {
// Why panic and not ignore?
//
// We could easily ignore the call in flush, but if you don't set a
// handler, you are using this type incorrectly in the first place.
//
// So we could panic in Flush instead. However, that makes the panic
// more disconnected from the code that is flawed. The call stack would
// originate from a DOM mutating call, such as Node.AppendChild; where
// this is in a call stask where test code (assumably) is setting up an
// observer.
//
// So panicing is the most helpful for a developer to find the issue in
// client code.
//
// Client code can still _remove_ the handler after creating. But that
// problem is not dealt with here, and will implicitly panic when
// flushing.
panic("Observer.ObserveOptions: A handler must be set before")
}
if o.closer != nil {
panic("Observer.ObserveOptions: Observer is already observing a DOM node")
}
}

func (o *Observer) Disconnect() {
o.closer.Close()
o.closer = nil
}

func (o *Observer) TakeRecords() (res []Record) {
res = o.pending
o.pending = nil
return
}

func (o *Observer) Process(e dom.ChangeEvent) {
if e.Target != o.target && !o.options.Subtree {
return
}
r := Record{Target: e.Target, AddedNodes: e.AddedNodes, RemovedNodes: e.RemovedNodes}
o.pending = append(o.pending, r)
}

// Deprecated: Flush is a temporary solution while developing, and is not
// intended to be called by client code.
func (o *Observer) Flush() {
records := o.TakeRecords()
if len(records) > 0 {
o.Callback.HandleMutation(records, o)
}
}
163 changes: 163 additions & 0 deletions internal/dom/mutation/observer_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
package mutation_test

import (
"slices"
"testing"

"github.com/gost-dom/browser/dom"
"github.com/gost-dom/browser/html"
. "github.com/gost-dom/browser/internal/dom/mutation"
"github.com/gost-dom/browser/internal/gosterror"
dominterfaces "github.com/gost-dom/browser/internal/interfaces/dom-interfaces"
"github.com/onsi/gomega"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
)

func TestMutationObserverConformsToTheIDLSpecs(t *testing.T) {
var observer dominterfaces.MutationObserver = &Observer{}

_, observerConforms := observer.(dominterfaces.MutationObserver)
assert.True(t, observerConforms,
"mutation.Observer conforms to the MutationObserver IDL interface",
)
}

type MutationObserverTestSuite struct {
suite.Suite
}

type MutationRecorder struct {
Records []Record
}

func (r *MutationRecorder) Clear() { r.Records = nil }

func (r *MutationRecorder) HandleMutation(recs []Record, _ *Observer) {
r.Records = append(r.Records, recs...)
}

func (r MutationRecorder) Targets() []dom.Node {
result := make([]dom.Node, len(r.Records))
for i, r := range r.Records {
result[i] = r.Target
}
return result
}

func (r MutationRecorder) AddedNodes() []dom.Node {
lists := make([][]dom.Node, len(r.Records))
for i, r := range r.Records {
if nodes := r.AddedNodes; nodes != nil {
lists[i] = nodes.All()
}
}
return slices.Concat(lists...)
}

func (r MutationRecorder) RemovedNodes() []dom.Node {
lists := make([][]dom.Node, len(r.Records))
for i, r := range r.Records {
if nodes := r.RemovedNodes; nodes != nil {
lists[i] = nodes.All()
}
}
return slices.Concat(lists...)
}

func (s *MutationObserverTestSuite) TestObserveChildListNoSubtree() {
var recorder MutationRecorder
observer := NewObserver(&recorder)

doc := html.NewHTMLDocument(nil)
body := doc.Body()

observer.Observe(body, ChildList)

div := doc.CreateElement("div")
div.SetAttribute("id", "parent")
body.AppendChild(div)

observer.Flush()
s.Assert().Equal([]dom.Node{body}, recorder.Targets())
s.Assert().Equal([]dom.Node{div}, recorder.AddedNodes())
s.Assert().Empty(recorder.RemovedNodes())
recorder.Clear()

div.AppendChild(doc.CreateElement("div"))
observer.Flush()
s.Assert().Empty(recorder.Records, "Child node was notified when subtree=false")

body.RemoveChild(div)
observer.Flush()
s.Assert().Equal([]dom.Node{body}, recorder.Targets())
g := gomega.NewWithT(s.T())
g.Expect(recorder.RemovedNodes()).To(gomega.ConsistOf(div))
s.Assert().Empty(recorder.AddedNodes())
}

func (s *MutationObserverTestSuite) TestObserveChildListWithSubtree() {
var recorder MutationRecorder
observer := NewObserver(&recorder)

doc := html.NewHTMLDocument(nil)
body := doc.Body()

div := doc.CreateElement("div")
body.AppendChild(div)
observer.Observe(body, ChildList, Subtree)

child := doc.CreateElement("div")
div.AppendChild(child)

observer.Flush()
s.Assert().Equal([]dom.Node{div}, recorder.Targets())
s.Assert().Equal([]dom.Node{child}, recorder.AddedNodes())
}

func TestValidOptions(t *testing.T) {
assert := assert.New(t)
var rec = new(MutationRecorder)

doc := html.NewHTMLDocument(nil)

assert.NoError(NewObserver(rec).Observe(doc, ChildList), "Error when including ChildList")
assert.NoError(NewObserver(rec).Observe(doc, Attributes), "Error when including Attributes")
assert.NoError(NewObserver(rec).Observe(doc, CharacterData),
"Error when including CharacterData")

observer := NewObserver(rec)
assert.ErrorIs(observer.Observe(doc), gosterror.TypeError{},
"Error when calling with no arguments")
assert.ErrorIs(
NewObserver(rec).Observe(doc,
Subtree,
AttributeOldValue,
CharacterDataOldValue,
AttributeFilter([]string{"dummy"})),
gosterror.TypeError{},
"Error when _all_ non other options than one of the 3 required is passed",
)
}

func Test(t *testing.T) {
suite.Run(t, new(MutationObserverTestSuite))
}

/*
TODO: Note this about subtree monitoring:
subtree (optional)
Set to true to extend monitoring to the entire subtree of nodes rooted at
target. All of the other properties are then extended to all of the nodes in the
subtree instead of applying solely to the target node. The default value is
false.
**Note that if a descendant of target is removed, changes in that
descendant subtree will continue to be observed, until the notification about
the removal itself has been delivered.**
source: https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver/observe
*/
16 changes: 16 additions & 0 deletions internal/dom/mutation/options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package mutation

import dominterfaces "github.com/gost-dom/browser/internal/interfaces/dom-interfaces"

type Options = dominterfaces.MutationObserverInit

func Subtree(o *Options) { o.Subtree = true }
func ChildList(o *Options) { o.ChildList = true }
func Attributes(o *Options) { o.Attributes = true }
func CharacterData(o *Options) { o.CharacterData = true }
func AttributeOldValue(o *Options) { o.AttributeOldValue = true }
func CharacterDataOldValue(o *Options) { o.CharacterDataOldValue = true }

func AttributeFilter(val []string) func(*Options) {
return func(o *Options) { o.AttributeFilter = val }
}
26 changes: 26 additions & 0 deletions internal/gosterror/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package gosterror

import (
"fmt"
)

// Represents a type that should become a TypeError in JavaScript. This is
// rarely created in Go code, but can happen through invalid combination of
// options. E.g., MutationObserver.Observe(options) will throw a TypeError if
// the options doesn't include one of ChildList, Attributes, or CharacterData.
type TypeError struct{ Message string }

func (e TypeError) Error() string {
return fmt.Sprintf("TypeError: %s", e.Message)
}

func (e TypeError) Is(err error) bool {
_, is := err.(TypeError)
return is
}

func NewTypeError(msg string) error {
return TypeError{msg}
}

var ErrTypeError = NewTypeError("TypeError")
47 changes: 28 additions & 19 deletions internal/html/xml_http_request.go
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@ import (
"strings"

"github.com/gost-dom/browser/dom/event"
"github.com/gost-dom/browser/html"
"github.com/gost-dom/browser/internal/clock"
"github.com/gost-dom/browser/internal/log"
"github.com/gost-dom/browser/url"
@@ -55,28 +56,36 @@ type XmlHttpRequest interface {

type xmlHttpRequest struct {
event.EventTarget
location string
client http.Client
async bool
status int
method string
url string
response []byte
res *http.Response
headers http.Header
clock *clock.Clock
}

func NewXmlHttpRequest(client http.Client, location string, clock *clock.Clock) XmlHttpRequest {
log.Info("NewXmlHttpRequest", "location", location)
return &xmlHttpRequest{
logSource log.LogSource
location string
client http.Client
async bool
status int
method string
url string
response []byte
res *http.Response
headers http.Header
clock *clock.Clock
}

func NewXmlHttpRequest(ctx html.BrowsingContext, clock *clock.Clock) XmlHttpRequest {
location := ctx.LocationHREF()
result := &xmlHttpRequest{
EventTarget: event.NewEventTarget(),
logSource: ctx,
location: location,
client: client,
client: ctx.HTTPClient(),
headers: make(map[string][]string),
clock: clock,
async: true,
}
event.SetEventTargetSelf(result)
log.Info(result.logSource.Logger(), "NewXmlHttpRequest", "location", location)
return result
}
func (r *xmlHttpRequest) logger() log.Logger {
return r.logSource.Logger()
}

type RequestOption = func(req *xmlHttpRequest)
@@ -88,7 +97,7 @@ func (req *xmlHttpRequest) Open(
// binding layer? Or different methods?
url string,
options ...RequestOption) {
log.Info("XmlHttpRequest.Open", "method", method, "url", url)
log.Info(req.logger(), "XmlHttpRequest.Open", "method", method, "url", url)

req.method = method
req.url = url
@@ -103,7 +112,7 @@ func (req *xmlHttpRequest) send(body io.Reader) error {
if u := url.ParseURLBase(req.url, req.location); u != nil {
reqUrl = u.Href()
}
log.Info("XmlHttpRequest.send", "url", reqUrl)
log.Info(req.logger(), "XmlHttpRequest.send", "url", reqUrl)
httpRequest, err := http.NewRequest(req.method, reqUrl, body)
if err != nil {
return err
@@ -118,7 +127,7 @@ func (req *xmlHttpRequest) send(body io.Reader) error {
b := new(bytes.Buffer) // TODO, branch out depending on content-type
_, err = b.ReadFrom(res.Body)
req.response = b.Bytes()
log.Debug("Response received", "Status", res.StatusCode)
log.Debug(req.logger(), "Response received", "Status", res.StatusCode)
req.DispatchEvent(&event.Event{Type: XHREventLoad})
return err
}
407 changes: 176 additions & 231 deletions internal/html/xml_http_request_test.go

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions internal/interfaces/dom-interfaces/mutation_observer_generated.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// This file is generated. Do not edit.

package dominterfaces

import dom "github.com/gost-dom/browser/dom"

type MutationObserver interface {
Observe(dom.Node, ...func(*MutationObserverInit)) error
Disconnect()
TakeRecords() []MutationRecord
}
11 changes: 11 additions & 0 deletions internal/interfaces/dom-interfaces/mutation_observer_init.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package dominterfaces

type MutationObserverInit struct {
Subtree bool
ChildList bool
Attributes bool
AttributeFilter []string
AttributeOldValue bool
CharacterData bool
CharacterDataOldValue bool
}
17 changes: 17 additions & 0 deletions internal/interfaces/dom-interfaces/mutation_record_generated.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// This file is generated. Do not edit.

package dominterfaces

import dom "github.com/gost-dom/browser/dom"

type MutationRecord struct {
Type string
Target dom.Node
AddedNodes dom.NodeList
RemovedNodes dom.NodeList
PreviousSibling dom.Node
NextSibling dom.Node
AttributeName string
AttributeNamespace string
OldValue string
}
3 changes: 3 additions & 0 deletions internal/interfaces/dom-interfaces/package.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
//go:generate ../../code-gen/code-gen -g gotypes -p dominterfaces

package dominterfaces
17 changes: 12 additions & 5 deletions internal/interfaces/package.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
// Package interfaces is an internal package containing generated go interfaces
// Package interfaces contains go interfaces generated from IDL specs
//
// These exist as a "guarantee" that types implementing a specific IDL interface
// has the correct methods. Some of these may be used in actual code, e.g.,
// javascript wrapper classes; and some may not even be used in real code; but
// with a test in this package to ensure that a type conforms to the interface.
// The generated interfaces guarantee that go interfaces correspond to IDL
// specifications. Not all interfaces are used in production code; but then they
// are used in test code, where a type assertion is used to guarantee that a go
// type corresponds to a concrete interface.
//
// This serves as a verification that web APIs are implemented according to the
// interfaces, as a test will fail if not; and can detect changes to the web IDL
// standards.
//
// The types are also kept in a separate package for that exact reason, to avoid
// polluting run-time packages with code that has not use at run-time.
package interfaces
33 changes: 24 additions & 9 deletions internal/log/log.go
Original file line number Diff line number Diff line change
@@ -5,7 +5,14 @@ import (
"log/slog"
)

var defaultLogger *slog.Logger
type LogSource interface{ Logger() *slog.Logger }
type Logger = *slog.Logger

type LoggerLogSource struct{ L *slog.Logger }

func (s LoggerLogSource) Logger() Logger { return s.L }

var defaultLogger Logger

func SetDefault(logger *slog.Logger) {
defaultLogger = logger
@@ -22,18 +29,26 @@ func init() {
defaultLogger = slog.New(nullHandler{})
}

func Info(msg string, args ...any) {
defaultLogger.Info(msg, args...)
func logger(source Logger) *slog.Logger {
if source != nil {
return source
} else {
return defaultLogger
}
}

func Info(source Logger, msg string, args ...any) {
logger(source).Info(msg, args...)
}

func Warn(msg string, args ...any) {
defaultLogger.Warn(msg, args...)
func Warn(source Logger, msg string, args ...any) {
logger(source).Warn(msg, args...)
}

func Debug(msg string, args ...any) {
defaultLogger.Debug(msg, args...)
func Debug(source Logger, msg string, args ...any) {
logger(source).Debug(msg, args...)
}

func Error(msg string, args ...any) {
defaultLogger.Error(msg, args...)
func Error(source Logger, msg string, args ...any) {
logger(source).Error(msg, args...)
}
2 changes: 2 additions & 0 deletions internal/testing/gomega-matchers/gomega-matchers.go
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@ package gomegamatchers
import "github.com/onsi/gomega"

var Equal = gomega.Equal
var HaveValue = gomega.HaveValue
var BeEquivalentTo = gomega.BeEquivalentTo
var BeTrue = gomega.BeTrue
var BeFalse = gomega.BeFalse
@@ -22,3 +23,4 @@ var BeEmpty = gomega.BeEmpty
var WithTransform = gomega.WithTransform

var ContainElement = gomega.ContainElement
var ConsistOf = gomega.ConsistOf
47 changes: 23 additions & 24 deletions release
Original file line number Diff line number Diff line change
@@ -17,9 +17,11 @@ set -e
# 1.9, but a 2.0 is already release, 2.0 shouldn't be merged to this branch and
# not reachable from here)
BASE_VERSION=$(git tag --merged | sort -V | tail -1)
echo "Base version: $BASE_VERSION"

pnpm exec commit-and-tag-version

exit 0

# Hmm for some reason the following fails to extract the suggested version from
# gorelease output on github, but works locally.
@@ -32,28 +34,25 @@ if [ "$BASE_VERSION" = "$NEW_VERSION" ]; then
exit 1
fi

# For some reason, the following fails to extract the suggested version on
# github, but not locally
# RELEASE_OUTPUT=$(gorelease -base=$BASE_VERSION)
SUGGESTED_VERSION=$(gorelease -base=$BASE_VERSION | tail -1 | grep -Po 'v{1,}\d(\.\d{1,}){2}$')
# echo "LAST LINE: $(echo $RELEASE_OUTPUT | tail -1)"

# # RELEASE_OUTPUT=$(gorelease -base=$BASE_VERSION)
# SUGGESTED_VERSION=$(gorelease -base=$BASE_VERSION | grep -E "v\d(\.\d{1,}){2}$" -o)
# # echo "LAST LINE: $(echo $RELEASE_OUTPUT | tail -1)"
#
# if [ "$SUGGESTED_VERSION" = "" ]; then
# echo "Error detecting suggested release"
# gorelease -base=$BASE_VERSION
# echo "Base version: $BASE_VERSION"
# echo "New version (from commits): $NEW_VERSION"
# echo "Suggested version (from gorelease): $SUGGESTED_VERSION"
# exit 1
# fi
#
# if [ "$SUGGESTED_VERSION" != "$NEW_VERSION" ]; then
# echo "New version does not match suggested version"
# echo "Base version: $BASE_VERSION"
# echo "New version (from commits): $NEW_VERSION"
# echo "Suggested version (from gorelease): $SUGGESTED_VERSION"
# exit 1
# fi
#
# echo "Suggested: $SUGGESTED_VERSION"
if [ "$SUGGESTED_VERSION" = "" ]; then
echo "Error detecting suggested release"
gorelease -base=$BASE_VERSION
echo "Base version: $BASE_VERSION"
echo "New version (from commits): $NEW_VERSION"
echo "Suggested version (from gorelease): $SUGGESTED_VERSION"
exit 1
fi

if [ "$SUGGESTED_VERSION" != "$NEW_VERSION" ]; then
echo "New version does not match suggested version"
echo "Base version: $BASE_VERSION"
echo "New version (from commits): $NEW_VERSION"
echo "Suggested version (from gorelease): $SUGGESTED_VERSION"
exit 1
fi

echo "Suggested: $SUGGESTED_VERSION"
18 changes: 9 additions & 9 deletions scripting/v8host/dom_token_list_generated.go
Original file line number Diff line number Diff line change
@@ -51,7 +51,7 @@ func (w domTokenListV8Wrapper) Constructor(info *v8.FunctionCallbackInfo) (*v8.V

func (w domTokenListV8Wrapper) item(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
ctx := w.mustGetContext(info)
log.Debug("V8 Function call: DOMTokenList.item")
log.Debug(w.logger(info), "V8 Function call: DOMTokenList.item")
args := newArgumentHelper(w.scriptHost, info)
instance, err0 := w.getInstance(info)
index, err1 := tryParseArg(args, 0, w.decodeUnsignedLong)
@@ -68,7 +68,7 @@ func (w domTokenListV8Wrapper) item(info *v8.FunctionCallbackInfo) (*v8.Value, e

func (w domTokenListV8Wrapper) contains(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
ctx := w.mustGetContext(info)
log.Debug("V8 Function call: DOMTokenList.contains")
log.Debug(w.logger(info), "V8 Function call: DOMTokenList.contains")
args := newArgumentHelper(w.scriptHost, info)
instance, err0 := w.getInstance(info)
token, err1 := tryParseArg(args, 0, w.decodeDOMString)
@@ -84,7 +84,7 @@ func (w domTokenListV8Wrapper) contains(info *v8.FunctionCallbackInfo) (*v8.Valu
}

func (w domTokenListV8Wrapper) add(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: DOMTokenList.add")
log.Debug(w.logger(info), "V8 Function call: DOMTokenList.add")
args := newArgumentHelper(w.scriptHost, info)
instance, err0 := w.getInstance(info)
tokens, err1 := tryParseArg(args, 0, w.decodeDOMString)
@@ -100,7 +100,7 @@ func (w domTokenListV8Wrapper) add(info *v8.FunctionCallbackInfo) (*v8.Value, er
}

func (w domTokenListV8Wrapper) remove(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: DOMTokenList.remove")
log.Debug(w.logger(info), "V8 Function call: DOMTokenList.remove")
args := newArgumentHelper(w.scriptHost, info)
instance, err0 := w.getInstance(info)
tokens, err1 := tryParseArg(args, 0, w.decodeDOMString)
@@ -117,7 +117,7 @@ func (w domTokenListV8Wrapper) remove(info *v8.FunctionCallbackInfo) (*v8.Value,

func (w domTokenListV8Wrapper) replace(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
ctx := w.mustGetContext(info)
log.Debug("V8 Function call: DOMTokenList.replace")
log.Debug(w.logger(info), "V8 Function call: DOMTokenList.replace")
args := newArgumentHelper(w.scriptHost, info)
instance, err0 := w.getInstance(info)
token, err1 := tryParseArg(args, 0, w.decodeDOMString)
@@ -134,13 +134,13 @@ func (w domTokenListV8Wrapper) replace(info *v8.FunctionCallbackInfo) (*v8.Value
}

func (w domTokenListV8Wrapper) supports(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: DOMTokenList.supports")
log.Debug(w.logger(info), "V8 Function call: DOMTokenList.supports")
return nil, errors.New("DOMTokenList.supports: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w domTokenListV8Wrapper) length(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
ctx := w.mustGetContext(info)
log.Debug("V8 Function call: DOMTokenList.length")
log.Debug(w.logger(info), "V8 Function call: DOMTokenList.length")
instance, err := w.getInstance(info)
if err != nil {
return nil, err
@@ -151,7 +151,7 @@ func (w domTokenListV8Wrapper) length(info *v8.FunctionCallbackInfo) (*v8.Value,

func (w domTokenListV8Wrapper) value(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
ctx := w.mustGetContext(info)
log.Debug("V8 Function call: DOMTokenList.value")
log.Debug(w.logger(info), "V8 Function call: DOMTokenList.value")
instance, err := w.getInstance(info)
if err != nil {
return nil, err
@@ -161,7 +161,7 @@ func (w domTokenListV8Wrapper) value(info *v8.FunctionCallbackInfo) (*v8.Value,
}

func (w domTokenListV8Wrapper) setValue(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: DOMTokenList.setValue")
log.Debug(w.logger(info), "V8 Function call: DOMTokenList.setValue")
args := newArgumentHelper(w.scriptHost, info)
instance, err0 := w.getInstance(info)
val, err1 := tryParseArg(args, 0, w.decodeDOMString)
68 changes: 34 additions & 34 deletions scripting/v8host/element_generated.go
Original file line number Diff line number Diff line change
@@ -99,22 +99,22 @@ func (w elementV8Wrapper) Constructor(info *v8.FunctionCallbackInfo) (*v8.Value,
}

func (w elementV8Wrapper) hasAttributes(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: Element.hasAttributes")
log.Debug(w.logger(info), "V8 Function call: Element.hasAttributes")
return nil, errors.New("Element.hasAttributes: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w elementV8Wrapper) getAttributeNames(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: Element.getAttributeNames")
log.Debug(w.logger(info), "V8 Function call: Element.getAttributeNames")
return nil, errors.New("Element.getAttributeNames: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w elementV8Wrapper) getAttributeNS(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: Element.getAttributeNS")
log.Debug(w.logger(info), "V8 Function call: Element.getAttributeNS")
return nil, errors.New("Element.getAttributeNS: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w elementV8Wrapper) setAttribute(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: Element.setAttribute")
log.Debug(w.logger(info), "V8 Function call: Element.setAttribute")
args := newArgumentHelper(w.scriptHost, info)
instance, err0 := w.getInstance(info)
qualifiedName, err1 := tryParseArg(args, 0, w.decodeDOMString)
@@ -131,12 +131,12 @@ func (w elementV8Wrapper) setAttribute(info *v8.FunctionCallbackInfo) (*v8.Value
}

func (w elementV8Wrapper) setAttributeNS(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: Element.setAttributeNS")
log.Debug(w.logger(info), "V8 Function call: Element.setAttributeNS")
return nil, errors.New("Element.setAttributeNS: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w elementV8Wrapper) removeAttribute(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: Element.removeAttribute")
log.Debug(w.logger(info), "V8 Function call: Element.removeAttribute")
args := newArgumentHelper(w.scriptHost, info)
instance, err0 := w.getInstance(info)
qualifiedName, err1 := tryParseArg(args, 0, w.decodeDOMString)
@@ -152,18 +152,18 @@ func (w elementV8Wrapper) removeAttribute(info *v8.FunctionCallbackInfo) (*v8.Va
}

func (w elementV8Wrapper) removeAttributeNS(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: Element.removeAttributeNS")
log.Debug(w.logger(info), "V8 Function call: Element.removeAttributeNS")
return nil, errors.New("Element.removeAttributeNS: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w elementV8Wrapper) toggleAttribute(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: Element.toggleAttribute")
log.Debug(w.logger(info), "V8 Function call: Element.toggleAttribute")
return nil, errors.New("Element.toggleAttribute: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w elementV8Wrapper) hasAttribute(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
ctx := w.mustGetContext(info)
log.Debug("V8 Function call: Element.hasAttribute")
log.Debug(w.logger(info), "V8 Function call: Element.hasAttribute")
args := newArgumentHelper(w.scriptHost, info)
instance, err0 := w.getInstance(info)
qualifiedName, err1 := tryParseArg(args, 0, w.decodeDOMString)
@@ -179,43 +179,43 @@ func (w elementV8Wrapper) hasAttribute(info *v8.FunctionCallbackInfo) (*v8.Value
}

func (w elementV8Wrapper) hasAttributeNS(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: Element.hasAttributeNS")
log.Debug(w.logger(info), "V8 Function call: Element.hasAttributeNS")
return nil, errors.New("Element.hasAttributeNS: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w elementV8Wrapper) getAttributeNode(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: Element.getAttributeNode")
log.Debug(w.logger(info), "V8 Function call: Element.getAttributeNode")
return nil, errors.New("Element.getAttributeNode: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w elementV8Wrapper) getAttributeNodeNS(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: Element.getAttributeNodeNS")
log.Debug(w.logger(info), "V8 Function call: Element.getAttributeNodeNS")
return nil, errors.New("Element.getAttributeNodeNS: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w elementV8Wrapper) setAttributeNode(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: Element.setAttributeNode")
log.Debug(w.logger(info), "V8 Function call: Element.setAttributeNode")
return nil, errors.New("Element.setAttributeNode: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w elementV8Wrapper) setAttributeNodeNS(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: Element.setAttributeNodeNS")
log.Debug(w.logger(info), "V8 Function call: Element.setAttributeNodeNS")
return nil, errors.New("Element.setAttributeNodeNS: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w elementV8Wrapper) removeAttributeNode(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: Element.removeAttributeNode")
log.Debug(w.logger(info), "V8 Function call: Element.removeAttributeNode")
return nil, errors.New("Element.removeAttributeNode: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w elementV8Wrapper) attachShadow(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: Element.attachShadow")
log.Debug(w.logger(info), "V8 Function call: Element.attachShadow")
return nil, errors.New("Element.attachShadow: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w elementV8Wrapper) matches(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
ctx := w.mustGetContext(info)
log.Debug("V8 Function call: Element.matches")
log.Debug(w.logger(info), "V8 Function call: Element.matches")
args := newArgumentHelper(w.scriptHost, info)
instance, err0 := w.getInstance(info)
selectors, err1 := tryParseArg(args, 0, w.decodeDOMString)
@@ -235,48 +235,48 @@ func (w elementV8Wrapper) matches(info *v8.FunctionCallbackInfo) (*v8.Value, err
}

func (w elementV8Wrapper) getElementsByTagName(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: Element.getElementsByTagName")
log.Debug(w.logger(info), "V8 Function call: Element.getElementsByTagName")
return nil, errors.New("Element.getElementsByTagName: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w elementV8Wrapper) getElementsByTagNameNS(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: Element.getElementsByTagNameNS")
log.Debug(w.logger(info), "V8 Function call: Element.getElementsByTagNameNS")
return nil, errors.New("Element.getElementsByTagNameNS: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w elementV8Wrapper) getElementsByClassName(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: Element.getElementsByClassName")
log.Debug(w.logger(info), "V8 Function call: Element.getElementsByClassName")
return nil, errors.New("Element.getElementsByClassName: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w elementV8Wrapper) insertAdjacentElement(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: Element.insertAdjacentElement")
log.Debug(w.logger(info), "V8 Function call: Element.insertAdjacentElement")
return nil, errors.New("Element.insertAdjacentElement: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w elementV8Wrapper) insertAdjacentText(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: Element.insertAdjacentText")
log.Debug(w.logger(info), "V8 Function call: Element.insertAdjacentText")
return nil, errors.New("Element.insertAdjacentText: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w elementV8Wrapper) namespaceURI(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: Element.namespaceURI")
log.Debug(w.logger(info), "V8 Function call: Element.namespaceURI")
return nil, errors.New("Element.namespaceURI: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w elementV8Wrapper) prefix(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: Element.prefix")
log.Debug(w.logger(info), "V8 Function call: Element.prefix")
return nil, errors.New("Element.prefix: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w elementV8Wrapper) localName(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: Element.localName")
log.Debug(w.logger(info), "V8 Function call: Element.localName")
return nil, errors.New("Element.localName: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w elementV8Wrapper) tagName(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
ctx := w.mustGetContext(info)
log.Debug("V8 Function call: Element.tagName")
log.Debug(w.logger(info), "V8 Function call: Element.tagName")
instance, err := w.getInstance(info)
if err != nil {
return nil, err
@@ -286,38 +286,38 @@ func (w elementV8Wrapper) tagName(info *v8.FunctionCallbackInfo) (*v8.Value, err
}

func (w elementV8Wrapper) id(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: Element.id")
log.Debug(w.logger(info), "V8 Function call: Element.id")
return nil, errors.New("Element.id: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w elementV8Wrapper) setId(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: Element.setId")
log.Debug(w.logger(info), "V8 Function call: Element.setId")
return nil, errors.New("Element.setId: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w elementV8Wrapper) className(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: Element.className")
log.Debug(w.logger(info), "V8 Function call: Element.className")
return nil, errors.New("Element.className: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w elementV8Wrapper) setClassName(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: Element.setClassName")
log.Debug(w.logger(info), "V8 Function call: Element.setClassName")
return nil, errors.New("Element.setClassName: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w elementV8Wrapper) slot(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: Element.slot")
log.Debug(w.logger(info), "V8 Function call: Element.slot")
return nil, errors.New("Element.slot: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w elementV8Wrapper) setSlot(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: Element.setSlot")
log.Debug(w.logger(info), "V8 Function call: Element.setSlot")
return nil, errors.New("Element.setSlot: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w elementV8Wrapper) attributes(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
ctx := w.mustGetContext(info)
log.Debug("V8 Function call: Element.attributes")
log.Debug(w.logger(info), "V8 Function call: Element.attributes")
instance, err := w.getInstance(info)
if err != nil {
return nil, err
@@ -327,6 +327,6 @@ func (w elementV8Wrapper) attributes(info *v8.FunctionCallbackInfo) (*v8.Value,
}

func (w elementV8Wrapper) shadowRoot(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: Element.shadowRoot")
log.Debug(w.logger(info), "V8 Function call: Element.shadowRoot")
return nil, errors.New("Element.shadowRoot: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}
6 changes: 6 additions & 0 deletions scripting/v8host/es_wrapper.go
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@ import (
"github.com/gost-dom/browser/dom"
"github.com/gost-dom/browser/html"
"github.com/gost-dom/browser/internal/entity"
"github.com/gost-dom/browser/internal/log"

v8 "github.com/gost-dom/v8go"
)
@@ -163,6 +164,11 @@ type handleReffedObject[T any] struct {
converters
}

func (w handleReffedObject[T]) logger(info *v8.FunctionCallbackInfo) log.Logger {
ctx := w.mustGetContext(info)
return ctx.window.Logger()
}

func (o handleReffedObject[T]) mustGetContext(info *v8.FunctionCallbackInfo) *V8ScriptContext {
return o.scriptHost.mustGetContext(info.Context())
}
14 changes: 7 additions & 7 deletions scripting/v8host/event_generated.go
Original file line number Diff line number Diff line change
@@ -79,7 +79,7 @@ func (w eventV8Wrapper) Constructor(info *v8.FunctionCallbackInfo) (*v8.Value, e
}

func (w eventV8Wrapper) stopPropagation(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: Event.stopPropagation")
log.Debug(w.logger(info), "V8 Function call: Event.stopPropagation")
instance, err := w.getInstance(info)
if err != nil {
return nil, err
@@ -89,7 +89,7 @@ func (w eventV8Wrapper) stopPropagation(info *v8.FunctionCallbackInfo) (*v8.Valu
}

func (w eventV8Wrapper) preventDefault(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: Event.preventDefault")
log.Debug(w.logger(info), "V8 Function call: Event.preventDefault")
instance, err := w.getInstance(info)
if err != nil {
return nil, err
@@ -100,7 +100,7 @@ func (w eventV8Wrapper) preventDefault(info *v8.FunctionCallbackInfo) (*v8.Value

func (w eventV8Wrapper) type_(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
ctx := w.mustGetContext(info)
log.Debug("V8 Function call: Event.type")
log.Debug(w.logger(info), "V8 Function call: Event.type")
instance, err := w.getInstance(info)
if err != nil {
return nil, err
@@ -111,7 +111,7 @@ func (w eventV8Wrapper) type_(info *v8.FunctionCallbackInfo) (*v8.Value, error)

func (w eventV8Wrapper) target(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
ctx := w.mustGetContext(info)
log.Debug("V8 Function call: Event.target")
log.Debug(w.logger(info), "V8 Function call: Event.target")
instance, err := w.getInstance(info)
if err != nil {
return nil, err
@@ -122,7 +122,7 @@ func (w eventV8Wrapper) target(info *v8.FunctionCallbackInfo) (*v8.Value, error)

func (w eventV8Wrapper) currentTarget(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
ctx := w.mustGetContext(info)
log.Debug("V8 Function call: Event.currentTarget")
log.Debug(w.logger(info), "V8 Function call: Event.currentTarget")
instance, err := w.getInstance(info)
if err != nil {
return nil, err
@@ -133,7 +133,7 @@ func (w eventV8Wrapper) currentTarget(info *v8.FunctionCallbackInfo) (*v8.Value,

func (w eventV8Wrapper) bubbles(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
ctx := w.mustGetContext(info)
log.Debug("V8 Function call: Event.bubbles")
log.Debug(w.logger(info), "V8 Function call: Event.bubbles")
instance, err := w.getInstance(info)
if err != nil {
return nil, err
@@ -144,7 +144,7 @@ func (w eventV8Wrapper) bubbles(info *v8.FunctionCallbackInfo) (*v8.Value, error

func (w eventV8Wrapper) cancelable(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
ctx := w.mustGetContext(info)
log.Debug("V8 Function call: Event.cancelable")
log.Debug(w.logger(info), "V8 Function call: Event.cancelable")
instance, err := w.getInstance(info)
if err != nil {
return nil, err
14 changes: 7 additions & 7 deletions scripting/v8host/history_generated.go
Original file line number Diff line number Diff line change
@@ -47,7 +47,7 @@ func (w historyV8Wrapper) Constructor(info *v8.FunctionCallbackInfo) (*v8.Value,
}

func (w historyV8Wrapper) go_(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: History.go")
log.Debug(w.logger(info), "V8 Function call: History.go")
args := newArgumentHelper(w.scriptHost, info)
instance, err0 := w.getInstance(info)
delta, err1 := tryParseArgWithDefault(args, 0, w.defaultDelta, w.decodeLong)
@@ -63,7 +63,7 @@ func (w historyV8Wrapper) go_(info *v8.FunctionCallbackInfo) (*v8.Value, error)
}

func (w historyV8Wrapper) back(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: History.back")
log.Debug(w.logger(info), "V8 Function call: History.back")
instance, err := w.getInstance(info)
if err != nil {
return nil, err
@@ -73,7 +73,7 @@ func (w historyV8Wrapper) back(info *v8.FunctionCallbackInfo) (*v8.Value, error)
}

func (w historyV8Wrapper) forward(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: History.forward")
log.Debug(w.logger(info), "V8 Function call: History.forward")
instance, err := w.getInstance(info)
if err != nil {
return nil, err
@@ -83,7 +83,7 @@ func (w historyV8Wrapper) forward(info *v8.FunctionCallbackInfo) (*v8.Value, err
}

func (w historyV8Wrapper) pushState(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: History.pushState")
log.Debug(w.logger(info), "V8 Function call: History.pushState")
args := newArgumentHelper(w.scriptHost, info)
instance, err0 := w.getInstance(info)
data, err1 := tryParseArg(args, 0, w.decodeAny)
@@ -100,7 +100,7 @@ func (w historyV8Wrapper) pushState(info *v8.FunctionCallbackInfo) (*v8.Value, e
}

func (w historyV8Wrapper) replaceState(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: History.replaceState")
log.Debug(w.logger(info), "V8 Function call: History.replaceState")
args := newArgumentHelper(w.scriptHost, info)
instance, err0 := w.getInstance(info)
data, err1 := tryParseArg(args, 0, w.decodeAny)
@@ -118,7 +118,7 @@ func (w historyV8Wrapper) replaceState(info *v8.FunctionCallbackInfo) (*v8.Value

func (w historyV8Wrapper) length(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
ctx := w.mustGetContext(info)
log.Debug("V8 Function call: History.length")
log.Debug(w.logger(info), "V8 Function call: History.length")
instance, err := w.getInstance(info)
if err != nil {
return nil, err
@@ -129,7 +129,7 @@ func (w historyV8Wrapper) length(info *v8.FunctionCallbackInfo) (*v8.Value, erro

func (w historyV8Wrapper) state(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
ctx := w.mustGetContext(info)
log.Debug("V8 Function call: History.state")
log.Debug(w.logger(info), "V8 Function call: History.state")
instance, err := w.getInstance(info)
if err != nil {
return nil, err
4 changes: 2 additions & 2 deletions scripting/v8host/html_anchor_element_generated.go
Original file line number Diff line number Diff line change
@@ -53,7 +53,7 @@ func (w htmlAnchorElementV8Wrapper) Constructor(info *v8.FunctionCallbackInfo) (

func (w htmlAnchorElementV8Wrapper) target(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
ctx := w.mustGetContext(info)
log.Debug("V8 Function call: HTMLAnchorElement.target")
log.Debug(w.logger(info), "V8 Function call: HTMLAnchorElement.target")
instance, err := w.getInstance(info)
if err != nil {
return nil, err
@@ -63,7 +63,7 @@ func (w htmlAnchorElementV8Wrapper) target(info *v8.FunctionCallbackInfo) (*v8.V
}

func (w htmlAnchorElementV8Wrapper) setTarget(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: HTMLAnchorElement.setTarget")
log.Debug(w.logger(info), "V8 Function call: HTMLAnchorElement.setTarget")
args := newArgumentHelper(w.scriptHost, info)
instance, err0 := w.getInstance(info)
val, err1 := tryParseArg(args, 0, w.decodeDOMString)
2 changes: 1 addition & 1 deletion scripting/v8host/html_element_generated.go
Original file line number Diff line number Diff line change
@@ -47,7 +47,7 @@ func (w htmlElementV8Wrapper) Constructor(info *v8.FunctionCallbackInfo) (*v8.Va
}

func (w htmlElementV8Wrapper) click(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: HTMLElement.click")
log.Debug(w.logger(info), "V8 Function call: HTMLElement.click")
instance, err := w.getInstance(info)
if err != nil {
return nil, err
48 changes: 24 additions & 24 deletions scripting/v8host/html_form_element_generated.go
Original file line number Diff line number Diff line change
@@ -92,7 +92,7 @@ func (w htmlFormElementV8Wrapper) Constructor(info *v8.FunctionCallbackInfo) (*v
}

func (w htmlFormElementV8Wrapper) submit(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: HTMLFormElement.submit")
log.Debug(w.logger(info), "V8 Function call: HTMLFormElement.submit")
instance, err := w.getInstance(info)
if err != nil {
return nil, err
@@ -102,7 +102,7 @@ func (w htmlFormElementV8Wrapper) submit(info *v8.FunctionCallbackInfo) (*v8.Val
}

func (w htmlFormElementV8Wrapper) requestSubmit(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: HTMLFormElement.requestSubmit")
log.Debug(w.logger(info), "V8 Function call: HTMLFormElement.requestSubmit")
args := newArgumentHelper(w.scriptHost, info)
instance, err0 := w.getInstance(info)
submitter, err1 := tryParseArgWithDefault(args, 0, w.defaultHTMLElement, w.decodeHTMLElement)
@@ -118,33 +118,33 @@ func (w htmlFormElementV8Wrapper) requestSubmit(info *v8.FunctionCallbackInfo) (
}

func (w htmlFormElementV8Wrapper) reset(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: HTMLFormElement.reset")
log.Debug(w.logger(info), "V8 Function call: HTMLFormElement.reset")
return nil, errors.New("HTMLFormElement.reset: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w htmlFormElementV8Wrapper) checkValidity(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: HTMLFormElement.checkValidity")
log.Debug(w.logger(info), "V8 Function call: HTMLFormElement.checkValidity")
return nil, errors.New("HTMLFormElement.checkValidity: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w htmlFormElementV8Wrapper) reportValidity(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: HTMLFormElement.reportValidity")
log.Debug(w.logger(info), "V8 Function call: HTMLFormElement.reportValidity")
return nil, errors.New("HTMLFormElement.reportValidity: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w htmlFormElementV8Wrapper) acceptCharset(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: HTMLFormElement.acceptCharset")
log.Debug(w.logger(info), "V8 Function call: HTMLFormElement.acceptCharset")
return nil, errors.New("HTMLFormElement.acceptCharset: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w htmlFormElementV8Wrapper) setAcceptCharset(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: HTMLFormElement.setAcceptCharset")
log.Debug(w.logger(info), "V8 Function call: HTMLFormElement.setAcceptCharset")
return nil, errors.New("HTMLFormElement.setAcceptCharset: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w htmlFormElementV8Wrapper) action(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
ctx := w.mustGetContext(info)
log.Debug("V8 Function call: HTMLFormElement.action")
log.Debug(w.logger(info), "V8 Function call: HTMLFormElement.action")
instance, err := w.getInstance(info)
if err != nil {
return nil, err
@@ -154,7 +154,7 @@ func (w htmlFormElementV8Wrapper) action(info *v8.FunctionCallbackInfo) (*v8.Val
}

func (w htmlFormElementV8Wrapper) setAction(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: HTMLFormElement.setAction")
log.Debug(w.logger(info), "V8 Function call: HTMLFormElement.setAction")
args := newArgumentHelper(w.scriptHost, info)
instance, err0 := w.getInstance(info)
val, err1 := tryParseArg(args, 0, w.decodeUSVString)
@@ -170,38 +170,38 @@ func (w htmlFormElementV8Wrapper) setAction(info *v8.FunctionCallbackInfo) (*v8.
}

func (w htmlFormElementV8Wrapper) autocomplete(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: HTMLFormElement.autocomplete")
log.Debug(w.logger(info), "V8 Function call: HTMLFormElement.autocomplete")
return nil, errors.New("HTMLFormElement.autocomplete: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w htmlFormElementV8Wrapper) setAutocomplete(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: HTMLFormElement.setAutocomplete")
log.Debug(w.logger(info), "V8 Function call: HTMLFormElement.setAutocomplete")
return nil, errors.New("HTMLFormElement.setAutocomplete: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w htmlFormElementV8Wrapper) enctype(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: HTMLFormElement.enctype")
log.Debug(w.logger(info), "V8 Function call: HTMLFormElement.enctype")
return nil, errors.New("HTMLFormElement.enctype: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w htmlFormElementV8Wrapper) setEnctype(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: HTMLFormElement.setEnctype")
log.Debug(w.logger(info), "V8 Function call: HTMLFormElement.setEnctype")
return nil, errors.New("HTMLFormElement.setEnctype: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w htmlFormElementV8Wrapper) encoding(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: HTMLFormElement.encoding")
log.Debug(w.logger(info), "V8 Function call: HTMLFormElement.encoding")
return nil, errors.New("HTMLFormElement.encoding: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w htmlFormElementV8Wrapper) setEncoding(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: HTMLFormElement.setEncoding")
log.Debug(w.logger(info), "V8 Function call: HTMLFormElement.setEncoding")
return nil, errors.New("HTMLFormElement.setEncoding: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w htmlFormElementV8Wrapper) method(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
ctx := w.mustGetContext(info)
log.Debug("V8 Function call: HTMLFormElement.method")
log.Debug(w.logger(info), "V8 Function call: HTMLFormElement.method")
instance, err := w.getInstance(info)
if err != nil {
return nil, err
@@ -211,7 +211,7 @@ func (w htmlFormElementV8Wrapper) method(info *v8.FunctionCallbackInfo) (*v8.Val
}

func (w htmlFormElementV8Wrapper) setMethod(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: HTMLFormElement.setMethod")
log.Debug(w.logger(info), "V8 Function call: HTMLFormElement.setMethod")
args := newArgumentHelper(w.scriptHost, info)
instance, err0 := w.getInstance(info)
val, err1 := tryParseArg(args, 0, w.decodeDOMString)
@@ -227,33 +227,33 @@ func (w htmlFormElementV8Wrapper) setMethod(info *v8.FunctionCallbackInfo) (*v8.
}

func (w htmlFormElementV8Wrapper) target(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: HTMLFormElement.target")
log.Debug(w.logger(info), "V8 Function call: HTMLFormElement.target")
return nil, errors.New("HTMLFormElement.target: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w htmlFormElementV8Wrapper) setTarget(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: HTMLFormElement.setTarget")
log.Debug(w.logger(info), "V8 Function call: HTMLFormElement.setTarget")
return nil, errors.New("HTMLFormElement.setTarget: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w htmlFormElementV8Wrapper) rel(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: HTMLFormElement.rel")
log.Debug(w.logger(info), "V8 Function call: HTMLFormElement.rel")
return nil, errors.New("HTMLFormElement.rel: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w htmlFormElementV8Wrapper) setRel(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: HTMLFormElement.setRel")
log.Debug(w.logger(info), "V8 Function call: HTMLFormElement.setRel")
return nil, errors.New("HTMLFormElement.setRel: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w htmlFormElementV8Wrapper) relList(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: HTMLFormElement.relList")
log.Debug(w.logger(info), "V8 Function call: HTMLFormElement.relList")
return nil, errors.New("HTMLFormElement.relList: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w htmlFormElementV8Wrapper) elements(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
ctx := w.mustGetContext(info)
log.Debug("V8 Function call: HTMLFormElement.elements")
log.Debug(w.logger(info), "V8 Function call: HTMLFormElement.elements")
instance, err := w.getInstance(info)
if err != nil {
return nil, err
@@ -263,6 +263,6 @@ func (w htmlFormElementV8Wrapper) elements(info *v8.FunctionCallbackInfo) (*v8.V
}

func (w htmlFormElementV8Wrapper) length(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: HTMLFormElement.length")
log.Debug(w.logger(info), "V8 Function call: HTMLFormElement.length")
return nil, errors.New("HTMLFormElement.length: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}
42 changes: 21 additions & 21 deletions scripting/v8host/html_hyperlink_element_utils_generated.go
Original file line number Diff line number Diff line change
@@ -84,7 +84,7 @@ func (w htmlHyperlinkElementUtilsV8Wrapper) Constructor(info *v8.FunctionCallbac

func (w htmlHyperlinkElementUtilsV8Wrapper) href(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
ctx := w.mustGetContext(info)
log.Debug("V8 Function call: HTMLHyperlinkElementUtils.href")
log.Debug(w.logger(info), "V8 Function call: HTMLHyperlinkElementUtils.href")
instance, err := w.getInstance(info)
if err != nil {
return nil, err
@@ -94,7 +94,7 @@ func (w htmlHyperlinkElementUtilsV8Wrapper) href(info *v8.FunctionCallbackInfo)
}

func (w htmlHyperlinkElementUtilsV8Wrapper) setHref(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: HTMLHyperlinkElementUtils.setHref")
log.Debug(w.logger(info), "V8 Function call: HTMLHyperlinkElementUtils.setHref")
args := newArgumentHelper(w.scriptHost, info)
instance, err0 := w.getInstance(info)
val, err1 := tryParseArg(args, 0, w.decodeUSVString)
@@ -111,7 +111,7 @@ func (w htmlHyperlinkElementUtilsV8Wrapper) setHref(info *v8.FunctionCallbackInf

func (w htmlHyperlinkElementUtilsV8Wrapper) origin(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
ctx := w.mustGetContext(info)
log.Debug("V8 Function call: HTMLHyperlinkElementUtils.origin")
log.Debug(w.logger(info), "V8 Function call: HTMLHyperlinkElementUtils.origin")
instance, err := w.getInstance(info)
if err != nil {
return nil, err
@@ -122,7 +122,7 @@ func (w htmlHyperlinkElementUtilsV8Wrapper) origin(info *v8.FunctionCallbackInfo

func (w htmlHyperlinkElementUtilsV8Wrapper) protocol(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
ctx := w.mustGetContext(info)
log.Debug("V8 Function call: HTMLHyperlinkElementUtils.protocol")
log.Debug(w.logger(info), "V8 Function call: HTMLHyperlinkElementUtils.protocol")
instance, err := w.getInstance(info)
if err != nil {
return nil, err
@@ -132,7 +132,7 @@ func (w htmlHyperlinkElementUtilsV8Wrapper) protocol(info *v8.FunctionCallbackIn
}

func (w htmlHyperlinkElementUtilsV8Wrapper) setProtocol(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: HTMLHyperlinkElementUtils.setProtocol")
log.Debug(w.logger(info), "V8 Function call: HTMLHyperlinkElementUtils.setProtocol")
args := newArgumentHelper(w.scriptHost, info)
instance, err0 := w.getInstance(info)
val, err1 := tryParseArg(args, 0, w.decodeUSVString)
@@ -149,7 +149,7 @@ func (w htmlHyperlinkElementUtilsV8Wrapper) setProtocol(info *v8.FunctionCallbac

func (w htmlHyperlinkElementUtilsV8Wrapper) username(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
ctx := w.mustGetContext(info)
log.Debug("V8 Function call: HTMLHyperlinkElementUtils.username")
log.Debug(w.logger(info), "V8 Function call: HTMLHyperlinkElementUtils.username")
instance, err := w.getInstance(info)
if err != nil {
return nil, err
@@ -159,7 +159,7 @@ func (w htmlHyperlinkElementUtilsV8Wrapper) username(info *v8.FunctionCallbackIn
}

func (w htmlHyperlinkElementUtilsV8Wrapper) setUsername(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: HTMLHyperlinkElementUtils.setUsername")
log.Debug(w.logger(info), "V8 Function call: HTMLHyperlinkElementUtils.setUsername")
args := newArgumentHelper(w.scriptHost, info)
instance, err0 := w.getInstance(info)
val, err1 := tryParseArg(args, 0, w.decodeUSVString)
@@ -176,7 +176,7 @@ func (w htmlHyperlinkElementUtilsV8Wrapper) setUsername(info *v8.FunctionCallbac

func (w htmlHyperlinkElementUtilsV8Wrapper) password(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
ctx := w.mustGetContext(info)
log.Debug("V8 Function call: HTMLHyperlinkElementUtils.password")
log.Debug(w.logger(info), "V8 Function call: HTMLHyperlinkElementUtils.password")
instance, err := w.getInstance(info)
if err != nil {
return nil, err
@@ -186,7 +186,7 @@ func (w htmlHyperlinkElementUtilsV8Wrapper) password(info *v8.FunctionCallbackIn
}

func (w htmlHyperlinkElementUtilsV8Wrapper) setPassword(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: HTMLHyperlinkElementUtils.setPassword")
log.Debug(w.logger(info), "V8 Function call: HTMLHyperlinkElementUtils.setPassword")
args := newArgumentHelper(w.scriptHost, info)
instance, err0 := w.getInstance(info)
val, err1 := tryParseArg(args, 0, w.decodeUSVString)
@@ -203,7 +203,7 @@ func (w htmlHyperlinkElementUtilsV8Wrapper) setPassword(info *v8.FunctionCallbac

func (w htmlHyperlinkElementUtilsV8Wrapper) host(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
ctx := w.mustGetContext(info)
log.Debug("V8 Function call: HTMLHyperlinkElementUtils.host")
log.Debug(w.logger(info), "V8 Function call: HTMLHyperlinkElementUtils.host")
instance, err := w.getInstance(info)
if err != nil {
return nil, err
@@ -213,7 +213,7 @@ func (w htmlHyperlinkElementUtilsV8Wrapper) host(info *v8.FunctionCallbackInfo)
}

func (w htmlHyperlinkElementUtilsV8Wrapper) setHost(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: HTMLHyperlinkElementUtils.setHost")
log.Debug(w.logger(info), "V8 Function call: HTMLHyperlinkElementUtils.setHost")
args := newArgumentHelper(w.scriptHost, info)
instance, err0 := w.getInstance(info)
val, err1 := tryParseArg(args, 0, w.decodeUSVString)
@@ -230,7 +230,7 @@ func (w htmlHyperlinkElementUtilsV8Wrapper) setHost(info *v8.FunctionCallbackInf

func (w htmlHyperlinkElementUtilsV8Wrapper) hostname(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
ctx := w.mustGetContext(info)
log.Debug("V8 Function call: HTMLHyperlinkElementUtils.hostname")
log.Debug(w.logger(info), "V8 Function call: HTMLHyperlinkElementUtils.hostname")
instance, err := w.getInstance(info)
if err != nil {
return nil, err
@@ -240,7 +240,7 @@ func (w htmlHyperlinkElementUtilsV8Wrapper) hostname(info *v8.FunctionCallbackIn
}

func (w htmlHyperlinkElementUtilsV8Wrapper) setHostname(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: HTMLHyperlinkElementUtils.setHostname")
log.Debug(w.logger(info), "V8 Function call: HTMLHyperlinkElementUtils.setHostname")
args := newArgumentHelper(w.scriptHost, info)
instance, err0 := w.getInstance(info)
val, err1 := tryParseArg(args, 0, w.decodeUSVString)
@@ -257,7 +257,7 @@ func (w htmlHyperlinkElementUtilsV8Wrapper) setHostname(info *v8.FunctionCallbac

func (w htmlHyperlinkElementUtilsV8Wrapper) port(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
ctx := w.mustGetContext(info)
log.Debug("V8 Function call: HTMLHyperlinkElementUtils.port")
log.Debug(w.logger(info), "V8 Function call: HTMLHyperlinkElementUtils.port")
instance, err := w.getInstance(info)
if err != nil {
return nil, err
@@ -267,7 +267,7 @@ func (w htmlHyperlinkElementUtilsV8Wrapper) port(info *v8.FunctionCallbackInfo)
}

func (w htmlHyperlinkElementUtilsV8Wrapper) setPort(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: HTMLHyperlinkElementUtils.setPort")
log.Debug(w.logger(info), "V8 Function call: HTMLHyperlinkElementUtils.setPort")
args := newArgumentHelper(w.scriptHost, info)
instance, err0 := w.getInstance(info)
val, err1 := tryParseArg(args, 0, w.decodeUSVString)
@@ -284,7 +284,7 @@ func (w htmlHyperlinkElementUtilsV8Wrapper) setPort(info *v8.FunctionCallbackInf

func (w htmlHyperlinkElementUtilsV8Wrapper) pathname(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
ctx := w.mustGetContext(info)
log.Debug("V8 Function call: HTMLHyperlinkElementUtils.pathname")
log.Debug(w.logger(info), "V8 Function call: HTMLHyperlinkElementUtils.pathname")
instance, err := w.getInstance(info)
if err != nil {
return nil, err
@@ -294,7 +294,7 @@ func (w htmlHyperlinkElementUtilsV8Wrapper) pathname(info *v8.FunctionCallbackIn
}

func (w htmlHyperlinkElementUtilsV8Wrapper) setPathname(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: HTMLHyperlinkElementUtils.setPathname")
log.Debug(w.logger(info), "V8 Function call: HTMLHyperlinkElementUtils.setPathname")
args := newArgumentHelper(w.scriptHost, info)
instance, err0 := w.getInstance(info)
val, err1 := tryParseArg(args, 0, w.decodeUSVString)
@@ -311,7 +311,7 @@ func (w htmlHyperlinkElementUtilsV8Wrapper) setPathname(info *v8.FunctionCallbac

func (w htmlHyperlinkElementUtilsV8Wrapper) search(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
ctx := w.mustGetContext(info)
log.Debug("V8 Function call: HTMLHyperlinkElementUtils.search")
log.Debug(w.logger(info), "V8 Function call: HTMLHyperlinkElementUtils.search")
instance, err := w.getInstance(info)
if err != nil {
return nil, err
@@ -321,7 +321,7 @@ func (w htmlHyperlinkElementUtilsV8Wrapper) search(info *v8.FunctionCallbackInfo
}

func (w htmlHyperlinkElementUtilsV8Wrapper) setSearch(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: HTMLHyperlinkElementUtils.setSearch")
log.Debug(w.logger(info), "V8 Function call: HTMLHyperlinkElementUtils.setSearch")
args := newArgumentHelper(w.scriptHost, info)
instance, err0 := w.getInstance(info)
val, err1 := tryParseArg(args, 0, w.decodeUSVString)
@@ -338,7 +338,7 @@ func (w htmlHyperlinkElementUtilsV8Wrapper) setSearch(info *v8.FunctionCallbackI

func (w htmlHyperlinkElementUtilsV8Wrapper) hash(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
ctx := w.mustGetContext(info)
log.Debug("V8 Function call: HTMLHyperlinkElementUtils.hash")
log.Debug(w.logger(info), "V8 Function call: HTMLHyperlinkElementUtils.hash")
instance, err := w.getInstance(info)
if err != nil {
return nil, err
@@ -348,7 +348,7 @@ func (w htmlHyperlinkElementUtilsV8Wrapper) hash(info *v8.FunctionCallbackInfo)
}

func (w htmlHyperlinkElementUtilsV8Wrapper) setHash(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: HTMLHyperlinkElementUtils.setHash")
log.Debug(w.logger(info), "V8 Function call: HTMLHyperlinkElementUtils.setHash")
args := newArgumentHelper(w.scriptHost, info)
instance, err0 := w.getInstance(info)
val, err1 := tryParseArg(args, 0, w.decodeUSVString)
6 changes: 3 additions & 3 deletions scripting/v8host/html_input_element_generated.go
Original file line number Diff line number Diff line change
@@ -49,7 +49,7 @@ func (w htmlInputElementV8Wrapper) Constructor(info *v8.FunctionCallbackInfo) (*

func (w htmlInputElementV8Wrapper) checkValidity(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
ctx := w.mustGetContext(info)
log.Debug("V8 Function call: HTMLInputElement.checkValidity")
log.Debug(w.logger(info), "V8 Function call: HTMLInputElement.checkValidity")
instance, err := w.getInstance(info)
if err != nil {
return nil, err
@@ -60,7 +60,7 @@ func (w htmlInputElementV8Wrapper) checkValidity(info *v8.FunctionCallbackInfo)

func (w htmlInputElementV8Wrapper) type_(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
ctx := w.mustGetContext(info)
log.Debug("V8 Function call: HTMLInputElement.type")
log.Debug(w.logger(info), "V8 Function call: HTMLInputElement.type")
instance, err := w.getInstance(info)
if err != nil {
return nil, err
@@ -70,7 +70,7 @@ func (w htmlInputElementV8Wrapper) type_(info *v8.FunctionCallbackInfo) (*v8.Val
}

func (w htmlInputElementV8Wrapper) setType(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: HTMLInputElement.setType")
log.Debug(w.logger(info), "V8 Function call: HTMLInputElement.setType")
args := newArgumentHelper(w.scriptHost, info)
instance, err0 := w.getInstance(info)
val, err1 := tryParseArg(args, 0, w.decodeDOMString)
2 changes: 1 addition & 1 deletion scripting/v8host/html_or_svgelement.go
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@ import (
)

func (w htmlOrSVGElementV8Wrapper) focus(info *v8go.FunctionCallbackInfo) (*v8go.Value, error) {
log.Debug("V8 Function call: HTMLOrSVGElement.focus")
log.Debug(w.logger(info), "V8 Function call: HTMLOrSVGElement.focus")
instance, err := w.getInstance(info)
if err != nil {
return nil, err
16 changes: 8 additions & 8 deletions scripting/v8host/html_or_svgelement_generated.go
Original file line number Diff line number Diff line change
@@ -57,7 +57,7 @@ func (w htmlOrSVGElementV8Wrapper) Constructor(info *v8.FunctionCallbackInfo) (*
}

func (w htmlOrSVGElementV8Wrapper) blur(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: HTMLOrSVGElement.blur")
log.Debug(w.logger(info), "V8 Function call: HTMLOrSVGElement.blur")
instance, err := w.getInstance(info)
if err != nil {
return nil, err
@@ -67,13 +67,13 @@ func (w htmlOrSVGElementV8Wrapper) blur(info *v8.FunctionCallbackInfo) (*v8.Valu
}

func (w htmlOrSVGElementV8Wrapper) dataset(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: HTMLOrSVGElement.dataset")
log.Debug(w.logger(info), "V8 Function call: HTMLOrSVGElement.dataset")
return nil, errors.New("HTMLOrSVGElement.dataset: Not implemented. Create an issue: https://github.com/gost-dom/browser/issues")
}

func (w htmlOrSVGElementV8Wrapper) nonce(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
ctx := w.mustGetContext(info)
log.Debug("V8 Function call: HTMLOrSVGElement.nonce")
log.Debug(w.logger(info), "V8 Function call: HTMLOrSVGElement.nonce")
instance, err := w.getInstance(info)
if err != nil {
return nil, err
@@ -83,7 +83,7 @@ func (w htmlOrSVGElementV8Wrapper) nonce(info *v8.FunctionCallbackInfo) (*v8.Val
}

func (w htmlOrSVGElementV8Wrapper) setNonce(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: HTMLOrSVGElement.setNonce")
log.Debug(w.logger(info), "V8 Function call: HTMLOrSVGElement.setNonce")
args := newArgumentHelper(w.scriptHost, info)
instance, err0 := w.getInstance(info)
val, err1 := tryParseArg(args, 0, w.decodeDOMString)
@@ -100,7 +100,7 @@ func (w htmlOrSVGElementV8Wrapper) setNonce(info *v8.FunctionCallbackInfo) (*v8.

func (w htmlOrSVGElementV8Wrapper) autofocus(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
ctx := w.mustGetContext(info)
log.Debug("V8 Function call: HTMLOrSVGElement.autofocus")
log.Debug(w.logger(info), "V8 Function call: HTMLOrSVGElement.autofocus")
instance, err := w.getInstance(info)
if err != nil {
return nil, err
@@ -110,7 +110,7 @@ func (w htmlOrSVGElementV8Wrapper) autofocus(info *v8.FunctionCallbackInfo) (*v8
}

func (w htmlOrSVGElementV8Wrapper) setAutofocus(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: HTMLOrSVGElement.setAutofocus")
log.Debug(w.logger(info), "V8 Function call: HTMLOrSVGElement.setAutofocus")
args := newArgumentHelper(w.scriptHost, info)
instance, err0 := w.getInstance(info)
val, err1 := tryParseArg(args, 0, w.decodeBoolean)
@@ -127,7 +127,7 @@ func (w htmlOrSVGElementV8Wrapper) setAutofocus(info *v8.FunctionCallbackInfo) (

func (w htmlOrSVGElementV8Wrapper) tabIndex(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
ctx := w.mustGetContext(info)
log.Debug("V8 Function call: HTMLOrSVGElement.tabIndex")
log.Debug(w.logger(info), "V8 Function call: HTMLOrSVGElement.tabIndex")
instance, err := w.getInstance(info)
if err != nil {
return nil, err
@@ -137,7 +137,7 @@ func (w htmlOrSVGElementV8Wrapper) tabIndex(info *v8.FunctionCallbackInfo) (*v8.
}

func (w htmlOrSVGElementV8Wrapper) setTabIndex(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
log.Debug("V8 Function call: HTMLOrSVGElement.setTabIndex")
log.Debug(w.logger(info), "V8 Function call: HTMLOrSVGElement.setTabIndex")
args := newArgumentHelper(w.scriptHost, info)
instance, err0 := w.getInstance(info)
val, err1 := tryParseArg(args, 0, w.decodeLong)
Loading