Skip to content

Commit c86d229

Browse files
committed
Fixing legacy Firefox driver (and atoms) to throw proper exception on an attempt to return recursive object.
1 parent e4ad062 commit c86d229

File tree

4 files changed

+80
-65
lines changed

4 files changed

+80
-65
lines changed

java/client/test/org/openqa/selenium/ExecutingJavascriptTest.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
import static org.junit.Assert.fail;
3333
import static org.junit.Assume.assumeTrue;
3434
import static org.openqa.selenium.testing.Driver.CHROME;
35-
import static org.openqa.selenium.testing.Driver.FIREFOX;
3635
import static org.openqa.selenium.testing.Driver.HTMLUNIT;
3736
import static org.openqa.selenium.testing.Driver.IE;
3837
import static org.openqa.selenium.testing.Driver.MARIONETTE;
@@ -566,7 +565,6 @@ public void shouldHandleObjectThatThatHaveToJSONMethod() {
566565
@Ignore(CHROME)
567566
@Ignore(value = IE, issue = "540")
568567
@Ignore(SAFARI)
569-
@Ignore(value = FIREFOX, issue = "540")
570568
@Ignore(HTMLUNIT)
571569
public void shouldHandleRecursiveStructures() {
572570
driver.get(pages.simpleTestPage);

javascript/atoms/inject.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ bot.inject.wrapValue = function(value) {
121121
// a ton of compiler warnings.
122122
value = /**@type {!Object}*/ (value);
123123
if (seen.indexOf(value) >= 0) {
124-
throw new bot.Error(bot.ErrorCode.UNKNOWN_ERROR,
124+
throw new bot.Error(bot.ErrorCode.JAVASCRIPT_ERROR,
125125
'Recursive object cannot be transferred');
126126
}
127127

javascript/firefox-driver/js/firefoxDriver.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,11 @@ function injectAndExecuteScript(respond, parameters, isAsync, timer) {
306306
}
307307

308308
var result = unwrappedDoc['__webdriver_evaluate']['result'];
309-
respond.value = Utils.wrapResult(result, doc);
309+
try {
310+
respond.value = Utils.wrapResult(result, doc);
311+
} catch (e) {
312+
respond.sendError(new WebDriverError(bot.ErrorCode.JAVASCRIPT_ERROR, e));
313+
}
310314
respond.status = unwrappedDoc['__webdriver_evaluate']['code'];
311315

312316
// I have no idea why this started happening. Roll on m-day

javascript/firefox-driver/js/utils.js

Lines changed: 74 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -822,83 +822,96 @@ Utils.unwrapParameters = function(wrappedParameters, doc) {
822822

823823

824824
Utils.wrapResult = function(result, doc) {
825-
result = fxdriver.moz.unwrap(result);
825+
var _wrap = function(result, doc, seen) {
826+
result = fxdriver.moz.unwrap(result);
826827

827-
// Sophisticated.
828-
switch (typeof result) {
829-
case 'string':
830-
case 'number':
831-
case 'boolean':
832-
return result;
833-
834-
case 'function':
835-
return result.toString();
828+
// Sophisticated.
829+
switch (typeof result) {
830+
case 'string':
831+
case 'number':
832+
case 'boolean':
833+
return result;
836834

837-
case 'undefined':
838-
return null;
835+
case 'function':
836+
return result.toString();
839837

840-
case 'object':
841-
if (result == null) {
838+
case 'undefined':
842839
return null;
843-
}
844840

845-
// There's got to be a more intelligent way of detecting this.
846-
if (result.nodeType == 1 && result['tagName']) {
847-
return {'ELEMENT': Utils.addToKnownElements(result)};
848-
}
841+
case 'object':
842+
if (result == null) {
843+
return null;
844+
}
849845

850-
if (typeof result.getMonth === 'function') {
851-
return result.toJSON();
852-
}
846+
if (seen.indexOf(result) >= 0) {
847+
throw new bot.Error(bot.ErrorCode.JAVASCRIPT_ERROR,
848+
'Recursive object cannot be transferred');
849+
}
853850

854-
if (typeof result.length === 'number' &&
855-
!(result.propertyIsEnumerable('length'))) {
856-
var array = [];
857-
for (var i = 0; i < result.length; i++) {
858-
array.push(Utils.wrapResult(result[i], doc));
851+
// There's got to be a more intelligent way of detecting this.
852+
if (result.nodeType == 1 && result['tagName']) {
853+
return {'ELEMENT': Utils.addToKnownElements(result)};
859854
}
860-
return array;
861-
}
862855

863-
// Document. Grab the document element.
864-
if (result.nodeType == 9) {
865-
return Utils.wrapResult(result.documentElement);
866-
}
856+
if (typeof result.getMonth === 'function') {
857+
return result.toJSON();
858+
}
867859

868-
try {
869-
var nodeList = result.QueryInterface(CI.nsIDOMNodeList);
870-
var array = [];
871-
for (var i = 0; i < nodeList.length; i++) {
872-
array.push(Utils.wrapResult(result.item(i), doc));
860+
seen.push(result);
861+
862+
if (typeof result.length === 'number' &&
863+
!(result.propertyIsEnumerable('length'))) {
864+
var array = [];
865+
for (var i = 0; i < result.length; i++) {
866+
array.push(_wrap(result[i], doc, seen));
867+
}
868+
return array;
869+
}
870+
871+
// Document. Grab the document element.
872+
if (result.nodeType == 9) {
873+
return _wrap(result.documentElement, doc, seen);
873874
}
874-
return array;
875-
} catch (ignored) {
876-
goog.log.warning(Utils.LOG_, 'Error wrapping NodeList', ignored);
877-
}
878875

879-
try {
880-
// There's got to be a better way, but 'result instanceof Error' returns false
881-
if (Object.getPrototypeOf(result) != null && goog.string.endsWith(Object.getPrototypeOf(result).toString(), 'Error')) {
882-
try {
883-
return fxdriver.error.toJSON(result);
884-
} catch (ignored2) {
885-
goog.log.info(Utils.LOG_, 'Error', ignored2);
886-
return result.toString();
876+
var nodeList;
877+
try {
878+
nodeList = result.QueryInterface(CI.nsIDOMNodeList);
879+
} catch (ignored) {
880+
}
881+
if (nodeList) {
882+
var array = [];
883+
for (var i = 0; i < nodeList.length; i++) {
884+
array.push(_wrap(result.item(i), doc, seen));
887885
}
886+
return array;
888887
}
889-
} catch (ignored) {
890-
goog.log.info(Utils.LOG_, 'Error', ignored);
891-
}
892888

893-
var convertedObj = {};
894-
for (var prop in result) {
895-
convertedObj[prop] = Utils.wrapResult(result[prop], doc);
896-
}
897-
return convertedObj;
889+
try {
890+
// There's got to be a better way, but 'result instanceof Error' returns false
891+
if (Object.getPrototypeOf(result) != null && goog.string.endsWith(
892+
Object.getPrototypeOf(result).toString(), 'Error')) {
893+
try {
894+
return fxdriver.error.toJSON(result);
895+
} catch (ignored2) {
896+
goog.log.info(Utils.LOG_, 'Error', ignored2);
897+
return result.toString();
898+
}
899+
}
900+
} catch (ignored) {
901+
goog.log.info(Utils.LOG_, 'Error', ignored);
902+
}
898903

899-
default:
900-
return result;
901-
}
904+
var convertedObj = {};
905+
for (var prop in result) {
906+
convertedObj[prop] = _wrap(result[prop], doc, seen);
907+
}
908+
return convertedObj;
909+
910+
default:
911+
return result;
912+
}
913+
};
914+
return _wrap(result, doc, []);
902915
};
903916

904917

0 commit comments

Comments
 (0)