no bug - Bumping Firefox l10n changesets r=release a=l10n-bump DONTBUILD CLOSED TREE
[gecko.git] / js / xpconnect / src / xpcpublic.h
blob08da56e2fc9a628a3f6b3faa41522868a13ef54d
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/. */
7 #ifndef xpcpublic_h
8 #define xpcpublic_h
10 #include <cstddef>
11 #include <cstdint>
12 #include <type_traits>
13 #include "ErrorList.h"
14 #include "js/BuildId.h"
15 #include "js/ErrorReport.h"
16 #include "js/GCAPI.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"
22 #include "js/Value.h"
23 #include "jsapi.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"
32 #include "nsAtom.h"
33 #include "nsCOMPtr.h"
34 #include "nsISupports.h"
35 #include "nsIURI.h"
36 #include "nsStringBuffer.h"
37 #include "nsStringFwd.h"
38 #include "nsTArray.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"
45 class JSObject;
46 class JSString;
47 class JSTracer;
48 class nsGlobalWindowInner;
49 class nsIGlobalObject;
50 class nsIHandleReportCallback;
51 class nsIPrincipal;
52 class nsPIDOMWindowInner;
53 struct JSContext;
54 struct nsID;
55 struct nsXPTInterfaceInfo;
57 namespace JS {
58 class Compartment;
59 class ContextOptions;
60 class PrefableCompileOptions;
61 class Realm;
62 class RealmOptions;
63 class Value;
64 struct RuntimeStats;
65 } // namespace JS
67 namespace mozilla {
68 class BasePrincipal;
70 namespace dom {
71 class Exception;
72 } // namespace dom
73 } // namespace mozilla
75 using xpcGCCallback = void (*)(JSGCStatus);
77 namespace xpc {
79 class Scriptability {
80 public:
81 explicit Scriptability(JS::Realm* realm);
82 bool Allowed();
83 bool IsImmuneToScriptPolicy();
85 void Block();
86 void Unblock();
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);
96 private:
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
108 // policy.
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
154 // JSContext.
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 */
194 namespace JS {
196 struct RuntimeStats;
198 } // namespace JS
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) {
214 if (cache) {
215 JSObject* wrapper = cache->GetWrapper();
216 if (wrapper &&
217 JS::GetCompartment(wrapper) == js::GetContextCompartment(cx)) {
218 vp.setObject(*wrapper);
219 return wrapper;
223 return nullptr;
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,
240 nsAString& dest) {
241 buffer->ToString(len, dest);
243 inline void AssignFromStringBuffer(nsStringBuffer* buffer, size_t len,
244 nsACString& dest) {
245 buffer->ToString(len, dest);
248 // readable string conversions, static methods and members only
249 class XPCStringConvert {
250 public:
251 // If the string shares the readable's buffer, that buffer will
252 // get assigned to *sharedBuffer. Otherwise null will be
253 // assigned.
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);
271 if (!str) {
272 return false;
274 rval.setString(str);
275 return true;
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);
284 if (!str) {
285 return false;
287 rval.setString(str);
288 return true;
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);
297 if (!str) {
298 return false;
300 rval.setString(str);
301 return true;
304 static inline bool StringLiteralToJSVal(JSContext* cx,
305 const char16_t* literal,
306 uint32_t length,
307 JS::MutableHandle<JS::Value> rval) {
308 bool ignored;
309 JSString* str = JS_NewMaybeExternalUCString(
310 cx, literal, length, &sLiteralExternalString, &ignored);
311 if (!str) {
312 return false;
314 rval.setString(str);
315 return true;
318 static inline bool StringLiteralToJSVal(JSContext* cx,
319 const JS::Latin1Char* literal,
320 uint32_t length,
321 JS::MutableHandle<JS::Value> rval) {
322 bool ignored;
323 JSString* str = JS_NewMaybeExternalStringLatin1(
324 cx, literal, length, &sLiteralExternalString, &ignored);
325 if (!str) {
326 return false;
328 rval.setString(str);
329 return true;
332 static inline bool UTF8StringLiteralToJSVal(
333 JSContext* cx, const JS::UTF8Chars& chars,
334 JS::MutableHandle<JS::Value> rval) {
335 bool ignored;
336 JSString* str = JS_NewMaybeExternalStringUTF8(
337 cx, chars, &sLiteralExternalString, &ignored);
338 if (!str) {
339 return false;
341 rval.setString(str);
342 return true;
345 private:
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,
360 typename T>
361 static MOZ_ALWAYS_INLINE bool MaybeAssignStringChars(JSString* s, size_t len,
362 T& dest) {
363 MOZ_ASSERT(len == JS::GetStringLength(s));
364 static_assert(sizeof(SrcCharT) == sizeof(DestCharT));
365 if constexpr (encoding == AcceptedEncoding::ASCII) {
366 static_assert(
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))) {
375 return false;
378 if (callbacks == &sDOMStringExternalString) {
379 if constexpr (encoding == AcceptedEncoding::ASCII) {
380 if (!mozilla::IsAscii(mozilla::Span(chars, len))) {
381 return false;
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);
393 return true;
395 } else if (callbacks == &sLiteralExternalString) {
396 if constexpr (encoding == AcceptedEncoding::ASCII) {
397 if (!mozilla::IsAscii(mozilla::Span(chars, len))) {
398 return false;
402 // The characters represent a literal string constant
403 // compiled into libxul; we can just use it as-is.
404 dest.AssignLiteral(chars, len);
405 return true;
408 return false;
411 public:
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>(
416 s, len, dest);
419 template <typename T>
420 static MOZ_ALWAYS_INLINE bool MaybeAssignLatin1StringChars(JSString* s,
421 size_t len,
422 T& dest) {
423 return MaybeAssignStringChars<JS::Latin1Char, char, AcceptedEncoding::All>(
424 s, len, dest);
427 template <typename T>
428 static MOZ_ALWAYS_INLINE bool MaybeAssignUTF8StringChars(JSString* s,
429 size_t len,
430 T& dest) {
431 return MaybeAssignStringChars<JS::Latin1Char, char,
432 AcceptedEncoding::ASCII>(s, len, dest);
435 private:
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;
458 namespace xpc {
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.
478 if (str.IsVoid()) {
479 rval.setNull();
480 return true;
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.
488 if (str.IsVoid()) {
489 rval.setNull();
490 return true;
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) {
500 if (str.IsEmpty()) {
501 rval.set(JS_GetEmptyStringValue(cx));
502 return true;
505 if (str.HasStringBuffer()) {
506 uint32_t length = str.StringBufferLength();
507 nsStringBuffer* buf = str.StringBuffer();
508 bool shared;
509 if (!XPCStringConvert::UCStringBufferToJSVal(cx, buf, length, rval,
510 &shared)) {
511 return false;
513 if (shared) {
514 // JS now needs to hold a reference to the buffer
515 str.RelinquishBufferOwnership();
517 return true;
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);
529 MOZ_ALWAYS_INLINE
530 bool StringToJsval(JSContext* cx, mozilla::dom::DOMString& str,
531 JS::MutableHandle<JS::Value> rval) {
532 if (str.IsNull()) {
533 rval.setNull();
534 return true;
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) {
549 if (str.IsVoid()) {
550 rval.setNull();
551 return true;
553 return NonVoidLatin1StringToJsval(cx, str, rval);
556 inline bool Latin1StringToJsval(JSContext* cx, const nsACString& str,
557 JS::MutableHandle<JS::Value> rval) {
558 if (str.IsVoid()) {
559 rval.setNull();
560 return true;
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) {
575 if (str.IsVoid()) {
576 rval.setNull();
577 return true;
579 return NonVoidUTF8StringToJsval(cx, str, rval);
582 inline bool UTF8StringToJsval(JSContext* cx, const nsACString& str,
583 JS::MutableHandle<JS::Value> rval) {
584 if (str.IsVoid()) {
585 rval.setNull();
586 return true;
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
601 // of JS::ZoneStats.
602 class ZoneStatsExtras {
603 public:
604 ZoneStatsExtras() = default;
606 nsCString pathPrefix;
608 private:
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 {
616 public:
617 RealmStatsExtras() = default;
619 nsCString jsPathPrefix;
620 nsCString domPathPrefix;
621 nsCOMPtr<nsIURI> location;
623 private:
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,
662 JSContext* cx);
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
679 * on that fact.
681 JSObject* PrivilegedJunkScope();
684 * Shared compilation scope for XUL prototype documents and XBL
685 * precompilation.
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
692 * global.
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
717 * that prototype.
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,
728 JSContext* aCx) {
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 {
740 bool mActive;
741 bool mOldValue;
743 public:
744 explicit AutoScriptActivity(bool aActive);
745 ~AutoScriptActivity();
748 // This function may be used off-main-thread, in which case it is benignly
749 // racey.
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
765 // object.)
766 void InitGlobalObjectOptions(JS::RealmOptions& aOptions,
767 bool aIsSystemPrincipal, bool aSecureContext,
768 bool aForceUTC, bool aAlwaysUseFdlibm,
769 bool aLocaleEnUS);
771 class ErrorBase {
772 public:
773 nsString mErrorMsg;
774 nsString mFileName;
775 uint32_t mSourceId;
776 // Line number (1-origin).
777 uint32_t mLineNumber;
778 // Column number in UTF-16 code units (1-origin).
779 uint32_t mColumn;
781 ErrorBase() : mSourceId(0), mLineNumber(0), mColumn(0) {}
783 void Init(JSErrorBase* aReport);
785 void AppendErrorDetailsTo(nsCString& error);
788 class ErrorNote : public ErrorBase {
789 public:
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
794 // attached.
795 static void ErrorNoteToMessageString(JSErrorNotes::Note* aNote,
796 nsAString& aString);
798 // Log the error note to the stderr.
799 void LogToStderr();
802 class ErrorReport : public ErrorBase {
803 public:
804 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ErrorReport);
806 nsTArray<ErrorNote> mNotes;
808 nsCString mCategory;
809 nsString mSourceLine;
810 nsString mErrorMsgName;
811 uint64_t mWindowID;
812 bool mIsWarning;
813 bool mIsMuted;
814 bool mIsPromiseRejection;
816 ErrorReport()
817 : mWindowID(0),
818 mIsWarning(false),
819 mIsMuted(false),
820 mIsPromiseRejection(false) {}
822 void Init(JSErrorReport* aReport, const char* aToStringResult, bool aIsChrome,
823 uint64_t aWindowID);
824 void Init(JSContext* aCx, mozilla::dom::Exception* aException, bool aIsChrome,
825 uint64_t aWindowID);
827 // Log the error report to the console. Which console will depend on the
828 // window id it was initialized with.
829 void LogToConsole();
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
834 // CCW.
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
842 // message attached.
843 static void ErrorReportToMessageString(JSErrorReport* aReport,
844 nsAString& aString);
846 // Log the error report to the stderr.
847 void LogToStderr();
849 bool IsWarning() const { return mIsWarning; };
851 private:
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
866 // exceptionValue.
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
886 // property.
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;
897 #else
898 const size_t kAutomationPageSize = 4096;
899 #endif
901 struct alignas(kAutomationPageSize) ReadOnlyPage final {
902 bool mNonLocalConnectionsDisabled = false;
903 bool mTurnOffAllSecurityPref = false;
905 static void Init();
907 #ifdef MOZ_TSAN
908 // TSan is confused by write access to read-only section.
909 static ReadOnlyPage sInstance;
910 #else
911 static const volatile ReadOnlyPage sInstance;
912 #endif
914 private:
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) {
928 return false;
930 MOZ_RELEASE_ASSERT(AreNonLocalConnectionsDisabled());
931 return true;
934 void InitializeJSContext();
937 * Extract the native nsID object from a JS ID, IfaceID, ClassID, or ContractID
938 * value.
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 {
973 public:
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);
991 } // namespace xpc
993 namespace mozilla {
994 namespace dom {
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);
1014 } // namespace dom
1017 * Fill the given vector with the buildid.
1019 bool GetBuildId(JS::BuildIdCharVector* aBuildID);
1021 } // namespace mozilla
1023 #endif