js/xpconnect/src/nsCxPusher.h

Thu, 15 Jan 2015 15:55:04 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:55:04 +0100
branch
TOR_BUG_9701
changeset 9
a63d609f5ebe
permissions
-rw-r--r--

Back out 97036ab72558 which inappropriately compared turds to third parties.

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #ifndef nsCxPusher_h
michael@0 8 #define nsCxPusher_h
michael@0 9
michael@0 10 #include "jsapi.h"
michael@0 11 #include "mozilla/Maybe.h"
michael@0 12 #include "nsCOMPtr.h"
michael@0 13
michael@0 14 namespace mozilla {
michael@0 15 namespace dom {
michael@0 16 class EventTarget;
michael@0 17 }
michael@0 18 }
michael@0 19
michael@0 20 class nsIScriptContext;
michael@0 21
michael@0 22 namespace mozilla {
michael@0 23
michael@0 24 /**
michael@0 25 * Fundamental cx pushing class. All other cx pushing classes are implemented
michael@0 26 * in terms of this class.
michael@0 27 */
michael@0 28 class MOZ_STACK_CLASS AutoCxPusher
michael@0 29 {
michael@0 30 public:
michael@0 31 AutoCxPusher(JSContext *aCx, bool aAllowNull = false);
michael@0 32 // XPCShell uses an nsCxPusher, which contains an AutoCxPusher.
michael@0 33 ~AutoCxPusher();
michael@0 34
michael@0 35 nsIScriptContext* GetScriptContext() { return mScx; }
michael@0 36
michael@0 37 // Returns true if this AutoCxPusher performed the push that is currently at
michael@0 38 // the top of the cx stack.
michael@0 39 bool IsStackTop();
michael@0 40
michael@0 41 private:
michael@0 42 mozilla::Maybe<JSAutoRequest> mAutoRequest;
michael@0 43 mozilla::Maybe<JSAutoCompartment> mAutoCompartment;
michael@0 44 nsCOMPtr<nsIScriptContext> mScx;
michael@0 45 uint32_t mStackDepthAfterPush;
michael@0 46 #ifdef DEBUG
michael@0 47 JSContext* mPushedContext;
michael@0 48 unsigned mCompartmentDepthOnEntry;
michael@0 49 #endif
michael@0 50 };
michael@0 51
michael@0 52 } /* namespace mozilla */
michael@0 53
michael@0 54 /**
michael@0 55 * Legacy cx pushing class.
michael@0 56 *
michael@0 57 * This class provides a rather wonky interface, with the following quirks:
michael@0 58 * * The constructor is a no-op, and callers must explicitly call one of
michael@0 59 * the Push() methods.
michael@0 60 * * Null must be pushed with PushNull().
michael@0 61 * * The cx pusher can be reused multiple times with RePush().
michael@0 62 *
michael@0 63 * This class implements this interface in terms of the much simpler
michael@0 64 * AutoCxPusher class below.
michael@0 65 */
michael@0 66 class MOZ_STACK_CLASS nsCxPusher
michael@0 67 {
michael@0 68 public:
michael@0 69 // Returns false if something erroneous happened.
michael@0 70 bool Push(mozilla::dom::EventTarget *aCurrentTarget);
michael@0 71 // If nothing has been pushed to stack, this works like Push.
michael@0 72 // Otherwise if context will change, Pop and Push will be called.
michael@0 73 bool RePush(mozilla::dom::EventTarget *aCurrentTarget);
michael@0 74 // If a null JSContext is passed to Push(), that will cause no
michael@0 75 // push to happen and false to be returned.
michael@0 76 void Push(JSContext *cx);
michael@0 77 // Explicitly push a null JSContext on the the stack
michael@0 78 void PushNull();
michael@0 79
michael@0 80 // Pop() will be a no-op if Push() or PushNull() fail
michael@0 81 void Pop();
michael@0 82
michael@0 83 nsIScriptContext* GetCurrentScriptContext() {
michael@0 84 return mPusher.empty() ? nullptr : mPusher.ref().GetScriptContext();
michael@0 85 }
michael@0 86
michael@0 87 private:
michael@0 88 mozilla::Maybe<mozilla::AutoCxPusher> mPusher;
michael@0 89 };
michael@0 90
michael@0 91 namespace mozilla {
michael@0 92
michael@0 93 /**
michael@0 94 * Use AutoJSContext when you need a JS context on the stack but don't have one
michael@0 95 * passed as a parameter. AutoJSContext will take care of finding the most
michael@0 96 * appropriate JS context and release it when leaving the stack.
michael@0 97 */
michael@0 98 class MOZ_STACK_CLASS AutoJSContext {
michael@0 99 public:
michael@0 100 AutoJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM);
michael@0 101 operator JSContext*() const;
michael@0 102
michael@0 103 protected:
michael@0 104 AutoJSContext(bool aSafe MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
michael@0 105
michael@0 106 // We need this Init() method because we can't use delegating constructor for
michael@0 107 // the moment. It is a C++11 feature and we do not require C++11 to be
michael@0 108 // supported to be able to compile Gecko.
michael@0 109 void Init(bool aSafe MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
michael@0 110
michael@0 111 JSContext* mCx;
michael@0 112 Maybe<AutoCxPusher> mPusher;
michael@0 113 MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
michael@0 114 };
michael@0 115
michael@0 116 /**
michael@0 117 * Use ThreadsafeAutoJSContext when you want an AutoJSContext but might be
michael@0 118 * running on a worker thread.
michael@0 119 */
michael@0 120 class MOZ_STACK_CLASS ThreadsafeAutoJSContext {
michael@0 121 public:
michael@0 122 ThreadsafeAutoJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM);
michael@0 123 operator JSContext*() const;
michael@0 124
michael@0 125 private:
michael@0 126 JSContext* mCx; // Used on workers. Null means mainthread.
michael@0 127 Maybe<JSAutoRequest> mRequest; // Used on workers.
michael@0 128 Maybe<AutoJSContext> mAutoJSContext; // Used on main thread.
michael@0 129 MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
michael@0 130 };
michael@0 131
michael@0 132 /**
michael@0 133 * AutoSafeJSContext is similar to AutoJSContext but will only return the safe
michael@0 134 * JS context. That means it will never call ::GetCurrentJSContext().
michael@0 135 */
michael@0 136 class MOZ_STACK_CLASS AutoSafeJSContext : public AutoJSContext {
michael@0 137 public:
michael@0 138 AutoSafeJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM);
michael@0 139 private:
michael@0 140 JSAutoCompartment mAc;
michael@0 141 };
michael@0 142
michael@0 143 /**
michael@0 144 * Like AutoSafeJSContext but can be used safely on worker threads.
michael@0 145 */
michael@0 146 class MOZ_STACK_CLASS ThreadsafeAutoSafeJSContext {
michael@0 147 public:
michael@0 148 ThreadsafeAutoSafeJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM);
michael@0 149 operator JSContext*() const;
michael@0 150
michael@0 151 private:
michael@0 152 JSContext* mCx; // Used on workers. Null means mainthread.
michael@0 153 Maybe<JSAutoRequest> mRequest; // Used on workers.
michael@0 154 Maybe<AutoSafeJSContext> mAutoSafeJSContext; // Used on main thread.
michael@0 155 MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
michael@0 156 };
michael@0 157
michael@0 158 /**
michael@0 159 * Use AutoPushJSContext when you want to use a specific JSContext that may or
michael@0 160 * may not be already on the stack. This differs from nsCxPusher in that it only
michael@0 161 * pushes in the case that the given cx is not the active cx on the JSContext
michael@0 162 * stack, which avoids an expensive JS_SaveFrameChain in the common case.
michael@0 163 *
michael@0 164 * Most consumers of this should probably just use AutoJSContext. But the goal
michael@0 165 * here is to preserve the existing behavior while ensure proper cx-stack
michael@0 166 * semantics in edge cases where the context being used doesn't match the active
michael@0 167 * context.
michael@0 168 *
michael@0 169 * NB: This will not push a null cx even if aCx is null. Make sure you know what
michael@0 170 * you're doing.
michael@0 171 */
michael@0 172 class MOZ_STACK_CLASS AutoPushJSContext {
michael@0 173 Maybe<AutoCxPusher> mPusher;
michael@0 174 JSContext* mCx;
michael@0 175
michael@0 176 public:
michael@0 177 AutoPushJSContext(JSContext* aCx);
michael@0 178 operator JSContext*() { return mCx; }
michael@0 179 };
michael@0 180
michael@0 181 } // namespace mozilla
michael@0 182
michael@0 183 #endif /* nsCxPusher_h */

mercurial