Basically the implementation we have with JS onEnterFrame callbacks and friends is not sufficiently performant, and is a real pain to work with on large complex websites. This implementation instead serializes all of the necessary information to a ring buffer hanging off of the JSContext and outputs a JS object containing that information when prompted. There may be some subtle oddities in the design here, or more indirection in some areas than you might expect. It should be kept in mind that this evolved from a prototype which used a shmem to allow visualizing this trace live in the parent process, which is a model we eventually want to return to, but this felt like the safest first patch. Differential Revision: https://phabricator.services.mozilla.com/D215932
75 lines
2.8 KiB
C++
75 lines
2.8 KiB
C++
/* -*- 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/. */
|
|
|
|
#include "EventCallbackDebuggerNotification.h"
|
|
|
|
#include "DebuggerNotificationManager.h"
|
|
#include "mozilla/CycleCollectedJSContext.h"
|
|
#include "mozilla/dom/EventTarget.h"
|
|
#include "mozilla/dom/Worker.h"
|
|
#include "mozilla/dom/XMLHttpRequestEventTarget.h"
|
|
#include "nsIGlobalObject.h"
|
|
#include "nsINode.h"
|
|
#include "nsQueryObject.h"
|
|
|
|
namespace mozilla::dom {
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_INHERITED(EventCallbackDebuggerNotification,
|
|
CallbackDebuggerNotification, mEvent)
|
|
|
|
NS_IMPL_ADDREF_INHERITED(EventCallbackDebuggerNotification,
|
|
CallbackDebuggerNotification)
|
|
NS_IMPL_RELEASE_INHERITED(EventCallbackDebuggerNotification,
|
|
CallbackDebuggerNotification)
|
|
|
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(EventCallbackDebuggerNotification)
|
|
NS_INTERFACE_MAP_END_INHERITING(CallbackDebuggerNotification)
|
|
|
|
JSObject* EventCallbackDebuggerNotification::WrapObject(
|
|
JSContext* aCx, JS::Handle<JSObject*> aGivenProto) {
|
|
return EventCallbackDebuggerNotification_Binding::Wrap(aCx, this,
|
|
aGivenProto);
|
|
}
|
|
|
|
already_AddRefed<DebuggerNotification>
|
|
EventCallbackDebuggerNotification::CloneInto(nsIGlobalObject* aNewOwner) const {
|
|
RefPtr<EventCallbackDebuggerNotification> notification(
|
|
new EventCallbackDebuggerNotification(mDebuggeeGlobal, mType, mEvent,
|
|
mTargetType, mPhase, aNewOwner));
|
|
return notification.forget();
|
|
}
|
|
|
|
void EventCallbackDebuggerNotificationGuard::DispatchToManager(
|
|
const RefPtr<DebuggerNotificationManager>& aManager,
|
|
CallbackDebuggerNotificationPhase aPhase) {
|
|
if (!mEventTarget) {
|
|
MOZ_ASSERT(false, "target should exist");
|
|
return;
|
|
}
|
|
|
|
Maybe<EventCallbackDebuggerNotificationType> notificationType(
|
|
mEventTarget->GetDebuggerNotificationType());
|
|
|
|
if (notificationType) {
|
|
CycleCollectedJSContext* ccjcx = CycleCollectedJSContext::Get();
|
|
if (ccjcx) {
|
|
nsAutoString eventType;
|
|
mEvent->GetType(eventType);
|
|
if (aPhase == CallbackDebuggerNotificationPhase::Pre) {
|
|
JS_TracerEnterLabelTwoByte(ccjcx->Context(), eventType.get());
|
|
} else {
|
|
JS_TracerLeaveLabelTwoByte(ccjcx->Context(), eventType.get());
|
|
}
|
|
}
|
|
aManager->Dispatch<EventCallbackDebuggerNotification>(
|
|
DebuggerNotificationType::DomEvent,
|
|
// The DOM event will always be live during event dispatch.
|
|
MOZ_KnownLive(mEvent), *notificationType, aPhase);
|
|
}
|
|
}
|
|
|
|
} // namespace mozilla::dom
|