SimpleGlobalObject.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  4. * You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "mozilla/dom/SimpleGlobalObject.h"
  6. #include "jsapi.h"
  7. #include "js/Class.h"
  8. #include "nsJSPrincipals.h"
  9. #include "nsNullPrincipal.h"
  10. #include "nsThreadUtils.h"
  11. #include "nsContentUtils.h"
  12. #include "nsWrapperCacheInlines.h"
  13. #include "xpcprivate.h"
  14. #include "mozilla/dom/ScriptSettings.h"
  15. namespace mozilla {
  16. namespace dom {
  17. NS_IMPL_CYCLE_COLLECTION_CLASS(SimpleGlobalObject)
  18. NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(SimpleGlobalObject)
  19. NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
  20. tmp->UnlinkHostObjectURIs();
  21. NS_IMPL_CYCLE_COLLECTION_UNLINK_END
  22. NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(SimpleGlobalObject)
  23. tmp->TraverseHostObjectURIs(cb);
  24. NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
  25. NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(SimpleGlobalObject)
  26. NS_IMPL_CYCLE_COLLECTING_ADDREF(SimpleGlobalObject)
  27. NS_IMPL_CYCLE_COLLECTING_RELEASE(SimpleGlobalObject)
  28. NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SimpleGlobalObject)
  29. NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
  30. NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
  31. NS_INTERFACE_MAP_END
  32. static void
  33. SimpleGlobal_finalize(js::FreeOp *fop, JSObject *obj)
  34. {
  35. SimpleGlobalObject* globalObject =
  36. static_cast<SimpleGlobalObject*>(JS_GetPrivate(obj));
  37. NS_RELEASE(globalObject);
  38. }
  39. static void
  40. SimpleGlobal_moved(JSObject *obj, const JSObject *old)
  41. {
  42. SimpleGlobalObject* globalObject =
  43. static_cast<SimpleGlobalObject*>(JS_GetPrivate(obj));
  44. globalObject->UpdateWrapper(obj, old);
  45. }
  46. static const js::ClassOps SimpleGlobalClassOps = {
  47. nullptr,
  48. nullptr,
  49. nullptr,
  50. nullptr,
  51. JS_EnumerateStandardClasses,
  52. JS_ResolveStandardClass,
  53. JS_MayResolveStandardClass,
  54. SimpleGlobal_finalize,
  55. nullptr,
  56. nullptr,
  57. nullptr,
  58. JS_GlobalObjectTraceHook,
  59. };
  60. static const js::ClassExtension SimpleGlobalClassExtension = {
  61. nullptr,
  62. SimpleGlobal_moved
  63. };
  64. const js::Class SimpleGlobalClass = {
  65. "",
  66. JSCLASS_GLOBAL_FLAGS |
  67. JSCLASS_HAS_PRIVATE |
  68. JSCLASS_PRIVATE_IS_NSISUPPORTS |
  69. JSCLASS_FOREGROUND_FINALIZE,
  70. &SimpleGlobalClassOps,
  71. JS_NULL_CLASS_SPEC,
  72. &SimpleGlobalClassExtension,
  73. JS_NULL_OBJECT_OPS
  74. };
  75. // static
  76. JSObject*
  77. SimpleGlobalObject::Create(GlobalType globalType, JS::Handle<JS::Value> proto)
  78. {
  79. // We can't root our return value with our AutoJSAPI because the rooting
  80. // analysis thinks ~AutoJSAPI can GC. So we need to root in a scope outside
  81. // the lifetime of the AutoJSAPI.
  82. JS::Rooted<JSObject*> global(RootingCx());
  83. { // Scope to ensure the AutoJSAPI destructor runs before we end up returning
  84. AutoJSAPI jsapi;
  85. jsapi.Init();
  86. JSContext* cx = jsapi.cx();
  87. JS::CompartmentOptions options;
  88. options.creationOptions().setInvisibleToDebugger(true);
  89. if (NS_IsMainThread()) {
  90. nsCOMPtr<nsIPrincipal> principal = nsNullPrincipal::Create();
  91. options.creationOptions().setTrace(xpc::TraceXPCGlobal);
  92. global = xpc::CreateGlobalObject(cx, js::Jsvalify(&SimpleGlobalClass),
  93. nsJSPrincipals::get(principal),
  94. options);
  95. } else {
  96. global = JS_NewGlobalObject(cx, js::Jsvalify(&SimpleGlobalClass),
  97. nullptr,
  98. JS::DontFireOnNewGlobalHook, options);
  99. }
  100. if (!global) {
  101. jsapi.ClearException();
  102. return nullptr;
  103. }
  104. JSAutoCompartment ac(cx, global);
  105. // It's important to create the nsIGlobalObject for our new global before we
  106. // start trying to wrap things like the prototype into its compartment,
  107. // because the wrap operation relies on the global having its
  108. // nsIGlobalObject already.
  109. RefPtr<SimpleGlobalObject> globalObject =
  110. new SimpleGlobalObject(global, globalType);
  111. // Pass on ownership of globalObject to |global|.
  112. JS_SetPrivate(global, globalObject.forget().take());
  113. if (proto.isObjectOrNull()) {
  114. JS::Rooted<JSObject*> protoObj(cx, proto.toObjectOrNull());
  115. if (!JS_WrapObject(cx, &protoObj)) {
  116. jsapi.ClearException();
  117. return nullptr;
  118. }
  119. if (!JS_SplicePrototype(cx, global, protoObj)) {
  120. jsapi.ClearException();
  121. return nullptr;
  122. }
  123. } else if (!proto.isUndefined()) {
  124. // Bogus proto.
  125. return nullptr;
  126. }
  127. JS_FireOnNewGlobalObject(cx, global);
  128. }
  129. return global;
  130. }
  131. // static
  132. SimpleGlobalObject::GlobalType
  133. SimpleGlobalObject::SimpleGlobalType(JSObject* obj)
  134. {
  135. if (js::GetObjectClass(obj) != &SimpleGlobalClass) {
  136. return SimpleGlobalObject::GlobalType::NotSimpleGlobal;
  137. }
  138. SimpleGlobalObject* globalObject =
  139. static_cast<SimpleGlobalObject*>(JS_GetPrivate(obj));
  140. return globalObject->Type();
  141. }
  142. } // namespace mozilla
  143. } // namespace dom