我正在尝试使用C语言构建类似于puppeteer的东西。
执行page.waitForSelector时,我观察到以下消息在puppeteer和devtools之间交换。我看到puppeteer共发送了5个请求,而devtools则发送了5个响应,如下所示。
我无法理解req1中会发生什么。它正在发送一个JavaScript。通过将JavaScript发送到devtools可以实现什么。而且executionContextId的值为4,其中从p那里获取的值为4。
它与addScriptToEvaluateOnNewDocument是否有任何关系。 使用addScriptToEvaluateOnNewDocument时的实际用例是什么。
请帮助我理解这一点。
1. req1
--------------------------------------
{"sessionId":"1C18E8AED956A5DA393C88E73D76B255","method":"Runtime.callFunctionOn","params":{"functionDeclaration":"async function waitForPredicatePageFunction(predicateBody, polling, timeout, ...args) {\n const predicate = new Function('...args', predicateBody);\n let timedOut = false;\n if (timeout)\n setTimeout(() => timedOut = true, timeout);\n if (polling === 'raf')\n return await pollRaf();\n if (polling === 'mutation')\n return await pollMutation();\n if (typeof polling === 'number')\n return await pollInterval(polling);\n\n /**\n * @return {!Promise<*>}\n */\n function pollMutation() {\n const success = predicate.apply(null, args);\n if (success)\n return Promise.resolve(success);\n\n let fulfill;\n const result = new Promise(x => fulfill = x);\n const observer = new MutationObserver(mutations => {\n if (timedOut) {\n observer.disconnect();\n fulfill();\n }\n const success = predicate.apply(null, args);\n if (success) {\n observer.disconnect();\n fulfill(success);\n }\n });\n observer.observe(document, {\n childList: true,\n subtree: true,\n attributes: true\n });\n return result;\n }\n\n /**\n * @return {!Promise<*>}\n */\n function pollRaf() {\n let fulfill;\n const result = new Promise(x => fulfill = x);\n onRaf();\n return result;\n\n function onRaf() {\n if (timedOut) {\n fulfill();\n return;\n }\n const success = predicate.apply(null, args);\n if (success)\n fulfill(success);\n else\n requestAnimationFrame(onRaf);\n }\n }\n\n /**\n * @param {number} pollInterval\n * @return {!Promise<*>}\n */\n function pollInterval(pollInterval) {\n let fulfill;\n const result = new Promise(x => fulfill = x);\n onTimeout();\n return result;\n\n function onTimeout() {\n if (timedOut) {\n fulfill();\n return;\n }\n const success = predicate.apply(null, args);\n if (success)\n fulfill(success);\n else\n setTimeout(onTimeout, pollInterval);\n }\n }\n}\n//# sourceURL=__puppeteer_evaluation_script__\n","executionContextId":4,"arguments":[{"value":"return (function predicate(selectorOrXPath, isXPath, waitForVisible, waitForHidden) {\n const node = isXPath\n ? document.evaluate(selectorOrXPath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue\n : document.querySelector(selectorOrXPath);\n if (!node)\n return waitForHidden;\n if (!waitForVisible && !waitForHidden)\n return node;\n const element = /** @type {Element} */ (node.nodeType === Node.TEXT_NODE ? node.parentElement : node);\n\n const style = window.getComputedStyle(element);\n const isVisible = style && style.visibility !== 'hidden' && hasVisibleBoundingBox();\n const success = (waitForVisible === isVisible || waitForHidden === !isVisible);\n return success ? node : null;\n\n /**\n * @return {boolean}\n */\n function hasVisibleBoundingBox() {\n const rect = element.getBoundingClientRect();\n return !!(rect.top || rect.bottom || rect.width || rect.height);\n }\n })(...args)"},{"value":"mutation"},{"value":30000},{"value":"input[name=\"name\"]"},{"value":false},{"value":false},{"value":false}],"returnByValue":false,"awaitPromise":true,"userGesture":true},"id":18}
2. resp1
--------------------------------------
{"id":18,"result":{"result":{"type":"object","subtype":"node","className":"HTMLInputElement","description":"input#edit-name.form-text.required","objectId":"{\"injectedScriptId\":4,\"id\":1}"}},"sessionId":"1C18E8AED956A5DA393C88E73D76B255"}
3. req2
--------------------------------------
{"sessionId":"1C18E8AED956A5DA393C88E73D76B255","method":"Runtime.callFunctionOn","params":{"functionDeclaration":"s => !s\n//# sourceURL=__puppeteer_evaluation_script__\n","executionContextId":4,"arguments":[{"objectId":"{\"injectedScriptId\":4,\"id\":1}"}],"returnByValue":true,"awaitPromise":true,"userGesture":true},"id":19}
4. resp2
--------------------------------------
{"id":19,"result":{"result":{"type":"boolean","value":false}},"sessionId":"1C18E8AED956A5DA393C88E73D76B255"}
5. req3
--------------------------------------
{"sessionId":"1C18E8AED956A5DA393C88E73D76B255","method":"DOM.describeNode","params":{"objectId":"{\"injectedScriptId\":4,\"id\":1}"},"id":20}
6. resp3
--------------------------------------
{"id":20,"result":{"node":{"nodeId":0,"backendNodeId":44,"nodeType":1,"nodeName":"INPUT","localName":"input","nodeValue":"","childNodeCount":0,"attributes":["type","text","id","edit-name","name","name","value","","size","60","maxlength","60","class","form-text required"],"shadowRoots":[{"nodeId":0,"backendNodeId":45,"nodeType":11,"nodeName":"#document-fragment","localName":"","nodeValue":"","childNodeCount":1,"shadowRootType":"user-agent"}]}},"sessionId":"1C18E8AED956A5DA393C88E73D76B255"}
7. req4
--------------------------------------
{"sessionId":"1C18E8AED956A5DA393C88E73D76B255","method":"DOM.resolveNode","params":{"backendNodeId":44,"executionContextId":3},"id":21}
8. resp4
--------------------------------------
{"id":21,"result":{"object":{"type":"object","subtype":"node","className":"HTMLInputElement","description":"input#edit-name.form-text.required","objectId":"{\"injectedScriptId\":3,\"id\":2}"}},"sessionId":"1C18E8AED956A5DA393C88E73D76B255"}
9. req5
--------------------------------------
{"sessionId":"1C18E8AED956A5DA393C88E73D76B255","method":"Runtime.releaseObject","params":{"objectId":"{\"injectedScriptId\":4,\"id\":1}"},"id":22}
10. resp2
--------------------------------------
{"id":22,"result":{},"sessionId":"1C18E8AED956A5DA393C88E73D76B255"}