Bug 1274274 - Disassociate convertWrappedArguments from element store; r?automatedtester
Moved ElementManager#convertWrappedArguments to the
testing/marionette/element.js module scope and renamed it to fromJson.
MozReview-Commit-ID: JMTZcG0JSUE
--- a/testing/marionette/action.js
+++ b/testing/marionette/action.js
@@ -53,18 +53,19 @@ action.Chain.prototype.dispatchActions =
touchProvider) {
// Some touch events code in the listener needs to do ipc, so we can't
// share this code across chrome/content.
if (touchProvider) {
this.touchProvider = touchProvider;
}
this.elementManager = elementManager;
- let commandArray = elementManager.convertWrappedArguments(args, container);
this.container = container;
+ let commandArray = element.fromJson(
+ args, elementManager, container.frame, container.shadowRoot);
if (touchId == null) {
touchId = this.nextTouchId++;
}
if (!container.frame.document.createTouch) {
this.mouseEventsOnly = true;
}
--- a/testing/marionette/driver.js
+++ b/testing/marionette/driver.js
@@ -882,17 +882,17 @@ GeckoDriver.prototype.execute_ = functio
if (opts.sandboxName) {
sb = sandbox.augment(sb, new logging.Adapter(this.marionetteLog));
sb = sandbox.augment(sb, {global: sb});
sb = sandbox.augment(sb, new emulator.Adapter(this.emulator));
}
opts.timeout = timeout;
script = this.importedScripts.for(Context.CHROME).concat(script);
- let wargs = this.curBrowser.elementManager.convertWrappedArguments(args, {frame: sb.window});
+ let wargs = element.fromJson(args, this.curBrowser.elementManager, sb.window);
let evaluatePromise = evaluate.sandbox(sb, script, wargs, opts);
return evaluatePromise.then(res => this.curBrowser.elementManager.wrapValue(res));
}
};
/**
* Execute pure JavaScript. Used to execute simpletest harness tests,
* which are like mochitests only injected using Marionette.
@@ -907,17 +907,17 @@ GeckoDriver.prototype.executeJSScript =
filename: cmd.parameters.filename,
line: cmd.parameters.line,
async: cmd.parameters.async,
};
switch (this.context) {
case Context.CHROME:
let win = this.getCurrentWindow();
- let wargs = this.curBrowser.elementManager.convertWrappedArguments(args, {frame: win});
+ let wargs = element.fromJson(args, this.curBrowser.elementManager, win);
let harness = new simpletest.Harness(
win,
Context.CHROME,
this.marionetteLog,
scriptTimeout,
function() {},
this.testName);
--- a/testing/marionette/element.js
+++ b/testing/marionette/element.js
@@ -245,66 +245,16 @@ element.Store = class {
}
}
}
break;
}
return result;
}
-
- /**
- * Convert any ELEMENT references in 'args' to the actual elements
- *
- * @param object args
- * Arguments passed in by client
- * @param nsIDOMWindow, ShadowRoot container
- * The window and an optional shadow root that contains the element
- *
- * @returns object
- * Returns the objects passed in by the client, with the
- * reference IDs replaced by the actual elements.
- */
- convertWrappedArguments(args, container) {
- let converted;
- switch (typeof(args)) {
- case 'number':
- case 'string':
- case 'boolean':
- converted = args;
- break;
- case 'object':
- if (args == null) {
- converted = null;
- }
- else if (Object.prototype.toString.call(args) == '[object Array]') {
- converted = [];
- for (let i in args) {
- converted.push(this.convertWrappedArguments(args[i], container));
- }
- }
- else if (((typeof(args[element.LegacyKey]) === 'string') && args.hasOwnProperty(element.LegacyKey)) ||
- ((typeof(args[element.Key]) === 'string') &&
- args.hasOwnProperty(element.Key))) {
- let elementUniqueIdentifier = args[element.Key] ? args[element.Key] : args[element.LegacyKey];
- converted = this.get(elementUniqueIdentifier, container);
- if (converted == null) {
- throw new WebDriverError(`Unknown element: ${elementUniqueIdentifier}`);
- }
- }
- else {
- converted = {};
- for (let prop in args) {
- converted[prop] = this.convertWrappedArguments(args[prop], container);
- }
- }
- break;
- }
- return converted;
- }
};
/**
* Find a single element or a collection of elements starting at the
* document root or a given node.
*
* If |timeout| is above 0, an implicit search technique is used.
* This will wait for the duration of |timeout| for the element
@@ -701,16 +651,73 @@ element.makeWebElement = function(uuid)
};
element.generateUUID = function() {
let uuid = uuidGen.generateUUID().toString();
return uuid.substring(1, uuid.length - 1);
};
/**
+ * Convert any web elements in arbitrary objects to DOM elements by
+ * looking them up in the seen element store.
+ *
+ * @param {?} obj
+ * Arbitrary object containing web elements.
+ * @param {element.Store} seenEls
+ * Element store to use for lookup of web element references.
+ * @param {Window} win
+ * Window.
+ * @param {ShadowRoot} shadowRoot
+ * Shadow root.
+ *
+ * @return {?}
+ * Same object as provided by |obj| with the web elements replaced
+ * by DOM elements.
+ */
+element.fromJson = function(
+ obj, seenEls, win, shadowRoot = undefined) {
+ switch (typeof(obj)) {
+ case "boolean":
+ case "number":
+ case "string":
+ return obj;
+
+ case "object":
+ if (obj === null) {
+ return obj;
+ }
+
+ // arrays
+ else if (Array.isArray(obj)) {
+ return obj.map(e => element.fromJson(e, seenEls, win, shadowRoot));
+ }
+
+ // web elements
+ else if (Object.keys(obj).includes(element.Key) ||
+ Object.keys(obj).includes(element.LegacyKey)) {
+ let uuid = obj[element.Key] || obj[element.LegacyKey];
+ let el = seenEls.get(uuid, {frame: win, shadowRoot: shadowRoot});
+ if (!el) {
+ throw new WebDriverError(`Unknown element: ${uuid}`);
+ }
+ return el;
+ }
+
+ // arbitrary objects
+ else {
+ let rv = {};
+ for (let prop in obj) {
+ rv[prop] = element.fromJson(obj[prop], seenEls, win, shadowRoot);
+ }
+ return rv;
+ }
+ }
+};
+
+/**
* Check if the element is detached from the current frame as well as
* the optional shadow root (when inside a Shadow DOM context).
*
* @param {nsIDOMElement} el
* Element to be checked.
* @param nsIDOMWindow frame
* Window object that contains the element or the current host
* of the shadow root.
--- a/testing/marionette/listener.js
+++ b/testing/marionette/listener.js
@@ -521,17 +521,18 @@ function checkForInterrupted() {
}
}
function* execute(script, args, timeout, opts) {
opts.timeout = timeout;
script = importedScripts.for("content").concat(script);
let sb = sandbox.createMutable(curContainer.frame);
- let wargs = elementManager.convertWrappedArguments(args, curContainer);
+ let wargs = element.fromJson(
+ args, elementManager, curContainer.frame, curContainer.shadowRoot);
let res = yield evaluate.sandbox(sb, script, wargs, opts);
return elementManager.wrapValue(res);
}
function* executeInSandbox(script, args, timeout, opts) {
opts.timeout = timeout;
script = importedScripts.for("content").concat(script);
@@ -539,17 +540,18 @@ function* executeInSandbox(script, args,
let sb = sandboxes.get(opts.sandboxName, opts.newSandbox);
if (opts.sandboxName) {
sb = sandbox.augment(sb, {global: sb});
sb = sandbox.augment(sb, new logging.Adapter(contentLog));
let emulatorClient = new emulator.EmulatorServiceClient(asyncChrome);
sb = sandbox.augment(sb, new emulator.Adapter(emulatorClient));
}
- let wargs = elementManager.convertWrappedArguments(args, curContainer);
+ let wargs = element.fromJson(
+ args, elementManager, curContainer.frame, curContainer.shadowRoot);
let evaluatePromise = evaluate.sandbox(sb, script, wargs, opts);
let res = yield evaluatePromise;
sendSyncMessage("Marionette:shareData", {log: elementManager.wrapValue(contentLog.get())});
return elementManager.wrapValue(res);
}
function* executeSimpleTest(script, args, timeout, opts) {
@@ -562,17 +564,18 @@ function* executeSimpleTest(script, args
"content",
contentLog,
timeout,
marionetteTestName);
let sb = sandbox.createSimpleTest(curContainer.frame, harness);
// TODO(ato): Not sure this is needed:
sb = sandbox.augment(sb, new logging.Adapter(contentLog));
- let wargs = elementManager.convertWrappedArguments(args, curContainer);
+ let wargs = element.fromJson(
+ args, elementManager, curContainer.frame, curContainer.shadowRoot);
let evaluatePromise = evaluate.sandbox(sb, script, wargs, opts);
let res = yield evaluatePromise;
sendSyncMessage("Marionette:shareData", {log: elementManager.wrapValue(contentLog.get())});
return elementManager.wrapValue(res);
}
/**
@@ -840,17 +843,18 @@ function setDispatch(batches, touches, b
/**
* Start multi-action.
*
* @param {Number} maxLen
* Longest action chain for one finger.
*/
function multiAction(args, maxLen) {
// unwrap the original nested array
- let commandArray = elementManager.convertWrappedArguments(args, curContainer);
+ let commandArray = element.fromJson(
+ args, elementManager, curContainer.frame, curContainer.shadowRoot);
let concurrentEvent = [];
let temp;
for (let i = 0; i < maxLen; i++) {
let row = [];
for (let j = 0; j < commandArray.length; j++) {
if (typeof commandArray[j][i] != "undefined") {
// add finger id to the front of each action, i.e. [finger_id, action, element]
temp = commandArray[j][i];