1
0
mirror of https://github.com/MontFerret/ferret.git synced 2025-02-03 13:11:45 +02:00

Bugfix/#575 element children (#580)

* Fixed retreival of child elements

* Fixed formatting

* Set tree depth to 0

* Removed redundant code
This commit is contained in:
Tim Voronov 2020-12-19 13:42:57 -05:00 committed by GitHub
parent 06043b98e3
commit 526916efb6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 248 additions and 413 deletions

View File

@ -0,0 +1,8 @@
LET doc = DOCUMENT(@lab.cdn.dynamic + "/#/lists", { driver:"cdp" })
LET list = ELEMENT(doc, ".track-list")
T::EQ(list.length, 20)
T::LEN(list, 20)
RETURN NONE

View File

@ -0,0 +1,8 @@
LET doc = DOCUMENT(@lab.cdn.dynamic + "/#/lists", { driver:"cdp" })
LET list = ELEMENT(doc, ".track-list")
LET children = list.children
T::NOT::NONE(children)
T::NOT::EMPTY(children)
RETURN NONE

View File

@ -0,0 +1,7 @@
LET doc = DOCUMENT(@lab.cdn.dynamic + "/#/lists", { driver:"cdp" })
LET list = ELEMENT(doc, ".track-list")
T::NOT::NONE(list.children[0])
T::NOT::NONE(list.children[1])
RETURN NONE

View File

@ -0,0 +1,9 @@
LET url = @lab.cdn.static + '/list.html'
LET doc = DOCUMENT(url)
LET list = ELEMENT(doc, ".track-list")
T::EQ(list.length, 20)
T::LEN(list, 20)
RETURN NONE

View File

@ -0,0 +1,9 @@
LET url = @lab.cdn.static + '/list.html'
LET doc = DOCUMENT(url)
LET list = ELEMENT(doc, ".track-list")
LET children = list.children
T::NOT::NONE(children)
T::NOT::EMPTY(children)
RETURN NONE

View File

@ -0,0 +1,9 @@
LET url = @lab.cdn.static + '/list.html'
LET doc = DOCUMENT(url)
LET list = ELEMENT(doc, ".track-list")
T::NOT::NONE(list.children[0])
T::NOT::NONE(list.children[1])
RETURN NONE

View File

@ -193,10 +193,6 @@ func (doc *HTMLDocument) Frame() page.FrameTree {
return doc.frameTree
}
func (doc *HTMLDocument) IsDetached() values.Boolean {
return doc.element.IsDetached()
}
func (doc *HTMLDocument) GetNodeType() values.Int {
return 9
}

View File

@ -7,7 +7,6 @@ import (
"hash/fnv"
"strconv"
"strings"
"sync"
"time"
"github.com/mafredri/cdp"
@ -37,25 +36,15 @@ type (
ObjectID runtime.RemoteObjectID
}
elementListeners struct {
pageReload events.ListenerID
childNodeInserted events.ListenerID
childNodeRemoved events.ListenerID
}
HTMLElement struct {
mu sync.Mutex
logger *zerolog.Logger
client *cdp.Client
dom *Manager
input *input.Manager
exec *eval.ExecutionContext
connected values.Boolean
id HTMLElementIdentity
nodeType html.NodeType
nodeName values.String
children []HTMLElementIdentity
listeners *elementListeners
logger *zerolog.Logger
client *cdp.Client
dom *Manager
input *input.Manager
exec *eval.ExecutionContext
id HTMLElementIdentity
nodeType html.NodeType
nodeName values.String
}
)
@ -113,7 +102,7 @@ func LoadHTMLElementWithID(
dom.
NewDescribeNodeArgs().
SetObjectID(id.ObjectID).
SetDepth(1),
SetDepth(0),
)
if err != nil {
@ -129,7 +118,6 @@ func LoadHTMLElementWithID(
id,
node.Node.NodeType,
node.Node.NodeName,
createChildrenArray(node.Node.Children),
), nil
}
@ -142,7 +130,6 @@ func NewHTMLElement(
id HTMLElementIdentity,
nodeType int,
nodeName string,
children []HTMLElementIdentity,
) *HTMLElement {
el := new(HTMLElement)
el.logger = logger
@ -150,35 +137,14 @@ func NewHTMLElement(
el.dom = domManager
el.input = input
el.exec = exec
el.connected = values.True
el.id = id
el.nodeType = common.ToHTMLType(nodeType)
el.nodeName = values.NewString(nodeName)
el.children = children
el.listeners = &elementListeners{
pageReload: domManager.AddDocumentUpdatedListener(el.handlePageReload),
childNodeInserted: domManager.AddChildNodeInsertedListener(el.handleChildInserted),
childNodeRemoved: domManager.AddChildNodeRemovedListener(el.handleChildRemoved),
}
return el
}
func (el *HTMLElement) Close() error {
el.mu.Lock()
defer el.mu.Unlock()
// already closed
if !el.connected {
return nil
}
el.connected = values.False
el.dom.RemoveReloadListener(el.listeners.pageReload)
el.dom.RemoveChildNodeInsertedListener(el.listeners.childNodeInserted)
el.dom.RemoveChildNodeRemovedListener(el.listeners.childNodeRemoved)
return nil
}
@ -247,18 +213,10 @@ func (el *HTMLElement) SetIn(ctx context.Context, path []core.Value, value core.
}
func (el *HTMLElement) GetValue(ctx context.Context) (core.Value, error) {
if el.IsDetached() {
return values.None, drivers.ErrDetached
}
return el.exec.ReadProperty(ctx, el.id.ObjectID, "value")
}
func (el *HTMLElement) SetValue(ctx context.Context, value core.Value) error {
if el.IsDetached() {
return drivers.ErrDetached
}
return el.client.DOM.SetNodeValue(ctx, dom.NewSetNodeValueArgs(el.id.NodeID, value.String()))
}
@ -271,14 +229,20 @@ func (el *HTMLElement) GetNodeName() values.String {
}
func (el *HTMLElement) Length() values.Int {
return values.NewInt(len(el.children))
value, err := el.exec.EvalWithArgumentsAndReturnValue(context.Background(), templates.GetChildrenCount(), runtime.CallArgument{
ObjectID: &el.id.ObjectID,
})
if err != nil {
el.logError(err)
return 0
}
return values.ToInt(value)
}
func (el *HTMLElement) GetStyles(ctx context.Context) (*values.Object, error) {
if el.IsDetached() {
return values.NewObject(), drivers.ErrDetached
}
value, err := el.exec.EvalWithArgumentsAndReturnValue(ctx, templates.GetStyles(), runtime.CallArgument{
ObjectID: &el.id.ObjectID,
})
@ -295,10 +259,6 @@ func (el *HTMLElement) GetStyles(ctx context.Context) (*values.Object, error) {
}
func (el *HTMLElement) GetStyle(ctx context.Context, name values.String) (core.Value, error) {
if el.IsDetached() {
return values.None, drivers.ErrDetached
}
styles, err := el.GetStyles(ctx)
if err != nil {
@ -315,10 +275,6 @@ func (el *HTMLElement) GetStyle(ctx context.Context, name values.String) (core.V
}
func (el *HTMLElement) SetStyles(ctx context.Context, styles *values.Object) error {
if el.IsDetached() {
return drivers.ErrDetached
}
if styles == nil {
return nil
}
@ -341,10 +297,6 @@ func (el *HTMLElement) SetStyles(ctx context.Context, styles *values.Object) err
}
func (el *HTMLElement) SetStyle(ctx context.Context, name, value values.String) error {
if el.IsDetached() {
return drivers.ErrDetached
}
// we manually set only those that are defined in attribute only
attrValue, err := el.GetAttribute(ctx, common.AttrNameStyle)
@ -374,10 +326,6 @@ func (el *HTMLElement) SetStyle(ctx context.Context, name, value values.String)
}
func (el *HTMLElement) RemoveStyle(ctx context.Context, names ...values.String) error {
if el.IsDetached() {
return drivers.ErrDetached
}
if len(names) == 0 {
return nil
}
@ -409,10 +357,6 @@ func (el *HTMLElement) RemoveStyle(ctx context.Context, names ...values.String)
}
func (el *HTMLElement) GetAttributes(ctx context.Context) (*values.Object, error) {
if el.IsDetached() {
return values.NewObject(), drivers.ErrDetached
}
repl, err := el.client.DOM.GetAttributes(ctx, dom.NewGetAttributesArgs(el.id.NodeID))
if err != nil {
@ -446,10 +390,6 @@ func (el *HTMLElement) GetAttributes(ctx context.Context) (*values.Object, error
}
func (el *HTMLElement) GetAttribute(ctx context.Context, name values.String) (core.Value, error) {
if el.IsDetached() {
return values.None, drivers.ErrDetached
}
repl, err := el.client.DOM.GetAttributes(ctx, dom.NewGetAttributesArgs(el.id.NodeID))
if err != nil {
@ -483,10 +423,6 @@ func (el *HTMLElement) GetAttribute(ctx context.Context, name values.String) (co
}
func (el *HTMLElement) SetAttributes(ctx context.Context, attrs *values.Object) error {
if el.IsDetached() {
return drivers.ErrDetached
}
var err error
attrs.ForEach(func(value core.Value, key string) bool {
@ -499,10 +435,6 @@ func (el *HTMLElement) SetAttributes(ctx context.Context, attrs *values.Object)
}
func (el *HTMLElement) SetAttribute(ctx context.Context, name, value values.String) error {
if el.IsDetached() {
return drivers.ErrDetached
}
return el.client.DOM.SetAttributeValue(
ctx,
dom.NewSetAttributeValueArgs(el.id.NodeID, string(name), string(value)),
@ -510,10 +442,6 @@ func (el *HTMLElement) SetAttribute(ctx context.Context, name, value values.Stri
}
func (el *HTMLElement) RemoveAttribute(ctx context.Context, names ...values.String) error {
if el.IsDetached() {
return drivers.ErrDetached
}
for _, name := range names {
err := el.client.DOM.RemoveAttribute(
ctx,
@ -529,51 +457,45 @@ func (el *HTMLElement) RemoveAttribute(ctx context.Context, names ...values.Stri
}
func (el *HTMLElement) GetChildNodes(ctx context.Context) (*values.Array, error) {
if el.IsDetached() {
return values.NewArray(0), drivers.ErrDetached
out, err := el.exec.EvalWithArgumentsAndReturnReference(ctx, templates.GetChildren(),
runtime.CallArgument{
ObjectID: &el.id.ObjectID,
},
)
if err != nil {
return values.EmptyArray(), err
}
res := values.NewArray(len(el.children))
val, err := el.convertEvalResult(ctx, out)
for _, childID := range el.children {
child, err := LoadHTMLElement(
ctx,
el.logger,
el.client,
el.dom,
el.input,
el.exec,
childID.NodeID,
)
if err != nil {
el.logError(err)
if err != nil {
el.logError(err).Msg("failed to load child elements")
continue
}
res.Push(child)
return values.EmptyArray(), err
}
return res, nil
arr, ok := val.(*values.Array)
if ok {
return arr, nil
}
return values.EmptyArray(), nil
}
func (el *HTMLElement) GetChildNode(ctx context.Context, idx values.Int) (core.Value, error) {
if el.IsDetached() {
return values.None, drivers.ErrDetached
out, err := el.exec.EvalWithArgumentsAndReturnReference(ctx, templates.GetChildByIndex(int64(idx)),
runtime.CallArgument{
ObjectID: &el.id.ObjectID,
},
)
if err != nil {
return values.None, err
}
nodeIdentity := el.children[idx]
return LoadHTMLElement(
ctx,
el.logger,
el.client,
el.dom,
el.input,
el.exec,
nodeIdentity.NodeID,
)
return el.convertEvalResult(ctx, out)
}
func (el *HTMLElement) GetParentElement(ctx context.Context) (core.Value, error) {
@ -589,10 +511,6 @@ func (el *HTMLElement) GetNextElementSibling(ctx context.Context) (core.Value, e
}
func (el *HTMLElement) evalAndGetElement(ctx context.Context, expr string) (core.Value, error) {
if el.IsDetached() {
return values.None, drivers.ErrDetached
}
obj, err := el.exec.EvalWithArgumentsAndReturnReference(ctx, expr, runtime.CallArgument{
ObjectID: &el.id.ObjectID,
})
@ -626,10 +544,6 @@ func (el *HTMLElement) evalAndGetElement(ctx context.Context, expr string) (core
}
func (el *HTMLElement) QuerySelector(ctx context.Context, selector values.String) (core.Value, error) {
if el.IsDetached() {
return values.None, drivers.ErrDetached
}
selectorArgs := dom.NewQuerySelectorArgs(el.id.NodeID, selector.String())
found, err := el.client.DOM.QuerySelector(ctx, selectorArgs)
@ -659,15 +573,11 @@ func (el *HTMLElement) QuerySelector(ctx context.Context, selector values.String
}
func (el *HTMLElement) QuerySelectorAll(ctx context.Context, selector values.String) (*values.Array, error) {
if el.IsDetached() {
return values.NewArray(0), drivers.ErrDetached
}
selectorArgs := dom.NewQuerySelectorAllArgs(el.id.NodeID, selector.String())
res, err := el.client.DOM.QuerySelectorAll(ctx, selectorArgs)
if err != nil {
return values.NewArray(0), err
return values.EmptyArray(), err
}
arr := values.NewArray(len(res.NodeIDs))
@ -692,16 +602,7 @@ func (el *HTMLElement) QuerySelectorAll(ctx context.Context, selector values.Str
)
if err != nil {
// close elements that are already loaded, but won't be used because of the error
if arr.Length() > 0 {
arr.ForEach(func(e core.Value, _ int) bool {
e.(*HTMLElement).Close()
return true
})
}
return values.NewArray(0), err
return values.EmptyArray(), err
}
arr.Push(childEl)
@ -730,155 +631,18 @@ func (el *HTMLElement) XPath(ctx context.Context, expression values.String) (res
return values.None, err
}
typeName := out.Type
// checking whether it's actually an array
if typeName == "object" {
if out.ClassName != nil && *out.ClassName == "Array" {
typeName = "array"
}
}
switch typeName {
case "string", "number", "boolean":
return eval.Unmarshal(&out)
case "array":
if out.ObjectID == nil {
return values.None, nil
}
props, err := el.client.Runtime.GetProperties(ctx, runtime.NewGetPropertiesArgs(*out.ObjectID).SetOwnProperties(true))
if err != nil {
return values.None, err
}
if props.ExceptionDetails != nil {
exception := *props.ExceptionDetails
return values.None, errors.New(exception.Text)
}
result := values.NewArray(len(props.Result))
defer func() {
if err != nil {
result.ForEach(func(value core.Value, idx int) bool {
el, ok := value.(*HTMLElement)
if ok {
el.Close()
}
return true
})
}
}()
for _, descr := range props.Result {
if !descr.Enumerable {
continue
}
if descr.Value == nil {
continue
}
// it's not a Node, it's an attr value
if descr.Value.ObjectID == nil {
var value interface{}
if err := json.Unmarshal(descr.Value.Value, &value); err != nil {
return values.None, err
}
result.Push(values.Parse(value))
continue
}
repl, err := el.client.DOM.RequestNode(ctx, dom.NewRequestNodeArgs(*descr.Value.ObjectID))
if err != nil {
return values.None, err
}
el, err := LoadHTMLElementWithID(
ctx,
el.logger,
el.client,
el.dom,
el.input,
el.exec,
HTMLElementIdentity{
NodeID: repl.NodeID,
ObjectID: *descr.Value.ObjectID,
},
)
if err != nil {
return values.None, err
}
result.Push(el)
}
return result, nil
case "object":
if out.ObjectID == nil {
var value interface{}
if err := json.Unmarshal(out.Value, &value); err != nil {
return values.None, err
}
return values.Parse(value), nil
}
repl, err := el.client.DOM.RequestNode(ctx, dom.NewRequestNodeArgs(*out.ObjectID))
if err != nil {
return values.None, err
}
return LoadHTMLElementWithID(
ctx,
el.logger,
el.client,
el.dom,
el.input,
el.exec,
HTMLElementIdentity{
NodeID: repl.NodeID,
ObjectID: *out.ObjectID,
},
)
default:
return values.None, nil
}
return el.convertEvalResult(ctx, out)
}
func (el *HTMLElement) GetInnerText(ctx context.Context) (values.String, error) {
if el.IsDetached() {
return values.EmptyString, drivers.ErrDetached
}
return getInnerText(ctx, el.client, el.exec, el.id, el.nodeType)
}
func (el *HTMLElement) SetInnerText(ctx context.Context, innerText values.String) error {
if el.IsDetached() {
return drivers.ErrDetached
}
return setInnerText(ctx, el.client, el.exec, el.id, innerText)
}
func (el *HTMLElement) GetInnerTextBySelector(ctx context.Context, selector values.String) (values.String, error) {
if el.IsDetached() {
return values.EmptyString, drivers.ErrDetached
}
sel, err := selector.MarshalJSON()
if err != nil {
@ -904,10 +668,6 @@ func (el *HTMLElement) GetInnerTextBySelector(ctx context.Context, selector valu
}
func (el *HTMLElement) SetInnerTextBySelector(ctx context.Context, selector, innerText values.String) error {
if el.IsDetached() {
return drivers.ErrDetached
}
sel, err := selector.MarshalJSON()
if err != nil {
@ -936,10 +696,6 @@ func (el *HTMLElement) SetInnerTextBySelector(ctx context.Context, selector, inn
}
func (el *HTMLElement) GetInnerTextBySelectorAll(ctx context.Context, selector values.String) (*values.Array, error) {
if el.IsDetached() {
return values.NewArray(0), drivers.ErrDetached
}
sel, err := selector.MarshalJSON()
if err != nil {
@ -958,39 +714,27 @@ func (el *HTMLElement) GetInnerTextBySelectorAll(ctx context.Context, selector v
)
if err != nil {
return values.NewArray(0), err
return values.EmptyArray(), err
}
arr, ok := out.(*values.Array)
if !ok {
return values.NewArray(0), errors.New("unexpected output")
return values.EmptyArray(), errors.New("unexpected output")
}
return arr, nil
}
func (el *HTMLElement) GetInnerHTML(ctx context.Context) (values.String, error) {
if el.IsDetached() {
return values.EmptyString, drivers.ErrDetached
}
return getInnerHTML(ctx, el.client, el.exec, el.id, el.nodeType)
}
func (el *HTMLElement) SetInnerHTML(ctx context.Context, innerHTML values.String) error {
if el.IsDetached() {
return drivers.ErrDetached
}
return setInnerHTML(ctx, el.client, el.exec, el.id, innerHTML)
}
func (el *HTMLElement) GetInnerHTMLBySelector(ctx context.Context, selector values.String) (values.String, error) {
if el.IsDetached() {
return values.EmptyString, drivers.ErrDetached
}
sel, err := selector.MarshalJSON()
if err != nil {
@ -1016,10 +760,6 @@ func (el *HTMLElement) GetInnerHTMLBySelector(ctx context.Context, selector valu
}
func (el *HTMLElement) SetInnerHTMLBySelector(ctx context.Context, selector, innerHTML values.String) error {
if el.IsDetached() {
return drivers.ErrDetached
}
sel, err := selector.MarshalJSON()
if err != nil {
@ -1048,14 +788,10 @@ func (el *HTMLElement) SetInnerHTMLBySelector(ctx context.Context, selector, inn
}
func (el *HTMLElement) GetInnerHTMLBySelectorAll(ctx context.Context, selector values.String) (*values.Array, error) {
if el.IsDetached() {
return values.NewArray(0), drivers.ErrDetached
}
sel, err := selector.MarshalJSON()
if err != nil {
return values.NewArray(0), err
return values.EmptyArray(), err
}
out, err := el.exec.EvalWithArgumentsAndReturnValue(
@ -1070,23 +806,19 @@ func (el *HTMLElement) GetInnerHTMLBySelectorAll(ctx context.Context, selector v
)
if err != nil {
return values.NewArray(0), err
return values.EmptyArray(), err
}
arr, ok := out.(*values.Array)
if !ok {
return values.NewArray(0), errors.New("unexpected output")
return values.EmptyArray(), errors.New("unexpected output")
}
return arr, nil
}
func (el *HTMLElement) CountBySelector(ctx context.Context, selector values.String) (values.Int, error) {
if el.IsDetached() {
return values.ZeroInt, drivers.ErrDetached
}
selectorArgs := dom.NewQuerySelectorAllArgs(el.id.NodeID, selector.String())
res, err := el.client.DOM.QuerySelectorAll(ctx, selectorArgs)
@ -1098,11 +830,6 @@ func (el *HTMLElement) CountBySelector(ctx context.Context, selector values.Stri
}
func (el *HTMLElement) ExistsBySelector(ctx context.Context, selector values.String) (values.Boolean, error) {
if el.IsDetached() {
return values.False, drivers.ErrDetached
}
// TODO: Can we use RemoteObjectID or BackendID instead of NodeId?
selectorArgs := dom.NewQuerySelectorArgs(el.id.NodeID, selector.String())
res, err := el.client.DOM.QuerySelector(ctx, selectorArgs)
@ -1270,80 +997,126 @@ func (el *HTMLElement) HoverBySelector(ctx context.Context, selector values.Stri
return el.input.MoveMouseBySelector(ctx, el.id.NodeID, selector.String())
}
func (el *HTMLElement) IsDetached() values.Boolean {
el.mu.Lock()
defer el.mu.Unlock()
func (el *HTMLElement) convertEvalResult(ctx context.Context, out runtime.RemoteObject) (core.Value, error) {
typeName := out.Type
return !el.connected
}
func (el *HTMLElement) handlePageReload(_ context.Context) {
el.Close()
}
func (el *HTMLElement) handleChildInserted(_ context.Context, parentNodeID, prevNodeID dom.NodeID, node dom.Node) {
if parentNodeID != el.id.NodeID {
return
}
targetIDx := -1
prevID := prevNodeID
nextID := node.NodeID
if el.IsDetached() {
return
}
el.mu.Lock()
defer el.mu.Unlock()
for idx, id := range el.children {
if id.NodeID == prevID {
targetIDx = idx
break
// checking whether it's actually an array
if typeName == "object" {
if out.ClassName != nil {
switch *out.ClassName {
case "Array":
typeName = "array"
case "HTMLCollection":
typeName = "HTMLCollection"
default:
break
}
}
}
if targetIDx == -1 {
return
}
nextIdentity := HTMLElementIdentity{
NodeID: nextID,
}
arr := el.children
el.children = append(arr[:targetIDx], append([]HTMLElementIdentity{nextIdentity}, arr[targetIDx:]...)...)
}
func (el *HTMLElement) handleChildRemoved(_ context.Context, nodeID, prevNodeID dom.NodeID) {
if nodeID != el.id.NodeID {
return
}
targetIDx := -1
targetID := prevNodeID
if el.IsDetached() {
return
}
el.mu.Lock()
defer el.mu.Unlock()
for idx, id := range el.children {
if id.NodeID == targetID {
targetIDx = idx
break
switch typeName {
case "string", "number", "boolean":
return eval.Unmarshal(&out)
case "array":
if out.ObjectID == nil {
return values.None, nil
}
}
if targetIDx == -1 {
return
}
props, err := el.client.Runtime.GetProperties(ctx, runtime.NewGetPropertiesArgs(*out.ObjectID).SetOwnProperties(true))
arr := el.children
el.children = append(arr[:targetIDx], arr[targetIDx+1:]...)
if err != nil {
return values.None, err
}
if props.ExceptionDetails != nil {
exception := *props.ExceptionDetails
return values.None, errors.New(exception.Text)
}
result := values.NewArray(len(props.Result))
for _, descr := range props.Result {
if !descr.Enumerable {
continue
}
if descr.Value == nil {
continue
}
// it's not a Node, it's an attr value
if descr.Value.ObjectID == nil {
var value interface{}
if err := json.Unmarshal(descr.Value.Value, &value); err != nil {
return values.None, err
}
result.Push(values.Parse(value))
continue
}
repl, err := el.client.DOM.RequestNode(ctx, dom.NewRequestNodeArgs(*descr.Value.ObjectID))
if err != nil {
return values.None, err
}
el, err := LoadHTMLElementWithID(
ctx,
el.logger,
el.client,
el.dom,
el.input,
el.exec,
HTMLElementIdentity{
NodeID: repl.NodeID,
ObjectID: *descr.Value.ObjectID,
},
)
if err != nil {
return values.None, err
}
result.Push(el)
}
return result, nil
case "object":
if out.ObjectID == nil {
var value interface{}
if err := json.Unmarshal(out.Value, &value); err != nil {
return values.None, err
}
return values.Parse(value), nil
}
repl, err := el.client.DOM.RequestNode(ctx, dom.NewRequestNodeArgs(*out.ObjectID))
if err != nil {
return values.None, err
}
return LoadHTMLElementWithID(
ctx,
el.logger,
el.client,
el.dom,
el.input,
el.exec,
HTMLElementIdentity{
NodeID: repl.NodeID,
ObjectID: *out.ObjectID,
},
)
default:
return values.None, nil
}
}
func (el *HTMLElement) logError(err error) *zerolog.Event {

View File

@ -203,6 +203,7 @@ func createChildrenArray(nodes []dom.Node) []HTMLElementIdentity {
for idx, child := range nodes {
child := child
children[idx] = HTMLElementIdentity{
NodeID: child.NodeID,
}

View File

@ -0,0 +1,23 @@
package templates
import (
"fmt"
"github.com/MontFerret/ferret/pkg/drivers/cdp/eval"
)
const getChildren = "(el) => Array.from(el.children)"
const getChildrenCount = "(el) => el.children.length"
func GetChildren() string {
return getChildren
}
func GetChildrenCount() string {
return getChildrenCount
}
func GetChildByIndex(idx int64) string {
return fmt.Sprintf(`
(el) => el.children[%s]
`, eval.ParamInt(idx))
}

View File

@ -230,8 +230,6 @@ func GetInNode(ctx context.Context, node drivers.HTMLNode, path []core.Value) (c
segment := segment.(values.String)
switch segment {
case "isDetached":
return node.IsDetached(), nil
case "nodeType":
return node.GetNodeType(), nil
case "nodeName":

View File

@ -178,10 +178,6 @@ func (doc *HTMLDocument) XPath(ctx context.Context, expression values.String) (c
return doc.element.XPath(ctx, expression)
}
func (doc *HTMLDocument) IsDetached() values.Boolean {
return values.False
}
func (doc *HTMLDocument) GetTitle() values.String {
title := doc.doc.Find("head > title")

View File

@ -86,10 +86,6 @@ func (el *HTMLElement) Copy() core.Value {
return c
}
func (el *HTMLElement) IsDetached() values.Boolean {
return values.True
}
func (el *HTMLElement) GetNodeType() values.Int {
nodes := el.selection.Nodes

View File

@ -24,8 +24,6 @@ type (
collections.Measurable
io.Closer
IsDetached() values.Boolean
GetNodeType() values.Int
GetNodeName() values.String

View File

@ -22,6 +22,10 @@ type (
}
)
func EmptyArray() *Array {
return &Array{items: make([]core.Value, 0, 0)}
}
func NewArray(size int) *Array {
return &Array{items: make([]core.Value, 0, size)}
}

View File

@ -375,7 +375,7 @@ func ToArray(ctx context.Context, input core.Value) *Array {
return arr
default:
return NewArray(0)
return EmptyArray()
}
}