Bug 1676361 - Move AutoEntryScript to a separate header file to avoid pulling in GeckoProfiler.h everywhere. r=mccr8

Differential Revision: https://phabricator.services.mozilla.com/D97742
This commit is contained in:
Simon Giesecke 2021-03-05 15:29:49 +00:00
parent 3f6eec2f43
commit 7c6ccbe4a8
46 changed files with 377 additions and 252 deletions

View File

@ -51,6 +51,7 @@
#include "mozilla/Unused.h"
#include "mozilla/WidgetUtils.h"
#include "mozilla/dom/AutoEntryScript.h"
#include "mozilla/dom/ChildProcessChannelListener.h"
#include "mozilla/dom/ClientChannelHelper.h"
#include "mozilla/dom/ClientHandle.h"

View File

@ -6,6 +6,7 @@
#include "BodyStream.h"
#include "mozilla/CycleCollectedJSContext.h"
#include "mozilla/dom/AutoEntryScript.h"
#include "mozilla/dom/DOMException.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/WorkerCommon.h"

View File

@ -8,6 +8,7 @@
#include "mozilla/AsyncEventDispatcher.h"
#include "mozilla/CycleCollectedJSContext.h"
#include "mozilla/dom/AutoEntryScript.h"
#include "mozilla/dom/CustomElementRegistryBinding.h"
#include "mozilla/dom/ElementBinding.h"
#include "mozilla/dom/HTMLElementBinding.h"

View File

@ -9,6 +9,10 @@
#include "mozilla/dom/TimeoutManager.h"
#include "nsGlobalWindowInner.h"
#ifdef MOZ_GECKO_PROFILER
# include "GeckoProfiler.h"
#endif
namespace mozilla::dom {
Timeout::Timeout()

View File

@ -25,6 +25,10 @@
#include "mozilla/net/WebSocketEventService.h"
#include "mozilla/MediaManager.h"
#if MOZ_GECKO_PROFILER
# include "GeckoProfiler.h"
#endif
using namespace mozilla;
using namespace mozilla::dom;

View File

@ -126,6 +126,7 @@
#include "mozilla/Variant.h"
#include "mozilla/ViewportUtils.h"
#include "mozilla/dom/AncestorIterator.h"
#include "mozilla/dom/AutoEntryScript.h"
#include "mozilla/dom/AutocompleteInfoBinding.h"
#include "mozilla/dom/AutoSuppressEventHandlingAndSuspend.h"
#include "mozilla/dom/BindingDeclarations.h"

View File

@ -40,6 +40,7 @@
#include "mozilla/TimeStamp.h"
#include "mozilla/TypedEnumBits.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/dom/AutoEntryScript.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/CallbackObject.h"
#include "mozilla/dom/ChildProcessMessageManager.h"

View File

@ -86,6 +86,7 @@
#include "mozilla/UniquePtr.h"
#include "mozilla/Unused.h"
#include "mozilla/dom/AudioContext.h"
#include "mozilla/dom/AutoEntryScript.h"
#include "mozilla/dom/BarProps.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/BindingUtils.h"

View File

@ -30,6 +30,7 @@
#include "mozilla/Maybe.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/RefPtr.h"
#include "mozilla/dom/AutoEntryScript.h"
#include "mozilla/dom/BindingCallContext.h"
#include "mozilla/dom/ScriptSettings.h"
#include "nsCOMPtr.h"

View File

@ -8,6 +8,7 @@
#include "InternalResponse.h"
#include "js/Stream.h"
#include "mozilla/ConsoleReportCollector.h"
#include "mozilla/dom/AutoEntryScript.h"
#include "mozilla/dom/DOMException.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/PromiseBinding.h"

View File

@ -10,6 +10,7 @@
#include "MemMapSnapshot.h"
#include "ScriptPreloader-inl.h"
#include "mozilla/dom/AutoEntryScript.h"
#include "mozilla/dom/BlobImpl.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/ContentProcessMessageManager.h"

View File

@ -10,6 +10,7 @@
#include "chrome/common/ipc_channel.h"
#include "mozilla/Attributes.h"
#include "mozilla/FunctionRef.h"
#include "mozilla/dom/AutoEntryScript.h"
#include "mozilla/dom/ClonedErrorHolder.h"
#include "mozilla/dom/ClonedErrorHolderBinding.h"
#include "mozilla/dom/DOMException.h"

View File

@ -5,6 +5,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/JSActorManager.h"
#include "mozilla/dom/AutoEntryScript.h"
#include "mozilla/dom/JSActorService.h"
#include "mozilla/dom/PWindowGlobal.h"
#include "mozilla/ipc/ProtocolUtils.h"

View File

@ -42,6 +42,7 @@
#include "nsSandboxFlags.h"
#include "mozilla/BasePrincipal.h"
#include "mozilla/CycleCollectedJSContext.h"
#include "mozilla/dom/AutoEntryScript.h"
#include "mozilla/dom/DOMSecurityMonitor.h"
#include "mozilla/dom/JSExecutionContext.h"
#include "mozilla/dom/ScriptSettings.h"

View File

@ -10,6 +10,7 @@
#include "nsIScriptError.h"
#include "DOMLocalization.h"
#include "mozilla/intl/LocaleService.h"
#include "mozilla/dom/AutoEntryScript.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/L10nOverlays.h"

View File

@ -6,6 +6,7 @@
#include "DocumentL10n.h"
#include "nsIContentSink.h"
#include "mozilla/dom/AutoEntryScript.h"
#include "mozilla/dom/Document.h"
#include "mozilla/dom/DocumentL10nBinding.h"
#include "mozilla/Telemetry.h"

View File

@ -14,6 +14,7 @@
#include "js/experimental/TypedData.h" // JS_NewFloat32Array, JS_GetFloat32ArrayData, JS_GetTypedArrayLength, JS_GetArrayBufferViewBuffer
#include "mozilla/dom/AudioWorkletNodeBinding.h"
#include "mozilla/dom/AudioParamMapBinding.h"
#include "mozilla/dom/AutoEntryScript.h"
#include "mozilla/dom/RootedDictionary.h"
#include "mozilla/dom/ErrorEvent.h"
#include "mozilla/dom/Worklet.h"

View File

@ -11,7 +11,7 @@
#include "nsCOMPtr.h"
#include "nsPIDOMWindow.h" // nsPIDOMWindowInner
#include "mozilla/dom/ScriptSettings.h" // AutoEntryScript
#include "mozilla/dom/AutoEntryScript.h"
#include "nsIGlobalObject.h"
#include "js/RootingAPI.h" // JS::Rooted
#include "js/Value.h"

View File

@ -32,6 +32,7 @@
#include "mozilla/HashFunctions.h"
#include "mozilla/ProfilerLabels.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/dom/AutoEntryScript.h"
#include "mozilla/dom/ScriptSettings.h"
#define NPRUNTIME_JSCLASS_NAME "NPObject JS wrapper class"

View File

@ -32,6 +32,7 @@
#include "nsPIDOMWindow.h"
#include "nsGlobalWindow.h"
#include "mozilla/dom/AutoEntryScript.h"
#include "mozilla/dom/Document.h"
#include "nsIContent.h"
#include "nsIIDNService.h"

View File

@ -18,6 +18,7 @@
#include "mozilla/ResultExtensions.h"
#include "mozilla/Unused.h"
#include "mozilla/dom/AutoEntryScript.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/DOMException.h"
#include "mozilla/dom/DOMExceptionBinding.h"

View File

@ -19,6 +19,7 @@
#include "mozilla/RefPtr.h"
#include "mozilla/Result.h"
#include "mozilla/WeakPtr.h"
#include "mozilla/dom/AutoEntryScript.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/ToJSValue.h"
#include "nsCycleCollectionParticipant.h"

View File

@ -38,6 +38,7 @@
#include "nsMimeTypes.h"
#include "nsHtml5SVGLoadDispatcher.h"
#include "nsTextNode.h"
#include "mozilla/dom/AutoEntryScript.h"
#include "mozilla/dom/CDATASection.h"
#include "mozilla/dom/Comment.h"
#include "mozilla/dom/DocumentType.h"

View File

@ -0,0 +1,164 @@
/* -*- 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 "mozilla/dom/AutoEntryScript.h"
#include <stdint.h>
#include <utility>
#include "js/ProfilingCategory.h"
#include "js/ProfilingStack.h"
#include "jsapi.h"
#include "mozilla/Assertions.h"
#include "mozilla/Maybe.h"
#include "mozilla/Span.h"
#include "nsCOMPtr.h"
#include "nsContentUtils.h"
#include "nsGlobalWindowInner.h"
#include "nsIDocShell.h"
#include "nsJSUtils.h"
#include "nsPIDOMWindow.h"
#include "nsPIDOMWindowInlines.h"
#include "nsString.h"
#include "xpcpublic.h"
namespace mozilla::dom {
namespace {
// Assert if it's not safe to run script. The helper class
// AutoAllowLegacyScriptExecution allows to allow-list
// legacy cases where it's actually not safe to run script.
#ifdef DEBUG
void AssertIfNotSafeToRunScript() {
// if it's safe to run script, then there is nothing to do here.
if (nsContentUtils::IsSafeToRunScript()) {
return;
}
// auto allowing legacy script execution is fine for now.
if (AutoAllowLegacyScriptExecution::IsAllowed()) {
return;
}
MOZ_ASSERT(false, "is it safe to run script?");
}
#endif
static unsigned long gRunToCompletionListeners = 0;
} // namespace
void UseEntryScriptProfiling() {
MOZ_ASSERT(NS_IsMainThread());
++gRunToCompletionListeners;
}
void UnuseEntryScriptProfiling() {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(gRunToCompletionListeners > 0);
--gRunToCompletionListeners;
}
AutoEntryScript::AutoEntryScript(nsIGlobalObject* aGlobalObject,
const char* aReason, bool aIsMainThread)
: AutoJSAPI(aGlobalObject, aIsMainThread, eEntryScript),
mWebIDLCallerPrincipal(nullptr)
// This relies on us having a cx() because the AutoJSAPI constructor
// already ran.
,
mCallerOverride(cx())
#ifdef MOZ_GECKO_PROFILER
,
mAutoProfilerLabel(
"", aReason, JS::ProfilingCategoryPair::JS,
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS))
#endif
,
mJSThreadExecution(aGlobalObject, aIsMainThread) {
MOZ_ASSERT(aGlobalObject);
if (aIsMainThread) {
#ifdef DEBUG
AssertIfNotSafeToRunScript();
#endif
if (gRunToCompletionListeners > 0) {
mDocShellEntryMonitor.emplace(cx(), aReason);
}
mScriptActivity.emplace(true);
}
}
AutoEntryScript::AutoEntryScript(JSObject* aObject, const char* aReason,
bool aIsMainThread)
: AutoEntryScript(xpc::NativeGlobal(aObject), aReason, aIsMainThread) {
// xpc::NativeGlobal uses JS::GetNonCCWObjectGlobal, which asserts that
// aObject is not a CCW.
}
AutoEntryScript::~AutoEntryScript() = default;
AutoEntryScript::DocshellEntryMonitor::DocshellEntryMonitor(JSContext* aCx,
const char* aReason)
: JS::dbg::AutoEntryMonitor(aCx), mReason(aReason) {}
void AutoEntryScript::DocshellEntryMonitor::Entry(
JSContext* aCx, JSFunction* aFunction, JSScript* aScript,
JS::Handle<JS::Value> aAsyncStack, const char* aAsyncCause) {
JS::Rooted<JSFunction*> rootedFunction(aCx);
if (aFunction) {
rootedFunction = aFunction;
}
JS::Rooted<JSScript*> rootedScript(aCx);
if (aScript) {
rootedScript = aScript;
}
nsCOMPtr<nsPIDOMWindowInner> window = xpc::CurrentWindowOrNull(aCx);
if (!window || !window->GetDocShell() ||
!window->GetDocShell()->GetRecordProfileTimelineMarkers()) {
return;
}
nsCOMPtr<nsIDocShell> docShellForJSRunToCompletion = window->GetDocShell();
nsAutoJSString functionName;
if (rootedFunction) {
JS::Rooted<JSString*> displayId(aCx,
JS_GetFunctionDisplayId(rootedFunction));
if (displayId) {
if (!functionName.init(aCx, displayId)) {
JS_ClearPendingException(aCx);
return;
}
}
}
nsString filename;
uint32_t lineNumber = 0;
if (!rootedScript) {
rootedScript = JS_GetFunctionScript(aCx, rootedFunction);
}
if (rootedScript) {
CopyUTF8toUTF16(MakeStringSpan(JS_GetScriptFilename(rootedScript)),
filename);
lineNumber = JS_GetScriptBaseLineNumber(aCx, rootedScript);
}
if (!filename.IsEmpty() || !functionName.IsEmpty()) {
docShellForJSRunToCompletion->NotifyJSRunToCompletionStart(
mReason, functionName, filename, lineNumber, aAsyncStack, aAsyncCause);
}
}
void AutoEntryScript::DocshellEntryMonitor::Exit(JSContext* aCx) {
nsCOMPtr<nsPIDOMWindowInner> window = xpc::CurrentWindowOrNull(aCx);
// Not really worth checking GetRecordProfileTimelineMarkers here.
if (window && window->GetDocShell()) {
nsCOMPtr<nsIDocShell> docShellForJSRunToCompletion = window->GetDocShell();
docShellForJSRunToCompletion->NotifyJSRunToCompletionStop();
}
}
} // namespace mozilla::dom

View File

@ -0,0 +1,125 @@
/* -*- 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/. */
#ifndef DOM_SCRIPT_AUTOENTRYSCRIPT_H_
#define DOM_SCRIPT_AUTOENTRYSCRIPT_H_
#include "MainThreadUtils.h"
#include "js/Debug.h"
#include "js/TypeDecls.h"
#include "jsapi.h"
#include "mozilla/Attributes.h"
#include "mozilla/Maybe.h"
#include "mozilla/dom/JSExecutionManager.h"
#include "mozilla/dom/ScriptSettings.h"
#ifdef MOZ_GECKO_PROFILER
# include "mozilla/ProfilerLabels.h"
#endif
class nsIGlobalObject;
class nsIPrincipal;
namespace xpc {
class AutoScriptActivity;
}
namespace mozilla::dom {
/*
* Static helpers in ScriptSettings which track the number of listeners
* of Javascript RunToCompletion events. These should be used by the code in
* nsDocShell::SetRecordProfileTimelineMarkers to indicate to script
* settings that script run-to-completion needs to be monitored.
* SHOULD BE CALLED ONLY BY MAIN THREAD.
*/
void UseEntryScriptProfiling();
void UnuseEntryScriptProfiling();
/*
* A class that represents a new script entry point.
*
* |aReason| should be a statically-allocated C string naming the reason we're
* invoking JavaScript code: "setTimeout", "event", and so on. The devtools use
* these strings to label JS execution in timeline and profiling displays.
*
*/
class MOZ_STACK_CLASS AutoEntryScript : public AutoJSAPI {
public:
// Constructing the AutoEntryScript will ensure that it enters the
// Realm of aGlobalObject's JSObject and exposes that JSObject to active JS.
AutoEntryScript(nsIGlobalObject* aGlobalObject, const char* aReason,
bool aIsMainThread = NS_IsMainThread());
// aObject can be any object from the relevant global. It must not be a
// cross-compartment wrapper because CCWs are not associated with a single
// global.
//
// Constructing the AutoEntryScript will ensure that it enters the
// Realm of aObject JSObject and exposes aObject's global to active JS.
AutoEntryScript(JSObject* aObject, const char* aReason,
bool aIsMainThread = NS_IsMainThread());
~AutoEntryScript();
void SetWebIDLCallerPrincipal(nsIPrincipal* aPrincipal) {
mWebIDLCallerPrincipal = aPrincipal;
}
private:
// A subclass of AutoEntryMonitor that notifies the docshell.
class DocshellEntryMonitor final : public JS::dbg::AutoEntryMonitor {
public:
DocshellEntryMonitor(JSContext* aCx, const char* aReason);
// Please note that |aAsyncCause| here is owned by the caller, and its
// lifetime must outlive the lifetime of the DocshellEntryMonitor object.
// In practice, |aAsyncCause| is identical to |aReason| passed into
// the AutoEntryScript constructor, so the lifetime requirements are
// trivially satisfied by |aReason| being a statically allocated string.
void Entry(JSContext* aCx, JSFunction* aFunction,
JS::Handle<JS::Value> aAsyncStack,
const char* aAsyncCause) override {
Entry(aCx, aFunction, nullptr, aAsyncStack, aAsyncCause);
}
void Entry(JSContext* aCx, JSScript* aScript,
JS::Handle<JS::Value> aAsyncStack,
const char* aAsyncCause) override {
Entry(aCx, nullptr, aScript, aAsyncStack, aAsyncCause);
}
void Exit(JSContext* aCx) override;
private:
void Entry(JSContext* aCx, JSFunction* aFunction, JSScript* aScript,
JS::Handle<JS::Value> aAsyncStack, const char* aAsyncCause);
const char* mReason;
};
// It's safe to make this a weak pointer, since it's the subject principal
// when we go on the stack, so can't go away until after we're gone. In
// particular, this is only used from the CallSetup constructor, and only in
// the aIsJSImplementedWebIDL case. And in that case, the subject principal
// is the principal of the callee function that is part of the CallArgs just a
// bit up the stack, and which will outlive us. So we know the principal
// can't go away until then either.
nsIPrincipal* MOZ_NON_OWNING_REF mWebIDLCallerPrincipal;
friend nsIPrincipal* GetWebIDLCallerPrincipal();
Maybe<DocshellEntryMonitor> mDocShellEntryMonitor;
Maybe<xpc::AutoScriptActivity> mScriptActivity;
JS::AutoHideScriptedCaller mCallerOverride;
#ifdef MOZ_GECKO_PROFILER
AutoProfilerLabel mAutoProfilerLabel;
#endif
AutoRequestJSThreadExecution mJSThreadExecution;
};
} // namespace mozilla::dom
#endif // DOM_SCRIPT_AUTOENTRYSCRIPT_H_

View File

@ -29,6 +29,7 @@
#include "nsCycleCollectionParticipant.h"
#include "nsIContent.h"
#include "nsJSUtils.h"
#include "mozilla/dom/AutoEntryScript.h"
#include "mozilla/dom/DocGroup.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/JSExecutionContext.h"

View File

@ -5,32 +5,47 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/ScriptSettings.h"
#include <utility>
#include "LoadedScript.h"
#include "MainThreadUtils.h"
#include "js/CharacterEncoding.h"
#include "js/CompilationAndEvaluation.h"
#include "js/Conversions.h"
#include "js/ErrorReport.h"
#include "js/Exception.h"
#include "js/GCAPI.h"
#include "js/TypeDecls.h"
#include "js/Value.h"
#include "js/Warnings.h"
#include "js/Wrapper.h"
#include "js/friend/ErrorMessages.h"
#include "jsapi.h"
#include "mozilla/Assertions.h"
#include "mozilla/BasePrincipal.h"
#include "mozilla/CycleCollectedJSContext.h"
#include "mozilla/ThreadLocal.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/Maybe.h"
#include "mozilla/RefPtr.h"
#include "mozilla/ThreadLocal.h"
#include "mozilla/dom/AutoEntryScript.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/Document.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/JSExecutionManager.h"
#include "mozilla/dom/WorkerPrivate.h"
#include "jsapi.h"
#include "js/CompilationAndEvaluation.h"
#include "js/friend/ErrorMessages.h" // JSMSG_OUT_OF_MEMORY
#include "js/Warnings.h" // JS::{Get,}WarningReporter
#include "xpcpublic.h"
#include "nsIGlobalObject.h"
#include "nsIDocShell.h"
#include "nsIScriptGlobalObject.h"
#include "nsIScriptContext.h"
#include "mozilla/dom/ScriptLoadRequest.h"
#include "mozilla/dom/WorkerCommon.h"
#include "nsContentUtils.h"
#include "nsGlobalWindow.h"
#include "nsPIDOMWindow.h"
#include "nsTArray.h"
#include "nsDebug.h"
#include "nsGlobalWindowInner.h"
#include "nsIGlobalObject.h"
#include "nsINode.h"
#include "nsIPrincipal.h"
#include "nsISupports.h"
#include "nsJSUtils.h"
#include "nsDOMJSUtils.h"
#include "nsPIDOMWindow.h"
#include "nsString.h"
#include "nscore.h"
#include "xpcpublic.h"
namespace mozilla {
namespace dom {
@ -66,25 +81,6 @@ JSObject* GetElementCallback(JSContext* aCx, JS::HandleValue aValue) {
static MOZ_THREAD_LOCAL(ScriptSettingsStackEntry*) sScriptSettingsTLS;
// Assert if it's not safe to run script. The helper class
// AutoAllowLegacyScriptExecution allows to allow-list
// legacy cases where it's actually not safe to run script.
#ifdef DEBUG
static void AssertIfNotSafeToRunScript() {
// if it's safe to run script, then there is nothing to do here.
if (nsContentUtils::IsSafeToRunScript()) {
return;
}
// auto allowing legacy script execution is fine for now.
if (AutoAllowLegacyScriptExecution::IsAllowed()) {
return;
}
MOZ_ASSERT(false, "is it safe to run script?");
}
#endif
class ScriptSettingsStack {
public:
static ScriptSettingsStackEntry* Top() { return sScriptSettingsTLS.get(); }
@ -152,19 +148,6 @@ class ScriptSettingsStack {
#endif // DEBUG
};
static unsigned long gRunToCompletionListeners = 0;
void UseEntryScriptProfiling() {
MOZ_ASSERT(NS_IsMainThread());
++gRunToCompletionListeners;
}
void UnuseEntryScriptProfiling() {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(gRunToCompletionListeners > 0);
--gRunToCompletionListeners;
}
void InitScriptSettings() {
bool success = sScriptSettingsTLS.init();
if (!success) {
@ -632,106 +615,6 @@ bool AutoJSAPI::IsStackTop() const {
}
#endif // DEBUG
AutoEntryScript::AutoEntryScript(nsIGlobalObject* aGlobalObject,
const char* aReason, bool aIsMainThread)
: AutoJSAPI(aGlobalObject, aIsMainThread, eEntryScript),
mWebIDLCallerPrincipal(nullptr)
// This relies on us having a cx() because the AutoJSAPI constructor
// already ran.
,
mCallerOverride(cx())
#ifdef MOZ_GECKO_PROFILER
,
mAutoProfilerLabel(
"", aReason, JS::ProfilingCategoryPair::JS,
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS))
#endif
,
mJSThreadExecution(aGlobalObject, aIsMainThread) {
MOZ_ASSERT(aGlobalObject);
if (aIsMainThread) {
#ifdef DEBUG
AssertIfNotSafeToRunScript();
#endif
if (gRunToCompletionListeners > 0) {
mDocShellEntryMonitor.emplace(cx(), aReason);
}
mScriptActivity.emplace(true);
}
}
AutoEntryScript::AutoEntryScript(JSObject* aObject, const char* aReason,
bool aIsMainThread)
: AutoEntryScript(xpc::NativeGlobal(aObject), aReason, aIsMainThread) {
// xpc::NativeGlobal uses JS::GetNonCCWObjectGlobal, which asserts that
// aObject is not a CCW.
}
AutoEntryScript::~AutoEntryScript() = default;
AutoEntryScript::DocshellEntryMonitor::DocshellEntryMonitor(JSContext* aCx,
const char* aReason)
: JS::dbg::AutoEntryMonitor(aCx), mReason(aReason) {}
void AutoEntryScript::DocshellEntryMonitor::Entry(
JSContext* aCx, JSFunction* aFunction, JSScript* aScript,
JS::Handle<JS::Value> aAsyncStack, const char* aAsyncCause) {
JS::Rooted<JSFunction*> rootedFunction(aCx);
if (aFunction) {
rootedFunction = aFunction;
}
JS::Rooted<JSScript*> rootedScript(aCx);
if (aScript) {
rootedScript = aScript;
}
nsCOMPtr<nsPIDOMWindowInner> window = xpc::CurrentWindowOrNull(aCx);
if (!window || !window->GetDocShell() ||
!window->GetDocShell()->GetRecordProfileTimelineMarkers()) {
return;
}
nsCOMPtr<nsIDocShell> docShellForJSRunToCompletion = window->GetDocShell();
nsAutoJSString functionName;
if (rootedFunction) {
JS::Rooted<JSString*> displayId(aCx,
JS_GetFunctionDisplayId(rootedFunction));
if (displayId) {
if (!functionName.init(aCx, displayId)) {
JS_ClearPendingException(aCx);
return;
}
}
}
nsString filename;
uint32_t lineNumber = 0;
if (!rootedScript) {
rootedScript = JS_GetFunctionScript(aCx, rootedFunction);
}
if (rootedScript) {
CopyUTF8toUTF16(MakeStringSpan(JS_GetScriptFilename(rootedScript)),
filename);
lineNumber = JS_GetScriptBaseLineNumber(aCx, rootedScript);
}
if (!filename.IsEmpty() || !functionName.IsEmpty()) {
docShellForJSRunToCompletion->NotifyJSRunToCompletionStart(
mReason, functionName, filename, lineNumber, aAsyncStack, aAsyncCause);
}
}
void AutoEntryScript::DocshellEntryMonitor::Exit(JSContext* aCx) {
nsCOMPtr<nsPIDOMWindowInner> window = xpc::CurrentWindowOrNull(aCx);
// Not really worth checking GetRecordProfileTimelineMarkers here.
if (window && window->GetDocShell()) {
nsCOMPtr<nsIDocShell> docShellForJSRunToCompletion = window->GetDocShell();
docShellForJSRunToCompletion->NotifyJSRunToCompletionStop();
}
}
AutoIncumbentScript::AutoIncumbentScript(nsIGlobalObject* aGlobalObject)
: ScriptSettingsStackEntry(aGlobalObject, eIncumbentScript),
mCallerOverride(nsContentUtils::GetCurrentJSContext()) {

View File

@ -9,23 +9,15 @@
#ifndef mozilla_dom_ScriptSettings_h
#define mozilla_dom_ScriptSettings_h
#include "MainThreadUtils.h"
#include "xpcpublic.h"
#include "mozilla/dom/JSExecutionManager.h"
#include "mozilla/Maybe.h"
#include "jsapi.h"
#include "js/Debug.h"
#include "js/Warnings.h" // JS::WarningReporter
#ifdef MOZ_GECKO_PROFILER
# include "GeckoProfiler.h"
#endif
class JSFunction;
class JSObject;
class JSScript;
class nsIGlobalObject;
class nsIPrincipal;
class nsPIDOMWindowInner;
@ -50,16 +42,6 @@ class Document;
void InitScriptSettings();
void DestroyScriptSettings();
/*
* Static helpers in ScriptSettings which track the number of listeners
* of Javascript RunToCompletion events. These should be used by the code in
* nsDocShell::SetRecordProfileTimelineMarkers to indicate to script
* settings that script run-to-completion needs to be monitored.
* SHOULD BE CALLED ONLY BY MAIN THREAD.
*/
void UseEntryScriptProfiling();
void UnuseEntryScriptProfiling();
// To implement a web-compatible browser, it is often necessary to obtain the
// global object that is "associated" with the currently-running code. This
// process is made more complicated by the fact that, historically, different
@ -317,87 +299,6 @@ class MOZ_STACK_CLASS AutoJSAPI : protected ScriptSettingsStackEntry {
AutoJSAPI& operator=(const AutoJSAPI&) = delete;
};
/*
* A class that represents a new script entry point.
*
* |aReason| should be a statically-allocated C string naming the reason we're
* invoking JavaScript code: "setTimeout", "event", and so on. The devtools use
* these strings to label JS execution in timeline and profiling displays.
*
*/
class MOZ_STACK_CLASS AutoEntryScript : public AutoJSAPI {
public:
// Constructing the AutoEntryScript will ensure that it enters the
// Realm of aGlobalObject's JSObject and exposes that JSObject to active JS.
AutoEntryScript(nsIGlobalObject* aGlobalObject, const char* aReason,
bool aIsMainThread = NS_IsMainThread());
// aObject can be any object from the relevant global. It must not be a
// cross-compartment wrapper because CCWs are not associated with a single
// global.
//
// Constructing the AutoEntryScript will ensure that it enters the
// Realm of aObject JSObject and exposes aObject's global to active JS.
AutoEntryScript(JSObject* aObject, const char* aReason,
bool aIsMainThread = NS_IsMainThread());
~AutoEntryScript();
void SetWebIDLCallerPrincipal(nsIPrincipal* aPrincipal) {
mWebIDLCallerPrincipal = aPrincipal;
}
private:
// A subclass of AutoEntryMonitor that notifies the docshell.
class DocshellEntryMonitor final : public JS::dbg::AutoEntryMonitor {
public:
DocshellEntryMonitor(JSContext* aCx, const char* aReason);
// Please note that |aAsyncCause| here is owned by the caller, and its
// lifetime must outlive the lifetime of the DocshellEntryMonitor object.
// In practice, |aAsyncCause| is identical to |aReason| passed into
// the AutoEntryScript constructor, so the lifetime requirements are
// trivially satisfied by |aReason| being a statically allocated string.
void Entry(JSContext* aCx, JSFunction* aFunction,
JS::Handle<JS::Value> aAsyncStack,
const char* aAsyncCause) override {
Entry(aCx, aFunction, nullptr, aAsyncStack, aAsyncCause);
}
void Entry(JSContext* aCx, JSScript* aScript,
JS::Handle<JS::Value> aAsyncStack,
const char* aAsyncCause) override {
Entry(aCx, nullptr, aScript, aAsyncStack, aAsyncCause);
}
void Exit(JSContext* aCx) override;
private:
void Entry(JSContext* aCx, JSFunction* aFunction, JSScript* aScript,
JS::Handle<JS::Value> aAsyncStack, const char* aAsyncCause);
const char* mReason;
};
// It's safe to make this a weak pointer, since it's the subject principal
// when we go on the stack, so can't go away until after we're gone. In
// particular, this is only used from the CallSetup constructor, and only in
// the aIsJSImplementedWebIDL case. And in that case, the subject principal
// is the principal of the callee function that is part of the CallArgs just a
// bit up the stack, and which will outlive us. So we know the principal
// can't go away until then either.
nsIPrincipal* MOZ_NON_OWNING_REF mWebIDLCallerPrincipal;
friend nsIPrincipal* GetWebIDLCallerPrincipal();
Maybe<DocshellEntryMonitor> mDocShellEntryMonitor;
Maybe<xpc::AutoScriptActivity> mScriptActivity;
JS::AutoHideScriptedCaller mCallerOverride;
#ifdef MOZ_GECKO_PROFILER
AutoProfilerLabel mAutoProfilerLabel;
#endif
AutoRequestJSThreadExecution mJSThreadExecution;
};
/*
* A class that can be used to force a particular incumbent script on the stack.
*/

View File

@ -18,6 +18,7 @@ EXPORTS += [
]
EXPORTS.mozilla.dom += [
"AutoEntryScript.h",
"LoadedScript.h",
"ScriptDecoding.h",
"ScriptElement.h",
@ -28,6 +29,7 @@ EXPORTS.mozilla.dom += [
]
UNIFIED_SOURCES += [
"AutoEntryScript.cpp",
"LoadedScript.cpp",
"ModuleLoadRequest.cpp",
"nsIScriptElement.cpp",

View File

@ -39,6 +39,7 @@
#include "mozilla/StorageAccess.h"
#include "mozilla/TaskCategory.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/dom/AutoEntryScript.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/BlobURLProtocolHandler.h"

View File

@ -7,6 +7,7 @@
#include "Worklet.h"
#include "WorkletThread.h"
#include "mozilla/dom/AutoEntryScript.h"
#include "mozilla/dom/WorkletBinding.h"
#include "mozilla/dom/WorkletGlobalScope.h"
#include "mozilla/dom/BlobBinding.h"

View File

@ -41,6 +41,7 @@
#include "mozilla/Telemetry.h"
#ifdef MOZ_GECKO_PROFILER
# include "mozilla/BaseProfilerMarkerTypes.h"
# include "GeckoProfiler.h"
#endif
namespace mozilla {

View File

@ -44,6 +44,10 @@
using namespace mozilla::tasktracer;
#endif
#ifdef MOZ_GECKO_PROFILER
# include "GeckoProfiler.h"
#endif
// Undo the damage done by mozzconf.h
#undef compress
@ -2788,6 +2792,7 @@ void MessageChannel::DumpInterruptStack(const char* const pfx) const {
void MessageChannel::AddProfilerMarker(const IPC::Message& aMessage,
MessageDirection aDirection) {
mMonitor->AssertCurrentThreadOwns();
#ifdef MOZ_GECKO_PROFILER
if (profiler_feature_active(ProfilerFeature::IPCMessages)) {
int32_t pid = mListener->OtherPidMaybeInvalid();

View File

@ -8,6 +8,7 @@
#include "jsfriendapi.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/dom/AutoEntryScript.h"
#include "mozilla/dom/ScriptSettings.h"
#include "xpcpublic.h"

View File

@ -27,6 +27,7 @@
#include "mozilla/Utf8.h" // mozilla::Utf8Unit
#include "mozilla/XPCOM.h"
#include "mozilla/dom/AutoEntryScript.h"
#include "mozilla/dom/ScriptSettings.h"
#include "nsIPrincipal.h"

View File

@ -62,6 +62,7 @@
#include "mozilla/ResultExtensions.h"
#include "mozilla/ScriptPreloader.h"
#include "mozilla/ScopeExit.h"
#include "mozilla/dom/AutoEntryScript.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/ResultExtensions.h"
#include "mozilla/UniquePtrExtensions.h"

View File

@ -32,6 +32,7 @@
#include "xpc_make_class.h"
#include "XPCWrapper.h"
#include "Crypto.h"
#include "mozilla/dom/AutoEntryScript.h"
#include "mozilla/dom/BindingCallContext.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/BlobBinding.h"

View File

@ -80,7 +80,6 @@
using namespace mozilla;
using namespace xpc;
using namespace JS;
using mozilla::dom::AutoEntryScript;
// The watchdog thread loop is pretty trivial, and should not require much stack
// space to do its job. So only give it 32KiB or the platform minimum.

View File

@ -86,7 +86,6 @@
using namespace mozilla;
using namespace xpc;
using namespace JS;
using mozilla::dom::AutoEntryScript;
using mozilla::dom::PerThreadAtomCache;
/***************************************************************************/

View File

@ -15,6 +15,7 @@
#include "js/PropertySpec.h"
#include "js/SourceText.h" // JS::SourceText
#include "mozilla/ChaosMode.h"
#include "mozilla/dom/AutoEntryScript.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/IOInterposer.h"
#include "mozilla/Preferences.h"

View File

@ -17,6 +17,7 @@
#include "nsJSUtils.h"
#include "nsPrintfCString.h"
#include "mozilla/Attributes.h"
#include "mozilla/dom/AutoEntryScript.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/DOMException.h"
#include "mozilla/dom/DOMExceptionBinding.h"

View File

@ -161,6 +161,7 @@
namespace mozilla {
namespace dom {
class AutoEntryScript;
class Exception;
} // namespace dom
} // namespace mozilla

View File

@ -114,6 +114,10 @@
#include "mozilla/layers/WebRenderMessages.h"
#include "mozilla/layers/WebRenderScrollData.h"
#ifdef MOZ_GECKO_PROFILER
# include "GeckoProfiler.h"
#endif
using namespace mozilla;
using namespace mozilla::layers;
using namespace mozilla::dom;

View File

@ -5,6 +5,7 @@
#include "nsSocketTransportService2.h"
#include "GeckoProfiler.h"
#include "IOActivityMonitor.h"
#include "mozilla/Atomics.h"
#include "mozilla/ChaosMode.h"

View File

@ -15,6 +15,7 @@
#include "mozilla/extensions/StreamFilterChild.h"
#include "mozilla/extensions/StreamFilterEvents.h"
#include "mozilla/extensions/StreamFilterParent.h"
#include "mozilla/dom/AutoEntryScript.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/ipc/Endpoint.h"
#include "nsContentUtils.h"

View File

@ -77,6 +77,7 @@
#include "mozilla/TimelineConsumers.h"
#include "mozilla/TimelineMarker.h"
#include "mozilla/Unused.h"
#include "mozilla/dom/AutoEntryScript.h"
#include "mozilla/dom/DOMJSClass.h"
#include "mozilla/dom/JSExecutionManager.h"
#include "mozilla/dom/ProfileTimelineMarkerBinding.h"