Bug 1251308; r=luke
authorBenjamin Bouvier <benj@benj.me>
Wed, 09 Mar 2016 11:20:11 +0100
changeset 288545 2b83147ead2695427cd346eb80cf8c33a2210ba7
parent 288544 ec1879bdc5dc04d4a810c5177be94eb9b3218b9b
child 288546 193a242cef5449eb7f1bfbbdb8a17c4ea8992152
push id73448
push userbenj@benj.me
push dateMon, 14 Mar 2016 13:48:37 +0000
treeherdermozilla-inbound@2b83147ead26 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs1251308
milestone48.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 1251308; r=luke MozReview-Commit-ID: AqsMX4m7Qh9
caps/nsScriptSecurityManager.cpp
dom/base/WebSocket.cpp
dom/base/nsGlobalWindow.cpp
dom/base/nsJSUtils.cpp
dom/workers/RuntimeService.cpp
dom/workers/WorkerPrivate.cpp
dom/workers/WorkerScope.cpp
js/src/asmjs/Wasm.cpp
js/src/builtin/TestingFunctions.cpp
js/src/jit-test/tests/wasm/basic.js
js/src/jsapi.cpp
js/src/jsapi.h
js/src/shell/OSObject.cpp
js/src/shell/js.cpp
js/src/vm/Stack.cpp
js/src/vm/Stack.h
js/xpconnect/loader/mozJSSubScriptLoader.cpp
js/xpconnect/src/XPCShellImpl.cpp
js/xpconnect/wrappers/XrayWrapper.cpp
--- a/caps/nsScriptSecurityManager.cpp
+++ b/caps/nsScriptSecurityManager.cpp
@@ -497,17 +497,17 @@ nsScriptSecurityManager::ContentSecurity
         return true; // fail open to not break sites.
     }
 
     if (reportViolation) {
         nsAutoString fileName;
         unsigned lineNum = 0;
         NS_NAMED_LITERAL_STRING(scriptSample, "call to eval() or related function blocked by CSP");
 
-        JS::UniqueChars scriptFilename;
+        JS::AutoFilename scriptFilename;
         if (JS::DescribeScriptedCaller(cx, &scriptFilename, &lineNum)) {
             if (const char *file = scriptFilename.get()) {
                 CopyUTF8toUTF16(nsDependentCString(file), fileName);
             }
         } else {
             MOZ_ASSERT(!JS_IsExceptionPending(cx));
         }
         csp->LogViolationDetails(nsIContentSecurityPolicy::VIOLATION_TYPE_EVAL,
--- a/dom/base/WebSocket.cpp
+++ b/dom/base/WebSocket.cpp
@@ -1232,17 +1232,17 @@ WebSocket::Constructor(const GlobalObjec
     // In workers we have to keep the worker alive using a feature in order to
     // dispatch messages correctly.
     if (!webSocket->mImpl->RegisterFeature()) {
       aRv.Throw(NS_ERROR_FAILURE);
       return nullptr;
     }
 
     unsigned lineno, column;
-    JS::UniqueChars file;
+    JS::AutoFilename file;
     if (!JS::DescribeScriptedCaller(aGlobal.Context(), &file, &lineno,
                                     &column)) {
       NS_WARNING("Failed to get line number and filename in workers.");
     }
 
     RefPtr<InitRunnable> runnable =
       new InitRunnable(webSocket->mImpl, aUrl, protocolArray,
                        nsAutoCString(file.get()), lineno, column, aRv,
@@ -1468,17 +1468,17 @@ WebSocketImpl::Init(JSContext* aCx,
   if (mWorkerPrivate) {
     mScriptFile = aScriptFile;
     mScriptLine = aScriptLine;
     mScriptColumn = aScriptColumn;
   } else {
     MOZ_ASSERT(aCx);
 
     unsigned lineno, column;
-    JS::UniqueChars file;
+    JS::AutoFilename file;
     if (JS::DescribeScriptedCaller(aCx, &file, &lineno, &column)) {
       mScriptFile = file.get();
       mScriptLine = lineno;
       mScriptColumn = column;
     }
   }
 
   // If we don't have aCx, we are window-less, so we don't have a
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -10654,17 +10654,17 @@ nsGlobalWindow::ShowSlowScriptDialog()
   }
 
   // If our document is not active, just kill the script: we've been unloaded
   if (!AsInner()->HasActiveDocument()) {
     return KillSlowScript;
   }
 
   // Check if we should offer the option to debug
-  JS::UniqueChars filename;
+  JS::AutoFilename filename;
   unsigned lineno;
   bool hasFrame = JS::DescribeScriptedCaller(cx, &filename, &lineno);
 
   // Record the slow script event if we haven't done so already for this inner window
   // (which represents a particular page to the user).
   if (!mHasHadSlowScript) {
     Telemetry::Accumulate(Telemetry::SLOW_SCRIPT_PAGE_COUNT, 1);
   }
--- a/dom/base/nsJSUtils.cpp
+++ b/dom/base/nsJSUtils.cpp
@@ -32,30 +32,30 @@
 #include "mozilla/dom/ScriptSettings.h"
 
 using namespace mozilla::dom;
 
 bool
 nsJSUtils::GetCallingLocation(JSContext* aContext, nsACString& aFilename,
                               uint32_t* aLineno, uint32_t* aColumn)
 {
-  JS::UniqueChars filename;
+  JS::AutoFilename filename;
   if (!JS::DescribeScriptedCaller(aContext, &filename, aLineno, aColumn)) {
     return false;
   }
 
   aFilename.Assign(filename.get());
   return true;
 }
 
 bool
 nsJSUtils::GetCallingLocation(JSContext* aContext, nsAString& aFilename,
                               uint32_t* aLineno, uint32_t* aColumn)
 {
-  JS::UniqueChars filename;
+  JS::AutoFilename filename;
   if (!JS::DescribeScriptedCaller(aContext, &filename, aLineno, aColumn)) {
     return false;
   }
 
   aFilename.Assign(NS_ConvertUTF8toUTF16(filename.get()));
   return true;
 }
 
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -616,17 +616,17 @@ ContentSecurityPolicyAllows(JSContext* a
 {
   WorkerPrivate* worker = GetWorkerPrivateFromContext(aCx);
   worker->AssertIsOnWorkerThread();
 
   if (worker->GetReportCSPViolations()) {
     nsString fileName;
     uint32_t lineNum = 0;
 
-    JS::UniqueChars file;
+    JS::AutoFilename file;
     if (JS::DescribeScriptedCaller(aCx, &file, &lineNum) && file.get()) {
       fileName = NS_ConvertUTF8toUTF16(file.get());
     } else {
       MOZ_ASSERT(!JS_IsExceptionPending(aCx));
     }
 
     RefPtr<LogViolationDetailsRunnable> runnable =
         new LogViolationDetailsRunnable(worker, fileName, lineNum);
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -4291,17 +4291,17 @@ WorkerPrivate::GetLoadInfo(JSContext* aC
       loadInfo.mStorageAllowed = access > nsContentUtils::StorageAccess::eDeny;
       loadInfo.mPrivateBrowsing = nsContentUtils::IsInPrivateBrowsing(document);
     } else {
       // Not a window
       MOZ_ASSERT(isChrome);
 
       // We're being created outside of a window. Need to figure out the script
       // that is creating us in order for us to use relative URIs later on.
-      JS::UniqueChars fileName;
+      JS::AutoFilename fileName;
       if (JS::DescribeScriptedCaller(aCx, &fileName)) {
         // In most cases, fileName is URI. In a few other cases
         // (e.g. xpcshell), fileName is a file path. Ideally, we would
         // prefer testing whether fileName parses as an URI and fallback
         // to file path in case of error, but Windows file paths have
         // the interesting property that they can be parsed as bogus
         // URIs (e.g. C:/Windows/Tmp is interpreted as scheme "C",
         // hostname "Windows", path "Tmp"), which defeats this algorithm.
--- a/dom/workers/WorkerScope.cpp
+++ b/dom/workers/WorkerScope.cpp
@@ -902,17 +902,17 @@ WorkerDebuggerGlobalScope::SetImmediate(
 {
   mWorkerPrivate->SetDebuggerImmediate(aHandler, aRv);
 }
 
 void
 WorkerDebuggerGlobalScope::ReportError(JSContext* aCx,
                                        const nsAString& aMessage)
 {
-  JS::UniqueChars chars;
+  JS::AutoFilename chars;
   uint32_t lineno = 0;
   JS::DescribeScriptedCaller(aCx, &chars, &lineno);
   nsString filename(NS_ConvertUTF8toUTF16(chars.get()));
   mWorkerPrivate->ReportErrorToDebugger(filename, lineno, aMessage);
 }
 
 Console*
 WorkerDebuggerGlobalScope::GetConsole(ErrorResult& aRv)
--- a/js/src/asmjs/Wasm.cpp
+++ b/js/src/asmjs/Wasm.cpp
@@ -1576,18 +1576,22 @@ wasm::Eval(JSContext* cx, Handle<TypedAr
 
     Vector<uint8_t> copy(cx);
     if (code->bufferUnshared()->hasInlineData()) {
         if (!copy.append(bytes, length))
             return false;
         bytes = copy.begin();
     }
 
-    UniqueChars file;
-    if (!DescribeScriptedCaller(cx, &file))
+    JS::AutoFilename filename;
+    if (!DescribeScriptedCaller(cx, &filename))
+        return false;
+
+    UniqueChars file = DuplicateString(filename.get());
+    if (!file)
         return false;
 
     ImportNameVector importNames;
     UniqueExportMap exportMap;
     Rooted<ArrayBufferObject*> heap(cx);
     Rooted<WasmModuleObject*> moduleObj(cx);
 
     if (!DecodeModule(cx, Move(file), bytes, length, &importNames, &exportMap, &heap, &moduleObj)) {
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -2830,17 +2830,17 @@ EvalReturningScope(JSContext* cx, unsign
     AutoStableStringChars strChars(cx);
     if (!strChars.initTwoByte(cx, str))
         return false;
 
     mozilla::Range<const char16_t> chars = strChars.twoByteRange();
     size_t srclen = chars.length();
     const char16_t* src = chars.start().get();
 
-    JS::UniqueChars filename;
+    JS::AutoFilename filename;
     unsigned lineno;
 
     JS::DescribeScriptedCaller(cx, &filename, &lineno);
 
     JS::CompileOptions options(cx);
     options.setFileAndLine(filename.get(), lineno);
     options.setNoScriptRval(true);
 
@@ -2916,17 +2916,17 @@ ShellCloneAndExecuteScript(JSContext* cx
     AutoStableStringChars strChars(cx);
     if (!strChars.initTwoByte(cx, str))
         return false;
 
     mozilla::Range<const char16_t> chars = strChars.twoByteRange();
     size_t srclen = chars.length();
     const char16_t* src = chars.start().get();
 
-    JS::UniqueChars filename;
+    JS::AutoFilename filename;
     unsigned lineno;
 
     JS::DescribeScriptedCaller(cx, &filename, &lineno);
 
     JS::CompileOptions options(cx);
     options.setFileAndLine(filename.get(), lineno);
     options.setNoScriptRval(true);
 
--- a/js/src/jit-test/tests/wasm/basic.js
+++ b/js/src/jit-test/tests/wasm/basic.js
@@ -338,16 +338,18 @@ assertThrowsInstanceOf(() => f(), Intern
 
 var code = '(module (import "one" "" (result i32)) (import "two" "" (result i32)) (func (result i32) (i32.const 3)) (func (result i32) (i32.const 4)) (func (result i32) BODY) (export "" 2))';
 var imports = {one:()=>1, two:()=>2};
 assertEq(wasmEvalText(code.replace('BODY', '(call_import 0)'), imports)(), 1);
 assertEq(wasmEvalText(code.replace('BODY', '(call_import 1)'), imports)(), 2);
 assertEq(wasmEvalText(code.replace('BODY', '(call 0)'), imports)(), 3);
 assertEq(wasmEvalText(code.replace('BODY', '(call 1)'), imports)(), 4);
 
+assertEq(wasmEvalText(`(module (import "evalcx" "" (param i32) (result i32)) (func (result i32) (call_import 0 (i32.const 0))) (export "" 0))`, {evalcx})(), 0);
+
 var {v2i, i2i, i2v} = wasmEvalText(`(module
     (type (func (result i32)))
     (type (func (param i32) (result i32)))
     (type (func (param i32)))
     (func (type 0) (i32.const 13))
     (func (type 0) (i32.const 42))
     (func (type 1) (i32.add (get_local 0) (i32.const 1)))
     (func (type 1) (i32.add (get_local 0) (i32.const 2)))
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -6025,18 +6025,61 @@ JS_IsIdentifier(JSContext* cx, HandleStr
 JS_PUBLIC_API(bool)
 JS_IsIdentifier(const char16_t* chars, size_t length)
 {
     return js::frontend::IsIdentifier(chars, length);
 }
 
 namespace JS {
 
-JS_PUBLIC_API(bool)
-DescribeScriptedCaller(JSContext* cx, UniqueChars* filename, unsigned* lineno,
+void AutoFilename::reset()
+{
+    if (ss_) {
+        reinterpret_cast<ScriptSource*>(ss_)->decref();
+        ss_ = nullptr;
+    }
+    if (filename_.is<const char*>())
+        filename_.as<const char*>() = nullptr;
+    else
+        filename_.as<UniqueChars>().reset();
+}
+
+void AutoFilename::setScriptSource(void* p)
+{
+    MOZ_ASSERT(!ss_);
+    MOZ_ASSERT(!get());
+    ss_ = p;
+    if (p) {
+        ScriptSource* ss = reinterpret_cast<ScriptSource*>(p);
+        ss->incref();
+        setUnowned(ss->filename());
+    }
+}
+
+void AutoFilename::setUnowned(const char* filename)
+{
+    MOZ_ASSERT(!get());
+    filename_.as<const char*>() = filename;
+}
+
+void AutoFilename::setOwned(UniqueChars&& filename)
+{
+    MOZ_ASSERT(!get());
+    filename_ = AsVariant(Move(filename));
+}
+
+const char* AutoFilename::get() const
+{
+    if (filename_.is<const char*>())
+        return filename_.as<const char*>();
+    return filename_.as<UniqueChars>().get();
+}
+
+JS_PUBLIC_API(bool)
+DescribeScriptedCaller(JSContext* cx, AutoFilename* filename, unsigned* lineno,
                        unsigned* column)
 {
     if (filename)
         filename->reset();
     if (lineno)
         *lineno = 0;
     if (column)
         *column = 0;
@@ -6045,21 +6088,28 @@ DescribeScriptedCaller(JSContext* cx, Un
     if (i.done())
         return false;
 
     // If the caller is hidden, the embedding wants us to return false here so
     // that it can check its own stack (see HideScriptedCaller).
     if (i.activation()->scriptedCallerIsHidden())
         return false;
 
-    if (filename && i.filename()) {
-        UniqueChars copy = DuplicateString(i.filename());
-        if (!copy)
-            return false;
-        *filename = Move(copy);
+    if (filename) {
+        if (i.isWasm()) {
+            // For Wasm, copy out the filename, there is no script source.
+            UniqueChars copy = DuplicateString(i.filename());
+            if (!copy)
+                filename->setUnowned("out of memory");
+            else
+                filename->setOwned(Move(copy));
+        } else {
+            // All other frames have a script source to read the filename from.
+            filename->setScriptSource(i.scriptSource());
+        }
     }
 
     if (lineno)
         *lineno = i.computeLine(column);
     else if (column)
         i.computeLine(column);
 
     return true;
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -10,16 +10,17 @@
 #define jsapi_h
 
 #include "mozilla/AlreadyAddRefed.h"
 #include "mozilla/FloatingPoint.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/Range.h"
 #include "mozilla/RangedPtr.h"
 #include "mozilla/RefPtr.h"
+#include "mozilla/Variant.h"
 
 #include <stdarg.h>
 #include <stddef.h>
 #include <stdint.h>
 #include <stdio.h>
 
 #include "jsalloc.h"
 #include "jspubtd.h"
@@ -5403,26 +5404,55 @@ JS_IsIdentifier(JSContext* cx, JS::Handl
  * This version is infallible, so just returns whether the chars are an
  * identifier.
  */
 extern JS_PUBLIC_API(bool)
 JS_IsIdentifier(const char16_t* chars, size_t length);
 
 namespace JS {
 
+class MOZ_RAII JS_PUBLIC_API(AutoFilename)
+{
+  private:
+    // Actually a ScriptSource, not put here to avoid including the world.
+    void* ss_;
+    mozilla::Variant<const char*, UniqueChars> filename_;
+
+    AutoFilename(const AutoFilename&) = delete;
+    AutoFilename& operator=(const AutoFilename&) = delete;
+
+  public:
+    AutoFilename()
+      : ss_(nullptr),
+        filename_(mozilla::AsVariant<const char*>(nullptr))
+    {}
+
+    ~AutoFilename() {
+        reset();
+    }
+
+    void reset();
+
+    void setOwned(UniqueChars&& filename);
+    void setUnowned(const char* filename);
+    void setScriptSource(void* ss);
+
+    const char* get() const;
+};
+
 /**
  * Return the current filename, line number and column number of the most
  * currently running frame. Returns true if a scripted frame was found, false
  * otherwise.
  *
  * If a the embedding has hidden the scripted caller for the topmost activation
  * record, this will also return false.
  */
 extern JS_PUBLIC_API(bool)
-DescribeScriptedCaller(JSContext* cx, UniqueChars* filename = nullptr,
+DescribeScriptedCaller(JSContext* cx, AutoFilename* filename = nullptr,
                        unsigned* lineno = nullptr, unsigned* column = nullptr);
 
 extern JS_PUBLIC_API(JSObject*)
 GetScriptedCallerGlobal(JSContext* cx);
 
 /**
  * Informs the JS engine that the scripted caller should be hidden. This can be
  * used by the embedding to maintain an override of the scripted caller in its
--- a/js/src/shell/OSObject.cpp
+++ b/js/src/shell/OSObject.cpp
@@ -108,17 +108,17 @@ ResolvePath(JSContext* cx, HandleString 
     JSAutoByteString filename(cx, filenameStr);
     if (!filename)
         return nullptr;
 
     if (IsAbsolutePath(filename))
         return filenameStr;
 
     /* Get the currently executing script's name. */
-    JS::UniqueChars scriptFilename;
+    JS::AutoFilename scriptFilename;
     if (!DescribeScriptedCaller(cx, &scriptFilename))
         return nullptr;
 
     if (!scriptFilename.get())
         return nullptr;
 
     if (strcmp(scriptFilename.get(), "-e") == 0 || strcmp(scriptFilename.get(), "typein") == 0)
         resolveMode = RootRelative;
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -2732,17 +2732,17 @@ EvalInContext(JSContext* cx, unsigned ar
             return false;
     }
 
     if (srclen == 0) {
         args.rval().setObject(*sobj);
         return true;
     }
 
-    JS::UniqueChars filename;
+    JS::AutoFilename filename;
     unsigned lineno;
 
     DescribeScriptedCaller(cx, &filename, &lineno);
     {
         Maybe<JSAutoCompartment> ac;
         unsigned flags;
         JSObject* unwrapped = UncheckedUnwrap(sobj, true, &flags);
         if (flags & Wrapper::CROSS_COMPARTMENT) {
@@ -4161,17 +4161,17 @@ DecompileThisScript(JSContext* cx, unsig
     return JS_WrapValue(cx, args.rval());
 }
 
 static bool
 ThisFilename(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
-    JS::UniqueChars filename;
+    JS::AutoFilename filename;
     if (!DescribeScriptedCaller(cx, &filename) || !filename.get()) {
         args.rval().setString(cx->runtime()->emptyString);
         return true;
     }
 
     JSString* str = JS_NewStringCopyZ(cx, filename.get());
     if (!str)
         return false;
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -875,16 +875,31 @@ FrameIter::functionDisplayAtom() const
         return calleeTemplate()->displayAtom();
       case WASM:
         return data_.wasmFrames_.functionDisplayAtom();
     }
 
     MOZ_CRASH("Unexpected state");
 }
 
+ScriptSource*
+FrameIter::scriptSource() const
+{
+    switch (data_.state_) {
+      case DONE:
+      case WASM:
+        break;
+      case INTERP:
+      case JIT:
+        return script()->scriptSource();
+    }
+
+    MOZ_CRASH("Unexpected state");
+}
+
 const char*
 FrameIter::filename() const
 {
     switch (data_.state_) {
       case DONE:
         break;
       case INTERP:
       case JIT:
--- a/js/src/vm/Stack.h
+++ b/js/src/vm/Stack.h
@@ -1749,16 +1749,17 @@ class FrameIter
     bool isEvalFrame() const;
     bool isFunctionFrame() const;
     bool hasArgs() const { return isFunctionFrame(); }
 
     // These two methods may not be called with asm frames.
     inline bool hasCachedSavedFrame() const;
     inline void setHasCachedSavedFrame();
 
+    ScriptSource* scriptSource() const;
     const char* filename() const;
     const char16_t* displayURL() const;
     unsigned computeLine(uint32_t* column = nullptr) const;
     JSAtom* functionDisplayAtom() const;
     bool mutedErrors() const;
 
     bool hasScript() const { return !isWasm(); }
 
--- a/js/xpconnect/loader/mozJSSubScriptLoader.cpp
+++ b/js/xpconnect/loader/mozJSSubScriptLoader.cpp
@@ -595,17 +595,17 @@ mozJSSubScriptLoader::DoLoadSubScriptWit
 
     /* load up the url.  From here on, failures are reflected as ``custom''
      * js exceptions */
     nsCOMPtr<nsIURI> uri;
     nsAutoCString uriStr;
     nsAutoCString scheme;
 
     // Figure out who's calling us
-    JS::UniqueChars filename;
+    JS::AutoFilename filename;
     if (!JS::DescribeScriptedCaller(cx, &filename)) {
         // No scripted frame means we don't know who's calling, bail.
         return NS_ERROR_FAILURE;
     }
 
     // Suppress caching if we're compiling as content.
     StartupCache* cache = (principal == mSystemPrincipal)
                           ? StartupCache::GetSingleton()
--- a/js/xpconnect/src/XPCShellImpl.cpp
+++ b/js/xpconnect/src/XPCShellImpl.cpp
@@ -136,17 +136,17 @@ GetLocationProperty(JSContext* cx, unsig
     if (!args.thisv().isObject()) {
         JS_ReportError(cx, "Unexpected this value for GetLocationProperty");
         return false;
     }
 #if !defined(XP_WIN) && !defined(XP_UNIX)
     //XXX: your platform should really implement this
     return false;
 #else
-    JS::UniqueChars filename;
+    JS::AutoFilename filename;
     if (JS::DescribeScriptedCaller(cx, &filename) && filename.get()) {
         nsresult rv;
         nsCOMPtr<nsIXPConnect> xpc =
             do_GetService(kXPConnectServiceContractID, &rv);
 
 #if defined(XP_WIN)
         // convert from the system codepage to UTF-16
         int bufferSize = MultiByteToWideChar(CP_ACP, 0, filename.get(),
--- a/js/xpconnect/wrappers/XrayWrapper.cpp
+++ b/js/xpconnect/wrappers/XrayWrapper.cpp
@@ -198,17 +198,17 @@ ReportWrapperDenial(JSContext* cx, Handl
     RootedValue idval(cx);
     if (!JS_IdToValue(cx, id, &idval))
         return false;
     JSString* str = JS_ValueToSource(cx, idval);
     if (!str)
         return false;
     if (!propertyName.init(cx, str))
         return false;
-    UniqueChars filename;
+    AutoFilename filename;
     unsigned line = 0, column = 0;
     DescribeScriptedCaller(cx, &filename, &line, &column);
 
     // Warn to the terminal for the logs.
     NS_WARNING(nsPrintfCString("Silently denied access to property %s: %s (@%s:%u:%u)",
                                NS_LossyConvertUTF16toASCII(propertyName).get(), reason,
                                filename.get(), line, column).get());