88use HeadlessChromium \Communication \Message ;
99use HeadlessChromium \Communication \Response ;
1010use HeadlessChromium \Exception \DomException ;
11+ use HeadlessChromium \Exception \StaleElementException ;
1112use HeadlessChromium \Page ;
1213
1314class Node
@@ -22,16 +23,37 @@ class Node
2223 */
2324 protected $ nodeId ;
2425
26+ /**
27+ * @var bool
28+ */
29+ protected bool $ isStale = false ;
30+
2531 public function __construct (Page $ page , int $ nodeId )
2632 {
2733 $ this ->page = $ page ;
2834 $ this ->nodeId = $ nodeId ;
35+
36+ $ page ->getSession ()->on ('method:DOM.documentUpdated ' , function (...$ event ): void {
37+ $ this ->isStale = true ;
38+ });
39+ }
40+
41+ public function getNodeId (): int
42+ {
43+ return $ this ->nodeId ;
44+ }
45+
46+ public function getNodeIdForRequest (): int
47+ {
48+ $ this ->prepareForRequest ();
49+
50+ return $ this ->getNodeId ();
2951 }
3052
3153 public function getAttributes (): NodeAttributes
3254 {
3355 $ message = new Message ('DOM.getAttributes ' , [
34- 'nodeId ' => $ this ->nodeId ,
56+ 'nodeId ' => $ this ->getNodeIdForRequest () ,
3557 ]);
3658 $ response = $ this ->page ->getSession ()->sendMessageSync ($ message );
3759
@@ -45,7 +67,7 @@ public function getAttributes(): NodeAttributes
4567 public function setAttributeValue (string $ name , string $ value ): void
4668 {
4769 $ message = new Message ('DOM.setAttributeValue ' , [
48- 'nodeId ' => $ this ->nodeId ,
70+ 'nodeId ' => $ this ->getNodeIdForRequest () ,
4971 'name ' => $ name ,
5072 'value ' => $ value ,
5173 ]);
@@ -57,7 +79,7 @@ public function setAttributeValue(string $name, string $value): void
5779 public function querySelector (string $ selector ): ?self
5880 {
5981 $ message = new Message ('DOM.querySelector ' , [
60- 'nodeId ' => $ this ->nodeId ,
82+ 'nodeId ' => $ this ->getNodeIdForRequest () ,
6183 'selector ' => $ selector ,
6284 ]);
6385 $ response = $ this ->page ->getSession ()->sendMessageSync ($ message );
@@ -75,7 +97,7 @@ public function querySelector(string $selector): ?self
7597 public function querySelectorAll (string $ selector ): array
7698 {
7799 $ message = new Message ('DOM.querySelectorAll ' , [
78- 'nodeId ' => $ this ->nodeId ,
100+ 'nodeId ' => $ this ->getNodeIdForRequest () ,
79101 'selector ' => $ selector ,
80102 ]);
81103 $ response = $ this ->page ->getSession ()->sendMessageSync ($ message );
@@ -94,7 +116,7 @@ public function querySelectorAll(string $selector): array
94116 public function focus (): void
95117 {
96118 $ message = new Message ('DOM.focus ' , [
97- 'nodeId ' => $ this ->nodeId ,
119+ 'nodeId ' => $ this ->getNodeIdForRequest () ,
98120 ]);
99121 $ response = $ this ->page ->getSession ()->sendMessageSync ($ message );
100122
@@ -109,7 +131,7 @@ public function getAttribute(string $name): ?string
109131 public function getPosition (): ?NodePosition
110132 {
111133 $ message = new Message ('DOM.getBoxModel ' , [
112- 'nodeId ' => $ this ->nodeId ,
134+ 'nodeId ' => $ this ->getNodeIdForRequest () ,
113135 ]);
114136 $ response = $ this ->page ->getSession ()->sendMessageSync ($ message );
115137
@@ -132,7 +154,7 @@ public function hasPosition(): bool
132154 public function getHTML (): string
133155 {
134156 $ message = new Message ('DOM.getOuterHTML ' , [
135- 'nodeId ' => $ this ->nodeId ,
157+ 'nodeId ' => $ this ->getNodeIdForRequest () ,
136158 ]);
137159 $ response = $ this ->page ->getSession ()->sendMessageSync ($ message );
138160
@@ -144,7 +166,7 @@ public function getHTML(): string
144166 public function setHTML (string $ outerHTML ): void
145167 {
146168 $ message = new Message ('DOM.setOuterHTML ' , [
147- 'nodeId ' => $ this ->nodeId ,
169+ 'nodeId ' => $ this ->getNodeIdForRequest () ,
148170 'outerHTML ' => $ outerHTML ,
149171 ]);
150172 $ response = $ this ->page ->getSession ()->sendMessageSync ($ message );
@@ -160,7 +182,7 @@ public function getText(): string
160182 public function scrollIntoView (): void
161183 {
162184 $ message = new Message ('DOM.scrollIntoViewIfNeeded ' , [
163- 'nodeId ' => $ this ->nodeId ,
185+ 'nodeId ' => $ this ->getNodeIdForRequest () ,
164186 ]);
165187 $ response = $ this ->page ->getSession ()->sendMessageSync ($ message );
166188
@@ -199,7 +221,7 @@ public function sendFiles(array $filePaths): void
199221 {
200222 $ message = new Message ('DOM.setFileInputFiles ' , [
201223 'files ' => $ filePaths ,
202- 'nodeId ' => $ this ->nodeId ,
224+ 'nodeId ' => $ this ->getNodeIdForRequest () ,
203225 ]);
204226 $ response = $ this ->page ->getSession ()->sendMessageSync ($ message );
205227
@@ -231,4 +253,15 @@ public function getClip(): ?Clip
231253 $ position ->getHeight (),
232254 );
233255 }
256+
257+ protected function prepareForRequest (): void
258+ {
259+ $ this ->page ->assertNotClosed ();
260+
261+ $ this ->page ->getSession ()->getConnection ()->processAllEvents ();
262+
263+ if ($ this ->isStale ) {
264+ throw new StaleElementException ();
265+ }
266+ }
234267}
0 commit comments