Skip to content

Commit

Permalink
load js source code with //go:embed
Browse files Browse the repository at this point in the history
  • Loading branch information
ZekeLu committed Jun 9, 2021
1 parent 37ad92e commit 268e11c
Show file tree
Hide file tree
Showing 10 changed files with 153 additions and 126 deletions.
149 changes: 23 additions & 126 deletions js.go
@@ -1,157 +1,54 @@
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

// 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
)
3 changes: 3 additions & 0 deletions js/attribute.js
@@ -0,0 +1,3 @@
function attribute(n) {
return this[n];
}
4 changes: 4 additions & 0 deletions js/blur.js
@@ -0,0 +1,4 @@
function blur() {
this.blur();
return true;
}
10 changes: 10 additions & 0 deletions js/reset.js
@@ -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;
}
8 changes: 8 additions & 0 deletions js/setAttribute.js
@@ -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];
}
10 changes: 10 additions & 0 deletions js/submit.js
@@ -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;
}
6 changes: 6 additions & 0 deletions js/text.js
@@ -0,0 +1,6 @@
function text() {
if (this.offsetWidth || this.offsetHeight || this.getClientRects().length) {
return this.innerText;
}
return '';
}
3 changes: 3 additions & 0 deletions js/textContent.js
@@ -0,0 +1,3 @@
function textContent() {
return this.textContent;
}
3 changes: 3 additions & 0 deletions js/visible.js
@@ -0,0 +1,3 @@
function visible() {
return Boolean(this.offsetWidth || this.offsetHeight || this.getClientRects().length);
}
83 changes: 83 additions & 0 deletions js/waitForPredicatePageFunction.js
@@ -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);
}
}
}

0 comments on commit 268e11c

Please sign in to comment.