nsJSInspector.cpp (3235B)
1 /* -*- Mode: C++; tab-width: 2; 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 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #include "nsJSInspector.h" 7 #include "mozilla/HoldDropJSObjects.h" 8 #include "mozilla/SpinEventLoopUntil.h" 9 #include "mozilla/dom/ScriptSettings.h" 10 #include "nsTArray.h" 11 12 #define JSINSPECTOR_CONTRACTID "@mozilla.org/jsinspector;1" 13 14 #define JSINSPECTOR_CID \ 15 {0xec5aa99c, 0x7abb, 0x4142, {0xac, 0x5f, 0xaa, 0xb2, 0x41, 0x9e, 0x38, 0xe2}} 16 17 namespace mozilla { 18 namespace jsinspector { 19 20 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsJSInspector) 21 NS_INTERFACE_MAP_ENTRY(nsISupports) 22 NS_INTERFACE_MAP_ENTRY(nsIJSInspector) 23 NS_INTERFACE_MAP_END 24 25 NS_IMPL_CYCLE_COLLECTION_CLASS(nsJSInspector) 26 27 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsJSInspector) 28 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsJSInspector) 29 30 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsJSInspector) 31 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END 32 33 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsJSInspector) 34 tmp->mRequestors.Clear(); 35 tmp->mLastRequestor = JS::NullValue(); 36 NS_IMPL_CYCLE_COLLECTION_UNLINK_END 37 38 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsJSInspector) 39 for (uint32_t i = 0; i < tmp->mRequestors.Length(); ++i) { 40 NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mRequestors[i]) 41 } 42 NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mLastRequestor) 43 NS_IMPL_CYCLE_COLLECTION_TRACE_END 44 45 nsJSInspector::nsJSInspector() 46 : mNestedLoopLevel(0), mRequestors(1), mLastRequestor(JS::NullValue()) {} 47 48 nsJSInspector::~nsJSInspector() { 49 MOZ_ASSERT(mRequestors.Length() == 0); 50 MOZ_ASSERT(mLastRequestor.isNull()); 51 mozilla::DropJSObjects(this); 52 } 53 54 NS_IMETHODIMP 55 nsJSInspector::EnterNestedEventLoop(JS::Handle<JS::Value> requestor, 56 uint32_t* out) { 57 nsresult rv = NS_OK; 58 59 mLastRequestor = requestor; 60 mRequestors.AppendElement(requestor); 61 mozilla::HoldJSObjects(this); 62 63 mozilla::dom::AutoNoJSAPI nojsapi; 64 65 uint32_t nestLevel = ++mNestedLoopLevel; 66 if (!SpinEventLoopUntil("nsJSInspector::EnterNestedEventLoop"_ns, 67 [&]() { return mNestedLoopLevel < nestLevel; })) { 68 rv = NS_ERROR_UNEXPECTED; 69 } 70 71 NS_ASSERTION(mNestedLoopLevel <= nestLevel, 72 "nested event didn't unwind properly"); 73 74 if (mNestedLoopLevel == nestLevel) { 75 mLastRequestor = mRequestors.ElementAt(--mNestedLoopLevel); 76 } 77 78 *out = mNestedLoopLevel; 79 return rv; 80 } 81 82 NS_IMETHODIMP 83 nsJSInspector::ExitNestedEventLoop(uint32_t* out) { 84 if (mNestedLoopLevel > 0) { 85 mRequestors.RemoveElementAt(--mNestedLoopLevel); 86 if (mNestedLoopLevel > 0) 87 mLastRequestor = mRequestors.ElementAt(mNestedLoopLevel - 1); 88 else 89 mLastRequestor = JS::NullValue(); 90 } else { 91 return NS_ERROR_FAILURE; 92 } 93 94 *out = mNestedLoopLevel; 95 96 return NS_OK; 97 } 98 99 NS_IMETHODIMP 100 nsJSInspector::GetEventLoopNestLevel(uint32_t* out) { 101 *out = mNestedLoopLevel; 102 return NS_OK; 103 } 104 105 NS_IMETHODIMP 106 nsJSInspector::GetLastNestRequestor(JS::MutableHandle<JS::Value> out) { 107 out.set(mLastRequestor); 108 return NS_OK; 109 } 110 111 } // namespace jsinspector 112 } // namespace mozilla