Skip to content

Commit 28920a0

Browse files
committed
WIP mutation observer JS
1 parent 691142f commit 28920a0

File tree

10 files changed

+184
-26
lines changed

10 files changed

+184
-26
lines changed

internal/code-gen/customrules/customrules.go

+21-11
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ package customrules
1414
import (
1515
"github.com/gost-dom/code-gen/customrules/typerule"
1616
. "github.com/gost-dom/code-gen/customrules/typerule"
17+
"github.com/gost-dom/code-gen/packagenames"
1718
"github.com/gost-dom/webref/idl"
1819
)
1920

@@ -26,14 +27,21 @@ type CustomRules map[string]SpecRules
2627
// file. The key is the name of the interface the rule applies to
2728
type SpecRules map[string]InterfaceRule
2829

30+
type Package string
31+
2932
// InterfaceRule specifies the rules for a specific interface or interface
3033
// mixin.
3134
type InterfaceRule struct {
32-
Operations OperationRules
35+
InterfacePackage Package
36+
Operations OperationRules
3337
}
3438

3539
type OperationRules map[string]OperationRule
3640

41+
const (
42+
DomInterfaces = Package(packagenames.DomInterfaces)
43+
)
44+
3745
type OperationRule struct {
3846
// By default, an operation is assumed to not generate an error. Override
3947
// the behaviour by setting this to true.
@@ -107,16 +115,18 @@ var rules = CustomRules{
107115
"querySelector": parentNodeQueryOperation,
108116
"querySelectorAll": parentNodeQueryOperation,
109117
}},
110-
"MutationObserver": {Operations: OperationRules{
111-
"observe": {
112-
HasError: true,
113-
Arguments: ArgumentRules{
114-
"options": {
115-
Type: idl.Type{Name: "func(*MutationObserverInit)"},
116-
Variadic: true,
117-
},
118-
}},
119-
}},
118+
"MutationObserver": {
119+
InterfacePackage: DomInterfaces,
120+
Operations: OperationRules{
121+
"observe": {
122+
HasError: true,
123+
Arguments: ArgumentRules{
124+
"options": {
125+
Type: idl.Type{Name: "func(*MutationObserverInit)"},
126+
Variadic: true,
127+
},
128+
}},
129+
}},
120130
},
121131
"html": {
122132
"Location": {Operations: OperationRules{

internal/code-gen/packagenames/packagenames.go

+10-9
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,16 @@ const (
1010
ISSUE_URL = "https://github.com/gost-dom/browser/issues"
1111
// alternate url: "https://github.com/gost-dom/browser/issues?q=sort%3Aupdated-desc+is%3Aissue+is%3Aopen"
1212

13-
Dom = BASE_PKG + "/dom"
14-
Events = Dom + "/event"
15-
Html = BASE_PKG + "/html"
16-
V8host = BASE_PKG + "/scripting/v8host"
17-
Gojahost = BASE_PKG + "/scripting/gojahost"
18-
Log = BASE_PKG + "/internal/log"
19-
UIEvents = BASE_PKG + "/internal/uievents"
20-
V8go = "github.com/gost-dom/v8go"
21-
Goja = "github.com/dop251/goja"
13+
Dom = BASE_PKG + "/dom"
14+
Events = Dom + "/event"
15+
Html = BASE_PKG + "/html"
16+
V8host = BASE_PKG + "/scripting/v8host"
17+
Gojahost = BASE_PKG + "/scripting/gojahost"
18+
Log = BASE_PKG + "/internal/log"
19+
UIEvents = BASE_PKG + "/internal/uievents"
20+
DomInterfaces = BASE_PKG + "/internal/interfaces/dom-interfaces"
21+
V8go = "github.com/gost-dom/v8go"
22+
Goja = "github.com/dop251/goja"
2223
)
2324

2425
var names = map[string]string{

internal/code-gen/script-wrappers/configuration/v8_configuration.go

+5
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ func CreateV8Specs() WebIdlConfigurations {
3535
)
3636

3737
domSpecs := specs.Module("dom")
38+
configureMutationObserver(domSpecs)
3839

3940
parentNode := domSpecs.Type("ParentNode")
4041
parentNode.Method("children").Ignore()
@@ -269,3 +270,7 @@ func CreateV8Specs() WebIdlConfigurations {
269270

270271
return specs
271272
}
273+
274+
func configureMutationObserver(domSpecs *WebIdlConfiguration) {
275+
domSpecs.Type("MutationObserver")
276+
}

internal/code-gen/script-wrappers/model/es_constructor_data.go

+6-2
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,14 @@ func (d ESConstructorData) Includes() []idl.Interface {
3232
}
3333

3434
func (d ESConstructorData) GetInternalPackage() string {
35-
if d.Name() == "Event" {
35+
switch d.Name() {
36+
case "Event":
3637
return packagenames.Events
38+
case "MutationObserver":
39+
return packagenames.DomInterfaces
40+
default:
41+
return packagenames.PackageName(d.Spec.DomSpec.Name)
3742
}
38-
return packagenames.PackageName(d.Spec.DomSpec.Name)
3943
}
4044

4145
func (d ESConstructorData) WrapperFunctionsToInstall() iter.Seq[ESOperation] {

internal/code-gen/script-wrappers/model/es_operation.go

+7-2
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,15 @@ func (o ESOperation) Encoder() string {
3333
return e
3434
}
3535
converter := "to"
36-
if o.LegacyRetType.Nullable {
36+
t := o.RetType
37+
if t.Kind == idl.KindSequence {
38+
converter += "Sequence"
39+
t = *t.TypeParam
40+
}
41+
if t.Nullable {
3742
converter += "Nullable"
3843
}
39-
converter += IdlNameToGoName(o.LegacyRetType.TypeName)
44+
converter += IdlNameToGoName(t.Name)
4045
return converter
4146
}
4247

internal/code-gen/script-wrappers/model/es_operation_argument.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ type ESOperationArgument struct {
2121

2222
func (a ESOperationArgument) OptionalInGo() bool {
2323
hasDefault := a.ArgumentSpec.HasDefault
24-
return a.Optional && !hasDefault
24+
return a.Optional && !hasDefault && !a.CustomRule.Variadic
2525
}
2626

2727
func (a ESOperationArgument) DefaultValueInGo() (name string, ok bool) {

internal/code-gen/script-wrappers/v8gen/generators.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,11 @@ func CreateV8WrapperMethodInstanceInvocations(
142142

143143
callArgs := make([]g.Generator, i)
144144
for idx, a := range currentArgs {
145-
callArgs[idx] = a.ArgName
145+
arg := a.ArgName
146+
if a.Argument.CustomRule.Variadic {
147+
arg = g.Raw(arg.Generate().Op("..."))
148+
}
149+
callArgs[idx] = arg
146150
}
147151
callInstance := createCallInstance(functionName, callArgs, op)
148152
if i > 0 {

internal/dom/mutation/observer.go

+2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ func NewObserver(cb Callback) *Observer {
3232
return &Observer{Callback: cb}
3333
}
3434

35+
type ObserveOption = func(*Options)
36+
3537
// Start observing for changes for a specific dom node.
3638
//
3739
// Panics if the observer does not have a handler.

scripting/v8host/mutation_observer.go

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package v8host
2+
3+
import (
4+
mutation "github.com/gost-dom/browser/internal/dom/mutation"
5+
"github.com/gost-dom/v8go"
6+
)
7+
8+
func (w mutationObserverV8Wrapper) CreateInstance(
9+
ctx *V8ScriptContext,
10+
this *v8go.Object,
11+
cb mutation.Callback,
12+
) (*v8go.Value, error) {
13+
return nil, nil
14+
}
15+
16+
func (w mutationObserverV8Wrapper) decodeMutationCallback(
17+
ctx *V8ScriptContext,
18+
val *v8go.Value,
19+
) (mutation.Callback, error) {
20+
panic("TODO")
21+
}
22+
23+
func (w mutationObserverV8Wrapper) decodeMutationObserverInit(
24+
ctx *V8ScriptContext,
25+
val *v8go.Value,
26+
) ([]mutation.ObserveOption, error) {
27+
panic("TODO")
28+
}
29+
30+
func (w mutationObserverV8Wrapper) toSequenceMutationRecord(
31+
ctx *V8ScriptContext,
32+
records []mutation.Record,
33+
) (*v8go.Value, error) {
34+
panic("TODO")
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
// This file is generated. Do not edit.
2+
3+
package v8host
4+
5+
import (
6+
"errors"
7+
dominterfaces "github.com/gost-dom/browser/internal/interfaces/dom-interfaces"
8+
log "github.com/gost-dom/browser/internal/log"
9+
v8 "github.com/gost-dom/v8go"
10+
)
11+
12+
func init() {
13+
registerJSClass("MutationObserver", "", createMutationObserverPrototype)
14+
}
15+
16+
type mutationObserverV8Wrapper struct {
17+
handleReffedObject[dominterfaces.MutationObserver]
18+
}
19+
20+
func newMutationObserverV8Wrapper(scriptHost *V8ScriptHost) *mutationObserverV8Wrapper {
21+
return &mutationObserverV8Wrapper{newHandleReffedObject[dominterfaces.MutationObserver](scriptHost)}
22+
}
23+
24+
func createMutationObserverPrototype(scriptHost *V8ScriptHost) *v8.FunctionTemplate {
25+
iso := scriptHost.iso
26+
wrapper := newMutationObserverV8Wrapper(scriptHost)
27+
constructor := v8.NewFunctionTemplateWithError(iso, wrapper.Constructor)
28+
29+
instanceTmpl := constructor.InstanceTemplate()
30+
instanceTmpl.SetInternalFieldCount(1)
31+
32+
wrapper.installPrototype(constructor.PrototypeTemplate())
33+
34+
return constructor
35+
}
36+
func (w mutationObserverV8Wrapper) installPrototype(prototypeTmpl *v8.ObjectTemplate) {
37+
iso := w.scriptHost.iso
38+
prototypeTmpl.Set("observe", v8.NewFunctionTemplateWithError(iso, w.observe))
39+
prototypeTmpl.Set("disconnect", v8.NewFunctionTemplateWithError(iso, w.disconnect))
40+
prototypeTmpl.Set("takeRecords", v8.NewFunctionTemplateWithError(iso, w.takeRecords))
41+
}
42+
43+
func (w mutationObserverV8Wrapper) Constructor(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
44+
args := newArgumentHelper(w.scriptHost, info)
45+
callback, err1 := tryParseArg(args, 0, w.decodeMutationCallback)
46+
ctx := w.mustGetContext(info)
47+
if args.noOfReadArguments >= 1 {
48+
if err1 != nil {
49+
return nil, err1
50+
}
51+
return w.CreateInstance(ctx, info.This(), callback)
52+
}
53+
return nil, errors.New("MutationObserver.constructor: Missing arguments")
54+
}
55+
56+
func (w mutationObserverV8Wrapper) observe(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
57+
log.Debug(w.logger(info), "V8 Function call: MutationObserver.observe")
58+
args := newArgumentHelper(w.scriptHost, info)
59+
instance, err0 := w.getInstance(info)
60+
target, err1 := tryParseArg(args, 0, w.decodeNode)
61+
options, err2 := tryParseArg(args, 1, w.decodeMutationObserverInit)
62+
if args.noOfReadArguments >= 2 {
63+
err := errors.Join(err0, err1, err2)
64+
if err != nil {
65+
return nil, err
66+
}
67+
callErr := instance.Observe(target, options...)
68+
return nil, callErr
69+
}
70+
return nil, errors.New("MutationObserver.observe: Missing arguments")
71+
}
72+
73+
func (w mutationObserverV8Wrapper) disconnect(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
74+
log.Debug(w.logger(info), "V8 Function call: MutationObserver.disconnect")
75+
instance, err := w.getInstance(info)
76+
if err != nil {
77+
return nil, err
78+
}
79+
instance.Disconnect()
80+
return nil, nil
81+
}
82+
83+
func (w mutationObserverV8Wrapper) takeRecords(info *v8.FunctionCallbackInfo) (*v8.Value, error) {
84+
log.Debug(w.logger(info), "V8 Function call: MutationObserver.takeRecords")
85+
ctx := w.mustGetContext(info)
86+
instance, err := w.getInstance(info)
87+
if err != nil {
88+
return nil, err
89+
}
90+
result := instance.TakeRecords()
91+
return w.toSequenceMutationRecord(ctx, result)
92+
}

0 commit comments

Comments
 (0)