2626 * WebDriver\Execute class
2727 *
2828 * @package WebDriver
29- *
30- * @method array async() Execute Async Script
31- * @method array sync() Execute Script
3229 */
3330final class Execute extends AbstractWebDriver
3431{
@@ -37,9 +34,138 @@ final class Execute extends AbstractWebDriver
3734 */
3835 protected function methods ()
3936 {
40- return array (
41- 'async ' => array ('POST ' ),
42- 'sync ' => array ('POST ' ),
43- );
37+ return array ();
38+ }
39+
40+ /**
41+ * Inject a snippet of JavaScript into the page for execution in the context of the currently selected frame. (asynchronous)
42+ *
43+ * @param array{script: string, args: array} $jsonScript
44+ *
45+ * @return mixed
46+ */
47+ public function async (array $ jsonScript )
48+ {
49+ $ jsonScript ['args ' ] = $ this ->serializeArguments ($ jsonScript ['args ' ]);
50+
51+ $ result = $ this ->curl ('POST ' , '/execute_async ' , $ jsonScript );
52+
53+ return $ this ->unserializeResult ($ result ['value ' ]);
54+ }
55+
56+ /**
57+ * Inject a snippet of JavaScript into the page for execution in the context of the currently selected frame. (synchronous)
58+ *
59+ * @param array{script: string, args: array} $jsonScript
60+ *
61+ * @return mixed
62+ */
63+ public function sync (array $ jsonScript )
64+ {
65+ $ jsonScript ['args ' ] = $ this ->serializeArguments ($ jsonScript ['args ' ]);
66+
67+ $ result = $ this ->curl ('POST ' , '/execute ' , $ jsonScript );
68+
69+ return $ this ->unserializeResult ($ result ['value ' ]);
70+ }
71+
72+ /**
73+ * Serialize script arguments (containing web elements and/or shadow roots)
74+ *
75+ * @see https://w3c.github.io/webdriver/#executing-script
76+ *
77+ * @param array $arguments
78+ *
79+ * @return array
80+ */
81+ private function serializeArguments (array $ arguments )
82+ {
83+ foreach ($ arguments as $ key => $ value ) {
84+ switch (true ) {
85+ case $ value instanceof Element:
86+ $ arguments [$ key ] = [$ this ->isLegacy () ? Container::LEGACY_ELEMENT_ID : Container::WEB_ELEMENT_ID => $ value ->getID ()];
87+ break ;
88+
89+ case $ value instanceof Shadow:
90+ $ arguments [$ key ] = [Shadow::SHADOW_ROOT_ID => $ value ->getID ()];
91+ break ;
92+
93+ case is_array ($ value ):
94+ $ arguments [$ key ] = $ this ->serializeArguments ($ value );
95+ break ;
96+ }
97+ }
98+
99+ return $ arguments ;
100+ }
101+
102+ /**
103+ * Unserialize result (containing web elements and/or shadow roots)
104+ *
105+ * @param mixed $result
106+ *
107+ * @return mixed
108+ */
109+ private function unserializeResult ($ result )
110+ {
111+ $ element = is_array ($ result ) ? $ this ->webDriverElement ($ result ) : null ;
112+
113+ if ($ element !== null ) {
114+ return $ element ;
115+ }
116+
117+ if (is_array ($ result )) {
118+ foreach ($ result as $ key => $ value ) {
119+ $ result [$ key ] = $ this ->unserializeResult ($ value );
120+ }
121+ }
122+
123+ return $ result ;
124+ }
125+
126+ /**
127+ * Return WebDriver\Element wrapper for $value
128+ *
129+ * @param array $value
130+ *
131+ * @return \WebDriver\Element|\WebDriver\Shadow|null
132+ */
133+ protected function webDriverElement ($ value )
134+ {
135+ $ basePath = preg_replace ('~/execute$~ ' , '' , $ this ->url );
136+
137+ if (array_key_exists (Container::LEGACY_ELEMENT_ID , $ value )) {
138+ return new Element (
139+ $ basePath . '/element/ ' . $ value [Container::LEGACY_ELEMENT_ID ], // url
140+ $ value [Container::LEGACY_ELEMENT_ID ], // id
141+ $ this ->legacy
142+ );
143+ }
144+
145+ if (array_key_exists (Container::WEB_ELEMENT_ID , $ value )) {
146+ return new Element (
147+ $ basePath . '/element/ ' . $ value [Container::WEB_ELEMENT_ID ], // url
148+ $ value [Container::WEB_ELEMENT_ID ], // id
149+ $ this ->legacy
150+ );
151+ }
152+
153+ if (array_key_exists (Shadow::SHADOW_ROOT_ID , $ value )) {
154+ return new Shadow (
155+ $ basePath . '/shadow/ ' . $ value [Shadow::SHADOW_ROOT_ID ], // url
156+ $ value [Shadow::SHADOW_ROOT_ID ], // id
157+ $ this ->legacy
158+ );
159+ }
160+
161+ return null ;
162+ }
163+
164+ /**
165+ * {@inheritdoc}
166+ */
167+ protected function getElementPath ($ unused )
168+ {
169+ return $ this ->url ;
44170 }
45171}
0 commit comments