1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sts=2 et sw=2 tw=80:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef js_GlobalObject_h
#define js_GlobalObject_h
#include "mozilla/Attributes.h"
#include "jstypes.h"
#include "js/TypeDecls.h"
class JS_PUBLIC_API JSTracer;
struct JSClassOps;
extern JS_PUBLIC_API bool JS_IsGlobalObject(JSObject* obj);
namespace JS {
class JS_PUBLIC_API RealmOptions;
/**
* Get the current realm's global. Returns nullptr if no realm has been
* entered.
*/
extern JS_PUBLIC_API JSObject* CurrentGlobalOrNull(JSContext* cx);
/**
* Get the global object associated with an object's realm. The object must not
* be a cross-compartment wrapper (because CCWs are shared by all realms in the
* compartment).
*/
extern JS_PUBLIC_API JSObject* GetNonCCWObjectGlobal(JSObject* obj);
/**
* During global creation, we fire notifications to callbacks registered
* via the Debugger API. These callbacks are arbitrary script, and can touch
* the global in arbitrary ways. When that happens, the global should not be
* in a half-baked state. But this creates a problem for consumers that need
* to set slots on the global to put it in a consistent state.
*
* This API provides a way for consumers to set slots atomically (immediately
* after the global is created), before any debugger hooks are fired. It's
* unfortunately on the clunky side, but that's the way the cookie crumbles.
*
* If callers have no additional state on the global to set up, they may pass
* |FireOnNewGlobalHook| to JS_NewGlobalObject, which causes that function to
* fire the hook as its final act before returning. Otherwise, callers should
* pass |DontFireOnNewGlobalHook|, which means that they are responsible for
* invoking JS_FireOnNewGlobalObject upon successfully creating the global. If
* an error occurs and the operation aborts, callers should skip firing the
* hook. But otherwise, callers must take care to fire the hook exactly once
* before compiling any script in the global's scope (we have assertions in
* place to enforce this). This lets us be sure that debugger clients never miss
* breakpoints.
*/
enum OnNewGlobalHookOption { FireOnNewGlobalHook, DontFireOnNewGlobalHook };
} // namespace JS
extern JS_PUBLIC_API JSObject* JS_NewGlobalObject(
JSContext* cx, const JSClass* clasp, JSPrincipals* principals,
JS::OnNewGlobalHookOption hookOption, const JS::RealmOptions& options);
/**
* Spidermonkey does not have a good way of keeping track of what compartments
* should be marked on their own. We can mark the roots unconditionally, but
* marking GC things only relevant in live compartments is hard. To mitigate
* this, we create a static trace hook, installed on each global object, from
* which we can be sure the compartment is relevant, and mark it.
*
* It is still possible to specify custom trace hooks for global object classes.
* They can be provided via the RealmOptions passed to JS_NewGlobalObject.
*/
extern JS_PUBLIC_API void JS_GlobalObjectTraceHook(JSTracer* trc,
JSObject* global);
namespace JS {
/**
* This allows easily constructing a global object without having to deal with
* JSClassOps, forgetting to add JS_GlobalObjectTraceHook, or forgetting to call
* JS::InitRealmStandardClasses(). Example:
*
* const JSClass globalClass = { "MyGlobal", JSCLASS_GLOBAL_FLAGS,
* &JS::DefaultGlobalClassOps };
* JS_NewGlobalObject(cx, &globalClass, ...);
*/
extern JS_PUBLIC_DATA const JSClassOps DefaultGlobalClassOps;
} // namespace JS
extern JS_PUBLIC_API void JS_FireOnNewGlobalObject(JSContext* cx,
JS::HandleObject global);
#endif // js_GlobalObject_h
|