Skip to content

Commit e5934a7

Browse files
committed
complete querySelectorAll for frames
1 parent 2c9d080 commit e5934a7

File tree

1 file changed

+40
-7
lines changed

1 file changed

+40
-7
lines changed

src/AutomateBrowser.cls

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -784,7 +784,7 @@ End Function
784784

785785
' takes a Collection of nodeIds and returns a Dictionary of cdpDomNode objetcs
786786
' Note: resulting dictionary is keyed on id if node has one, else name if has one, else a unique numerical value
787-
Public Function getDomNodes(Optional ByVal nodeIds As Collection, Optional ByVal backendNodeIds As Collection, Optional objectIds As Collection, _
787+
Public Function getDomNodes(Optional ByVal nodeIds As Collection, Optional ByVal backendNodeIds As Collection, Optional objectIds As Collection, Optional ByVal remoteNodeList As cdpRuntimeRemoteObject, _
788788
Optional depth As Integer = -1, Optional ByVal pierce As Boolean = False) As Dictionary
789789
Dim nodes As Dictionary: Set nodes = New Dictionary
790790
Dim node As cdpDOMNode
@@ -796,27 +796,54 @@ Public Function getDomNodes(Optional ByVal nodeIds As Collection, Optional ByVal
796796
key = getNodeIdOrName(node)
797797
If key = vbNullString Or nodes.Exists(key) Then key = nodes.count
798798
Set nodes(key) = node
799+
Set node = Nothing
799800
Next v
800801
ElseIf Not backendNodeIds Is Nothing Then
801802
For Each v In backendNodeIds
802803
Set node = getDomNode(backendNodeId:=v, depth:=depth, pierce:=pierce)
803804
key = getNodeIdOrName(node)
804805
If key = vbNullString Or nodes.Exists(key) Then key = nodes.count
805806
Set nodes(key) = node
807+
Set node = Nothing
806808
Next v
807-
Else ' assume nodeIds is valid
809+
ElseIf Not nodeIds Is Nothing Then
808810
For Each v In nodeIds
809811
Set node = getDomNode(nodeId:=v, depth:=depth, pierce:=pierce)
810812
key = getNodeIdOrName(node)
811813
If key = vbNullString Or nodes.Exists(key) Then key = nodes.count
812814
Set nodes(key) = node
815+
Set node = Nothing
813816
Next v
817+
ElseIf remoteNodeList Is Nothing Then
818+
' using GetProperties we can actually retrieve the values in the NodeList
819+
Dim nodeList As Dictionary, result As Collection
820+
Set nodeList = cdp.Runtime.GetProperties(remoteNodeList.objectId, ownProperties:=True) ' we just want the nodes so skip all properties that are inherited
821+
Set result = nodeList("result")
822+
For Each v In result
823+
Dim propDesc As cdpRuntimePropertyDescriptor
824+
Set propDesc = New cdpRuntimePropertyDescriptor
825+
propDesc.init v
826+
If Not propDesc.Value Is Nothing Then
827+
If propDesc.Value.subtype = "node" Then
828+
Set node = getDomNode(objectId:=propDesc.Value.objectId, depth:=depth, pierce:=pierce)
829+
key = getNodeIdOrName(node)
830+
If key = vbNullString Or nodes.Exists(key) Then key = nodes.count
831+
Set nodes(key) = node
832+
Set node = Nothing
833+
End If
834+
End If
835+
Set propDesc = Nothing
836+
Next v
837+
Set result = Nothing
838+
Set nodeList = Nothing
839+
Else
840+
Debug.Print "getDomNodes - No source of DOM nodes provided!"
841+
Stop
814842
End If
815843

816844
Set getDomNodes = nodes
817845
End Function
818846

819-
820847
' converts a Runtime.RemoteObject into a DOM.Node
821848
Public Function RemoteObjectToDomNode(ByVal remoteObj As cdpRuntimeRemoteObject, Optional ByVal depth As Integer = -1, Optional ByVal pierce As Boolean = False) As cdpDOMNode
822849
Set RemoteObjectToDomNode = getDomNode(objectId:=remoteObj.objectId, depth:=depth, pierce:=pierce)
@@ -985,8 +1012,10 @@ End Function
9851012
' Note: resulting Dictionary will be empty (0 items) if an error or no matching elements found
9861013
Public Function querySelectorAll(ByVal selector As String, Optional ByVal rootId As Integer = 0, Optional ByVal frameId As String = vbNullString, _
9871014
Optional ByVal depth As Integer = -1, Optional ByVal pierce As Boolean = False) As Dictionary ' of cdpDomNode
1015+
On Error GoTo errHandler
9881016
Set querySelectorAll = New Dictionary
9891017
Dim nodeIds As Collection, dict As Dictionary
1018+
Dim remoteObj As cdpRuntimeRemoteObject
9901019
If frameId = vbNullString Then
9911020
' if no base element provided, use the document root of current target
9921021
If rootId < 1 Then
@@ -998,20 +1027,24 @@ Public Function querySelectorAll(ByVal selector As String, Optional ByVal rootId
9981027
If Not nodeIds Is Nothing Then Set querySelectorAll = getDomNodes(nodeIds, depth:=depth, pierce:=pierce)
9991028
End If
10001029
Else
1001-
' TODO ***
10021030
' get unique(Excution)Id associated with frame
10031031
If curSession.frameExecCtxMapping.Exists("$" & frameId) Then
10041032
Dim contextId As String
10051033
contextId = curSession.frameExecCtxMapping.Item("$" & frameId)
1006-
Set dict = jsEval("document.querySelectorAll('" & selector & "');", silent:=True, uniqueContextId:=contextId)
1034+
' we need returnByValue to be unset or False to ensure we get the RemoteObject id not a bunch of empty objects
1035+
Set dict = jsEval("document.querySelectorAll('" & selector & "');", silent:=True, uniqueContextId:=contextId, returnByValue:=False)
10071036
If cdp.ErrorCode = 0 Then
1008-
Dim remoteObj As cdpRuntimeRemoteObject
10091037
Set remoteObj = New cdpRuntimeRemoteObject
10101038
remoteObj.init dict
1011-
Set querySelectorAll = getDomNodes(objectIds:=remoteObj, depth:=depth, pierce:=pierce)
1039+
Set querySelectorAll = getDomNodes(remoteNodeList:=remoteObj, depth:=depth, pierce:=pierce)
10121040
End If
10131041
End If
10141042
End If
1043+
Exit Function
1044+
errHandler:
1045+
Debug.Print "AutomateBrowser.querySelectorAll - " & Err.description
1046+
Stop
1047+
Resume
10151048
End Function
10161049

10171050
' returns document root and all child elements of main frame, optinally piercing frames and shadow DOMs

0 commit comments

Comments
 (0)