1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
12 #include <type_traits>
13 #include "ErrorList.h"
14 #include "js/BuildId.h"
15 #include "js/ErrorReport.h"
17 #include "js/Object.h"
18 #include "js/RootingAPI.h"
19 #include "js/String.h"
20 #include "js/TypeDecls.h"
21 #include "js/Utility.h"
24 #include "mozilla/AlreadyAddRefed.h"
25 #include "mozilla/Assertions.h"
26 #include "mozilla/Attributes.h"
27 #include "mozilla/Maybe.h"
28 #include "mozilla/MemoryReporting.h"
29 #include "mozilla/TextUtils.h"
30 #include "mozilla/dom/DOMString.h"
31 #include "mozilla/fallible.h"
34 #include "nsISupports.h"
36 #include "nsStringBuffer.h"
37 #include "nsStringFwd.h"
39 #include "nsWrapperCache.h"
41 // XXX only for NukeAllWrappersForRealm, which is only used in
42 // dom/base/WindowDestroyedEvent.cpp outside of js
43 #include "jsfriendapi.h"
48 class nsGlobalWindowInner
;
49 class nsIGlobalObject
;
50 class nsIHandleReportCallback
;
52 class nsPIDOMWindowInner
;
55 struct nsXPTInterfaceInfo
;
60 class PrefableCompileOptions
;
73 } // namespace mozilla
75 using xpcGCCallback
= void (*)(JSGCStatus
);
81 explicit Scriptability(JS::Realm
* realm
);
83 bool IsImmuneToScriptPolicy();
87 void SetWindowAllowsScript(bool aAllowed
);
89 static Scriptability
& Get(JSObject
* aScope
);
91 // Returns true if scripting is allowed, false otherwise (if no Scriptability
92 // exists, like for example inside a ShadowRealm global, then script execution
93 // is assumed to be allowed)
94 static bool AllowedIfExists(JSObject
* aScope
);
97 // Whenever a consumer wishes to prevent script from running on a global,
98 // it increments this value with a call to Block(). When it wishes to
99 // re-enable it (if ever), it decrements this value with a call to Unblock().
100 // Script may not run if this value is non-zero.
101 uint32_t mScriptBlocks
;
103 // Whether the DOM window allows javascript in this scope. If this scope
104 // doesn't have a window, this value is always true.
105 bool mWindowAllowsScript
;
107 // Whether this scope is immune to user-defined or addon-defined script
109 bool mImmuneToScriptPolicy
;
111 // Whether the new-style domain policy when this compartment was created
112 // forbids script execution.
113 bool mScriptBlockedByPolicy
;
116 JSObject
* TransplantObject(JSContext
* cx
, JS::Handle
<JSObject
*> origobj
,
117 JS::Handle
<JSObject
*> target
);
119 JSObject
* TransplantObjectRetainingXrayExpandos(JSContext
* cx
,
120 JS::Handle
<JSObject
*> origobj
,
121 JS::Handle
<JSObject
*> target
);
123 // If origObj has an xray waiver, nuke it before transplant.
124 JSObject
* TransplantObjectNukingXrayWaiver(JSContext
* cx
,
125 JS::Handle
<JSObject
*> origObj
,
126 JS::Handle
<JSObject
*> target
);
128 bool IsUAWidgetCompartment(JS::Compartment
* compartment
);
129 bool IsUAWidgetScope(JS::Realm
* realm
);
130 bool IsInUAWidgetScope(JSObject
* obj
);
132 bool MightBeWebContentCompartment(JS::Compartment
* compartment
);
134 void SetCompartmentChangedDocumentDomain(JS::Compartment
* compartment
);
136 JSObject
* GetUAWidgetScope(JSContext
* cx
, nsIPrincipal
* principal
);
138 JSObject
* GetUAWidgetScope(JSContext
* cx
, JSObject
* contentScope
);
140 // Returns whether XBL scopes have been explicitly disabled for code running
141 // in this compartment. See the comment around mAllowContentXBLScope.
142 bool AllowContentXBLScope(JS::Realm
* realm
);
144 // Get the scope for creating reflectors for native anonymous content
145 // whose normal global would be the given global.
146 JSObject
* NACScope(JSObject
* global
);
148 bool IsSandboxPrototypeProxy(JSObject
* obj
);
149 bool IsWebExtensionContentScriptSandbox(JSObject
* obj
);
151 // The JSContext argument represents the Realm that's asking the question. This
152 // is needed to properly answer without exposing information unnecessarily
153 // from behind security wrappers. There will be no exceptions thrown on this
155 bool IsReflector(JSObject
* obj
, JSContext
* cx
);
157 bool IsXrayWrapper(JSObject
* obj
);
159 // If this function was created for a given XrayWrapper, returns the global of
160 // the Xrayed object. Otherwise, returns the global of the function.
162 // To emphasize the obvious: the return value here is not necessarily same-
163 // compartment with the argument.
164 JSObject
* XrayAwareCalleeGlobal(JSObject
* fun
);
166 void TraceXPCGlobal(JSTracer
* trc
, JSObject
* obj
);
169 * Creates a new global object using the given aCOMObj as the global object.
170 * The object will be set up according to the flags (defined below).
171 * aCOMObj must implement nsIXPCScriptable so it can resolve the standard
172 * classes when asked by the JS engine.
174 * @param aJSContext the context to use while creating the global object.
175 * @param aCOMObj the native object that represents the global object.
176 * @param aPrincipal the principal of the code that will run in this
177 * compartment. Can be null if not on the main thread.
178 * @param aFlags one of the flags below specifying what options this
179 * global object wants.
180 * @param aOptions JSAPI-specific options for the new compartment.
182 nsresult
InitClassesWithNewWrappedGlobal(
183 JSContext
* aJSContext
, nsISupports
* aCOMObj
, nsIPrincipal
* aPrincipal
,
184 uint32_t aFlags
, JS::RealmOptions
& aOptions
,
185 JS::MutableHandle
<JSObject
*> aNewGlobal
);
187 enum InitClassesFlag
{
188 DONT_FIRE_ONNEWGLOBALHOOK
= 1 << 0,
189 OMIT_COMPONENTS_OBJECT
= 1 << 1,
192 } /* namespace xpc */
200 static_assert(JSCLASS_GLOBAL_APPLICATION_SLOTS
> 0,
201 "Need at least one slot for JSCLASS_SLOT0_IS_NSISUPPORTS");
203 #define XPCONNECT_GLOBAL_FLAGS_WITH_EXTRA_SLOTS(n) \
204 JSCLASS_DOM_GLOBAL | JSCLASS_SLOT0_IS_NSISUPPORTS | \
205 JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(DOM_GLOBAL_SLOTS + n)
207 #define XPCONNECT_GLOBAL_EXTRA_SLOT_OFFSET \
208 (JSCLASS_GLOBAL_SLOT_COUNT + DOM_GLOBAL_SLOTS)
210 #define XPCONNECT_GLOBAL_FLAGS XPCONNECT_GLOBAL_FLAGS_WITH_EXTRA_SLOTS(0)
212 inline JSObject
* xpc_FastGetCachedWrapper(JSContext
* cx
, nsWrapperCache
* cache
,
213 JS::MutableHandle
<JS::Value
> vp
) {
215 JSObject
* wrapper
= cache
->GetWrapper();
217 JS::GetCompartment(wrapper
) == js::GetContextCompartment(cx
)) {
218 vp
.setObject(*wrapper
);
226 // If aWrappedJS is a JS wrapper, unmark its JSObject.
227 extern void xpc_TryUnmarkWrappedGrayObject(nsISupports
* aWrappedJS
);
229 extern void xpc_UnmarkSkippableJSHolders();
231 // Defined in XPCDebug.cpp.
232 extern bool xpc_DumpJSStack(bool showArgs
, bool showLocals
, bool showThisProps
);
234 // Return a newly-allocated string containing a representation of the
235 // current JS stack. Defined in XPCDebug.cpp.
236 extern JS::UniqueChars
xpc_PrintJSStack(JSContext
* cx
, bool showArgs
,
237 bool showLocals
, bool showThisProps
);
239 inline void AssignFromStringBuffer(nsStringBuffer
* buffer
, size_t len
,
241 buffer
->ToString(len
, dest
);
243 inline void AssignFromStringBuffer(nsStringBuffer
* buffer
, size_t len
,
245 buffer
->ToString(len
, dest
);
248 // readable string conversions, static methods and members only
249 class XPCStringConvert
{
251 // If the string shares the readable's buffer, that buffer will
252 // get assigned to *sharedBuffer. Otherwise null will be
254 static bool ReadableToJSVal(JSContext
* cx
, const nsAString
& readable
,
255 nsStringBuffer
** sharedBuffer
,
256 JS::MutableHandle
<JS::Value
> vp
);
257 static bool Latin1ToJSVal(JSContext
* cx
, const nsACString
& latin1
,
258 nsStringBuffer
** sharedBuffer
,
259 JS::MutableHandle
<JS::Value
> vp
);
260 static bool UTF8ToJSVal(JSContext
* cx
, const nsACString
& utf8
,
261 nsStringBuffer
** sharedBuffer
,
262 JS::MutableHandle
<JS::Value
> vp
);
264 // Convert the given stringbuffer/length pair to a jsval
265 static MOZ_ALWAYS_INLINE
bool UCStringBufferToJSVal(
266 JSContext
* cx
, nsStringBuffer
* buf
, uint32_t length
,
267 JS::MutableHandle
<JS::Value
> rval
, bool* sharedBuffer
) {
268 JSString
* str
= JS_NewMaybeExternalUCString(
269 cx
, static_cast<const char16_t
*>(buf
->Data()), length
,
270 &sDOMStringExternalString
, sharedBuffer
);
278 static MOZ_ALWAYS_INLINE
bool Latin1StringBufferToJSVal(
279 JSContext
* cx
, nsStringBuffer
* buf
, uint32_t length
,
280 JS::MutableHandle
<JS::Value
> rval
, bool* sharedBuffer
) {
281 JSString
* str
= JS_NewMaybeExternalStringLatin1(
282 cx
, static_cast<const JS::Latin1Char
*>(buf
->Data()), length
,
283 &sDOMStringExternalString
, sharedBuffer
);
291 static MOZ_ALWAYS_INLINE
bool UTF8StringBufferToJSVal(
292 JSContext
* cx
, nsStringBuffer
* buf
, uint32_t length
,
293 JS::MutableHandle
<JS::Value
> rval
, bool* sharedBuffer
) {
294 JSString
* str
= JS_NewMaybeExternalStringUTF8(
295 cx
, {static_cast<const char*>(buf
->Data()), length
},
296 &sDOMStringExternalString
, sharedBuffer
);
304 static inline bool StringLiteralToJSVal(JSContext
* cx
,
305 const char16_t
* literal
,
307 JS::MutableHandle
<JS::Value
> rval
) {
309 JSString
* str
= JS_NewMaybeExternalUCString(
310 cx
, literal
, length
, &sLiteralExternalString
, &ignored
);
318 static inline bool StringLiteralToJSVal(JSContext
* cx
,
319 const JS::Latin1Char
* literal
,
321 JS::MutableHandle
<JS::Value
> rval
) {
323 JSString
* str
= JS_NewMaybeExternalStringLatin1(
324 cx
, literal
, length
, &sLiteralExternalString
, &ignored
);
332 static inline bool UTF8StringLiteralToJSVal(
333 JSContext
* cx
, const JS::UTF8Chars
& chars
,
334 JS::MutableHandle
<JS::Value
> rval
) {
336 JSString
* str
= JS_NewMaybeExternalStringUTF8(
337 cx
, chars
, &sLiteralExternalString
, &ignored
);
346 static MOZ_ALWAYS_INLINE
bool MaybeGetExternalStringChars(
347 JSString
* str
, const JSExternalStringCallbacks
** callbacks
,
348 const char16_t
** chars
) {
349 return JS::IsExternalUCString(str
, callbacks
, chars
);
351 static MOZ_ALWAYS_INLINE
bool MaybeGetExternalStringChars(
352 JSString
* str
, const JSExternalStringCallbacks
** callbacks
,
353 const JS::Latin1Char
** chars
) {
354 return JS::IsExternalStringLatin1(str
, callbacks
, chars
);
357 enum class AcceptedEncoding
{ All
, ASCII
};
359 template <typename SrcCharT
, typename DestCharT
, AcceptedEncoding encoding
,
361 static MOZ_ALWAYS_INLINE
bool MaybeAssignStringChars(JSString
* s
, size_t len
,
363 MOZ_ASSERT(len
== JS::GetStringLength(s
));
364 static_assert(sizeof(SrcCharT
) == sizeof(DestCharT
));
365 if constexpr (encoding
== AcceptedEncoding::ASCII
) {
367 std::is_same_v
<DestCharT
, char>,
368 "AcceptedEncoding::ASCII can be used only with single byte");
371 const JSExternalStringCallbacks
* callbacks
;
372 const DestCharT
* chars
;
373 if (!MaybeGetExternalStringChars(
374 s
, &callbacks
, reinterpret_cast<const SrcCharT
**>(&chars
))) {
378 if (callbacks
== &sDOMStringExternalString
) {
379 if constexpr (encoding
== AcceptedEncoding::ASCII
) {
380 if (!mozilla::IsAscii(mozilla::Span(chars
, len
))) {
385 // The characters represent an existing string buffer that we shared with
386 // JS. We can share that buffer ourselves if the string corresponds to
387 // the whole buffer; otherwise we have to copy.
388 if (chars
[len
] == '\0') {
389 // NOTE: No need to worry about SrcCharT vs DestCharT, given
390 // nsStringBuffer::FromData takes void*.
391 AssignFromStringBuffer(
392 nsStringBuffer::FromData(const_cast<DestCharT
*>(chars
)), len
, dest
);
395 } else if (callbacks
== &sLiteralExternalString
) {
396 if constexpr (encoding
== AcceptedEncoding::ASCII
) {
397 if (!mozilla::IsAscii(mozilla::Span(chars
, len
))) {
402 // The characters represent a literal string constant
403 // compiled into libxul; we can just use it as-is.
404 dest
.AssignLiteral(chars
, len
);
412 template <typename T
>
413 static MOZ_ALWAYS_INLINE
bool MaybeAssignUCStringChars(JSString
* s
,
414 size_t len
, T
& dest
) {
415 return MaybeAssignStringChars
<char16_t
, char16_t
, AcceptedEncoding::All
>(
419 template <typename T
>
420 static MOZ_ALWAYS_INLINE
bool MaybeAssignLatin1StringChars(JSString
* s
,
423 return MaybeAssignStringChars
<JS::Latin1Char
, char, AcceptedEncoding::All
>(
427 template <typename T
>
428 static MOZ_ALWAYS_INLINE
bool MaybeAssignUTF8StringChars(JSString
* s
,
431 return MaybeAssignStringChars
<JS::Latin1Char
, char,
432 AcceptedEncoding::ASCII
>(s
, len
, dest
);
436 struct LiteralExternalString
: public JSExternalStringCallbacks
{
437 void finalize(JS::Latin1Char
* aChars
) const override
;
438 void finalize(char16_t
* aChars
) const override
;
439 size_t sizeOfBuffer(const JS::Latin1Char
* aChars
,
440 mozilla::MallocSizeOf aMallocSizeOf
) const override
;
441 size_t sizeOfBuffer(const char16_t
* aChars
,
442 mozilla::MallocSizeOf aMallocSizeOf
) const override
;
444 struct DOMStringExternalString
: public JSExternalStringCallbacks
{
445 void finalize(JS::Latin1Char
* aChars
) const override
;
446 void finalize(char16_t
* aChars
) const override
;
447 size_t sizeOfBuffer(const JS::Latin1Char
* aChars
,
448 mozilla::MallocSizeOf aMallocSizeOf
) const override
;
449 size_t sizeOfBuffer(const char16_t
* aChars
,
450 mozilla::MallocSizeOf aMallocSizeOf
) const override
;
452 static const LiteralExternalString sLiteralExternalString
;
453 static const DOMStringExternalString sDOMStringExternalString
;
455 XPCStringConvert() = delete;
460 // If these functions return false, then an exception will be set on cx.
461 bool Base64Encode(JSContext
* cx
, JS::Handle
<JS::Value
> val
,
462 JS::MutableHandle
<JS::Value
> out
);
463 bool Base64Decode(JSContext
* cx
, JS::Handle
<JS::Value
> val
,
464 JS::MutableHandle
<JS::Value
> out
);
467 * Convert an nsString to jsval, returning true on success.
468 * Note, the ownership of the string buffer may be moved from str to rval.
469 * If that happens, str will point to an empty string after this call.
471 bool NonVoidStringToJsval(JSContext
* cx
, nsAString
& str
,
472 JS::MutableHandle
<JS::Value
> rval
);
473 bool NonVoidStringToJsval(JSContext
* cx
, const nsAString
& str
,
474 JS::MutableHandle
<JS::Value
> rval
);
475 inline bool StringToJsval(JSContext
* cx
, nsAString
& str
,
476 JS::MutableHandle
<JS::Value
> rval
) {
477 // From the T_ASTRING case in XPCConvert::NativeData2JS.
482 return NonVoidStringToJsval(cx
, str
, rval
);
485 inline bool StringToJsval(JSContext
* cx
, const nsAString
& str
,
486 JS::MutableHandle
<JS::Value
> rval
) {
487 // From the T_ASTRING case in XPCConvert::NativeData2JS.
492 return NonVoidStringToJsval(cx
, str
, rval
);
496 * As above, but for mozilla::dom::DOMString.
498 inline bool NonVoidStringToJsval(JSContext
* cx
, mozilla::dom::DOMString
& str
,
499 JS::MutableHandle
<JS::Value
> rval
) {
501 rval
.set(JS_GetEmptyStringValue(cx
));
505 if (str
.HasStringBuffer()) {
506 uint32_t length
= str
.StringBufferLength();
507 nsStringBuffer
* buf
= str
.StringBuffer();
509 if (!XPCStringConvert::UCStringBufferToJSVal(cx
, buf
, length
, rval
,
514 // JS now needs to hold a reference to the buffer
515 str
.RelinquishBufferOwnership();
520 if (str
.HasLiteral()) {
521 return XPCStringConvert::StringLiteralToJSVal(cx
, str
.Literal(),
522 str
.LiteralLength(), rval
);
525 // It's an actual XPCOM string
526 return NonVoidStringToJsval(cx
, str
.AsAString(), rval
);
530 bool StringToJsval(JSContext
* cx
, mozilla::dom::DOMString
& str
,
531 JS::MutableHandle
<JS::Value
> rval
) {
536 return NonVoidStringToJsval(cx
, str
, rval
);
540 * As above, but for nsACString with latin-1 (non-UTF8) content.
542 bool NonVoidLatin1StringToJsval(JSContext
* cx
, nsACString
& str
,
543 JS::MutableHandle
<JS::Value
> rval
);
544 bool NonVoidLatin1StringToJsval(JSContext
* cx
, const nsACString
& str
,
545 JS::MutableHandle
<JS::Value
> rval
);
547 inline bool Latin1StringToJsval(JSContext
* cx
, nsACString
& str
,
548 JS::MutableHandle
<JS::Value
> rval
) {
553 return NonVoidLatin1StringToJsval(cx
, str
, rval
);
556 inline bool Latin1StringToJsval(JSContext
* cx
, const nsACString
& str
,
557 JS::MutableHandle
<JS::Value
> rval
) {
562 return NonVoidLatin1StringToJsval(cx
, str
, rval
);
566 * As above, but for nsACString with UTF-8 content.
568 bool NonVoidUTF8StringToJsval(JSContext
* cx
, nsACString
& str
,
569 JS::MutableHandle
<JS::Value
> rval
);
570 bool NonVoidUTF8StringToJsval(JSContext
* cx
, const nsACString
& str
,
571 JS::MutableHandle
<JS::Value
> rval
);
573 inline bool UTF8StringToJsval(JSContext
* cx
, nsACString
& str
,
574 JS::MutableHandle
<JS::Value
> rval
) {
579 return NonVoidUTF8StringToJsval(cx
, str
, rval
);
582 inline bool UTF8StringToJsval(JSContext
* cx
, const nsACString
& str
,
583 JS::MutableHandle
<JS::Value
> rval
) {
588 return NonVoidUTF8StringToJsval(cx
, str
, rval
);
591 mozilla::BasePrincipal
* GetRealmPrincipal(JS::Realm
* realm
);
593 void NukeAllWrappersForRealm(JSContext
* cx
, JS::Realm
* realm
,
594 js::NukeReferencesToWindow nukeReferencesToWindow
=
595 js::NukeWindowReferences
);
597 void SetLocationForGlobal(JSObject
* global
, const nsACString
& location
);
598 void SetLocationForGlobal(JSObject
* global
, nsIURI
* locationURI
);
600 // ReportJSRuntimeExplicitTreeStats will expect this in the |extra| member
602 class ZoneStatsExtras
{
604 ZoneStatsExtras() = default;
606 nsCString pathPrefix
;
609 ZoneStatsExtras(const ZoneStatsExtras
& other
) = delete;
610 ZoneStatsExtras
& operator=(const ZoneStatsExtras
& other
) = delete;
613 // ReportJSRuntimeExplicitTreeStats will expect this in the |extra| member
614 // of JS::RealmStats.
615 class RealmStatsExtras
{
617 RealmStatsExtras() = default;
619 nsCString jsPathPrefix
;
620 nsCString domPathPrefix
;
621 nsCOMPtr
<nsIURI
> location
;
624 RealmStatsExtras(const RealmStatsExtras
& other
) = delete;
625 RealmStatsExtras
& operator=(const RealmStatsExtras
& other
) = delete;
628 // This reports all the stats in |rtStats| that belong in the "explicit" tree,
629 // (which isn't all of them).
630 // @see ZoneStatsExtras
631 // @see RealmStatsExtras
632 void ReportJSRuntimeExplicitTreeStats(const JS::RuntimeStats
& rtStats
,
633 const nsACString
& rtPath
,
634 nsIHandleReportCallback
* handleReport
,
635 nsISupports
* data
, bool anonymize
,
636 size_t* rtTotal
= nullptr);
639 * Throws an exception on cx and returns false.
641 bool Throw(JSContext
* cx
, nsresult rv
);
644 * Returns the nsISupports native behind a given reflector (either DOM or
645 * XPCWN). If a non-reflector object is passed in, null will be returned.
647 * This function will not correctly handle Window or Location objects behind
648 * cross-compartment wrappers: it will return null. If you care about getting
649 * non-null for Window or Location, use ReflectorToISupportsDynamic.
651 already_AddRefed
<nsISupports
> ReflectorToISupportsStatic(JSObject
* reflector
);
654 * Returns the nsISupports native behind a given reflector (either DOM or
655 * XPCWN). If a non-reflector object is passed in, null will be returned.
657 * The JSContext argument represents the Realm that's asking for the
658 * nsISupports. This is needed to properly handle Window and Location objects,
659 * which do dynamic security checks.
661 already_AddRefed
<nsISupports
> ReflectorToISupportsDynamic(JSObject
* reflector
,
665 * Singleton scopes for stuff that really doesn't fit anywhere else.
667 * If you find yourself wanting to use these compartments, you're probably doing
668 * something wrong. Callers MUST consult with the XPConnect module owner before
669 * using this compartment. If you don't, bholley will hunt you down.
671 JSObject
* UnprivilegedJunkScope();
673 JSObject
* UnprivilegedJunkScope(const mozilla::fallible_t
&);
675 bool IsUnprivilegedJunkScope(JSObject
*);
678 * This will generally be the shared JSM global, but callers should not depend
681 JSObject
* PrivilegedJunkScope();
684 * Shared compilation scope for XUL prototype documents and XBL
687 JSObject
* CompilationScope();
690 * Returns the nsIGlobalObject corresponding to |obj|'s JS global. |obj| must
691 * not be a cross-compartment wrapper: CCWs are not associated with a single
694 nsIGlobalObject
* NativeGlobal(JSObject
* obj
);
697 * Returns the nsIGlobalObject corresponding to |cx|'s JS global. Must not be
698 * called when |cx| is not in a Realm.
700 nsIGlobalObject
* CurrentNativeGlobal(JSContext
* cx
);
703 * If |aObj| is a window, returns the associated nsGlobalWindow.
704 * Otherwise, returns null.
706 nsGlobalWindowInner
* WindowOrNull(JSObject
* aObj
);
709 * If |aObj| has a window for a global, returns the associated nsGlobalWindow.
710 * Otherwise, returns null. Note: aObj must not be a cross-compartment wrapper
711 * because CCWs are not associated with a single global/realm.
713 nsGlobalWindowInner
* WindowGlobalOrNull(JSObject
* aObj
);
716 * If |aObj| is a Sandbox object and it has a sandboxPrototype, then return
718 * |aCx| is used for checked unwrapping of the prototype.
720 JSObject
* SandboxPrototypeOrNull(JSContext
* aCx
, JSObject
* aObj
);
723 * If |aObj| is a Sandbox object associated with a DOMWindow via a
724 * sandboxPrototype, then return that DOMWindow.
725 * |aCx| is used for checked unwrapping of the Window.
727 inline nsGlobalWindowInner
* SandboxWindowOrNull(JSObject
* aObj
,
729 JSObject
* proto
= SandboxPrototypeOrNull(aCx
, aObj
);
730 return proto
? WindowOrNull(proto
) : nullptr;
734 * If |cx| is in a realm whose global is a window, returns the associated
735 * nsGlobalWindow. Otherwise, returns null.
737 nsGlobalWindowInner
* CurrentWindowOrNull(JSContext
* cx
);
739 class MOZ_RAII AutoScriptActivity
{
744 explicit AutoScriptActivity(bool aActive
);
745 ~AutoScriptActivity();
748 // This function may be used off-main-thread, in which case it is benignly
750 bool ShouldDiscardSystemSource();
752 void SetPrefableRealmOptions(JS::RealmOptions
& options
);
753 void SetPrefableContextOptions(JS::ContextOptions
& options
);
755 // This function may be used off-main-thread.
756 void SetPrefableCompileOptions(JS::PrefableCompileOptions
& options
);
758 // Modify the provided realm options, consistent with |aIsSystemPrincipal| and
759 // with globally-cached values of various preferences.
761 // Call this function *before* |aOptions| is used to create the corresponding
762 // global object, as not all of the options it sets can be modified on an
763 // existing global object. (The type system should make this obvious, because
764 // you can't get a *mutable* JS::RealmOptions& from an existing global
766 void InitGlobalObjectOptions(JS::RealmOptions
& aOptions
,
767 bool aIsSystemPrincipal
, bool aSecureContext
,
768 bool aForceUTC
, bool aAlwaysUseFdlibm
,
776 // Line number (1-origin).
777 uint32_t mLineNumber
;
778 // Column number in UTF-16 code units (1-origin).
781 ErrorBase() : mSourceId(0), mLineNumber(0), mColumn(0) {}
783 void Init(JSErrorBase
* aReport
);
785 void AppendErrorDetailsTo(nsCString
& error
);
788 class ErrorNote
: public ErrorBase
{
790 void Init(JSErrorNotes::Note
* aNote
);
792 // Produce an error event message string from the given JSErrorNotes::Note.
793 // This may produce an empty string if aNote doesn't have a message
795 static void ErrorNoteToMessageString(JSErrorNotes::Note
* aNote
,
798 // Log the error note to the stderr.
802 class ErrorReport
: public ErrorBase
{
804 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ErrorReport
);
806 nsTArray
<ErrorNote
> mNotes
;
809 nsString mSourceLine
;
810 nsString mErrorMsgName
;
814 bool mIsPromiseRejection
;
820 mIsPromiseRejection(false) {}
822 void Init(JSErrorReport
* aReport
, const char* aToStringResult
, bool aIsChrome
,
824 void Init(JSContext
* aCx
, mozilla::dom::Exception
* aException
, bool aIsChrome
,
827 // Log the error report to the console. Which console will depend on the
828 // window id it was initialized with.
830 // Log to console, using the given stack object (which should be a stack of
831 // the sort that JS::CaptureCurrentStack produces). aStack is allowed to be
832 // null. If aStack is non-null, aStackGlobal must be a non-null global
833 // object that's same-compartment with aStack. Note that aStack might be a
835 void LogToConsoleWithStack(nsGlobalWindowInner
* aWin
,
836 JS::Handle
<mozilla::Maybe
<JS::Value
>> aException
,
837 JS::Handle
<JSObject
*> aStack
,
838 JS::Handle
<JSObject
*> aStackGlobal
);
840 // Produce an error event message string from the given JSErrorReport. Note
841 // that this may produce an empty string if aReport doesn't have a
843 static void ErrorReportToMessageString(JSErrorReport
* aReport
,
846 // Log the error report to the stderr.
849 bool IsWarning() const { return mIsWarning
; };
852 ~ErrorReport() = default;
855 void DispatchScriptErrorEvent(nsPIDOMWindowInner
* win
,
856 JS::RootingContext
* rootingCx
,
857 xpc::ErrorReport
* xpcReport
,
858 JS::Handle
<JS::Value
> exception
,
859 JS::Handle
<JSObject
*> exceptionStack
);
861 // Get a stack (as stackObj outparam) of the sort that can be passed to
862 // xpc::ErrorReport::LogToConsoleWithStack from the given exception value. Can
863 // be nullptr if the exception value doesn't have an associated stack, and if
864 // there is no stack supplied by the JS engine in exceptionStack. The
865 // returned stack, if any, may also not be in the same compartment as
868 // The "win" argument passed in here should be the same as the window whose
869 // WindowID() is used to initialize the xpc::ErrorReport. This may be null, of
870 // course. If it's not null, this function may return a null stack object if
871 // the window is far enough gone, because in those cases we don't want to have
872 // the stack in the console message keeping the window alive.
874 // If this function sets stackObj to a non-null value, stackGlobal is set to
875 // either the JS exception object's global or the global of the SavedFrame we
876 // got from a DOM or XPConnect exception. In all cases, stackGlobal is an
877 // unwrapped global object and is same-compartment with stackObj.
878 void FindExceptionStackForConsoleReport(
879 nsPIDOMWindowInner
* win
, JS::Handle
<JS::Value
> exceptionValue
,
880 JS::Handle
<JSObject
*> exceptionStack
, JS::MutableHandle
<JSObject
*> stackObj
,
881 JS::MutableHandle
<JSObject
*> stackGlobal
);
883 // Return a name for the realm.
884 // This function makes reasonable efforts to make this name both mostly
885 // human-readable and unique. However, there are no guarantees of either
887 extern void GetCurrentRealmName(JSContext
*, nsCString
& name
);
889 nsCString
GetFunctionName(JSContext
* cx
, JS::Handle
<JSObject
*> obj
);
891 void AddGCCallback(xpcGCCallback cb
);
892 void RemoveGCCallback(xpcGCCallback cb
);
894 // We need an exact page size only if we run the binary in automation.
895 #if (defined(XP_DARWIN) && defined(__aarch64__)) || defined(__loongarch__)
896 const size_t kAutomationPageSize
= 16384;
898 const size_t kAutomationPageSize
= 4096;
901 struct alignas(kAutomationPageSize
) ReadOnlyPage final
{
902 bool mNonLocalConnectionsDisabled
= false;
903 bool mTurnOffAllSecurityPref
= false;
908 // TSan is confused by write access to read-only section.
909 static ReadOnlyPage sInstance
;
911 static const volatile ReadOnlyPage sInstance
;
915 constexpr ReadOnlyPage() = default;
916 ReadOnlyPage(const ReadOnlyPage
&) = delete;
917 void operator=(const ReadOnlyPage
&) = delete;
919 static void Write(const volatile bool* aPtr
, bool aValue
);
922 inline bool AreNonLocalConnectionsDisabled() {
923 return ReadOnlyPage::sInstance
.mNonLocalConnectionsDisabled
;
926 inline bool IsInAutomation() {
927 if (!ReadOnlyPage::sInstance
.mTurnOffAllSecurityPref
) {
930 MOZ_RELEASE_ASSERT(AreNonLocalConnectionsDisabled());
934 void InitializeJSContext();
937 * Extract the native nsID object from a JS ID, IfaceID, ClassID, or ContractID
940 * Returns 'Nothing()' if 'aVal' does is not one of the supported ID types.
942 mozilla::Maybe
<nsID
> JSValue2ID(JSContext
* aCx
, JS::Handle
<JS::Value
> aVal
);
945 * Reflect an ID into JS
947 bool ID2JSValue(JSContext
* aCx
, const nsID
& aId
,
948 JS::MutableHandle
<JS::Value
> aVal
);
951 * Reflect an IfaceID into JS
953 * This object will expose constants from the selected interface, and support
954 * 'instanceof', in addition to the other methods available on JS ID objects.
956 * Use 'xpc::JSValue2ID' to unwrap JS::Values created with this function.
958 bool IfaceID2JSValue(JSContext
* aCx
, const nsXPTInterfaceInfo
& aInfo
,
959 JS::MutableHandle
<JS::Value
> aVal
);
962 * Reflect a ContractID into JS
964 * This object will expose 'getService' and 'createInstance' methods in addition
965 * to the other methods available on nsID objects.
967 * Use 'xpc::JSValue2ID' to unwrap JS::Values created with this function.
969 bool ContractID2JSValue(JSContext
* aCx
, JSString
* aContract
,
970 JS::MutableHandle
<JS::Value
> aVal
);
972 class JSStackFrameBase
{
974 virtual void Clear() = 0;
977 void RegisterJSStackFrame(JS::Realm
* aRealm
, JSStackFrameBase
* aStackFrame
);
978 void UnregisterJSStackFrame(JS::Realm
* aRealm
, JSStackFrameBase
* aStackFrame
);
979 void NukeJSStackFrames(JS::Realm
* aRealm
);
981 // Check whether the given jsid is a property name (string or symbol) whose
982 // value can be gotten cross-origin. Cross-origin gets always return undefined
983 // as the value, unless the Xray actually provides a different value.
984 bool IsCrossOriginWhitelistedProp(JSContext
* cx
,
985 JS::Handle
<JS::PropertyKey
> id
);
987 // Appends to props the jsids for property names (strings or symbols) whose
988 // value can be gotten cross-origin.
989 bool AppendCrossOriginWhitelistedPropNames(
990 JSContext
* cx
, JS::MutableHandle
<JS::StackGCVector
<JS::PropertyKey
>> props
);
997 * This is used to prevent UA widget code from directly creating and adopting
998 * nodes via the content document, since they should use the special
999 * create-and-insert apis instead.
1001 bool IsNotUAWidget(JSContext
* cx
, JSObject
* /* unused */);
1004 * A test for whether WebIDL methods that should only be visible to
1005 * chrome, XBL scopes, or UA Widget scopes.
1007 bool IsChromeOrUAWidget(JSContext
* cx
, JSObject
* /* unused */);
1010 * Same as IsChromeOrUAWidget but can be used in worker threads as well.
1012 bool ThreadSafeIsChromeOrUAWidget(JSContext
* cx
, JSObject
* obj
);
1017 * Fill the given vector with the buildid.
1019 bool GetBuildId(JS::BuildIdCharVector
* aBuildID
);
1021 } // namespace mozilla