Bug 1320199 - Add a function for throwing permission denied errors. r=arai
authorTom Schuster <evilpies@gmail.com>
Wed, 30 Nov 2016 16:06:06 +0100
changeset 324819 9ce6e0f0095e50c50df060e81f188324b7f961db
parent 324818 84ea3d3b32484f098a868e9dc091e8c457d35615
child 324820 13f67e1da316e494f62a3ddc4b7d2a940a07f4c2
push id24
push usermaklebus@msu.edu
push dateTue, 20 Dec 2016 03:11:33 +0000
reviewersarai
bugs1320199
milestone53.0a1
Bug 1320199 - Add a function for throwing permission denied errors. r=arai
js/src/builtin/Promise.cpp
js/src/builtin/TestingFunctions.cpp
js/src/js.msg
js/src/jsarray.cpp
js/src/jswrapper.h
js/src/proxy/Proxy.cpp
js/src/proxy/SecurityWrapper.cpp
js/src/proxy/Wrapper.cpp
js/src/vm/Debugger.cpp
js/src/vm/ErrorObject.cpp
js/src/vm/SelfHosting.cpp
js/src/vm/TypedArrayObject.cpp
--- a/js/src/builtin/Promise.cpp
+++ b/js/src/builtin/Promise.cpp
@@ -2237,17 +2237,17 @@ js::Promise_then(JSContext* cx, unsigned
     Rooted<PromiseObject*> promise(cx);
 
     bool isPromise = promiseObj->is<PromiseObject>();
     if (isPromise) {
         promise = &promiseObj->as<PromiseObject>();
     } else {
         RootedObject unwrappedPromiseObj(cx, CheckedUnwrap(promiseObj));
         if (!unwrappedPromiseObj) {
-            JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_UNWRAP_DENIED);
+            ReportAccessDenied(cx);
             return false;
         }
         if (!unwrappedPromiseObj->is<PromiseObject>()) {
             JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_INCOMPATIBLE_PROTO,
                                       "Promise", "then", "value");
             return false;
         }
         promise = &unwrappedPromiseObj->as<PromiseObject>();
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -2577,17 +2577,17 @@ SharedAddress(JSContext* cx, unsigned ar
         return false;
     }
 
 #ifdef JS_MORE_DETERMINISTIC
     args.rval().setString(cx->staticStrings().getUint(0));
 #else
     RootedObject obj(cx, CheckedUnwrap(&args[0].toObject()));
     if (!obj) {
-        JS_ReportErrorASCII(cx, "Permission denied to access object");
+        ReportAccessDenied(cx);
         return false;
     }
     if (!obj->is<SharedArrayBufferObject>()) {
         JS_ReportErrorASCII(cx, "Argument must be a SharedArrayBuffer");
         return false;
     }
     char buffer[64];
     uint32_t nchar =
@@ -3574,22 +3574,22 @@ GetLcovInfo(JSContext* cx, unsigned argc
         JS_ReportErrorASCII(cx, "Wrong number of arguments");
         return false;
     }
 
     RootedObject global(cx);
     if (args.hasDefined(0)) {
         global = ToObject(cx, args[0]);
         if (!global) {
-            JS_ReportErrorASCII(cx, "First argument should be an object");
+            JS_ReportErrorASCII(cx, "Permission denied to access global");
             return false;
         }
         global = CheckedUnwrap(global);
         if (!global) {
-            JS_ReportErrorASCII(cx, "Permission denied to access global");
+            ReportAccessDenied(cx);
             return false;
         }
         if (!global->is<GlobalObject>()) {
             JS_ReportErrorASCII(cx, "Argument must be a global object");
             return false;
         }
     } else {
         global = JS::CurrentGlobalOrNull(cx);
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -150,17 +150,18 @@ MSG_DEF(JSMSG_TOO_MANY_ARGUMENTS,      0
 
 // CSP
 MSG_DEF(JSMSG_CSP_BLOCKED_EVAL,        0, JSEXN_ERR, "call to eval() blocked by CSP")
 MSG_DEF(JSMSG_CSP_BLOCKED_FUNCTION,    0, JSEXN_ERR, "call to Function() blocked by CSP")
 
 // Wrappers
 MSG_DEF(JSMSG_ACCESSOR_DEF_DENIED,     1, JSEXN_ERR, "Permission denied to define accessor property {0}")
 MSG_DEF(JSMSG_DEAD_OBJECT,             0, JSEXN_TYPEERR, "can't access dead object")
-MSG_DEF(JSMSG_UNWRAP_DENIED,           0, JSEXN_ERR, "permission denied to unwrap object")
+MSG_DEF(JSMSG_OBJECT_ACCESS_DENIED,    0, JSEXN_ERR, "Permission denied to access object")
+MSG_DEF(JSMSG_PROPERTY_ACCESS_DENIED,  1, JSEXN_ERR, "Permission denied to access property {0}")
 
 // JSAPI-only (Not thrown as JS exceptions)
 MSG_DEF(JSMSG_BAD_CLONE_FUNOBJ_SCOPE,  0, JSEXN_TYPEERR, "bad cloned function scope chain")
 MSG_DEF(JSMSG_CANT_CLONE_OBJECT,       0, JSEXN_TYPEERR, "can't clone object")
 MSG_DEF(JSMSG_CANT_OPEN,               2, JSEXN_ERR, "can't open {0}: {1}")
 MSG_DEF(JSMSG_USER_DEFINED_ERROR,      0, JSEXN_ERR, "JS_ReportError was called")
 
 // Internal errors
@@ -407,18 +408,16 @@ MSG_DEF(JSMSG_CANT_REPORT_NC_AS_NE,    0
 MSG_DEF(JSMSG_CANT_REPORT_NEW,         0, JSEXN_TYPEERR, "proxy can't report a new property on a non-extensible object")
 MSG_DEF(JSMSG_CANT_REPORT_NE_AS_NC,    0, JSEXN_TYPEERR, "proxy can't report a non-existent property as non-configurable")
 MSG_DEF(JSMSG_CANT_SET_NW_NC,          0, JSEXN_TYPEERR, "proxy can't successfully set a non-writable, non-configurable property")
 MSG_DEF(JSMSG_CANT_SET_WO_SETTER,      0, JSEXN_TYPEERR, "proxy can't succesfully set an accessor property without a setter")
 MSG_DEF(JSMSG_CANT_SKIP_NC,            0, JSEXN_TYPEERR, "proxy can't skip a non-configurable property")
 MSG_DEF(JSMSG_ONWKEYS_STR_SYM,         0, JSEXN_TYPEERR,  "proxy [[OwnPropertyKeys]] must return an array with only string and symbol elements")
 MSG_DEF(JSMSG_MUST_REPORT_SAME_VALUE,  0, JSEXN_TYPEERR, "proxy must report the same value for a non-writable, non-configurable property")
 MSG_DEF(JSMSG_MUST_REPORT_UNDEFINED,   0, JSEXN_TYPEERR, "proxy must report undefined for a non-configurable accessor property without a getter")
-MSG_DEF(JSMSG_OBJECT_ACCESS_DENIED,    0, JSEXN_ERR, "Permission denied to access object")
-MSG_DEF(JSMSG_PROPERTY_ACCESS_DENIED,  1, JSEXN_ERR, "Permission denied to access property {0}")
 MSG_DEF(JSMSG_PROXY_CONSTRUCT_OBJECT,  0, JSEXN_TYPEERR, "proxy [[Construct]] must return an object")
 MSG_DEF(JSMSG_PROXY_EXTENSIBILITY,     0, JSEXN_TYPEERR, "proxy must report same extensiblitity as target")
 MSG_DEF(JSMSG_PROXY_GETOWN_OBJORUNDEF, 0, JSEXN_TYPEERR, "proxy [[GetOwnProperty]] must return an object or undefined")
 MSG_DEF(JSMSG_PROXY_REVOKED,           0, JSEXN_TYPEERR, "illegal operation attempted on a revoked proxy")
 MSG_DEF(JSMSG_PROXY_ARG_REVOKED,       1, JSEXN_TYPEERR, "argument {0} cannot be a revoked proxy")
 MSG_DEF(JSMSG_BAD_TRAP,                1, JSEXN_TYPEERR, "proxy handler's {0} trap wasn't undefined, null, or callable")
 
 // Structured cloning
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -901,17 +901,17 @@ js::IsWrappedArrayConstructor(JSContext*
 {
     if (!v.isObject()) {
         *result = false;
         return true;
     }
     if (v.toObject().is<WrapperObject>()) {
         JSObject* obj = CheckedUnwrap(&v.toObject());
         if (!obj) {
-            JS_ReportErrorASCII(cx, "Permission denied to access object");
+            ReportAccessDenied(cx);
             return false;
         }
 
         *result = IsArrayConstructor(obj);
     } else {
         *result = false;
     }
     return true;
--- a/js/src/jswrapper.h
+++ b/js/src/jswrapper.h
@@ -353,16 +353,19 @@ UncheckedUnwrap(JSObject* obj, bool stop
 JS_FRIEND_API(JSObject*)
 CheckedUnwrap(JSObject* obj, bool stopAtWindowProxy = true);
 
 // Unwrap only the outermost security wrapper, with the same semantics as
 // above. This is the checked version of Wrapper::wrappedObject.
 JS_FRIEND_API(JSObject*)
 UnwrapOneChecked(JSObject* obj, bool stopAtWindowProxy = true);
 
+void
+ReportAccessDenied(JSContext* cx);
+
 JS_FRIEND_API(bool)
 IsCrossCompartmentWrapper(JSObject* obj);
 
 void
 NukeCrossCompartmentWrapper(JSContext* cx, JSObject* wrapper);
 
 void
 RemapWrapper(JSContext* cx, JSObject* wobj, JSObject* newTarget);
--- a/js/src/proxy/Proxy.cpp
+++ b/js/src/proxy/Proxy.cpp
@@ -29,17 +29,17 @@ using namespace js::gc;
 
 void
 js::AutoEnterPolicy::reportErrorIfExceptionIsNotPending(JSContext* cx, jsid id)
 {
     if (JS_IsExceptionPending(cx))
         return;
 
     if (JSID_IS_VOID(id)) {
-        JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_OBJECT_ACCESS_DENIED);
+        ReportAccessDenied(cx);
     } else {
         RootedValue idVal(cx, IdToValue(id));
         JSString* str = ValueToSource(cx, idVal);
         if (!str) {
             return;
         }
         AutoStableStringChars chars(cx);
         const char16_t* prop = nullptr;
--- a/js/src/proxy/SecurityWrapper.cpp
+++ b/js/src/proxy/SecurityWrapper.cpp
@@ -6,56 +6,50 @@
 
 #include "jsapi.h"
 #include "jswrapper.h"
 
 #include "jsatominlines.h"
 
 using namespace js;
 
-static void
-ReportUnwrapDenied(JSContext *cx)
-{
-    JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_UNWRAP_DENIED);
-}
-
 template <class Base>
 bool
 SecurityWrapper<Base>::enter(JSContext* cx, HandleObject wrapper, HandleId id,
                              Wrapper::Action act, bool* bp) const
 {
-    ReportUnwrapDenied(cx);
+    ReportAccessDenied(cx);
     *bp = false;
     return false;
 }
 
 template <class Base>
 bool
 SecurityWrapper<Base>::nativeCall(JSContext* cx, IsAcceptableThis test, NativeImpl impl,
                                   const CallArgs& args) const
 {
-    ReportUnwrapDenied(cx);
+    ReportAccessDenied(cx);
     return false;
 }
 
 template <class Base>
 bool
 SecurityWrapper<Base>::setPrototype(JSContext* cx, HandleObject wrapper, HandleObject proto,
                                     ObjectOpResult& result) const
 {
-    ReportUnwrapDenied(cx);
+    ReportAccessDenied(cx);
     return false;
 }
 
 template <class Base>
 bool
 SecurityWrapper<Base>::setImmutablePrototype(JSContext* cx, HandleObject wrapper,
                                              bool* succeeded) const
 {
-    ReportUnwrapDenied(cx);
+    ReportAccessDenied(cx);
     return false;
 }
 
 template <class Base>
 bool
 SecurityWrapper<Base>::preventExtensions(JSContext* cx, HandleObject wrapper,
                                          ObjectOpResult& result) const
 {
@@ -82,17 +76,17 @@ SecurityWrapper<Base>::getBuiltinClass(J
     *cls = ESClass::Other;
     return true;
 }
 
 template <class Base>
 bool
 SecurityWrapper<Base>::isArray(JSContext* cx, HandleObject obj, JS::IsArrayAnswer* answer) const
 {
-    // This should ReportUnwrapDenied(cx), but bug 849730 disagrees.  :-(
+    // This should ReportAccessDenied(cx), but bug 849730 disagrees.  :-(
     *answer = JS::IsArrayAnswer::NotArray;
     return true;
 }
 
 template <class Base>
 bool
 SecurityWrapper<Base>::regexp_toShared(JSContext* cx, HandleObject obj, RegExpGuard* g) const
 {
@@ -130,24 +124,24 @@ SecurityWrapper<Base>::defineProperty(JS
     return Base::defineProperty(cx, wrapper, id, desc, result);
 }
 
 template <class Base>
 bool
 SecurityWrapper<Base>::watch(JSContext* cx, HandleObject proxy,
                              HandleId id, HandleObject callable) const
 {
-    ReportUnwrapDenied(cx);
+    ReportAccessDenied(cx);
     return false;
 }
 
 template <class Base>
 bool
 SecurityWrapper<Base>::unwatch(JSContext* cx, HandleObject proxy,
                                HandleId id) const
 {
-    ReportUnwrapDenied(cx);
+    ReportAccessDenied(cx);
     return false;
 }
 
 
 template class js::SecurityWrapper<Wrapper>;
 template class js::SecurityWrapper<CrossCompartmentWrapper>;
--- a/js/src/proxy/Wrapper.cpp
+++ b/js/src/proxy/Wrapper.cpp
@@ -377,16 +377,22 @@ js::UnwrapOneChecked(JSObject* obj, bool
     {
         return obj;
     }
 
     const Wrapper* handler = Wrapper::wrapperHandler(obj);
     return handler->hasSecurityPolicy() ? nullptr : Wrapper::wrappedObject(obj);
 }
 
+void
+js::ReportAccessDenied(JSContext* cx)
+{
+    JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_OBJECT_ACCESS_DENIED);
+}
+
 const char Wrapper::family = 0;
 const Wrapper Wrapper::singleton((unsigned)0);
 const Wrapper Wrapper::singletonWithPrototype((unsigned)0, true);
 JSObject* Wrapper::defaultProto = TaggedProto::LazyProto;
 
 /* Compartments. */
 
 JSObject*
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -3570,17 +3570,17 @@ Debugger::unwrapDebuggeeArgument(JSConte
         if (!unwrapDebuggeeValue(cx, &rv))
             return nullptr;
         obj = &rv.toObject();
     }
 
     /* If we have a cross-compartment wrapper, dereference as far as is secure. */
     obj = CheckedUnwrap(obj);
     if (!obj) {
-        JS_ReportErrorASCII(cx, "Permission denied to access object");
+        ReportAccessDenied(cx);
         return nullptr;
     }
 
     /* If that produced a WindowProxy, get the Window (global). */
     obj = ToWindowIfWindowProxy(obj);
 
     /* If that didn't produce a global object, it's an error. */
     if (!obj->is<GlobalObject>()) {
@@ -8496,31 +8496,31 @@ DebuggerObject_checkThis(JSContext* cx, 
     Debugger* dbg = Debugger::fromChildJSObject(obj);                         \
     obj = (JSObject*) obj->as<NativeObject>().getPrivate();                   \
     MOZ_ASSERT(obj)
 
 #define THIS_DEBUGOBJECT_PROMISE(cx, argc, vp, fnname, args, obj)                   \
    THIS_DEBUGOBJECT_REFERENT(cx, argc, vp, fnname, args, obj);                      \
    obj = CheckedUnwrap(obj);                                                        \
    if (!obj) {                                                                      \
-       JS_ReportErrorASCII(cx, "Permission denied to access object");               \
+       ReportAccessDenied(cx);                                                      \
        return false;                                                                \
    }                                                                                \
    if (!obj->is<PromiseObject>()) {                                                 \
        JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_NOT_EXPECTED_TYPE,\
                                  "Debugger", "Promise", obj->getClass()->name);     \
        return false;                                                                \
    }                                                                                \
    Rooted<PromiseObject*> promise(cx, &obj->as<PromiseObject>());
 
 #define THIS_DEBUGOBJECT_OWNER_PROMISE(cx, argc, vp, fnname, args, dbg, obj)        \
    THIS_DEBUGOBJECT_OWNER_REFERENT(cx, argc, vp, fnname, args, dbg, obj);           \
    obj = CheckedUnwrap(obj);                                                        \
    if (!obj) {                                                                      \
-       JS_ReportErrorASCII(cx, "Permission denied to access object");               \
+       ReportAccessDenied(cx);                                                      \
        return false;                                                                \
    }                                                                                \
    if (!obj->is<PromiseObject>()) {                                                 \
        JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_NOT_EXPECTED_TYPE,\
                                  "Debugger", "Promise", obj->getClass()->name);     \
        return false;                                                                \
    }                                                                                \
    Rooted<PromiseObject*> promise(cx, &obj->as<PromiseObject>());
@@ -9808,17 +9808,17 @@ DebuggerObject::getAllocationSite(JSCont
 /* static */ bool
 DebuggerObject::getErrorReport(JSContext* cx, HandleObject maybeError, JSErrorReport*& report)
 {
     JSObject* obj = maybeError;
     if (IsCrossCompartmentWrapper(obj))
         obj = CheckedUnwrap(obj);
 
     if (!obj) {
-        JS_ReportErrorASCII(cx, "Permission denied to access object");
+        ReportAccessDenied(cx);
         return false;
     }
 
     if (!obj->is<ErrorObject>()) {
         report = nullptr;
         return true;
     }
 
@@ -10382,17 +10382,17 @@ DebuggerObject::requireGlobal(JSContext*
 /* static */ bool
 DebuggerObject::requirePromise(JSContext* cx, HandleDebuggerObject object)
 {
    RootedObject referent(cx, object->referent());
 
    if (IsCrossCompartmentWrapper(referent)) {
        referent = CheckedUnwrap(referent);
        if (!referent) {
-           JS_ReportErrorASCII(cx, "Permission denied to access object");
+           ReportAccessDenied(cx);
            return false;
        }
    }
 
    if (!referent->is<PromiseObject>()) {
       JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_NOT_EXPECTED_TYPE,
                                 "Debugger", "Promise", object->getClass()->name);
       return false;
--- a/js/src/vm/ErrorObject.cpp
+++ b/js/src/vm/ErrorObject.cpp
@@ -172,17 +172,17 @@ FindErrorInstanceOrPrototype(JSContext* 
     // or
     //   function NYI() { }
     //   NYI.prototype = new Error;
     //   (new NYI).stack
     // to continue returning stacks that are useless, but at least don't throw.
 
     RootedObject target(cx, CheckedUnwrap(obj));
     if (!target) {
-        JS_ReportErrorASCII(cx, "Permission denied to access object");
+        ReportAccessDenied(cx);
         return false;
     }
 
     RootedObject proto(cx);
     while (!IsErrorProtoKey(StandardProtoKeyOrNull(target))) {
         if (!GetPrototype(cx, target, &proto))
             return false;
 
@@ -191,17 +191,17 @@ FindErrorInstanceOrPrototype(JSContext* 
             // object.
             JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_INCOMPATIBLE_PROTO,
                                       js_Error_str, "(get stack)", obj->getClass()->name);
             return false;
         }
 
         target = CheckedUnwrap(proto);
         if (!target) {
-            JS_ReportErrorASCII(cx, "Permission denied to access object");
+            ReportAccessDenied(cx);
             return false;
         }
     }
 
     result.set(target);
     return true;
 }
 
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -991,17 +991,17 @@ intrinsic_IsWrappedArrayBuffer(JSContext
     JSObject* obj = &args[0].toObject();
     if (!obj->is<WrapperObject>()) {
         args.rval().setBoolean(false);
         return true;
     }
 
     JSObject* unwrapped = CheckedUnwrap(obj);
     if (!unwrapped) {
-        JS_ReportErrorASCII(cx, "Permission denied to access object");
+        ReportAccessDenied(cx);
         return false;
     }
 
     args.rval().setBoolean(unwrapped->is<T>());
     return true;
 }
 
 template<typename T>
@@ -1022,17 +1022,17 @@ template<typename T>
 static bool
 intrinsic_PossiblyWrappedArrayBufferByteLength(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     MOZ_ASSERT(args.length() == 1);
 
     JSObject* obj = CheckedUnwrap(&args[0].toObject());
     if (!obj) {
-        JS_ReportErrorASCII(cx, "Permission denied to access object");
+        ReportAccessDenied(cx);
         return false;
     }
 
     uint32_t length = obj->as<T>().byteLength();
     args.rval().setInt32(mozilla::AssertedCast<int32_t>(length));
     return true;
 }
 
@@ -1047,17 +1047,17 @@ intrinsic_ArrayBufferCopyData(JSContext*
     Rooted<T*> toBuffer(cx);
     if (!isWrapped) {
         toBuffer = &args[0].toObject().as<T>();
     } else {
         JSObject* wrapped = &args[0].toObject();
         MOZ_ASSERT(wrapped->is<WrapperObject>());
         RootedObject toBufferObj(cx, CheckedUnwrap(wrapped));
         if (!toBufferObj) {
-            JS_ReportErrorASCII(cx, "Permission denied to access object");
+            ReportAccessDenied(cx);
             return false;
         }
         toBuffer = toBufferObj.as<T>();
     }
     Rooted<T*> fromBuffer(cx, &args[1].toObject().as<T>());
     uint32_t fromIndex = uint32_t(args[2].toInt32());
     uint32_t count = uint32_t(args[3].toInt32());
 
@@ -1130,17 +1130,17 @@ intrinsic_IsPossiblyWrappedTypedArray(JS
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     MOZ_ASSERT(args.length() == 1);
 
     bool isTypedArray = false;
     if (args[0].isObject()) {
         JSObject* obj = CheckedUnwrap(&args[0].toObject());
         if (!obj) {
-            JS_ReportErrorASCII(cx, "Permission denied to access object");
+            ReportAccessDenied(cx);
             return false;
         }
 
         isTypedArray = obj->is<TypedArrayObject>();
     }
 
     args.rval().setBoolean(isTypedArray);
     return true;
@@ -1203,17 +1203,17 @@ static bool
 intrinsic_PossiblyWrappedTypedArrayLength(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     MOZ_ASSERT(args.length() == 1);
     MOZ_ASSERT(args[0].isObject());
 
     JSObject* obj = CheckedUnwrap(&args[0].toObject());
     if (!obj) {
-        JS_ReportErrorASCII(cx, "Permission denied to access object");
+        ReportAccessDenied(cx);
         return false;
     }
 
     MOZ_ASSERT(obj->is<TypedArrayObject>());
     uint32_t typedArrayLength = obj->as<TypedArrayObject>().length();
     args.rval().setInt32(mozilla::AssertedCast<int32_t>(typedArrayLength));
     return true;
 }
@@ -1222,17 +1222,17 @@ static bool
 intrinsic_PossiblyWrappedTypedArrayHasDetachedBuffer(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     MOZ_ASSERT(args.length() == 1);
     MOZ_ASSERT(args[0].isObject());
 
     JSObject* obj = CheckedUnwrap(&args[0].toObject());
     if (!obj) {
-        JS_ReportErrorASCII(cx, "Permission denied to access object");
+        ReportAccessDenied(cx);
         return false;
     }
 
     MOZ_ASSERT(obj->is<TypedArrayObject>());
     bool detached = obj->as<TypedArrayObject>().hasDetachedBuffer();
     args.rval().setBoolean(detached);
     return true;
 }
--- a/js/src/vm/TypedArrayObject.cpp
+++ b/js/src/vm/TypedArrayObject.cpp
@@ -775,17 +775,17 @@ class TypedArrayObjectTemplate : public 
              * data without crossing compartment boundaries. So we use the
              * machinery underlying NonGenericMethodGuard directly to proxy the
              * native call. We will end up with a wrapper in the origin
              * compartment for a view in the target compartment referencing the
              * ArrayBufferObject in that same compartment.
              */
             JSObject* wrapped = CheckedUnwrap(bufobj);
             if (!wrapped) {
-                JS_ReportErrorASCII(cx, "Permission denied to access object");
+                ReportAccessDenied(cx);
                 return nullptr;
             }
 
             if (!IsAnyArrayBuffer(wrapped)) {
                 JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
                 return nullptr; // must be arrayBuffer
             }
 
@@ -1161,17 +1161,17 @@ TypedArrayObjectTemplate<T>::fromTypedAr
     Rooted<TypedArrayObject*> srcArray(cx);
     if (!isWrapped) {
         srcArray = &other->as<TypedArrayObject>();
         if (!TypedArrayObject::ensureHasBuffer(cx, srcArray))
             return nullptr;
     } else {
         RootedObject unwrapped(cx, CheckedUnwrap(other));
         if (!unwrapped) {
-            JS_ReportErrorASCII(cx, "Permission denied to access object");
+            ReportAccessDenied(cx);
             return nullptr;
         }
 
         JSAutoCompartment ac(cx, unwrapped);
 
         srcArray = &unwrapped->as<TypedArrayObject>();
         if (!TypedArrayObject::ensureHasBuffer(cx, srcArray))
             return nullptr;
@@ -1820,17 +1820,17 @@ DataViewObject::constructSameCompartment
 bool
 DataViewObject::constructWrapped(JSContext* cx, HandleObject bufobj, const CallArgs& args)
 {
     MOZ_ASSERT(args.isConstructing());
     MOZ_ASSERT(bufobj->is<WrapperObject>());
 
     JSObject* unwrapped = CheckedUnwrap(bufobj);
     if (!unwrapped) {
-        JS_ReportErrorASCII(cx, "Permission denied to access object");
+        ReportAccessDenied(cx);
         return false;
     }
 
     // NB: This entails the IsArrayBuffer check
     uint32_t byteOffset, byteLength;
     if (!getAndCheckConstructorArgs(cx, unwrapped, args, &byteOffset, &byteLength))
         return false;