Bug 720619 - Run the [[DefaultValue]] algorithm on the wrapper if subsumes fails. r=bz,ejbruel,luke a=akeybl
authorBobby Holley <bobbyholley@gmail.com>
Thu, 11 Oct 2012 12:54:44 -0400
changeset 82022 ebffbd29624cc2ac1007c5b17059d8eb5f9f5164
parent 82020 2d169702fd28d97b21d9333f01ce1427526915d4
child 82023 863bac88c122b54f68b5b7f662a946e3e17201f6
push id293
push useramccreight@mozilla.com
push dateThu, 11 Oct 2012 16:56:13 +0000
reviewersbz, ejbruel, luke, akeybl
bugs720619
milestone10.0.9esrpre
Bug 720619 - Run the [[DefaultValue]] algorithm on the wrapper if subsumes fails. r=bz,ejbruel,luke a=akeybl
js/src/jswrapper.cpp
js/xpconnect/tests/chrome/Makefile.in
js/xpconnect/tests/chrome/test_bug720619.xul
js/xpconnect/tests/mochitest/Makefile.in
js/xpconnect/tests/mochitest/file_bug720619.html
js/xpconnect/tests/mochitest/test_bug720619.html
--- a/js/src/jswrapper.cpp
+++ b/js/src/jswrapper.cpp
@@ -332,17 +332,33 @@ Wrapper::fun_toString(JSContext *cx, JSO
     JSString *str = ProxyHandler::fun_toString(cx, wrapper, indent);
     leave(cx, wrapper);
     return str;
 }
 
 bool
 Wrapper::defaultValue(JSContext *cx, JSObject *wrapper, JSType hint, Value *vp)
 {
-    *vp = ObjectValue(*wrappedObject(wrapper));
+    // If the wrapper doesn't subsume the wrapped object, run the default value
+    // algorithm on the wrapper itself. If it does, unwrap and process the
+    // underlying object.
+    JSObject *wrapped = wrappedObject(wrapper);
+    JSPrincipals *wrapperPrincipals = wrapper->compartment()->principals;
+    JSPrincipals *wrappedPrincipals = wrapped->compartment()->principals;
+    if (!wrapperPrincipals || !wrappedPrincipals ||
+        !wrapperPrincipals->subsume(wrapperPrincipals, wrappedPrincipals))
+    {
+        return DefaultValue(cx, wrapper, hint, vp);
+    }
+
+    AutoCompartment call(cx, wrapped);
+    if (!call.enter())
+        return false;
+
+    *vp = ObjectValue(*wrapped);
     if (hint == JSTYPE_VOID)
         return ToPrimitive(cx, vp);
     return ToPrimitive(cx, hint, vp);
 }
 
 void
 Wrapper::trace(JSTracer *trc, JSObject *wrapper)
 {
@@ -825,25 +841,22 @@ CrossCompartmentWrapper::fun_toString(JS
     if (!call.origin->wrap(cx, &str))
         return NULL;
     return str;
 }
 
 bool
 CrossCompartmentWrapper::defaultValue(JSContext *cx, JSObject *wrapper, JSType hint, Value *vp)
 {
-    AutoCompartment call(cx, wrappedObject(wrapper));
-    if (!call.enter())
-        return false;
-
+    // We don't want to enter the compartment yet. Wrapper::defaultValue will
+    // decide whether to do that or not.
     if (!Wrapper::defaultValue(cx, wrapper, hint, vp))
         return false;
 
-    call.leave();
-    return call.origin->wrap(cx, vp);
+    return cx->compartment->wrap(cx, vp);
 }
 
 void
 CrossCompartmentWrapper::trace(JSTracer *trc, JSObject *wrapper)
 {
     MarkCrossCompartmentObject(trc, *wrappedObject(wrapper), "wrappedObject");
 }
 
--- a/js/xpconnect/tests/chrome/Makefile.in
+++ b/js/xpconnect/tests/chrome/Makefile.in
@@ -63,16 +63,17 @@ include $(topsrcdir)/config/rules.mk
 		test_bug614757.xul \
 		test_bug616992.xul \
 		test_bug618176.xul \
 		file_bug618176.xul \
 		test_bug596580.xul \
 		test_bug654370.xul \
 		test_bug658560.xul \
 		test_bug679861.xul \
+		test_bug720619.xul \
 		test_bug760109.xul \
 		test_APIExposer.xul \
 		test_bug664689.xul \
 		test_precisegc.xul \
 		test_nodelists.xul \
 		test_getweakmapkeys.xul \
 		$(NULL)
 
new file mode 100644
--- /dev/null
+++ b/js/xpconnect/tests/chrome/test_bug720619.xul
@@ -0,0 +1,50 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+                 type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=720619
+-->
+<window title="Mozilla Bug 720619"
+  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <!-- test results are displayed in the html:body -->
+  <body xmlns="http://www.w3.org/1999/xhtml">
+  <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=720619"
+     target="_blank">Mozilla Bug 720619</a>
+
+  <!-- test code goes here -->
+  <script type="application/javascript"><![CDATA[
+  /** Test for Bug 720619 **/
+  const Cu = Components.utils;
+
+  var obj = {
+    __exposedProps__: {},
+    valueOf: function () {
+      return 42;
+    },
+    toString: function () {
+      return 'str';
+    }
+  };
+
+  var content = new Cu.Sandbox("about:blank");
+  content.obj = obj;
+
+  ok(Cu.evalInSandbox("obj + ''", content) == "[object Object]");
+  ok(Cu.evalInSandbox("'' + obj", content) == "[object Object]");
+  ok(isNaN(Cu.evalInSandbox("obj - 0", content)));
+  ok(Cu.evalInSandbox("String(obj)", content) == "[object Object]");
+
+  var chrome = new Cu.Sandbox(window);
+  chrome.obj = obj;
+
+  ok(Cu.evalInSandbox("obj + ''", chrome) == "42");
+  ok(Cu.evalInSandbox("'' + obj", chrome) == "42");
+  ok(Cu.evalInSandbox("obj - 0", chrome) == 42);
+  ok(Cu.evalInSandbox("String(obj)", chrome) == "str");
+  ]]></script>
+  </body>
+</window>
--- a/js/xpconnect/tests/mochitest/Makefile.in
+++ b/js/xpconnect/tests/mochitest/Makefile.in
@@ -89,16 +89,18 @@ include $(topsrcdir)/config/rules.mk
 		test_bug618017.html \
 		test_bug636097.html \
 		test_bug661980.html \
 		test_bug650273.html \
 		file_bug650273.html \
 		file_bug658560.html \
 		test_bug655297.html \
 		test_bug691059.html \
+		test_bug720619.html \
+		file_bug720619.html \
 		file_nodelists.html \
 		$(NULL)
 
 _CHROME_FILES	= \
 		test_bug361111.xul \
 		$(NULL)
 
 ifneq ($(OS_TARGET),Android)
new file mode 100644
--- /dev/null
+++ b/js/xpconnect/tests/mochitest/file_bug720619.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <script>
+            valueOf = function() { return "v"; }
+            toString = function() { return "s"; }
+        </script>
+    </head>
+    <body></body>
+</html>
new file mode 100644
--- /dev/null
+++ b/js/xpconnect/tests/mochitest/test_bug720619.html
@@ -0,0 +1,55 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=720619
+-->
+<head>
+  <title>Test for Bug 629227</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=720619">Mozilla Bug 720619</a>
+<p id="display">
+  <iframe id="testTarget"></iframe>
+</p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 720619 **/
+SimpleTest.waitForExplicitFinish();
+
+function checkThrows(f, exception) {
+    try {
+        f();
+        ok(false, "should have thrown: " + f);
+    } catch (e) {
+        ok(exception.test(e.toString()), "correctly threw");
+    }
+}
+
+function go() {
+    var loc = $('ifr').contentWindow.location;
+    checkThrows(function() {loc + '';}, /Permission denied/);
+    checkThrows(function() {'' + loc;}, /Permission denied/);
+    checkThrows(function() {String(loc);}, /Permission denied/);
+
+    var win = $('ifr').contentWindow;
+    checkThrows(function() {win + '';}, /Permission denied/);
+    checkThrows(function() {'' + win;}, /Permission denied/);
+    checkThrows(function() {String(win);}, /Permission denied/);
+
+    SimpleTest.finish();
+}
+
+</script>
+
+<iframe id="ifr" onload="go()"
+        src="http://example.org/tests/js/xpconnect/tests/mochitest/file_bug720619.html">
+</iframe>
+</pre>
+</body>
+</html>