mirror of
https://github.com/NohamR/safari-internal-js.git
synced 2026-10-11 02:49:41 +00:00
Add 27.0 js src
This commit is contained in:
39
27.0/js/automation/WDElementAttribute.js
Normal file
39
27.0/js/automation/WDElementAttribute.js
Normal file
@@ -0,0 +1,39 @@
|
||||
//# sourceURL=__InjectedScript_WDElementAttribute.js
|
||||
function(element){"use strict";var utils={};utils.enclosingNodeOrSelfMatchingPredicate=function(targetNode,predicate){for(let node=targetNode;node&&node!==targetNode.getRootNode();node=node.parentNode)
|
||||
if(predicate(node))
|
||||
return node;return null;}
|
||||
utils.nodeIsElement=function(node){return!!node&&node.nodeType===Node.ELEMENT_NODE;}
|
||||
utils.parentElementForElement=function(element){if(!element)
|
||||
return null;return utils.enclosingNodeOrSelfMatchingPredicate(element.parentNode,utils.nodeIsElement);}
|
||||
utils.cascadedStylePropertyForElement=function(element,property){if(!element||!property)
|
||||
return null;let computedStyle=window.getComputedStyle(element);let computedStyleProperty=computedStyle.getPropertyValue(property);if(computedStyleProperty&&computedStyleProperty!=="inherit")
|
||||
return computedStyleProperty;
|
||||
|
||||
let parentElement=utils.parentElementForElement(element);return utils.cascadedStylePropertyForElement(parentElement,property);}
|
||||
utils.isShown=function(element){function enclosingElementOrSelfMatchingPredicate(targetElement,predicate){for(let element=targetElement;element&&element!==targetElement.getRootNode();element=utils.parentElementForElement(element))
|
||||
if(predicate(element))
|
||||
return element;return null;}
|
||||
function elementSubtreeHasNonZeroDimensions(element){let boundingBox=element.getBoundingClientRect();if(boundingBox.width>0&&boundingBox.height>0)
|
||||
return true;if(element.tagName.toUpperCase()==="PATH"&&boundingBox.width+boundingBox.height>0){let strokeWidth=utils.cascadedStylePropertyForElement(element,"stroke-width");return!!strokeWidth&&(parseInt(strokeWidth,10)>0);}
|
||||
let cascadedOverflow=utils.cascadedStylePropertyForElement(element,"overflow");if(cascadedOverflow==="hidden")
|
||||
return false;
|
||||
return Array.from(element.childNodes).some((childNode)=>{if(childNode.nodeType===Node.TEXT_NODE)
|
||||
return true;if(utils.nodeIsElement(childNode))
|
||||
return elementSubtreeHasNonZeroDimensions(childNode);return false;});}
|
||||
function elementOverflowsContainer(element){let cascadedOverflow=utils.cascadedStylePropertyForElement(element,"overflow");if(cascadedOverflow!=="hidden")
|
||||
return false;return true;}
|
||||
function isElementSubtreeHiddenByOverflow(element){if(!element)
|
||||
return false;if(!elementOverflowsContainer(element))
|
||||
return false;if(!element.childNodes.length)
|
||||
return false;return Array.from(element.childNodes).every((childNode)=>{if(!utils.nodeIsElement(childNode))
|
||||
return true;if(!elementSubtreeHasNonZeroDimensions(childNode))
|
||||
return true;return isElementSubtreeHiddenByOverflow(childNode);});}
|
||||
if(!(element instanceof Element))
|
||||
throw new Error("Cannot check the displayedness of a non-Element argument.");switch(element.tagName.toUpperCase()){case"BODY":return true;case"SCRIPT":case"NOSCRIPT":return false;case"OPTGROUP":case"OPTION":let enclosingSelectElement=utils.enclosingNodeOrSelfMatchingPredicate(element,(e)=>e.tagName.toUpperCase()==="SELECT");return utils.isShown(enclosingSelectElement);case"INPUT":if(element.type==="hidden")
|
||||
return false;break;case"MAP":default:break;}
|
||||
if(utils.cascadedStylePropertyForElement(element,"visibility")!=="visible")
|
||||
return false;let hasAncestorWithZeroOpacity=!!enclosingElementOrSelfMatchingPredicate(element,(e)=>{return Number(utils.cascadedStylePropertyForElement(e,"opacity"))===0;});let hasAncestorWithDisplayNone=!!enclosingElementOrSelfMatchingPredicate(element,(e)=>{return utils.cascadedStylePropertyForElement(e,"display")==="none";});if(hasAncestorWithZeroOpacity||hasAncestorWithDisplayNone)
|
||||
return false;if(!elementSubtreeHasNonZeroDimensions(element))
|
||||
return false;if(isElementSubtreeHiddenByOverflow(element))
|
||||
return false;return true;}
|
||||
return utils.isShown(element);}
|
||||
13
27.0/js/automation/WDElementDisplayed.js
Normal file
13
27.0/js/automation/WDElementDisplayed.js
Normal file
@@ -0,0 +1,13 @@
|
||||
//# sourceURL=__InjectedScript_WDElementDisplayed.js
|
||||
function fetchTagNameAndAttributesOfElement(element) {
|
||||
"use strict";
|
||||
let tagName = element.tagName.toUpperCase();
|
||||
let attributes = {};
|
||||
for (let i = 0; i < element.attributes.length; ++i) {
|
||||
let name = element.attributes[i].name.toLowerCase();
|
||||
let value = element.attributes[i].value;
|
||||
if (!value.length) value = null;
|
||||
attributes[name] = value;
|
||||
}
|
||||
return { tagName, attributes };
|
||||
}
|
||||
38
27.0/js/automation/WDElementFetchAttributes.js
Normal file
38
27.0/js/automation/WDElementFetchAttributes.js
Normal file
@@ -0,0 +1,38 @@
|
||||
//# sourceURL=__InjectedScript_WDElementFetchAttributes.js
|
||||
function enterFullscreen() {
|
||||
let callback = arguments[0];
|
||||
if (!document.fullscreenEnabled) {
|
||||
callback(false);
|
||||
return;
|
||||
}
|
||||
if (document.fullscreenElement) {
|
||||
callback(true);
|
||||
return;
|
||||
}
|
||||
let fullscreenChangeListener, fullscreenErrorListener;
|
||||
fullscreenChangeListener = (e) => {
|
||||
if (e.target !== document.documentElement) return;
|
||||
if (!document.fullscreenElement) return;
|
||||
document.removeEventListener("fullscreenchange", fullscreenChangeListener);
|
||||
document.documentElement.removeEventListener(
|
||||
"fullscreenerror",
|
||||
fullscreenErrorListener,
|
||||
);
|
||||
callback(true);
|
||||
};
|
||||
fullscreenErrorListener = (e) => {
|
||||
if (e.target !== document.documentElement) return;
|
||||
document.removeEventListener("fullscreenchange", fullscreenChangeListener);
|
||||
document.documentElement.removeEventListener(
|
||||
"fullscreenerror",
|
||||
fullscreenErrorListener,
|
||||
);
|
||||
callback(!!document.fullscreenElement);
|
||||
};
|
||||
document.addEventListener("fullscreenchange", fullscreenChangeListener);
|
||||
document.documentElement.addEventListener(
|
||||
"fullscreenerror",
|
||||
fullscreenErrorListener,
|
||||
);
|
||||
document.documentElement.requestFullscreen();
|
||||
}
|
||||
82
27.0/js/automation/WDEnterFullscreen.js
Normal file
82
27.0/js/automation/WDEnterFullscreen.js
Normal file
@@ -0,0 +1,82 @@
|
||||
//# sourceURL=__InjectedScript_WDEnterFullscreen.js
|
||||
function(strategy,ancestorElement,query,firstResultOnly,timeoutDuration,callback){"use strict";var utils={};utils.enclosingNodeOrSelfMatchingPredicate=function(targetNode,predicate){for(let node=targetNode;node&&node!==targetNode.getRootNode();node=node.parentNode)
|
||||
if(predicate(node))
|
||||
return node;return null;}
|
||||
utils.nodeIsElement=function(node){return!!node&&node.nodeType===Node.ELEMENT_NODE;}
|
||||
utils.parentElementForElement=function(element){if(!element)
|
||||
return null;return utils.enclosingNodeOrSelfMatchingPredicate(element.parentNode,utils.nodeIsElement);}
|
||||
utils.cascadedStylePropertyForElement=function(element,property){if(!element||!property)
|
||||
return null;let computedStyle=window.getComputedStyle(element);let computedStyleProperty=computedStyle.getPropertyValue(property);if(computedStyleProperty&&computedStyleProperty!=="inherit")
|
||||
return computedStyleProperty;
|
||||
|
||||
let parentElement=utils.parentElementForElement(element);return utils.cascadedStylePropertyForElement(parentElement,property);}
|
||||
utils.isShown=function(element){function enclosingElementOrSelfMatchingPredicate(targetElement,predicate){for(let element=targetElement;element&&element!==targetElement.getRootNode();element=utils.parentElementForElement(element))
|
||||
if(predicate(element))
|
||||
return element;return null;}
|
||||
function elementSubtreeHasNonZeroDimensions(element){let boundingBox=element.getBoundingClientRect();if(boundingBox.width>0&&boundingBox.height>0)
|
||||
return true;if(element.tagName.toUpperCase()==="PATH"&&boundingBox.width+boundingBox.height>0){let strokeWidth=utils.cascadedStylePropertyForElement(element,"stroke-width");return!!strokeWidth&&(parseInt(strokeWidth,10)>0);}
|
||||
let cascadedOverflow=utils.cascadedStylePropertyForElement(element,"overflow");if(cascadedOverflow==="hidden")
|
||||
return false;
|
||||
return Array.from(element.childNodes).some((childNode)=>{if(childNode.nodeType===Node.TEXT_NODE)
|
||||
return true;if(utils.nodeIsElement(childNode))
|
||||
return elementSubtreeHasNonZeroDimensions(childNode);return false;});}
|
||||
function elementOverflowsContainer(element){let cascadedOverflow=utils.cascadedStylePropertyForElement(element,"overflow");if(cascadedOverflow!=="hidden")
|
||||
return false;return true;}
|
||||
function isElementSubtreeHiddenByOverflow(element){if(!element)
|
||||
return false;if(!elementOverflowsContainer(element))
|
||||
return false;if(!element.childNodes.length)
|
||||
return false;return Array.from(element.childNodes).every((childNode)=>{if(!utils.nodeIsElement(childNode))
|
||||
return true;if(!elementSubtreeHasNonZeroDimensions(childNode))
|
||||
return true;return isElementSubtreeHiddenByOverflow(childNode);});}
|
||||
if(!(element instanceof Element))
|
||||
throw new Error("Cannot check the displayedness of a non-Element argument.");switch(element.tagName.toUpperCase()){case"BODY":return true;case"SCRIPT":case"NOSCRIPT":return false;case"OPTGROUP":case"OPTION":let enclosingSelectElement=utils.enclosingNodeOrSelfMatchingPredicate(element,(e)=>e.tagName.toUpperCase()==="SELECT");return utils.isShown(enclosingSelectElement);case"INPUT":if(element.type==="hidden")
|
||||
return false;break;case"MAP":default:break;}
|
||||
if(utils.cascadedStylePropertyForElement(element,"visibility")!=="visible")
|
||||
return false;let hasAncestorWithZeroOpacity=!!enclosingElementOrSelfMatchingPredicate(element,(e)=>{return Number(utils.cascadedStylePropertyForElement(e,"opacity"))===0;});let hasAncestorWithDisplayNone=!!enclosingElementOrSelfMatchingPredicate(element,(e)=>{return utils.cascadedStylePropertyForElement(e,"display")==="none";});if(hasAncestorWithZeroOpacity||hasAncestorWithDisplayNone)
|
||||
return false;if(!elementSubtreeHasNonZeroDimensions(element))
|
||||
return false;if(isElementSubtreeHiddenByOverflow(element))
|
||||
return false;return true;}
|
||||
utils.getText=function(element){var lines=[];function appendLinesFromTextNode(textNode,whitespace,textTransform){let text=textNode.nodeValue.replace(/[\u200b\u200e\u200f]/g,'');text=text.replace(/(\r\n|\r|\n)/g,'\n');let collapseAll=true;switch(whitespace){case"normal":case"nowrap":text=text.replace(/\n/g,' ');break;case"pre":case"pre-wrap":text=text.replace(/[ \f\t\v\u2028\u2029]/g,'\xa0');collapseAll=false;break;}
|
||||
if(collapseAll){text=text.replace(/[\ \f\t\v\u2028\u2029]+/g,' ');}
|
||||
switch(textTransform){case"capitalize":text=text.replace(/(^|[^\d\p{L}\p{S}])([\p{Ll}|\p{S}])/gu,function(){return arguments[1]+arguments[2].toUpperCase();});break;case"uppercase":text=text.toUpperCase();break;case"lowercase":text=text.toLowerCase();break;}
|
||||
let currentLine=lines.pop()||'';if(currentLine.endsWith(' ')&&text.startsWith(' '))
|
||||
text=text.substr(1);lines.push(currentLine+text);}
|
||||
function appendLinesFromNode(node,shown,whitespace,textTransform){switch(node.nodeType){case Node.TEXT_NODE:if(shown)
|
||||
appendLinesFromTextNode(node,whitespace,textTransform);break;case Node.ELEMENT_NODE:if(node.tagName.toUpperCase()=="SLOT"){let parentNode=node;while(parentNode.parentNode)
|
||||
parentNode=parentNode.parentNode;if(parentNode instanceof ShadowRoot){Array.from(node.assignedNodes()).forEach((childNode)=>{appendLinesFromNode(childNode,shown,whitespace,textTransform);});return;}}
|
||||
appendLinesFromElement(node);break;}}
|
||||
function appendLines(element){function currentLine(){return lines[lines.length-1]||'';}
|
||||
let isTableCell=false,display=null,isBlock=false;if(element.tagName.toUpperCase()==="BR")
|
||||
lines.push('');else{isTableCell=element.tagName.toUpperCase()==="TD";display=utils.cascadedStylePropertyForElement(element,"display");isBlock=!isTableCell&&!(display==="inline"||display==="inline-block"||display==="inline-table"||display==="none"||display==="table-cell"||display==="table-column"||display==="table-column-group");let previousElementSibling=element.previousElementSibling;let previousDisplay=previousElementSibling?utils.cascadedStylePropertyForElement(previousElementSibling,"display"):'';let elementFloat=utils.cascadedStylePropertyForElement(element,"float")||utils.cascadedStylePropertyForElement(element,"cssFloat");let runIntoThis=previousDisplay=="run-in"&&elementFloat=="none";if(isBlock&&!runIntoThis&&/^[\s\xa0]*$/.test(currentLine()))
|
||||
lines.push('');}
|
||||
let shown=utils.isShown(element);let whitespace=null,textTransform=null;if(shown){whitespace=utils.cascadedStylePropertyForElement(element,"white-space");textTransform=utils.cascadedStylePropertyForElement(element,"text-transform");}
|
||||
Array.from(element.childNodes).forEach((childNode)=>{if(!childNode.assignedSlot)
|
||||
appendLinesFromNode(childNode,shown,whitespace,textTransform);});let line=currentLine();if((isTableCell||display=="table-cell")&&line&&line.endsWith(' '))
|
||||
lines[lines.length-1]+=' ';if(isBlock&&display!="run-in"&&/^[\s\xa0]*$/.test(line))
|
||||
lines.push('');}
|
||||
function appendLinesFromElement(element){if(element.shadowRoot){Array.from(element.shadowRoot.childNodes).forEach((childNode)=>{appendLinesFromNode(childNode,true,null,null);});}
|
||||
appendLines(element);}
|
||||
appendLinesFromElement(element);lines=lines.map((str)=>str.replace(/^[^\S\xa0]+|[^\S\xa0]+$/g,''));let trimmed=lines.join('\n').replace(/^[^\S\xa0]+|[^\S\xa0]+$/g,'');return trimmed.replace(/\xa0/g,' ');}
|
||||
ancestorElement=ancestorElement||document;switch(strategy){case"id":strategy="css selector";query="[id=\""+escape(query)+"\"]";break;case"name":strategy="css selector";query="[name=\""+escape(query)+"\"]";break;}
|
||||
switch(strategy){case"css selector":case"link text":case"partial link text":case"tag name":case"class name":case"xpath":break;default:
|
||||
throw{name:"InvalidParameter",message:("Unsupported locator strategy: "+strategy+".")};}
|
||||
function escape(string){return string.replace(/\\/g,"\\\\").replace(/"/g,"\\\"");}
|
||||
function tryToFindNode(){try{switch(strategy){case"css selector":if(firstResultOnly)
|
||||
return ancestorElement.querySelector(query)||null;return Array.from(ancestorElement.querySelectorAll(query));case"link text":let linkTextResult=[];for(let link of ancestorElement.querySelectorAll("a")){if(utils.getText(link).trim()==query){linkTextResult.push(link);if(firstResultOnly)
|
||||
break;}}
|
||||
if(firstResultOnly)
|
||||
return linkTextResult[0]||null;return linkTextResult;case"partial link text":let partialLinkResult=[];for(let link of ancestorElement.querySelectorAll("a")){if(utils.getText(link).includes(query)){partialLinkResult.push(link);if(firstResultOnly)
|
||||
break;}}
|
||||
if(firstResultOnly)
|
||||
return partialLinkResult[0]||null;return partialLinkResult;case"tag name":let tagNameResult=ancestorElement.getElementsByTagName(query);if(firstResultOnly)
|
||||
return tagNameResult[0]||null;return Array.from(tagNameResult);case"class name":let classNameResult=ancestorElement.getElementsByClassName(query);if(firstResultOnly)
|
||||
return classNameResult[0]||null;return Array.from(classNameResult);case"xpath":if(firstResultOnly){let xpathResult=document.evaluate(query,ancestorElement,null,XPathResult.FIRST_ORDERED_NODE_TYPE,null);if(!xpathResult)
|
||||
return null;return xpathResult.singleNodeValue;}
|
||||
let xpathResult=document.evaluate(query,ancestorElement,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);if(!xpathResult||!xpathResult.snapshotLength)
|
||||
return[];let arrayResult=[];for(let i=0;i<xpathResult.snapshotLength;++i)
|
||||
arrayResult.push(xpathResult.snapshotItem(i));return arrayResult;}}catch(error){
|
||||
throw{name:"InvalidSelector",message:error.message};}}
|
||||
const pollInterval=50;let pollUntil=performance.now()+timeoutDuration;function pollForNode(){let result=tryToFindNode();if(typeof result==="string"||result instanceof Node||(result instanceof Array&&result.length)){callback(result);return;}
|
||||
let durationRemaining=pollUntil-performance.now();if(durationRemaining<pollInterval){callback(firstResultOnly?null:[]);return;}
|
||||
setTimeout(pollForNode,pollInterval);}
|
||||
pollForNode();}
|
||||
14
27.0/js/automation/WDFindNodes.js
Normal file
14
27.0/js/automation/WDFindNodes.js
Normal file
@@ -0,0 +1,14 @@
|
||||
//# sourceURL=__InjectedScript_WDFindNodes.js
|
||||
function(element){"use strict";function isEditable(element){if(element.disabled||element.readOnly)
|
||||
return false;if(element instanceof HTMLTextAreaElement)
|
||||
return true;if(element.isContentEditable)
|
||||
return true;if(element.tagName.toUpperCase()!="INPUT")
|
||||
return false;switch(element.type){case"color":case"date":case"datetime-local":case"email":case"file":case"month":case"number":case"password":case"range":case"search":case"tel":case"text":case"time":case"url":case"week":return true;}
|
||||
return false;}
|
||||
if(!isEditable(element))
|
||||
throw{name:"InvalidElementState",message:"Element must be user-editable in order to clear."};if(element.isContentEditable){if(element.innerHTML==="")
|
||||
return;element.focus();element.innerHTML="";element.blur();return;}
|
||||
function isResettableElementEmpty(element){if(element instanceof HTMLInputElement&&element.type=="file")
|
||||
return element.files.length==0;return element.value==="";}
|
||||
if(element.validity.valid&&isResettableElementEmpty(element))
|
||||
return;element.focus();element.value="";var event=document.createEvent("Event");event.initEvent("change",true,true);element.dispatchEvent(event);element.blur();}
|
||||
3
27.0/js/automation/WDFormElementClear.js
Normal file
3
27.0/js/automation/WDFormElementClear.js
Normal file
@@ -0,0 +1,3 @@
|
||||
//# sourceURL=__InjectedScript_WDFormElementClear.js
|
||||
function(element){for(let currentElement=element;currentElement&¤tElement!==document;currentElement=currentElement.parentNode){if(!(currentElement instanceof HTMLFormElement))
|
||||
continue;currentElement.submit();break;}}
|
||||
1
27.0/js/automation/WDFormSubmit.js
Normal file
1
27.0/js/automation/WDFormSubmit.js
Normal file
@@ -0,0 +1 @@
|
||||
//# sourceURL=__InjectedScript_WDFormSubmit.js
|
||||
410
27.0/js/automation/WebAutomationSessionProxy.js
Normal file
410
27.0/js/automation/WebAutomationSessionProxy.js
Normal file
@@ -0,0 +1,410 @@
|
||||
//# sourceURL=__InjectedScript_WebAutomationSessionProxy.js
|
||||
(function (sessionIdentifier, evaluate, createUUID, isValidNodeIdentifier) {
|
||||
const sessionNodePropertyName = "session-node-" + sessionIdentifier;
|
||||
let AutomationSessionProxy = class AutomationSessionProxy {
|
||||
constructor() {
|
||||
this._nodeToIdMap = new Map();
|
||||
this._idToNodeMap = new Map();
|
||||
}
|
||||
evaluateJavaScriptFunction(
|
||||
functionString,
|
||||
argumentStrings,
|
||||
expectsImplicitCallbackArgument,
|
||||
forceUserGesture,
|
||||
frameID,
|
||||
callbackID,
|
||||
resultCallback,
|
||||
callbackTimeout,
|
||||
) {
|
||||
this._execute(
|
||||
functionString,
|
||||
argumentStrings,
|
||||
expectsImplicitCallbackArgument,
|
||||
callbackTimeout,
|
||||
)
|
||||
.then((result) => {
|
||||
resultCallback(frameID, callbackID, this._jsonStringify(result));
|
||||
})
|
||||
.catch((error) => {
|
||||
resultCallback(frameID, callbackID, error);
|
||||
});
|
||||
}
|
||||
evaluateBidiScript(
|
||||
expression,
|
||||
awaitPromise,
|
||||
maxObjectDepth,
|
||||
frameID,
|
||||
callbackID,
|
||||
resultCallback,
|
||||
callbackTimeout,
|
||||
) {
|
||||
this._executeBidiScript(
|
||||
expression,
|
||||
awaitPromise,
|
||||
maxObjectDepth,
|
||||
callbackTimeout,
|
||||
)
|
||||
.then((result) => {
|
||||
resultCallback(frameID, callbackID, JSON.stringify(result));
|
||||
})
|
||||
.catch((error) => {
|
||||
resultCallback(frameID, callbackID, error);
|
||||
});
|
||||
}
|
||||
nodeForIdentifier(identifier) {
|
||||
this._clearStaleNodes();
|
||||
try {
|
||||
return this._nodeForIdentifier(identifier);
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
_execute(
|
||||
functionString,
|
||||
argumentStrings,
|
||||
expectsImplicitCallbackArgument,
|
||||
callbackTimeout,
|
||||
) {
|
||||
let timeoutPromise;
|
||||
let timeoutIdentifier = 0;
|
||||
if (callbackTimeout >= 0) {
|
||||
timeoutPromise = new Promise((resolve, reject) => {
|
||||
timeoutIdentifier = setTimeout(() => {
|
||||
reject({
|
||||
name: "JavaScriptTimeout",
|
||||
message: `script timed out after ${callbackTimeout}ms`,
|
||||
});
|
||||
}, callbackTimeout);
|
||||
});
|
||||
}
|
||||
let promise = new Promise((resolve, reject) => {
|
||||
let lines = functionString.split("\n");
|
||||
let prefixLines = [];
|
||||
while (lines && lines[0].startsWith("//")) {
|
||||
prefixLines.push(lines.shift());
|
||||
}
|
||||
functionString = lines.join("\n");
|
||||
let prefix = prefixLines.join("\n");
|
||||
if (prefix) prefix += "\n";
|
||||
let functionValue = evaluate(prefix + "(async " + functionString + ")");
|
||||
if (typeof functionValue !== "function")
|
||||
reject(new TypeError("Script did not evaluate to a function."));
|
||||
this._clearStaleNodes();
|
||||
let argumentValues = argumentStrings.map(this._jsonParse, this);
|
||||
if (expectsImplicitCallbackArgument) argumentValues.push(resolve);
|
||||
let resultPromise = functionValue.apply(null, argumentValues);
|
||||
let promises = [resultPromise];
|
||||
if (timeoutPromise) promises.push(timeoutPromise);
|
||||
Promise.race(promises)
|
||||
.then((result) => {
|
||||
if (!expectsImplicitCallbackArgument) {
|
||||
resolve(result);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
|
||||
let promises = [promise];
|
||||
if (timeoutPromise) promises.push(timeoutPromise);
|
||||
return Promise.race(promises).finally(() => {
|
||||
if (timeoutIdentifier) {
|
||||
clearTimeout(timeoutIdentifier);
|
||||
}
|
||||
});
|
||||
}
|
||||
_executeBidiScript(
|
||||
expression,
|
||||
awaitPromise,
|
||||
maxObjectDepth,
|
||||
callbackTimeout,
|
||||
) {
|
||||
let timeoutPromise;
|
||||
let timeoutIdentifier = 0;
|
||||
if (callbackTimeout >= 0) {
|
||||
timeoutPromise = new Promise((resolve, reject) => {
|
||||
timeoutIdentifier = setTimeout(() => {
|
||||
reject({
|
||||
name: "JavaScriptTimeout",
|
||||
message: `script timed out after ${callbackTimeout}ms`,
|
||||
});
|
||||
}, callbackTimeout);
|
||||
});
|
||||
}
|
||||
let promise = new Promise((resolve, reject) => {
|
||||
try {
|
||||
let result = globalThis.eval(expression);
|
||||
if (awaitPromise && result && typeof result.then === "function") {
|
||||
result.then(
|
||||
(value) => {
|
||||
let serializedValue = this.serializeBidiRemoteValue(
|
||||
value,
|
||||
maxObjectDepth,
|
||||
);
|
||||
resolve({ success: true, result: serializedValue });
|
||||
},
|
||||
(error) => {
|
||||
reject({
|
||||
success: false,
|
||||
error: {
|
||||
name: error.name,
|
||||
message: error.message,
|
||||
stack: error.stack,
|
||||
},
|
||||
});
|
||||
},
|
||||
);
|
||||
} else {
|
||||
let serializedValue = this.serializeBidiRemoteValue(
|
||||
result,
|
||||
maxObjectDepth,
|
||||
);
|
||||
resolve({ success: true, result: serializedValue });
|
||||
}
|
||||
} catch (error) {
|
||||
reject({
|
||||
success: false,
|
||||
error: {
|
||||
name: error.name,
|
||||
message: error.message,
|
||||
stack: error.stack,
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
let promises = [promise];
|
||||
if (timeoutPromise) promises.push(timeoutPromise);
|
||||
return Promise.race(promises).finally(() => {
|
||||
if (timeoutIdentifier) {
|
||||
clearTimeout(timeoutIdentifier);
|
||||
}
|
||||
});
|
||||
}
|
||||
_jsonParse(string) {
|
||||
if (!string) return undefined;
|
||||
return JSON.parse(string, (key, value) =>
|
||||
this._reviveJSONValue(key, value),
|
||||
);
|
||||
}
|
||||
_jsonStringify(value) {
|
||||
return JSON.stringify(this._jsonClone(value));
|
||||
}
|
||||
_reviveJSONValue(key, value) {
|
||||
if (value && typeof value === "object" && value[sessionNodePropertyName])
|
||||
return this._nodeForIdentifier(value[sessionNodePropertyName]);
|
||||
return value;
|
||||
}
|
||||
_isCollection(value) {
|
||||
switch (Object.prototype.toString.call(value)) {
|
||||
case "[object Arguments]":
|
||||
case "[object Array]":
|
||||
case "[object FileList]":
|
||||
case "[object HTMLAllCollection]":
|
||||
case "[object HTMLCollection]":
|
||||
case "[object HTMLFormControlsCollection]":
|
||||
case "[object HTMLOptionsCollection]":
|
||||
case "[object NodeList]":
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
_checkCyclic(value, stack = []) {
|
||||
function isCyclic(value, proxy, stack = []) {
|
||||
if (value === undefined || value === null) return false;
|
||||
if (
|
||||
typeof value === "boolean" ||
|
||||
typeof value === "number" ||
|
||||
typeof value === "string"
|
||||
)
|
||||
return false;
|
||||
if (value instanceof Node) return false;
|
||||
if (stack.includes(value)) return true;
|
||||
if (proxy._isCollection(value)) {
|
||||
stack.push(value);
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
if (isCyclic(value[i], proxy, stack)) return true;
|
||||
}
|
||||
stack.pop();
|
||||
return false;
|
||||
}
|
||||
stack.push(value);
|
||||
for (let property in value) {
|
||||
if (isCyclic(value[property], proxy, stack)) return true;
|
||||
}
|
||||
stack.pop();
|
||||
return false;
|
||||
}
|
||||
if (isCyclic(value, this))
|
||||
throw new TypeError("cannot serialize cyclic structures.");
|
||||
}
|
||||
_jsonClone(value) {
|
||||
if (value === undefined || value === null) return null;
|
||||
if (
|
||||
typeof value === "boolean" ||
|
||||
typeof value === "number" ||
|
||||
typeof value === "string"
|
||||
)
|
||||
return value;
|
||||
if (this._isCollection(value)) {
|
||||
this._checkCyclic(value);
|
||||
return [...value].map((item) => this._jsonClone(item));
|
||||
}
|
||||
if (value instanceof Node) return this._createNodeHandle(value);
|
||||
if (typeof value.toJSON === "function") return value.toJSON();
|
||||
let customObject = {};
|
||||
for (let property in value) {
|
||||
this._checkCyclic(value);
|
||||
customObject[property] = this._jsonClone(value[property]);
|
||||
}
|
||||
return customObject;
|
||||
}
|
||||
_createNodeHandle(node) {
|
||||
if (node.ownerDocument !== window.document || !node.isConnected)
|
||||
throw {
|
||||
name: "NodeNotFound",
|
||||
message: "Stale element found when trying to create the node handle",
|
||||
};
|
||||
return { [sessionNodePropertyName]: this._identifierForNode(node) };
|
||||
}
|
||||
_nodeForIdentifier(identifier) {
|
||||
if (!isValidNodeIdentifier(identifier))
|
||||
throw {
|
||||
name: "InvalidNodeIdentifier",
|
||||
message: "Node identifier '" + identifier + "' is invalid",
|
||||
};
|
||||
let node = this._idToNodeMap.get(identifier);
|
||||
if (node) return node;
|
||||
throw {
|
||||
name: "NodeNotFound",
|
||||
message: "Node with identifier '" + identifier + "' was not found",
|
||||
};
|
||||
}
|
||||
_identifierForNode(node) {
|
||||
let identifier = this._nodeToIdMap.get(node);
|
||||
if (identifier) return identifier;
|
||||
identifier = "node-" + createUUID();
|
||||
this._nodeToIdMap.set(node, identifier);
|
||||
this._idToNodeMap.set(identifier, node);
|
||||
return identifier;
|
||||
}
|
||||
_clearStaleNodes() {
|
||||
for (var [node, identifier] of this._nodeToIdMap) {
|
||||
const rootNode = node.getRootNode({ composed: true });
|
||||
if (rootNode !== document) {
|
||||
this._nodeToIdMap.delete(node);
|
||||
this._idToNodeMap.delete(identifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
serializeBidiRemoteValue(
|
||||
value,
|
||||
maxObjectDepth = 1,
|
||||
depth = 0,
|
||||
visitedObjects = new Set(),
|
||||
) {
|
||||
if (value === null) return { type: "null" };
|
||||
if (value === undefined) return { type: "undefined" };
|
||||
if (typeof value === "boolean") return { type: "boolean", value: value };
|
||||
if (typeof value === "string") return { type: "string", value: value };
|
||||
if (typeof value === "number") {
|
||||
if (isNaN(value)) return { type: "number", value: "NaN" };
|
||||
if (value === Infinity) return { type: "number", value: "Infinity" };
|
||||
if (value === -Infinity) return { type: "number", value: "-Infinity" };
|
||||
if (Object.is(value, -0)) return { type: "number", value: "-0" };
|
||||
return { type: "number", value: value };
|
||||
}
|
||||
if (typeof value === "bigint")
|
||||
return { type: "bigint", value: value.toString() };
|
||||
if (typeof value === "symbol") return { type: "symbol" };
|
||||
if (typeof value === "function") return { type: "function" };
|
||||
if (typeof value === "object" || typeof value === "function") {
|
||||
if (value === window)
|
||||
return {
|
||||
type: "window",
|
||||
value: { context: "context-id-placeholder" },
|
||||
};
|
||||
if (value instanceof Date)
|
||||
return { type: "date", value: value.toISOString() };
|
||||
if (value instanceof RegExp)
|
||||
return {
|
||||
type: "regexp",
|
||||
value: { pattern: value.source, flags: value.flags },
|
||||
};
|
||||
if (value instanceof Error) return { type: "error" };
|
||||
if (value instanceof Promise) return { type: "promise" };
|
||||
if (value instanceof Map) {
|
||||
let entries = [];
|
||||
for (let [k, v] of value.entries()) {
|
||||
entries.push({
|
||||
key: this.serializeBidiRemoteValue(
|
||||
k,
|
||||
maxObjectDepth,
|
||||
depth + 1,
|
||||
visitedObjects,
|
||||
),
|
||||
value: this.serializeBidiRemoteValue(
|
||||
v,
|
||||
maxObjectDepth,
|
||||
depth + 1,
|
||||
visitedObjects,
|
||||
),
|
||||
});
|
||||
}
|
||||
return { type: "map", value: entries };
|
||||
}
|
||||
if (value instanceof Set) {
|
||||
let items = [];
|
||||
for (let v of value.values())
|
||||
items.push(
|
||||
this.serializeBidiRemoteValue(
|
||||
v,
|
||||
maxObjectDepth,
|
||||
depth + 1,
|
||||
visitedObjects,
|
||||
),
|
||||
);
|
||||
return { type: "set", value: items };
|
||||
}
|
||||
if (value instanceof WeakMap) return { type: "weakmap" };
|
||||
if (value instanceof WeakSet) return { type: "weakset" };
|
||||
if (value instanceof ArrayBuffer) return { type: "arraybuffer" };
|
||||
if (ArrayBuffer.isView(value)) return { type: "typedarray" };
|
||||
if (visitedObjects.has(value)) return { type: "object", value: {} };
|
||||
if (depth >= maxObjectDepth) return { type: "object", value: {} };
|
||||
visitedObjects.add(value);
|
||||
try {
|
||||
if (Array.isArray(value)) {
|
||||
let serializedArray = [];
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
serializedArray[i] = this.serializeBidiRemoteValue(
|
||||
value[i],
|
||||
maxObjectDepth,
|
||||
depth + 1,
|
||||
visitedObjects,
|
||||
);
|
||||
}
|
||||
return { type: "array", value: serializedArray };
|
||||
} else {
|
||||
let serializedObject = {};
|
||||
let keys = Object.keys(value).sort();
|
||||
for (let i = 0; i < keys.length; ++i) {
|
||||
let key = keys[i];
|
||||
serializedObject[key] = this.serializeBidiRemoteValue(
|
||||
value[key],
|
||||
maxObjectDepth,
|
||||
depth + 1,
|
||||
visitedObjects,
|
||||
);
|
||||
}
|
||||
return { type: "object", value: serializedObject };
|
||||
}
|
||||
} finally {
|
||||
visitedObjects.delete(value);
|
||||
}
|
||||
}
|
||||
return { type: "undefined" };
|
||||
}
|
||||
};
|
||||
return new AutomationSessionProxy();
|
||||
});
|
||||
Reference in New Issue
Block a user