Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
165 additions
and
136 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,170 +1,59 @@ | ||
package chromedp | ||
|
||
const ( | ||
import ( | ||
_ "embed" | ||
) | ||
|
||
var ( | ||
// textJS is a javascript snippet that returns the innerText of the specified | ||
// visible (ie, offsetWidth || offsetHeight || getClientRects().length ) element. | ||
textJS = `function text() { | ||
if (this.offsetWidth || this.offsetHeight || this.getClientRects().length) { | ||
return this.innerText; | ||
} | ||
return ''; | ||
}` | ||
//go:embed js/text.js | ||
textJS string | ||
|
||
// textContentJS is a javascript snippet that returns the textContent of the | ||
// specified element. | ||
textContentJS = `function textContent() { | ||
return this.textContent; | ||
}` | ||
//go:embed js/textContent.js | ||
textContentJS string | ||
|
||
// blurJS is a javascript snippet that blurs the specified element. | ||
blurJS = `function blur() { | ||
this.blur(); | ||
return true; | ||
}` | ||
//go:embed js/blur.js | ||
blurJS string | ||
|
||
// submitJS is a javascript snippet that will call the containing form's | ||
// submit function, returning true or false if the call was successful. | ||
submitJS = `function submit() { | ||
if (this.nodeName === 'FORM') { | ||
HTMLFormElement.prototype.submit.call(this); | ||
return true; | ||
} else if (this.form !== null) { | ||
HTMLFormElement.prototype.submit.call(this.form); | ||
return true; | ||
} | ||
return false; | ||
}` | ||
//go:embed js/submit.js | ||
submitJS string | ||
|
||
// resetJS is a javascript snippet that will call the containing form's | ||
// reset function, returning true or false if the call was successful. | ||
resetJS = `function reset() { | ||
if (this.nodeName === 'FORM') { | ||
HTMLFormElement.prototype.reset.call(this); | ||
return true; | ||
} else if (this.form !== null) { | ||
HTMLFormElement.prototype.reset.call(this.form); | ||
return true; | ||
} | ||
return false; | ||
}` | ||
//go:embed js/reset.js | ||
resetJS string | ||
|
||
// attributeJS is a javascript snippet that returns the attribute of a specified | ||
// node. | ||
attributeJS = `function attribute(n) { | ||
return this[n]; | ||
}` | ||
//go:embed js/attribute.js | ||
attributeJS string | ||
|
||
// setAttributeJS is a javascript snippet that sets the value of the specified | ||
// node, and returns the value. | ||
setAttributeJS = `function setAttribute(n, v) { | ||
this[n] = v; | ||
if (n === 'value') { | ||
this.dispatchEvent(new Event('input', { bubbles: true })); | ||
this.dispatchEvent(new Event('change', { bubbles: true })); | ||
} | ||
return this[n]; | ||
}` | ||
//go:embed js/setAttribute.js | ||
setAttributeJS string | ||
|
||
// visibleJS is a javascript snippet that returns true or false depending on if | ||
// the specified node's offsetWidth, offsetHeight or getClientRects().length is | ||
// not null. | ||
visibleJS = `function visible() { | ||
return Boolean( this.offsetWidth || this.offsetHeight || this.getClientRects().length ); | ||
}` | ||
//go:embed js/visible.js | ||
visibleJS string | ||
|
||
// getClientRectJS is a javascript snippet that returns the information about the | ||
// size of the specified node and its position relative to its owner document. | ||
getClientRectJS = `function getClientRect() { | ||
const e = this.getBoundingClientRect(), | ||
t = this.ownerDocument.documentElement.getBoundingClientRect(); | ||
return { | ||
x: e.left - t.left, | ||
y: e.top - t.top, | ||
width: e.width, | ||
height: e.height, | ||
}; | ||
}` | ||
//go:embed js/getClientRect.js | ||
getClientRectJS string | ||
|
||
// waitForPredicatePageFunction is a javascript snippet that runs the polling in the | ||
// browser. It's copied from puppeteer. See | ||
// https://github.com/puppeteer/puppeteer/blob/669f04a7a6e96cc8353a8cb152898edbc25e7c15/src/common/DOMWorld.ts#L870-L944 | ||
// It's modified to make mutation polling respect timeout even when there is not DOM mutation. | ||
waitForPredicatePageFunction = `async function waitForPredicatePageFunction(predicateBody, polling, timeout, ...args) { | ||
const predicate = new Function('...args', predicateBody); | ||
let timedOut = false; | ||
if (timeout) | ||
setTimeout(() => (timedOut = true), timeout); | ||
if (polling === 'raf') | ||
return await pollRaf(); | ||
if (polling === 'mutation') | ||
return await pollMutation(); | ||
if (typeof polling === 'number') | ||
return await pollInterval(polling); | ||
/** | ||
* @returns {!Promise<*>} | ||
*/ | ||
async function pollMutation() { | ||
const success = await predicate(...args); | ||
if (success) | ||
return Promise.resolve(success); | ||
let fulfill; | ||
const result = new Promise((x) => (fulfill = x)); | ||
const observer = new MutationObserver(async () => { | ||
if (timedOut) { | ||
observer.disconnect(); | ||
fulfill(); | ||
} | ||
const success = await predicate(...args); | ||
if (success) { | ||
observer.disconnect(); | ||
fulfill(success); | ||
} | ||
}); | ||
observer.observe(document, { | ||
childList: true, | ||
subtree: true, | ||
attributes: true, | ||
}); | ||
if (timeout) | ||
setTimeout(() => { | ||
observer.disconnect(); | ||
fulfill(); | ||
}, timeout); | ||
return result; | ||
} | ||
async function pollRaf() { | ||
let fulfill; | ||
const result = new Promise((x) => (fulfill = x)); | ||
await onRaf(); | ||
return result; | ||
async function onRaf() { | ||
if (timedOut) { | ||
fulfill(); | ||
return; | ||
} | ||
const success = await predicate(...args); | ||
if (success) | ||
fulfill(success); | ||
else | ||
requestAnimationFrame(onRaf); | ||
} | ||
} | ||
async function pollInterval(pollInterval) { | ||
let fulfill; | ||
const result = new Promise((x) => (fulfill = x)); | ||
await onTimeout(); | ||
return result; | ||
async function onTimeout() { | ||
if (timedOut) { | ||
fulfill(); | ||
return; | ||
} | ||
const success = await predicate(...args); | ||
if (success) | ||
fulfill(success); | ||
else | ||
setTimeout(onTimeout, pollInterval); | ||
} | ||
} | ||
}` | ||
//go:embed js/waitForPredicatePageFunction.js | ||
waitForPredicatePageFunction string | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
function attribute(n) { | ||
return this[n]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
function blur() { | ||
this.blur(); | ||
return true; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
function getClientRect() { | ||
const e = this.getBoundingClientRect(), | ||
t = this.ownerDocument.documentElement.getBoundingClientRect(); | ||
return { | ||
x: e.left - t.left, | ||
y: e.top - t.top, | ||
width: e.width, | ||
height: e.height, | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
function reset() { | ||
if (this.nodeName === 'FORM') { | ||
HTMLFormElement.prototype.reset.call(this); | ||
return true; | ||
} else if (this.form !== null) { | ||
HTMLFormElement.prototype.reset.call(this.form); | ||
return true; | ||
} | ||
return false; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
function setAttribute(n, v) { | ||
this[n] = v; | ||
if (n === 'value') { | ||
this.dispatchEvent(new Event('input', {bubbles: true})); | ||
this.dispatchEvent(new Event('change', {bubbles: true})); | ||
} | ||
return this[n]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
function submit() { | ||
if (this.nodeName === 'FORM') { | ||
HTMLFormElement.prototype.submit.call(this); | ||
return true; | ||
} else if (this.form !== null) { | ||
HTMLFormElement.prototype.submit.call(this.form); | ||
return true; | ||
} | ||
return false; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
function text() { | ||
if (this.offsetWidth || this.offsetHeight || this.getClientRects().length) { | ||
return this.innerText; | ||
} | ||
return ''; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
function textContent() { | ||
return this.textContent; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
function visible() { | ||
return Boolean(this.offsetWidth || this.offsetHeight || this.getClientRects().length); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
async function waitForPredicatePageFunction(predicateBody, polling, timeout, ...args) { | ||
const predicate = new Function('...args', predicateBody); | ||
let timedOut = false; | ||
if (timeout) | ||
setTimeout(() => (timedOut = true), timeout); | ||
if (polling === 'raf') | ||
return await pollRaf(); | ||
if (polling === 'mutation') | ||
return await pollMutation(); | ||
if (typeof polling === 'number') | ||
return await pollInterval(polling); | ||
|
||
/** | ||
* @returns {!Promise<*>} | ||
*/ | ||
async function pollMutation() { | ||
const success = await predicate(...args); | ||
if (success) | ||
return Promise.resolve(success); | ||
let fulfill; | ||
const result = new Promise((x) => (fulfill = x)); | ||
const observer = new MutationObserver(async () => { | ||
if (timedOut) { | ||
observer.disconnect(); | ||
fulfill(); | ||
} | ||
const success = await predicate(...args); | ||
if (success) { | ||
observer.disconnect(); | ||
fulfill(success); | ||
} | ||
}); | ||
observer.observe(document, { | ||
childList: true, | ||
subtree: true, | ||
attributes: true, | ||
}); | ||
if (timeout) | ||
setTimeout(() => { | ||
observer.disconnect(); | ||
fulfill(); | ||
}, timeout); | ||
return result; | ||
} | ||
|
||
async function pollRaf() { | ||
let fulfill; | ||
const result = new Promise((x) => (fulfill = x)); | ||
await onRaf(); | ||
return result; | ||
|
||
async function onRaf() { | ||
if (timedOut) { | ||
fulfill(); | ||
return; | ||
} | ||
const success = await predicate(...args); | ||
if (success) | ||
fulfill(success); | ||
else | ||
requestAnimationFrame(onRaf); | ||
} | ||
} | ||
|
||
async function pollInterval(pollInterval) { | ||
let fulfill; | ||
const result = new Promise((x) => (fulfill = x)); | ||
await onTimeout(); | ||
return result; | ||
|
||
async function onTimeout() { | ||
if (timedOut) { | ||
fulfill(); | ||
return; | ||
} | ||
const success = await predicate(...args); | ||
if (success) | ||
fulfill(success); | ||
else | ||
setTimeout(onTimeout, pollInterval); | ||
} | ||
} | ||
} |