Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/bindings/SimpleGlobalObject.cpp
Line
Count
Source (jump to first uncovered line)
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 file,
5
 * You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "mozilla/dom/SimpleGlobalObject.h"
8
9
#include "jsapi.h"
10
#include "js/Class.h"
11
12
#include "nsJSPrincipals.h"
13
#include "nsThreadUtils.h"
14
#include "nsContentUtils.h"
15
16
#include "xpcprivate.h"
17
18
#include "mozilla/dom/ScriptSettings.h"
19
#include "mozilla/NullPrincipal.h"
20
21
namespace mozilla {
22
namespace dom {
23
24
NS_IMPL_CYCLE_COLLECTION_CLASS(SimpleGlobalObject)
25
26
0
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(SimpleGlobalObject)
27
0
  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
28
0
  tmp->UnlinkHostObjectURIs();
29
0
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
30
31
0
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(SimpleGlobalObject)
32
0
  tmp->TraverseHostObjectURIs(cb);
33
0
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
34
35
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(SimpleGlobalObject)
36
37
NS_IMPL_CYCLE_COLLECTING_ADDREF(SimpleGlobalObject)
38
NS_IMPL_CYCLE_COLLECTING_RELEASE(SimpleGlobalObject)
39
0
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SimpleGlobalObject)
40
0
  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
41
0
  NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
42
0
NS_INTERFACE_MAP_END
43
44
static void
45
SimpleGlobal_finalize(js::FreeOp *fop, JSObject *obj)
46
0
{
47
0
  SimpleGlobalObject* globalObject =
48
0
    static_cast<SimpleGlobalObject*>(JS_GetPrivate(obj));
49
0
  if (globalObject) {
50
0
    globalObject->ClearWrapper(obj);
51
0
    NS_RELEASE(globalObject);
52
0
  }
53
0
}
54
55
static size_t
56
SimpleGlobal_moved(JSObject *obj, JSObject *old)
57
0
{
58
0
  SimpleGlobalObject* globalObject =
59
0
    static_cast<SimpleGlobalObject*>(JS_GetPrivate(obj));
60
0
  if (globalObject) {
61
0
    globalObject->UpdateWrapper(obj, old);
62
0
  }
63
0
  return 0;
64
0
}
65
66
static const js::ClassOps SimpleGlobalClassOps = {
67
    nullptr,
68
    nullptr,
69
    nullptr,
70
    JS_NewEnumerateStandardClasses,
71
    JS_ResolveStandardClass,
72
    JS_MayResolveStandardClass,
73
    SimpleGlobal_finalize,
74
    nullptr,
75
    nullptr,
76
    nullptr,
77
    JS_GlobalObjectTraceHook,
78
};
79
80
static const js::ClassExtension SimpleGlobalClassExtension = {
81
  nullptr,
82
  SimpleGlobal_moved
83
};
84
85
const js::Class SimpleGlobalClass = {
86
    "",
87
    JSCLASS_GLOBAL_FLAGS |
88
    JSCLASS_HAS_PRIVATE |
89
    JSCLASS_PRIVATE_IS_NSISUPPORTS |
90
    JSCLASS_FOREGROUND_FINALIZE,
91
    &SimpleGlobalClassOps,
92
    JS_NULL_CLASS_SPEC,
93
    &SimpleGlobalClassExtension,
94
    JS_NULL_OBJECT_OPS
95
};
96
97
// static
98
JSObject*
99
SimpleGlobalObject::Create(GlobalType globalType, JS::Handle<JS::Value> proto)
100
0
{
101
0
  // We can't root our return value with our AutoJSAPI because the rooting
102
0
  // analysis thinks ~AutoJSAPI can GC.  So we need to root in a scope outside
103
0
  // the lifetime of the AutoJSAPI.
104
0
  JS::Rooted<JSObject*> global(RootingCx());
105
0
106
0
  { // Scope to ensure the AutoJSAPI destructor runs before we end up returning
107
0
    AutoJSAPI jsapi;
108
0
    jsapi.Init();
109
0
    JSContext* cx = jsapi.cx();
110
0
111
0
    JS::RealmOptions options;
112
0
    options.creationOptions()
113
0
           .setInvisibleToDebugger(true)
114
0
           // Put our SimpleGlobalObjects in the system zone, so we won't create
115
0
           // lots of zones for what are probably very short-lived
116
0
           // compartments.  This should help them be GCed quicker and take up
117
0
           // less memory before they're GCed.
118
0
           .setNewCompartmentInSystemZone();
119
0
120
0
    if (NS_IsMainThread()) {
121
0
      nsCOMPtr<nsIPrincipal> principal = NullPrincipal::CreateWithoutOriginAttributes();
122
0
      options.creationOptions().setTrace(xpc::TraceXPCGlobal);
123
0
      global = xpc::CreateGlobalObject(cx, js::Jsvalify(&SimpleGlobalClass),
124
0
                                       nsJSPrincipals::get(principal),
125
0
                                       options);
126
0
    } else {
127
0
      global = JS_NewGlobalObject(cx, js::Jsvalify(&SimpleGlobalClass),
128
0
                                  nullptr,
129
0
                                  JS::DontFireOnNewGlobalHook, options);
130
0
    }
131
0
132
0
    if (!global) {
133
0
      jsapi.ClearException();
134
0
      return nullptr;
135
0
    }
136
0
137
0
    JSAutoRealm ar(cx, global);
138
0
139
0
    // It's important to create the nsIGlobalObject for our new global before we
140
0
    // start trying to wrap things like the prototype into its compartment,
141
0
    // because the wrap operation relies on the global having its
142
0
    // nsIGlobalObject already.
143
0
    RefPtr<SimpleGlobalObject> globalObject =
144
0
      new SimpleGlobalObject(global, globalType);
145
0
146
0
    // Pass on ownership of globalObject to |global|.
147
0
    JS_SetPrivate(global, globalObject.forget().take());
148
0
149
0
    if (proto.isObjectOrNull()) {
150
0
      JS::Rooted<JSObject*> protoObj(cx, proto.toObjectOrNull());
151
0
      if (!JS_WrapObject(cx, &protoObj)) {
152
0
        jsapi.ClearException();
153
0
        return nullptr;
154
0
      }
155
0
156
0
      if (!JS_SplicePrototype(cx, global, protoObj)) {
157
0
        jsapi.ClearException();
158
0
        return nullptr;
159
0
      }
160
0
    } else if (!proto.isUndefined()) {
161
0
      // Bogus proto.
162
0
      return nullptr;
163
0
    }
164
0
165
0
    JS_FireOnNewGlobalObject(cx, global);
166
0
  }
167
0
168
0
  return global;
169
0
}
170
171
// static
172
SimpleGlobalObject::GlobalType
173
SimpleGlobalObject::SimpleGlobalType(JSObject* obj)
174
0
{
175
0
  if (js::GetObjectClass(obj) != &SimpleGlobalClass) {
176
0
    return SimpleGlobalObject::GlobalType::NotSimpleGlobal;
177
0
  }
178
0
179
0
  SimpleGlobalObject* globalObject =
180
0
    static_cast<SimpleGlobalObject*>(JS_GetPrivate(obj));
181
0
  return globalObject->Type();
182
0
}
183
184
} // namespace mozilla
185
} // namespace dom