Bug 1306472. Back out bug 1268047, because the spec it tried to implement backs the web. r=smaug
authorBoris Zbarsky <bzbarsky@mit.edu>
Thu, 13 Oct 2016 12:10:23 -0400
changeset 317886 0f5505bf10d26af2841ac99767677405334f7e59
parent 317885 559fa765dbf12c5f042debfa64f735e1f3c9a1d3
child 317887 1ae11d588928b3e328fa3ab46142ee71d569c09b
push id33170
push usercbook@mozilla.com
push dateFri, 14 Oct 2016 10:37:07 +0000
treeherderautoland@0d101ebfd95c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1306472, 1268047
milestone52.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 1306472. Back out bug 1268047, because the spec it tried to implement backs the web. r=smaug
dom/base/nsJSUtils.cpp
dom/base/nsJSUtils.h
dom/jsurl/nsJSProtocolHandler.cpp
testing/web-platform/tests/html/browsers/browsing-the-web/navigating-across-documents/javascript-url-return-value-handling.html
--- a/dom/base/nsJSUtils.cpp
+++ b/dom/base/nsJSUtils.cpp
@@ -147,16 +147,17 @@ nsJSUtils::EvaluateString(JSContext* aCx
                           JS::MutableHandle<JS::Value> aRetValue,
                           void **aOffThreadToken)
 {
   PROFILER_LABEL("nsJSUtils", "EvaluateString",
     js::ProfileEntry::Category::JS);
 
   MOZ_ASSERT_IF(aCompileOptions.versionSet,
                 aCompileOptions.version != JSVERSION_UNKNOWN);
+  MOZ_ASSERT_IF(aEvaluateOptions.coerceToString, !aCompileOptions.noScriptRval);
   MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
   MOZ_ASSERT(aSrcBuf.get());
   MOZ_ASSERT(js::GetGlobalForObjectCrossCompartment(aEvaluationGlobal) ==
              aEvaluationGlobal);
   MOZ_ASSERT_IF(aOffThreadToken, aCompileOptions.noScriptRval);
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(nsContentUtils::IsInMicroTask());
 
@@ -200,16 +201,23 @@ nsJSUtils::EvaluateString(JSContext* aCx
       if (script) {
         ok = JS_ExecuteScript(aCx, scopeChain, script);
       } else {
         ok = false;
       }
     } else if (ok) {
       ok = JS::Evaluate(aCx, scopeChain, aCompileOptions, aSrcBuf, aRetValue);
     }
+
+    if (ok && aEvaluateOptions.coerceToString && !aRetValue.isUndefined()) {
+      JS::Rooted<JS::Value> value(aCx, aRetValue);
+      JSString* str = JS::ToString(aCx, value);
+      ok = !!str;
+      aRetValue.set(ok ? JS::StringValue(str) : JS::UndefinedValue());
+    }
   }
 
   if (!ok) {
     if (JS_IsExceptionPending(aCx)) {
       rv = NS_SUCCESS_DOM_SCRIPT_EVALUATION_THREW;
     } else {
       rv = NS_SUCCESS_DOM_SCRIPT_EVALUATION_THREW_UNCATCHABLE;
     }
--- a/dom/base/nsJSUtils.h
+++ b/dom/base/nsJSUtils.h
@@ -60,21 +60,28 @@ public:
                                   JS::CompileOptions& aOptions,
                                   const nsACString& aName,
                                   uint32_t aArgCount,
                                   const char** aArgArray,
                                   const nsAString& aBody,
                                   JSObject** aFunctionObject);
 
   struct MOZ_STACK_CLASS EvaluateOptions {
+    bool coerceToString;
     JS::AutoObjectVector scopeChain;
 
     explicit EvaluateOptions(JSContext* cx)
-      : scopeChain(cx)
+      : coerceToString(false)
+      , scopeChain(cx)
     {}
+
+    EvaluateOptions& setCoerceToString(bool aCoerce) {
+      coerceToString = aCoerce;
+      return *this;
+    }
   };
 
   // aEvaluationGlobal is the global to evaluate in.  The return value
   // will then be wrapped back into the compartment aCx is in when
   // this function is called.  For all the EvaluateString overloads,
   // the JSContext must come from an AutoJSAPI that has had
   // TakeOwnershipOfErrorReporting() called on it.
   static nsresult EvaluateString(JSContext* aCx,
--- a/dom/jsurl/nsJSProtocolHandler.cpp
+++ b/dom/jsurl/nsJSProtocolHandler.cpp
@@ -263,22 +263,23 @@ nsresult nsJSThunk::EvaluateScript(nsICh
     }
 
     JS::Rooted<JS::Value> v (cx, JS::UndefinedValue());
     // Finally, we have everything needed to evaluate the expression.
     JS::CompileOptions options(cx);
     options.setFileAndLine(mURL.get(), 1)
            .setVersion(JSVERSION_DEFAULT);
     nsJSUtils::EvaluateOptions evalOptions(cx);
+    evalOptions.setCoerceToString(true);
     rv = nsJSUtils::EvaluateString(cx, NS_ConvertUTF8toUTF16(script),
                                    globalJSObject, options, evalOptions, &v);
 
-    if (NS_FAILED(rv)) {
+    if (NS_FAILED(rv) || !(v.isString() || v.isUndefined())) {
         return NS_ERROR_MALFORMED_URI;
-    } else if (!v.isString()) {
+    } else if (v.isUndefined()) {
         return NS_ERROR_DOM_RETVAL_UNDEFINED;
     } else {
         MOZ_ASSERT(rv != NS_SUCCESS_DOM_SCRIPT_EVALUATION_THREW,
                    "How did we get a non-undefined return value?");
         nsAutoJSString result;
         if (!result.init(cx, v)) {
             return NS_ERROR_OUT_OF_MEMORY;
         }
--- a/testing/web-platform/tests/html/browsers/browsing-the-web/navigating-across-documents/javascript-url-return-value-handling.html
+++ b/testing/web-platform/tests/html/browsers/browsing-the-web/navigating-across-documents/javascript-url-return-value-handling.html
@@ -11,22 +11,26 @@
 <iframe src="javascript:null"></iframe>
 <iframe src="javascript:true"></iframe>
 <iframe src="javascript:new String('1')"></iframe>
 <script>
   var t = async_test();
   onload = t.step_func_done(function() {
     assert_equals(frames[0].document.documentElement.textContent,
                   "1", "string return should cause navigation");
+    // The rest of the test is disabled for now, until
+    //  https://github.com/whatwg/html/issues/1895 gets sorted out
+/*
     assert_equals(frames[1].document.documentElement.textContent,
                   "", "number return should not cause navigation");
     assert_equals(frames[2].document.documentElement.textContent,
                   "", "object return should not cause navigation");
     assert_equals(frames[3].document.documentElement.textContent,
                   "", "undefined return should not cause navigation");
     assert_equals(frames[4].document.documentElement.textContent,
                   "", "null return should not cause navigation");
     assert_equals(frames[5].document.documentElement.textContent,
                   "", "null return should not cause navigation");
     assert_equals(frames[6].document.documentElement.textContent,
                   "", "String object return should not cause navigation");
+*/
   });
 </script>