Bug 1033927 - Drop support for custom [object XrayWrapper [object ClassName]] stringification. r=peterv
authorBobby Holley <bobbyholley@gmail.com>
Mon, 07 Jul 2014 13:11:24 -0700
changeset 213532 74c612bb014700b7953162aa4bb1e1c175c3f1f5
parent 213531 33082e3bfed9b198a3bb7577696f135226a56f4b
child 213533 5d696c6fe0a7d44afa8955d08fc0e7dc1d80cb3c
push id3857
push userraliiev@mozilla.com
push dateTue, 02 Sep 2014 16:39:23 +0000
treeherdermozilla-beta@5638b907b505 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspeterv
bugs1033927
milestone33.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1033927 - Drop support for custom [object XrayWrapper [object ClassName]] stringification. r=peterv
dom/bindings/BindingUtils.cpp
dom/bindings/BindingUtils.h
dom/tests/mochitest/chrome/test_sandbox_bindings.xul
js/xpconnect/tests/chrome/test_nodelists.xul
js/xpconnect/tests/unit/test_bug1033927.js
js/xpconnect/tests/unit/xpcshell.ini
js/xpconnect/wrappers/XrayWrapper.cpp
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -1593,18 +1593,17 @@ ConcatJSString(JSContext* cx, const char
     return nullptr;
   }
 
   return JS_ConcatStrings(cx, preString, postString);
 }
 
 bool
 NativeToString(JSContext* cx, JS::Handle<JSObject*> wrapper,
-               JS::Handle<JSObject*> obj, const char* pre,
-               const char* post,
+               JS::Handle<JSObject*> obj,
                JS::MutableHandle<JS::Value> v)
 {
   JS::Rooted<JSPropertyDescriptor> toStringDesc(cx);
   toStringDesc.object().set(nullptr);
   toStringDesc.setAttributes(0);
   toStringDesc.setGetter(nullptr);
   toStringDesc.setSetter(nullptr);
   toStringDesc.value().set(JS::UndefinedValue());
@@ -1639,17 +1638,16 @@ NativeToString(JSContext* cx, JS::Handle
         const DOMIfaceAndProtoJSClass* ifaceAndProtoJSClass =
           DOMIfaceAndProtoJSClass::FromJSClass(clasp);
         str = JS_NewStringCopyZ(cx, ifaceAndProtoJSClass->mToString);
       } else {
         MOZ_ASSERT(JS_IsNativeFunction(obj, Constructor));
         JS::Rooted<JSFunction*> fun(cx, JS_GetObjectFunction(obj));
         str = JS_DecompileFunction(cx, fun, 0);
       }
-      str = ConcatJSString(cx, pre, str, post);
     }
   }
 
   if (!str) {
     return false;
   }
 
   v.setString(str);
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -2380,24 +2380,21 @@ MustInheritFromNonRefcountedDOMObject(No
  * obj should create according to the WebIDL specification, ignoring any
  * modifications by script. The value is prefixed with pre and postfixed with
  * post, unless this is called for an object that has a stringifier. It is
  * specifically for use by Xray code.
  *
  * wrapper is the Xray JS object.
  * obj is the target object of the Xray, a binding's instance object or a
  *     interface or interface prototype object.
- * pre is a string that should be prefixed to the value.
- * post is a string that should be prefixed to the value.
  * v contains the JSString for the value if the function returns true.
  */
 bool
 NativeToString(JSContext* cx, JS::Handle<JSObject*> wrapper,
-               JS::Handle<JSObject*> obj, const char* pre,
-               const char* post,
+               JS::Handle<JSObject*> obj,
                JS::MutableHandle<JS::Value> v);
 
 HAS_MEMBER(JSBindingFinalized)
 
 template<class T, bool hasCallback=HasJSBindingFinalizedMember<T>::Value>
 struct JSBindingFinalized
 {
   static void Finalized(T* self)
--- a/dom/tests/mochitest/chrome/test_sandbox_bindings.xul
+++ b/dom/tests/mochitest/chrome/test_sandbox_bindings.xul
@@ -29,17 +29,17 @@ https://bugzilla.mozilla.org/show_bug.cg
     function doTest() {
       var win = $("t").contentWindow;
       var sandbox = Components.utils.Sandbox(win, { sandboxPrototype: win });
 
       is(sandbox._content, undefined, "_content does nothing over Xray");
 
       try {
         var css = Components.utils.evalInSandbox("CSSStyleDeclaration", sandbox);
-        is(css.prototype, "[object XrayWrapper [object CSSStyleDeclarationPrototype]]", "'CSSStyleDeclaration.prototype' in a sandbox should return the CSSStyleDeclaration interface prototype object");
+        is(css.prototype, "[object CSSStyleDeclarationPrototype]", "'CSSStyleDeclaration.prototype' in a sandbox should return the CSSStyleDeclaration interface prototype object");
       } catch (e) {
         ok(false, "'CSSStyleDeclaration' shouldn't throw in a sandbox");
       }
       try {
         var et = Components.utils.evalInSandbox("EventTarget", sandbox);
         ok(et, "'EventTarget' in a sandbox should return the EventTarget interface object");
         ok(isXrayWrapper(et), "Getting an interface object on an Xray wrapper should return an Xray wrapper");
       } catch (e) {
@@ -89,38 +89,38 @@ https://bugzilla.mozilla.org/show_bug.cg
       try {
         var xhr = Components.utils.evalInSandbox("XMLHttpRequest.prototype", sandbox);
         delete xhr.constructor;
       } catch (e) {
         is(xhr.constructor, undefined, "'XMLHttpRequest.prototype.constructor' should be permanent");
       }
       try {
         var xhr = Components.utils.evalInSandbox("XMLHttpRequest", sandbox);
-        is(xhr, "[object XrayWrapper " + XMLHttpRequest + "]", "'XMLHttpRequest' in a sandbox should return the XMLHttpRequest interface object");
+        is(xhr, XMLHttpRequest + "", "'XMLHttpRequest' in a sandbox should return the XMLHttpRequest interface object");
         ok(isXrayWrapper(xhr.prototype), "Getting the prototype property on an Xray wrapper of an interface object should return an Xray wrapper");
         isnot(Object.getOwnPropertyDescriptor(xhr, "UNSENT"), undefined,
               "We should claim to have an UNSENT constant");
         isnot(Object.keys(xhr).indexOf("OPENED"), -1,
               "We should claim to have an OPENED constant");
         isnot(Object.getOwnPropertyNames(xhr).indexOf("DONE"), -1,
               "We should claim to have a DONE constant");
         isnot(Object.getOwnPropertyDescriptor(xhr, "prototype"), undefined,
               "We should claim to have 'prototype' property");
       } catch (e) {
         ok(false, "'XMLHttpRequest' shouldn't throw in a sandbox");
       }
       try {
         var xhr = Components.utils.evalInSandbox("new XMLHttpRequest()", sandbox);
-        is("" + xhr, "[object XrayWrapper " + new XMLHttpRequest() + "]", "'XMLHttpRequest()' in a sandbox should create an XMLHttpRequest object");
+        is("" + xhr, new XMLHttpRequest() + "", "'XMLHttpRequest()' in a sandbox should create an XMLHttpRequest object");
       } catch (e) {
         ok(false, "'new XMLHttpRequest()' shouldn't throw in a sandbox (1)");
       }
       try {
         var xhr = Components.utils.evalInSandbox("XMLHttpRequest.prototype.toString = function () { return 'Failed'; }; new XMLHttpRequest();", sandbox);
-        is(xhr.toString(), "[object XrayWrapper " + new XMLHttpRequest() + "]", "XMLHttpRequest.prototype.toString in the sandbox should not override the native toString behaviour");
+        is(xhr.toString(), new XMLHttpRequest() + "", "XMLHttpRequest.prototype.toString in the sandbox should not override the native toString behaviour");
       } catch (e) {
         ok(false, "'new XMLHttpRequest()' shouldn't throw in a sandbox (2)");
       }
 
       try {
         // have to run this test before document.defaultView.XMLHttpRequest
         // gets munged in the sandbox.
         var proto = Components.utils.evalInSandbox("XMLHttpRequest.prototype", sandbox);
@@ -136,17 +136,17 @@ https://bugzilla.mozilla.org/show_bug.cg
       } catch (e) {
         ok(false, "XMLHttpRequest.prototype manipulation via an Xray shouldn't throw" + e);
       }
 
       try {
         Components.utils.evalInSandbox("document.defaultView.XMLHttpRequest = function() {};", sandbox);
         var win = Components.utils.evalInSandbox("document.defaultView", sandbox);
         var xhr = new win.XMLHttpRequest();
-        is("" + xhr, "[object XrayWrapper " + new XMLHttpRequest() + "]", "'XMLHttpRequest()' in a sandbox should create an XMLHttpRequest object");
+        is("" + xhr, new XMLHttpRequest() + "", "'XMLHttpRequest()' in a sandbox should create an XMLHttpRequest object");
       } catch (e) {
         ok(false, "'XMLHttpRequest()' shouldn't throw in a sandbox");
       }
       try {
         var canvas = Components.utils.evalInSandbox("document.createElement('canvas').getContext('2d')", sandbox);
         is(canvas.DRAWWINDOW_DRAW_CARET, CanvasRenderingContext2D.DRAWWINDOW_DRAW_CARET, "Constants should be defined on DOM objects in a sandbox");
       } catch (e) {
         ok(false, "'document.createElement('canvas').getContext('2D')' shouldn't throw in a sandbox");
--- a/js/xpconnect/tests/chrome/test_nodelists.xul
+++ b/js/xpconnect/tests/chrome/test_nodelists.xul
@@ -21,17 +21,17 @@
         var win = $('ifr').contentWindow;
         var list = win.document.getElementsByTagName('p');
         is(list.length, 3, "can get the length");
         ok(list[0].toString().indexOf("[object HTMLParagraphElement") >= 0, "can get list[0]");
         is(list[0], list.item(0), "list.item works");
         is(list.item, list.item, "don't recreate functions for each get");
 
         var list2 = list[2];
-        ok(list[2].toString().indexOf("[object HTMLParagraphElement"), "list[2] exists");
+        ok(list[2].toString().indexOf("[object HTMLParagraphElement") >= 0, "list[2] exists");
         ok("2" in list, "in operator works");
 
         is(win.document.body.removeChild(win.document.body.lastChild), list2, "remove last paragraph element");
         ok(!("2" in list), "in operator doesn't see phantom element");
         is(list[2], undefined, "no node there!");
         SimpleTest.finish();
       }
   ]]></script>
new file mode 100644
--- /dev/null
+++ b/js/xpconnect/tests/unit/test_bug1033927.js
@@ -0,0 +1,8 @@
+const Cu = Components.utils;
+function run_test() {
+  var sb = Cu.Sandbox('http://www.example.com', { wantGlobalProperties: ['XMLHttpRequest']});
+  var xhr = Cu.evalInSandbox('new XMLHttpRequest()', sb);
+  do_check_eq(xhr.toString(), '[object XMLHttpRequest]');
+  do_check_eq((new sb.Object()).toString(), '[object Object]');
+  do_check_eq((new sb.Uint16Array()).toString(), '[object Uint16Array]');
+}
--- a/js/xpconnect/tests/unit/xpcshell.ini
+++ b/js/xpconnect/tests/unit/xpcshell.ini
@@ -40,16 +40,17 @@ support-files =
 [test_bug872772.js]
 [test_bug885800.js]
 [test_bug961054.js]
 [test_bug976151.js]
 [test_bug1001094.js]
 [test_bug1021312.js]
 [test_bug1033253.js]
 [test_bug1033920.js]
+[test_bug1033927.js]
 [test_bug_442086.js]
 [test_file.js]
 [test_blob.js]
 [test_blob2.js]
 [test_file2.js]
 [test_import.js]
 [test_import_fail.js]
 [test_isModuleLoaded.js]
--- a/js/xpconnect/wrappers/XrayWrapper.cpp
+++ b/js/xpconnect/wrappers/XrayWrapper.cpp
@@ -2095,21 +2095,21 @@ XrayToString(JSContext *cx, unsigned arg
     }
     if (!IsWrapper(wrapper) || !WrapperFactory::IsXrayWrapper(wrapper)) {
         JS_ReportError(cx, "XrayToString called on an incompatible object");
         return false;
     }
 
     RootedObject obj(cx, XrayTraits::getTargetObject(wrapper));
 
+    if (UseDOMXray(obj))
+        return NativeToString(cx, wrapper, obj, args.rval());
+
     static const char start[] = "[object XrayWrapper ";
     static const char end[] = "]";
-    if (UseDOMXray(obj))
-        return NativeToString(cx, wrapper, obj, start, end, args.rval());
-
     nsAutoString result;
     result.AppendASCII(start);
 
     XPCCallContext ccx(JS_CALLER, cx, obj);
     XPCWrappedNative *wn = XPCWrappedNativeXrayTraits::getWN(wrapper);
     char *wrapperStr = wn->ToString();
     if (!wrapperStr) {
         JS_ReportOutOfMemory(cx);