From c45b7ee3a985b2b4862fb182cdb34f644f737048 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Tue, 30 Jun 2020 11:32:07 +0000 Subject: Issue #1603 - Part 1: Reorganize ScriptLoader/ScriptElement - Moves scripting parts of DOM into 'dom/script' - Renames nsScript{Loader/Element} to Script{Loader/Element} - Adjusts all callers --- dom/base/ImportManager.cpp | 8 +- dom/base/ImportManager.h | 8 +- dom/base/Location.cpp | 2 +- dom/base/ScriptSettings.cpp | 839 -------- dom/base/ScriptSettings.h | 465 ----- dom/base/moz.build | 7 - dom/base/nsContentPermissionHelper.cpp | 3 +- dom/base/nsContentSink.cpp | 2 +- dom/base/nsContentSink.h | 7 +- dom/base/nsDocument.cpp | 4 +- dom/base/nsDocument.h | 6 +- dom/base/nsFrameMessageManager.cpp | 8 +- dom/base/nsGlobalWindow.cpp | 2 +- dom/base/nsIDocument.h | 4 +- dom/base/nsIScriptElement.h | 329 ---- dom/base/nsIScriptLoaderObserver.idl | 47 - dom/base/nsInProcessTabChildGlobal.cpp | 2 +- dom/base/nsJSEnvironment.cpp | 2 +- dom/base/nsScriptElement.cpp | 150 -- dom/base/nsScriptElement.h | 52 - dom/base/nsScriptLoader.cpp | 3061 ----------------------------- dom/base/nsScriptLoader.h | 717 ------- dom/console/Console.cpp | 2 +- dom/events/DOMEventTargetHelper.cpp | 2 +- dom/html/HTMLScriptElement.cpp | 2 +- dom/html/HTMLScriptElement.h | 7 +- dom/html/nsGenericHTMLElement.cpp | 2 +- dom/html/nsHTMLContentSink.cpp | 2 +- dom/messagechannel/MessagePort.cpp | 2 +- dom/moz.build | 1 + dom/script/ScriptElement.cpp | 150 ++ dom/script/ScriptElement.h | 58 + dom/script/ScriptLoader.cpp | 3063 ++++++++++++++++++++++++++++++ dom/script/ScriptLoader.h | 719 +++++++ dom/script/ScriptSettings.cpp | 839 ++++++++ dom/script/ScriptSettings.h | 465 +++++ dom/script/moz.build | 33 + dom/script/nsIScriptElement.h | 329 ++++ dom/script/nsIScriptLoaderObserver.idl | 47 + dom/svg/SVGScriptElement.cpp | 4 +- dom/svg/SVGScriptElement.h | 6 +- dom/workers/ScriptLoader.cpp | 20 +- dom/workers/ServiceWorkerManager.cpp | 2 +- dom/workers/ServiceWorkerScriptCache.cpp | 14 +- dom/worklet/Worklet.cpp | 8 +- dom/xml/nsXMLContentSink.cpp | 2 +- dom/xml/nsXMLFragmentContentSink.cpp | 2 +- dom/xslt/xslt/txMozillaXMLOutput.cpp | 8 +- dom/xul/XULDocument.cpp | 8 +- dom/xul/XULDocument.h | 2 +- dom/xul/nsXULContentSink.cpp | 2 +- 51 files changed, 5783 insertions(+), 5743 deletions(-) delete mode 100644 dom/base/ScriptSettings.cpp delete mode 100644 dom/base/ScriptSettings.h delete mode 100644 dom/base/nsIScriptElement.h delete mode 100644 dom/base/nsIScriptLoaderObserver.idl delete mode 100644 dom/base/nsScriptElement.cpp delete mode 100644 dom/base/nsScriptElement.h delete mode 100644 dom/base/nsScriptLoader.cpp delete mode 100644 dom/base/nsScriptLoader.h create mode 100644 dom/script/ScriptElement.cpp create mode 100644 dom/script/ScriptElement.h create mode 100644 dom/script/ScriptLoader.cpp create mode 100644 dom/script/ScriptLoader.h create mode 100644 dom/script/ScriptSettings.cpp create mode 100644 dom/script/ScriptSettings.h create mode 100644 dom/script/moz.build create mode 100644 dom/script/nsIScriptElement.h create mode 100644 dom/script/nsIScriptLoaderObserver.idl (limited to 'dom') diff --git a/dom/base/ImportManager.cpp b/dom/base/ImportManager.cpp index d0e514b59..1f4d376b3 100644 --- a/dom/base/ImportManager.cpp +++ b/dom/base/ImportManager.cpp @@ -6,6 +6,7 @@ #include "ImportManager.h" +#include "mozilla/dom/ScriptLoader.h" #include "mozilla/EventListenerManager.h" #include "HTMLLinkElement.h" #include "nsContentPolicyUtils.h" @@ -18,7 +19,6 @@ #include "nsIDOMEvent.h" #include "nsIPrincipal.h" #include "nsIScriptObjectPrincipal.h" -#include "nsScriptLoader.h" #include "nsNetUtil.h" //----------------------------------------------------------------------------- @@ -156,7 +156,7 @@ ImportLoader::Updater::UpdateMainReferrer(uint32_t aNewIdx) // Our nearest predecessor has changed. So let's add the ScriptLoader to the // new one if there is any. And remove it from the old one. RefPtr manager = mLoader->Manager(); - nsScriptLoader* loader = mLoader->mDocument->ScriptLoader(); + ScriptLoader* loader = mLoader->mDocument->ScriptLoader(); ImportLoader*& pred = mLoader->mBlockingPredecessor; ImportLoader* newPred = manager->GetNearestPredecessor(newMainReferrer); if (pred) { @@ -339,7 +339,7 @@ ImportLoader::DispatchEventIfFinished(nsINode* aNode) } void -ImportLoader::AddBlockedScriptLoader(nsScriptLoader* aScriptLoader) +ImportLoader::AddBlockedScriptLoader(ScriptLoader* aScriptLoader) { if (mBlockedScriptLoaders.Contains(aScriptLoader)) { return; @@ -352,7 +352,7 @@ ImportLoader::AddBlockedScriptLoader(nsScriptLoader* aScriptLoader) } bool -ImportLoader::RemoveBlockedScriptLoader(nsScriptLoader* aScriptLoader) +ImportLoader::RemoveBlockedScriptLoader(ScriptLoader* aScriptLoader) { aScriptLoader->RemoveParserBlockingScriptExecutionBlocker(); return mBlockedScriptLoaders.RemoveElement(aScriptLoader); diff --git a/dom/base/ImportManager.h b/dom/base/ImportManager.h index 258d4691c..ccc00125a 100644 --- a/dom/base/ImportManager.h +++ b/dom/base/ImportManager.h @@ -45,8 +45,8 @@ #include "nsIStreamListener.h" #include "nsIWeakReferenceUtils.h" #include "nsRefPtrHashtable.h" -#include "nsScriptLoader.h" #include "nsURIHashKey.h" +#include "mozilla/dom/ScriptLoader.h" class nsIDocument; class nsIPrincipal; @@ -184,8 +184,8 @@ public: // and wait for that to run its scripts. We keep track of all the // ScriptRunners that are waiting for this import. NOTE: updating // the main referrer might change this list. - void AddBlockedScriptLoader(nsScriptLoader* aScriptLoader); - bool RemoveBlockedScriptLoader(nsScriptLoader* aScriptLoader); + void AddBlockedScriptLoader(ScriptLoader* aScriptLoader); + bool RemoveBlockedScriptLoader(ScriptLoader* aScriptLoader); void SetBlockingPredecessor(ImportLoader* aLoader); private: @@ -230,7 +230,7 @@ private: // List of pending ScriptLoaders that are waiting for this import // to finish. - nsTArray> mBlockedScriptLoaders; + nsTArray> mBlockedScriptLoaders; // There is always exactly one referrer link that is flagged as // the main referrer the primary link. This is the one that is diff --git a/dom/base/Location.cpp b/dom/base/Location.cpp index 1483c32f9..308e9a4ff 100644 --- a/dom/base/Location.cpp +++ b/dom/base/Location.cpp @@ -32,9 +32,9 @@ #include "mozilla/Likely.h" #include "nsCycleCollectionParticipant.h" #include "nsNullPrincipal.h" -#include "ScriptSettings.h" #include "mozilla/Unused.h" #include "mozilla/dom/LocationBinding.h" +#include "mozilla/dom/ScriptSettings.h" namespace mozilla { namespace dom { diff --git a/dom/base/ScriptSettings.cpp b/dom/base/ScriptSettings.cpp deleted file mode 100644 index 92ab221c9..000000000 --- a/dom/base/ScriptSettings.cpp +++ /dev/null @@ -1,839 +0,0 @@ -/* -*- 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/ScriptSettings.h" -#include "mozilla/ThreadLocal.h" -#include "mozilla/Assertions.h" -#include "mozilla/CycleCollectedJSContext.h" - -#include "jsapi.h" -#include "xpcpublic.h" -#include "nsIGlobalObject.h" -#include "nsIDocShell.h" -#include "nsIScriptGlobalObject.h" -#include "nsIScriptContext.h" -#include "nsContentUtils.h" -#include "nsGlobalWindow.h" -#include "nsPIDOMWindow.h" -#include "nsTArray.h" -#include "nsJSUtils.h" -#include "nsDOMJSUtils.h" -#include "WorkerPrivate.h" - -namespace mozilla { -namespace dom { - -static MOZ_THREAD_LOCAL(ScriptSettingsStackEntry*) sScriptSettingsTLS; -static bool sScriptSettingsTLSInitialized; - -class ScriptSettingsStack { -public: - static ScriptSettingsStackEntry* Top() { - return sScriptSettingsTLS.get(); - } - - static void Push(ScriptSettingsStackEntry *aEntry) { - MOZ_ASSERT(!aEntry->mOlder); - // Whenever JSAPI use is disabled, the next stack entry pushed must - // not be an AutoIncumbentScript. - MOZ_ASSERT_IF(!Top() || Top()->NoJSAPI(), - !aEntry->IsIncumbentScript()); - // Whenever the top entry is not an incumbent canidate, the next stack entry - // pushed must not be an AutoIncumbentScript. - MOZ_ASSERT_IF(Top() && !Top()->IsIncumbentCandidate(), - !aEntry->IsIncumbentScript()); - - aEntry->mOlder = Top(); - sScriptSettingsTLS.set(aEntry); - } - - static void Pop(ScriptSettingsStackEntry *aEntry) { - MOZ_ASSERT(aEntry == Top()); - sScriptSettingsTLS.set(aEntry->mOlder); - } - - static nsIGlobalObject* IncumbentGlobal() { - ScriptSettingsStackEntry *entry = Top(); - while (entry) { - if (entry->IsIncumbentCandidate()) { - return entry->mGlobalObject; - } - entry = entry->mOlder; - } - return nullptr; - } - - static ScriptSettingsStackEntry* EntryPoint() { - ScriptSettingsStackEntry *entry = Top(); - while (entry) { - if (entry->IsEntryCandidate()) { - return entry; - } - entry = entry->mOlder; - } - return nullptr; - } - - static nsIGlobalObject* EntryGlobal() { - ScriptSettingsStackEntry *entry = EntryPoint(); - if (!entry) { - return nullptr; - } - return entry->mGlobalObject; - } - -#ifdef DEBUG - static ScriptSettingsStackEntry* TopNonIncumbentScript() { - ScriptSettingsStackEntry *entry = Top(); - while (entry) { - if (!entry->IsIncumbentScript()) { - return entry; - } - entry = entry->mOlder; - } - return nullptr; - } -#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) { - MOZ_CRASH(); - } - - sScriptSettingsTLS.set(nullptr); - sScriptSettingsTLSInitialized = true; -} - -void -DestroyScriptSettings() -{ - MOZ_ASSERT(sScriptSettingsTLS.get() == nullptr); -} - -bool -ScriptSettingsInitialized() -{ - return sScriptSettingsTLSInitialized; -} - -ScriptSettingsStackEntry::ScriptSettingsStackEntry(nsIGlobalObject *aGlobal, - Type aType) - : mGlobalObject(aGlobal) - , mType(aType) - , mOlder(nullptr) -{ - MOZ_ASSERT_IF(IsIncumbentCandidate() && !NoJSAPI(), mGlobalObject); - MOZ_ASSERT(!mGlobalObject || mGlobalObject->GetGlobalJSObject(), - "Must have an actual JS global for the duration on the stack"); - MOZ_ASSERT(!mGlobalObject || - JS_IsGlobalObject(mGlobalObject->GetGlobalJSObject()), - "No outer windows allowed"); -} - -ScriptSettingsStackEntry::~ScriptSettingsStackEntry() -{ - // We must have an actual JS global for the entire time this is on the stack. - MOZ_ASSERT_IF(mGlobalObject, mGlobalObject->GetGlobalJSObject()); -} - -// If the entry or incumbent global ends up being something that the subject -// principal doesn't subsume, we don't want to use it. This never happens on -// the web, but can happen with asymmetric privilege relationships (i.e. -// nsExpandedPrincipal and System Principal). -// -// The most correct thing to use instead would be the topmost global on the -// callstack whose principal is subsumed by the subject principal. But that's -// hard to compute, so we just substitute the global of the current -// compartment. In practice, this is fine. -// -// Note that in particular things like: -// -// |SpecialPowers.wrap(crossOriginWindow).eval(open())| -// -// trigger this case. Although both the entry global and the current global -// have normal principals, the use of Gecko-specific System-Principaled JS -// puts the code from two different origins on the callstack at once, which -// doesn't happen normally on the web. -static nsIGlobalObject* -ClampToSubject(nsIGlobalObject* aGlobalOrNull) -{ - if (!aGlobalOrNull || !NS_IsMainThread()) { - return aGlobalOrNull; - } - - nsIPrincipal* globalPrin = aGlobalOrNull->PrincipalOrNull(); - NS_ENSURE_TRUE(globalPrin, GetCurrentGlobal()); - if (!nsContentUtils::SubjectPrincipalOrSystemIfNativeCaller()->SubsumesConsideringDomain(globalPrin)) { - return GetCurrentGlobal(); - } - - return aGlobalOrNull; -} - -nsIGlobalObject* -GetEntryGlobal() -{ - return ClampToSubject(ScriptSettingsStack::EntryGlobal()); -} - -nsIDocument* -GetEntryDocument() -{ - nsIGlobalObject* global = GetEntryGlobal(); - nsCOMPtr entryWin = do_QueryInterface(global); - - // If our entry global isn't a window, see if it's an addon scope associated - // with a window. If it is, the caller almost certainly wants that rather - // than null. - if (!entryWin && global) { - if (auto* win = xpc::AddonWindowOrNull(global->GetGlobalJSObject())) { - entryWin = win->AsInner(); - } - } - - return entryWin ? entryWin->GetExtantDoc() : nullptr; -} - -nsIGlobalObject* -GetIncumbentGlobal() -{ - // We need the current JSContext in order to check the JS for - // scripted frames that may have appeared since anyone last - // manipulated the stack. If it's null, that means that there - // must be no entry global on the stack, and therefore no incumbent - // global either. - JSContext *cx = nsContentUtils::GetCurrentJSContextForThread(); - if (!cx) { - MOZ_ASSERT(ScriptSettingsStack::EntryGlobal() == nullptr); - return nullptr; - } - - // See what the JS engine has to say. If we've got a scripted caller - // override in place, the JS engine will lie to us and pretend that - // there's nothing on the JS stack, which will cause us to check the - // incumbent script stack below. - if (JSObject *global = JS::GetScriptedCallerGlobal(cx)) { - return ClampToSubject(xpc::NativeGlobal(global)); - } - - // Ok, nothing from the JS engine. Let's use whatever's on the - // explicit stack. - return ClampToSubject(ScriptSettingsStack::IncumbentGlobal()); -} - -nsIGlobalObject* -GetCurrentGlobal() -{ - JSContext *cx = nsContentUtils::GetCurrentJSContextForThread(); - if (!cx) { - return nullptr; - } - - JSObject *global = JS::CurrentGlobalOrNull(cx); - if (!global) { - return nullptr; - } - - return xpc::NativeGlobal(global); -} - -nsIPrincipal* -GetWebIDLCallerPrincipal() -{ - MOZ_ASSERT(NS_IsMainThread()); - ScriptSettingsStackEntry *entry = ScriptSettingsStack::EntryPoint(); - - // If we have an entry point that is not NoJSAPI, we know it must be an - // AutoEntryScript. - if (!entry || entry->NoJSAPI()) { - return nullptr; - } - AutoEntryScript* aes = static_cast(entry); - - return aes->mWebIDLCallerPrincipal; -} - -bool -IsJSAPIActive() -{ - ScriptSettingsStackEntry* topEntry = ScriptSettingsStack::Top(); - return topEntry && !topEntry->NoJSAPI(); -} - -namespace danger { -JSContext* -GetJSContext() -{ - return CycleCollectedJSContext::Get()->Context(); -} -} // namespace danger - -JS::RootingContext* -RootingCx() -{ - return CycleCollectedJSContext::Get()->RootingCx(); -} - -AutoJSAPI::AutoJSAPI() - : ScriptSettingsStackEntry(nullptr, eJSAPI) - , mCx(nullptr) - , mIsMainThread(false) // For lack of anything better -{ -} - -AutoJSAPI::~AutoJSAPI() -{ - if (!mCx) { - // No need to do anything here: we never managed to Init, so can't have an - // exception on our (nonexistent) JSContext. We also don't need to restore - // any state on it. Finally, we never made it to pushing outselves onto the - // ScriptSettingsStack, so shouldn't pop. - MOZ_ASSERT(ScriptSettingsStack::Top() != this); - return; - } - - ReportException(); - - if (mOldWarningReporter.isSome()) { - JS::SetWarningReporter(cx(), mOldWarningReporter.value()); - } - - // Leave the request before popping. - if (mIsMainThread) { - mAutoRequest.reset(); - } - - ScriptSettingsStack::Pop(this); -} - -void -WarningOnlyErrorReporter(JSContext* aCx, JSErrorReport* aRep); - -void -AutoJSAPI::InitInternal(nsIGlobalObject* aGlobalObject, JSObject* aGlobal, - JSContext* aCx, bool aIsMainThread) -{ - MOZ_ASSERT(aCx); - MOZ_ASSERT(aCx == danger::GetJSContext()); - MOZ_ASSERT(aIsMainThread == NS_IsMainThread()); - MOZ_ASSERT(bool(aGlobalObject) == bool(aGlobal)); - MOZ_ASSERT_IF(aGlobalObject, aGlobalObject->GetGlobalJSObject() == aGlobal); -#ifdef DEBUG - bool haveException = JS_IsExceptionPending(aCx); -#endif // DEBUG - - mCx = aCx; - mIsMainThread = aIsMainThread; - mGlobalObject = aGlobalObject; - if (aIsMainThread) { - // We _could_ just unconditionally emplace mAutoRequest here. It's just not - // needed on worker threads, and we're hoping to kill it on the main thread - // too. - mAutoRequest.emplace(mCx); - } - if (aGlobal) { - JS::ExposeObjectToActiveJS(aGlobal); - } - mAutoNullableCompartment.emplace(mCx, aGlobal); - - ScriptSettingsStack::Push(this); - - mOldWarningReporter.emplace(JS::GetWarningReporter(aCx)); - - JS::SetWarningReporter(aCx, WarningOnlyErrorReporter); - -#ifdef DEBUG - if (haveException) { - JS::Rooted exn(aCx); - JS_GetPendingException(aCx, &exn); - - JS_ClearPendingException(aCx); - if (exn.isObject()) { - JS::Rooted exnObj(aCx, &exn.toObject()); - - nsAutoJSString stack, filename, name, message; - int32_t line; - - JS::Rooted tmp(aCx); - if (!JS_GetProperty(aCx, exnObj, "filename", &tmp)) { - JS_ClearPendingException(aCx); - } - if (tmp.isUndefined()) { - if (!JS_GetProperty(aCx, exnObj, "fileName", &tmp)) { - JS_ClearPendingException(aCx); - } - } - - if (!filename.init(aCx, tmp)) { - JS_ClearPendingException(aCx); - } - - if (!JS_GetProperty(aCx, exnObj, "stack", &tmp) || - !stack.init(aCx, tmp)) { - JS_ClearPendingException(aCx); - } - - if (!JS_GetProperty(aCx, exnObj, "name", &tmp) || - !name.init(aCx, tmp)) { - JS_ClearPendingException(aCx); - } - - if (!JS_GetProperty(aCx, exnObj, "message", &tmp) || - !message.init(aCx, tmp)) { - JS_ClearPendingException(aCx); - } - - if (!JS_GetProperty(aCx, exnObj, "lineNumber", &tmp) || - !JS::ToInt32(aCx, tmp, &line)) { - JS_ClearPendingException(aCx); - line = 0; - } - - printf_stderr("PREEXISTING EXCEPTION OBJECT: '%s: %s'\n%s:%d\n%s\n", - NS_ConvertUTF16toUTF8(name).get(), - NS_ConvertUTF16toUTF8(message).get(), - NS_ConvertUTF16toUTF8(filename).get(), line, - NS_ConvertUTF16toUTF8(stack).get()); - } else { - // It's a primitive... not much we can do other than stringify it. - nsAutoJSString exnStr; - if (!exnStr.init(aCx, exn)) { - JS_ClearPendingException(aCx); - } - - printf_stderr("PREEXISTING EXCEPTION PRIMITIVE: %s\n", - NS_ConvertUTF16toUTF8(exnStr).get()); - } - MOZ_ASSERT(false, "We had an exception; we should not have"); - } -#endif // DEBUG -} - -AutoJSAPI::AutoJSAPI(nsIGlobalObject* aGlobalObject, - bool aIsMainThread, - Type aType) - : ScriptSettingsStackEntry(aGlobalObject, aType) - , mIsMainThread(aIsMainThread) -{ - MOZ_ASSERT(aGlobalObject); - MOZ_ASSERT(aGlobalObject->GetGlobalJSObject(), "Must have a JS global"); - MOZ_ASSERT(aIsMainThread == NS_IsMainThread()); - - InitInternal(aGlobalObject, aGlobalObject->GetGlobalJSObject(), - danger::GetJSContext(), aIsMainThread); -} - -void -AutoJSAPI::Init() -{ - MOZ_ASSERT(!mCx, "An AutoJSAPI should only be initialised once"); - - InitInternal(/* aGlobalObject */ nullptr, /* aGlobal */ nullptr, - danger::GetJSContext(), NS_IsMainThread()); -} - -bool -AutoJSAPI::Init(nsIGlobalObject* aGlobalObject, JSContext* aCx) -{ - MOZ_ASSERT(!mCx, "An AutoJSAPI should only be initialised once"); - MOZ_ASSERT(aCx); - - if (NS_WARN_IF(!aGlobalObject)) { - return false; - } - - JSObject* global = aGlobalObject->GetGlobalJSObject(); - if (NS_WARN_IF(!global)) { - return false; - } - - InitInternal(aGlobalObject, global, aCx, NS_IsMainThread()); - return true; -} - -bool -AutoJSAPI::Init(nsIGlobalObject* aGlobalObject) -{ - return Init(aGlobalObject, danger::GetJSContext()); -} - -bool -AutoJSAPI::Init(JSObject* aObject) -{ - nsIGlobalObject* global = nullptr; - if (aObject) - global = xpc::NativeGlobal(aObject); - if (global) - return Init(global); - else - return false; -} - -bool -AutoJSAPI::Init(nsPIDOMWindowInner* aWindow, JSContext* aCx) -{ - return Init(nsGlobalWindow::Cast(aWindow), aCx); -} - -bool -AutoJSAPI::Init(nsPIDOMWindowInner* aWindow) -{ - return Init(nsGlobalWindow::Cast(aWindow)); -} - -bool -AutoJSAPI::Init(nsGlobalWindow* aWindow, JSContext* aCx) -{ - return Init(static_cast(aWindow), aCx); -} - -bool -AutoJSAPI::Init(nsGlobalWindow* aWindow) -{ - return Init(static_cast(aWindow)); -} - -// Even with autoJSAPIOwnsErrorReporting, the JS engine still sends warning -// reports to the JSErrorReporter as soon as they are generated. These go -// directly to the console, so we can handle them easily here. -// -// Eventually, SpiderMonkey will have a special-purpose callback for warnings -// only. -void -WarningOnlyErrorReporter(JSContext* aCx, JSErrorReport* aRep) -{ - MOZ_ASSERT(JSREPORT_IS_WARNING(aRep->flags)); - if (!NS_IsMainThread()) { - // Reporting a warning on workers is a bit complicated because we have to - // climb our parent chain until we get to the main thread. So go ahead and - // just go through the worker ReportError codepath here. - // - // That said, it feels like we should be able to short-circuit things a bit - // here by posting an appropriate runnable to the main thread directly... - // Worth looking into sometime. - workers::WorkerPrivate* worker = workers::GetWorkerPrivateFromContext(aCx); - MOZ_ASSERT(worker); - - worker->ReportError(aCx, JS::ConstUTF8CharsZ(), aRep); - return; - } - - RefPtr xpcReport = new xpc::ErrorReport(); - nsGlobalWindow* win = xpc::CurrentWindowOrNull(aCx); - if (!win) { - // We run addons in a separate privileged compartment, but if we're in an - // addon compartment we should log warnings to the console of the associated - // DOM Window. - win = xpc::AddonWindowOrNull(JS::CurrentGlobalOrNull(aCx)); - } - xpcReport->Init(aRep, nullptr, nsContentUtils::IsCallerChrome(), - win ? win->AsInner()->WindowID() : 0); - xpcReport->LogToConsole(); -} - -void -AutoJSAPI::ReportException() -{ - if (!HasException()) { - return; - } - - // AutoJSAPI uses a JSAutoNullableCompartment, and may be in a null - // compartment when the destructor is called. However, the JS engine - // requires us to be in a compartment when we fetch the pending exception. - // In this case, we enter the privileged junk scope and don't dispatch any - // error events. - JS::Rooted errorGlobal(cx(), JS::CurrentGlobalOrNull(cx())); - if (!errorGlobal) { - if (mIsMainThread) { - errorGlobal = xpc::PrivilegedJunkScope(); - } else { - errorGlobal = workers::GetCurrentThreadWorkerGlobal(); - } - } - JSAutoCompartment ac(cx(), errorGlobal); - JS::Rooted exn(cx()); - js::ErrorReport jsReport(cx()); - if (StealException(&exn) && - jsReport.init(cx(), exn, js::ErrorReport::WithSideEffects)) { - if (mIsMainThread) { - RefPtr xpcReport = new xpc::ErrorReport(); - - RefPtr win = xpc::WindowGlobalOrNull(errorGlobal); - if (!win) { - // We run addons in a separate privileged compartment, but they still - // expect to trigger the onerror handler of their associated DOM Window. - win = xpc::AddonWindowOrNull(errorGlobal); - } - nsPIDOMWindowInner* inner = win ? win->AsInner() : nullptr; - xpcReport->Init(jsReport.report(), jsReport.toStringResult().c_str(), - nsContentUtils::IsCallerChrome(), - inner ? inner->WindowID() : 0); - if (inner && jsReport.report()->errorNumber != JSMSG_OUT_OF_MEMORY) { - JS::RootingContext* rcx = JS::RootingContext::get(cx()); - DispatchScriptErrorEvent(inner, rcx, xpcReport, exn); - } else { - JS::Rooted stack(cx(), - xpc::FindExceptionStackForConsoleReport(inner, exn)); - xpcReport->LogToConsoleWithStack(stack); - } - } else { - // On a worker, we just use the worker error reporting mechanism and don't - // bother with xpc::ErrorReport. This will ensure that all the right - // events (which are a lot more complicated than in the window case) get - // fired. - workers::WorkerPrivate* worker = workers::GetCurrentThreadWorkerPrivate(); - MOZ_ASSERT(worker); - MOZ_ASSERT(worker->GetJSContext() == cx()); - // Before invoking ReportError, put the exception back on the context, - // because it may want to put it in its error events and has no other way - // to get hold of it. After we invoke ReportError, clear the exception on - // cx(), just in case ReportError didn't. - JS_SetPendingException(cx(), exn); - worker->ReportError(cx(), jsReport.toStringResult(), jsReport.report()); - ClearException(); - } - } else { - NS_WARNING("OOMed while acquiring uncaught exception from JSAPI"); - ClearException(); - } -} - -bool -AutoJSAPI::PeekException(JS::MutableHandle aVal) -{ - MOZ_ASSERT_IF(mIsMainThread, IsStackTop()); - MOZ_ASSERT(HasException()); - MOZ_ASSERT(js::GetContextCompartment(cx())); - if (!JS_GetPendingException(cx(), aVal)) { - return false; - } - return true; -} - -bool -AutoJSAPI::StealException(JS::MutableHandle aVal) -{ - if (!PeekException(aVal)) { - return false; - } - JS_ClearPendingException(cx()); - return true; -} - -#ifdef DEBUG -bool -AutoJSAPI::IsStackTop() const -{ - return ScriptSettingsStack::TopNonIncumbentScript() == this; -} -#endif // DEBUG - -AutoEntryScript::AutoEntryScript(nsIGlobalObject* aGlobalObject, - const char *aReason, - bool aIsMainThread) - : AutoJSAPI(aGlobalObject, aIsMainThread, eEntryScript) - , mWebIDLCallerPrincipal(nullptr) -{ - MOZ_ASSERT(aGlobalObject); - - if (aIsMainThread && gRunToCompletionListeners > 0) { - mDocShellEntryMonitor.emplace(cx(), aReason); - } -} - -AutoEntryScript::AutoEntryScript(JSObject* aObject, - const char *aReason, - bool aIsMainThread) - : AutoEntryScript(xpc::NativeGlobal(aObject), aReason, aIsMainThread) -{ -} - -AutoEntryScript::~AutoEntryScript() -{ - // GC when we pop a script entry point. This is a useful heuristic that helps - // us out on certain (flawed) benchmarks like sunspider, because it lets us - // avoid GCing during the timing loop. - JS_MaybeGC(cx()); -} - -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 aAsyncStack, - const char* aAsyncCause) -{ - JS::Rooted rootedFunction(aCx); - if (aFunction) { - rootedFunction = aFunction; - } - JS::Rooted rootedScript(aCx); - if (aScript) { - rootedScript = aScript; - } - - nsCOMPtr window = - do_QueryInterface(xpc::NativeGlobal(JS::CurrentGlobalOrNull(aCx))); - if (!window || !window->GetDocShell() || - !window->GetDocShell()->GetRecordProfileTimelineMarkers()) { - return; - } - - nsCOMPtr docShellForJSRunToCompletion = window->GetDocShell(); - nsString filename; - uint32_t lineNumber = 0; - - js::AutoStableStringChars functionName(aCx); - if (rootedFunction) { - JS::Rooted displayId(aCx, JS_GetFunctionDisplayId(rootedFunction)); - if (displayId) { - if (!functionName.initTwoByte(aCx, displayId)) { - JS_ClearPendingException(aCx); - return; - } - } - } - - if (!rootedScript) { - rootedScript = JS_GetFunctionScript(aCx, rootedFunction); - } - if (rootedScript) { - filename = NS_ConvertUTF8toUTF16(JS_GetScriptFilename(rootedScript)); - lineNumber = JS_GetScriptBaseLineNumber(aCx, rootedScript); - } - - if (!filename.IsEmpty() || functionName.isTwoByte()) { - const char16_t* functionNameChars = functionName.isTwoByte() ? - functionName.twoByteChars() : nullptr; - - docShellForJSRunToCompletion->NotifyJSRunToCompletionStart(mReason, - functionNameChars, - filename.BeginReading(), - lineNumber, aAsyncStack, - aAsyncCause); - } -} - -void -AutoEntryScript::DocshellEntryMonitor::Exit(JSContext* aCx) -{ - nsCOMPtr window = - do_QueryInterface(xpc::NativeGlobal(JS::CurrentGlobalOrNull(aCx))); - // Not really worth checking GetRecordProfileTimelineMarkers here. - if (window && window->GetDocShell()) { - nsCOMPtr docShellForJSRunToCompletion = window->GetDocShell(); - docShellForJSRunToCompletion->NotifyJSRunToCompletionStop(); - } -} - -AutoIncumbentScript::AutoIncumbentScript(nsIGlobalObject* aGlobalObject) - : ScriptSettingsStackEntry(aGlobalObject, eIncumbentScript) - , mCallerOverride(nsContentUtils::GetCurrentJSContextForThread()) -{ - ScriptSettingsStack::Push(this); -} - -AutoIncumbentScript::~AutoIncumbentScript() -{ - ScriptSettingsStack::Pop(this); -} - -AutoNoJSAPI::AutoNoJSAPI() - : ScriptSettingsStackEntry(nullptr, eNoJSAPI) -{ - ScriptSettingsStack::Push(this); -} - -AutoNoJSAPI::~AutoNoJSAPI() -{ - ScriptSettingsStack::Pop(this); -} - -} // namespace dom - -AutoJSContext::AutoJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL) - : mCx(nullptr) -{ - JS::AutoSuppressGCAnalysis nogc; - MOZ_ASSERT(!mCx, "mCx should not be initialized!"); - MOZ_ASSERT(NS_IsMainThread()); - - MOZ_GUARD_OBJECT_NOTIFIER_INIT; - - if (dom::IsJSAPIActive()) { - mCx = dom::danger::GetJSContext(); - } else { - mJSAPI.Init(); - mCx = mJSAPI.cx(); - } -} - -AutoJSContext::operator JSContext*() const -{ - return mCx; -} - -AutoSafeJSContext::AutoSafeJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL) - : AutoJSAPI() -{ - MOZ_ASSERT(NS_IsMainThread()); - - MOZ_GUARD_OBJECT_NOTIFIER_INIT; - - DebugOnly ok = Init(xpc::UnprivilegedJunkScope()); - MOZ_ASSERT(ok, - "This is quite odd. We should have crashed in the " - "xpc::NativeGlobal() call if xpc::UnprivilegedJunkScope() " - "returned null, and inited correctly otherwise!"); -} - -AutoSlowOperation::AutoSlowOperation(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL) - : AutoJSAPI() -{ - MOZ_ASSERT(NS_IsMainThread()); - - MOZ_GUARD_OBJECT_NOTIFIER_INIT; - - Init(); -} - -void -AutoSlowOperation::CheckForInterrupt() -{ - // JS_CheckForInterrupt expects us to be in a compartment. - JSAutoCompartment ac(cx(), xpc::UnprivilegedJunkScope()); - JS_CheckForInterrupt(cx()); -} - -} // namespace mozilla diff --git a/dom/base/ScriptSettings.h b/dom/base/ScriptSettings.h deleted file mode 100644 index 05e62f55e..000000000 --- a/dom/base/ScriptSettings.h +++ /dev/null @@ -1,465 +0,0 @@ -/* -*- 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/. */ - -/* Utilities for managing the script settings object stack defined in webapps */ - -#ifndef mozilla_dom_ScriptSettings_h -#define mozilla_dom_ScriptSettings_h - -#include "MainThreadUtils.h" -#include "nsIGlobalObject.h" -#include "nsIPrincipal.h" - -#include "mozilla/Maybe.h" - -#include "jsapi.h" -#include "js/Debug.h" - -class nsPIDOMWindowInner; -class nsGlobalWindow; -class nsIScriptContext; -class nsIDocument; -class nsIDocShell; - -namespace mozilla { -namespace dom { - -/* - * System-wide setup/teardown routines. Init and Destroy should be invoked - * once each, at startup and shutdown (respectively). - */ -void InitScriptSettings(); -void DestroyScriptSettings(); -bool ScriptSettingsInitialized(); - -/* - * 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 -// algorithms have operated with different definitions of the "associated" -// global. -// -// HTML5 formalizes this into two concepts: the "incumbent global" and the -// "entry global". The incumbent global corresponds to the global of the -// current script being executed, whereas the entry global corresponds to the -// global of the script where the current JS execution began. -// -// There is also a potentially-distinct third global that is determined by the -// current compartment. This roughly corresponds with the notion of Realms in -// ECMAScript. -// -// Suppose some event triggers an event listener in window |A|, which invokes a -// scripted function in window |B|, which invokes the |window.location.href| -// setter in window |C|. The entry global would be |A|, the incumbent global -// would be |B|, and the current compartment would be that of |C|. -// -// In general, it's best to use to use the most-closely-associated global -// unless the spec says to do otherwise. In 95% of the cases, the global of -// the current compartment (GetCurrentGlobal()) is the right thing. For -// example, WebIDL constructors (new C.XMLHttpRequest()) are initialized with -// the global of the current compartment (i.e. |C|). -// -// The incumbent global is very similar, but differs in a few edge cases. For -// example, if window |B| does |C.location.href = "..."|, the incumbent global -// used for the navigation algorithm is B, because no script from |C| was ever run. -// -// The entry global is used for various things like computing base URIs, mostly -// for historical reasons. -// -// Note that all of these functions return bonafide global objects. This means -// that, for Windows, they always return the inner. - -// Returns the global associated with the top-most Candidate Entry Point on -// the Script Settings Stack. See the HTML spec. This may be null. -nsIGlobalObject* GetEntryGlobal(); - -// If the entry global is a window, returns its extant document. Otherwise, -// returns null. -nsIDocument* GetEntryDocument(); - -// Returns the global associated with the top-most entry of the the Script -// Settings Stack. See the HTML spec. This may be null. -nsIGlobalObject* GetIncumbentGlobal(); - -// Returns the global associated with the current compartment. This may be null. -nsIGlobalObject* GetCurrentGlobal(); - -// JS-implemented WebIDL presents an interesting situation with respect to the -// subject principal. A regular C++-implemented API can simply examine the -// compartment of the most-recently-executed script, and use that to infer the -// responsible party. However, JS-implemented APIs are run with system -// principal, and thus clobber the subject principal of the script that -// invoked the API. So we have to do some extra work to keep track of this -// information. -// -// We therefore implement the following behavior: -// * Each Script Settings Object has an optional WebIDL Caller Principal field. -// This defaults to null. -// * When we push an Entry Point in preparation to run a JS-implemented WebIDL -// callback, we grab the subject principal at the time of invocation, and -// store that as the WebIDL Caller Principal. -// * When non-null, callers can query this principal from script via an API on -// Components.utils. -nsIPrincipal* GetWebIDLCallerPrincipal(); - -// This may be used by callers that know that their incumbent global is non- -// null (i.e. they know there have been no System Caller pushes since the -// inner-most script execution). -inline JSObject& IncumbentJSGlobal() -{ - return *GetIncumbentGlobal()->GetGlobalJSObject(); -} - -// Returns whether JSAPI is active right now. If it is not, working with a -// JSContext you grab from somewhere random is not OK and you should be doing -// AutoJSAPI or AutoEntryScript to get yourself a properly set up JSContext. -bool IsJSAPIActive(); - -namespace danger { - -// Get the JSContext for this thread. This is in the "danger" namespace because -// we generally want people using AutoJSAPI instead, unless they really know -// what they're doing. -JSContext* GetJSContext(); - -} // namespace danger - -JS::RootingContext* RootingCx(); - -class ScriptSettingsStack; -class ScriptSettingsStackEntry { - friend class ScriptSettingsStack; - -public: - ~ScriptSettingsStackEntry(); - - bool NoJSAPI() const { return mType == eNoJSAPI; } - bool IsEntryCandidate() const { - return mType == eEntryScript || mType == eNoJSAPI; - } - bool IsIncumbentCandidate() { return mType != eJSAPI; } - bool IsIncumbentScript() { return mType == eIncumbentScript; } - -protected: - enum Type { - eEntryScript, - eIncumbentScript, - eJSAPI, - eNoJSAPI - }; - - ScriptSettingsStackEntry(nsIGlobalObject *aGlobal, - Type aEntryType); - - nsCOMPtr mGlobalObject; - Type mType; - -private: - ScriptSettingsStackEntry *mOlder; -}; - -/* - * For any interaction with JSAPI, an AutoJSAPI (or one of its subclasses) - * must be on the stack. - * - * This base class should be instantiated as-is when the caller wants to use - * JSAPI but doesn't expect to run script. The caller must then call one of its - * Init functions before being able to access the JSContext through cx(). - * Its current duties are as-follows (see individual Init comments for details): - * - * * Grabbing an appropriate JSContext, and, on the main thread, pushing it onto - * the JSContext stack. - * * Entering an initial (possibly null) compartment, to ensure that the - * previously entered compartment for that JSContext is not used by mistake. - * * Reporting any exceptions left on the JSRuntime, unless the caller steals - * or silences them. - * * On main thread, entering a JSAutoRequest. - * - * Additionally, the following duties are planned, but not yet implemented: - * - * * De-poisoning the JSRuntime to allow manipulation of JSAPI. This requires - * implementing the poisoning first. For now, this de-poisoning - * effectively corresponds to having a non-null cx on the stack. - * - * In situations where the consumer expects to run script, AutoEntryScript - * should be used, which does additional manipulation of the script settings - * stack. In bug 991758, we'll add hard invariants to SpiderMonkey, such that - * any attempt to run script without an AutoEntryScript on the stack will - * fail. This prevents system code from accidentally triggering script - * execution at inopportune moments via surreptitious getters and proxies. - */ -class MOZ_STACK_CLASS AutoJSAPI : protected ScriptSettingsStackEntry { -public: - // Trivial constructor. One of the Init functions must be called before - // accessing the JSContext through cx(). - AutoJSAPI(); - - ~AutoJSAPI(); - - // This uses the SafeJSContext (or worker equivalent), and enters a null - // compartment, so that the consumer is forced to select a compartment to - // enter before manipulating objects. - // - // This variant will ensure that any errors reported by this AutoJSAPI as it - // comes off the stack will not fire error events or be associated with any - // particular web-visible global. - void Init(); - - // This uses the SafeJSContext (or worker equivalent), and enters the - // compartment of aGlobalObject. - // If aGlobalObject or its associated JS global are null then it returns - // false and use of cx() will cause an assertion. - // - // If aGlobalObject represents a web-visible global, errors reported by this - // AutoJSAPI as it comes off the stack will fire the relevant error events and - // show up in the corresponding web console. - MOZ_MUST_USE bool Init(nsIGlobalObject* aGlobalObject); - - // This is a helper that grabs the native global associated with aObject and - // invokes the above Init() with that. - MOZ_MUST_USE bool Init(JSObject* aObject); - - // Unsurprisingly, this uses aCx and enters the compartment of aGlobalObject. - // If aGlobalObject or its associated JS global are null then it returns - // false and use of cx() will cause an assertion. - // If aCx is null it will cause an assertion. - // - // If aGlobalObject represents a web-visible global, errors reported by this - // AutoJSAPI as it comes off the stack will fire the relevant error events and - // show up in the corresponding web console. - MOZ_MUST_USE bool Init(nsIGlobalObject* aGlobalObject, JSContext* aCx); - - // Convenience functions to take an nsPIDOMWindow* or nsGlobalWindow*, - // when it is more easily available than an nsIGlobalObject. - MOZ_MUST_USE bool Init(nsPIDOMWindowInner* aWindow); - MOZ_MUST_USE bool Init(nsPIDOMWindowInner* aWindow, JSContext* aCx); - - MOZ_MUST_USE bool Init(nsGlobalWindow* aWindow); - MOZ_MUST_USE bool Init(nsGlobalWindow* aWindow, JSContext* aCx); - - JSContext* cx() const { - MOZ_ASSERT(mCx, "Must call Init before using an AutoJSAPI"); - MOZ_ASSERT(IsStackTop()); - return mCx; - } - -#ifdef DEBUG - bool IsStackTop() const; -#endif - - // If HasException, report it. Otherwise, a no-op. - void ReportException(); - - bool HasException() const { - MOZ_ASSERT(IsStackTop()); - return JS_IsExceptionPending(cx()); - }; - - // Transfers ownership of the current exception from the JS engine to the - // caller. Callers must ensure that HasException() is true, and that cx() - // is in a non-null compartment. - // - // Note that this fails if and only if we OOM while wrapping the exception - // into the current compartment. - MOZ_MUST_USE bool StealException(JS::MutableHandle aVal); - - // Peek the current exception from the JS engine, without stealing it. - // Callers must ensure that HasException() is true, and that cx() is in a - // non-null compartment. - // - // Note that this fails if and only if we OOM while wrapping the exception - // into the current compartment. - MOZ_MUST_USE bool PeekException(JS::MutableHandle aVal); - - void ClearException() { - MOZ_ASSERT(IsStackTop()); - JS_ClearPendingException(cx()); - } - -protected: - // Protected constructor for subclasses. This constructor initialises the - // AutoJSAPI, so Init must NOT be called on subclasses that use this. - AutoJSAPI(nsIGlobalObject* aGlobalObject, bool aIsMainThread, Type aType); - -private: - mozilla::Maybe mAutoRequest; - mozilla::Maybe mAutoNullableCompartment; - JSContext *mCx; - - // Whether we're mainthread or not; set when we're initialized. - bool mIsMainThread; - Maybe mOldWarningReporter; - - void InitInternal(nsIGlobalObject* aGlobalObject, JSObject* aGlobal, - JSContext* aCx, bool aIsMainThread); - - AutoJSAPI(const AutoJSAPI&) = delete; - 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: - AutoEntryScript(nsIGlobalObject* aGlobalObject, - const char *aReason, - bool aIsMainThread = NS_IsMainThread()); - - AutoEntryScript(JSObject* aObject, // Any object from the relevant global - 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 aAsyncStack, - const char* aAsyncCause) override - { - Entry(aCx, aFunction, nullptr, aAsyncStack, aAsyncCause); - } - - void Entry(JSContext* aCx, JSScript* aScript, - JS::Handle 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 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 mDocShellEntryMonitor; -}; - -/* - * A class that can be used to force a particular incumbent script on the stack. - */ -class AutoIncumbentScript : protected ScriptSettingsStackEntry { -public: - explicit AutoIncumbentScript(nsIGlobalObject* aGlobalObject); - ~AutoIncumbentScript(); - -private: - JS::AutoHideScriptedCaller mCallerOverride; -}; - -/* - * A class to put the JS engine in an unusable state. The subject principal - * will become System, the information on the script settings stack is - * rendered inaccessible, and JSAPI may not be manipulated until the class is - * either popped or an AutoJSAPI instance is subsequently pushed. - * - * This class may not be instantiated if an exception is pending. - */ -class AutoNoJSAPI : protected ScriptSettingsStackEntry { -public: - explicit AutoNoJSAPI(); - ~AutoNoJSAPI(); -}; - -} // namespace dom - -/** - * Use AutoJSContext when you need a JS context on the stack but don't have one - * passed as a parameter. AutoJSContext will take care of finding the most - * appropriate JS context and release it when leaving the stack. - */ -class MOZ_RAII AutoJSContext { -public: - explicit AutoJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM); - operator JSContext*() const; - -protected: - JSContext* mCx; - dom::AutoJSAPI mJSAPI; - MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER -}; - -/** - * AutoSafeJSContext is similar to AutoJSContext but will only return the safe - * JS context. That means it will never call nsContentUtils::GetCurrentJSContext(). - * - * Note - This is deprecated. Please use AutoJSAPI instead. - */ -class MOZ_RAII AutoSafeJSContext : public dom::AutoJSAPI { -public: - explicit AutoSafeJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM); - operator JSContext*() const - { - return cx(); - } - -private: - MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER -}; - -/** - * Use AutoSlowOperation when native side calls many JS callbacks in a row - * and slow script dialog should be activated if too much time is spent going - * through those callbacks. - * AutoSlowOperation puts a JSAutoRequest on the stack so that we don't continue - * to reset the watchdog and CheckForInterrupt can be then used to check whether - * JS execution should be interrupted. - */ -class MOZ_RAII AutoSlowOperation : public dom::AutoJSAPI -{ -public: - explicit AutoSlowOperation(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM); - void CheckForInterrupt(); -private: - MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER -}; - -} // namespace mozilla - -#endif // mozilla_dom_ScriptSettings_h diff --git a/dom/base/moz.build b/dom/base/moz.build index cedaa0e49..ded203c50 100755 --- a/dom/base/moz.build +++ b/dom/base/moz.build @@ -26,7 +26,6 @@ XPIDL_SOURCES += [ 'nsIObjectLoadingContent.idl', 'nsIRemoteWindowContext.idl', 'nsIScriptChannel.idl', - 'nsIScriptLoaderObserver.idl', 'nsISelection.idl', 'nsISelectionController.idl', 'nsISelectionDisplay.idl', @@ -97,7 +96,6 @@ EXPORTS += [ 'nsINode.h', 'nsINodeList.h', 'nsIScriptContext.h', - 'nsIScriptElement.h', 'nsIScriptGlobalObject.h', 'nsIScriptNameSpaceManager.h', 'nsIScriptObjectPrincipal.h', @@ -118,7 +116,6 @@ EXPORTS += [ 'nsRange.h', 'nsReferencedElement.h', 'nsSandboxFlags.h', - 'nsScriptLoader.h', 'nsStructuredCloneContainer.h', 'nsStubAnimationObserver.h', 'nsStubDocumentObserver.h', @@ -210,7 +207,6 @@ EXPORTS.mozilla.dom += [ 'ResponsiveImageSelector.h', 'SameProcessMessageQueue.h', 'ScreenOrientation.h', - 'ScriptSettings.h', 'ShadowRoot.h', 'SimpleTreeIterator.h', 'StructuredCloneHolder.h', @@ -331,8 +327,6 @@ SOURCES += [ 'nsRange.cpp', 'nsReferencedElement.cpp', 'nsScreen.cpp', - 'nsScriptElement.cpp', - 'nsScriptLoader.cpp', 'nsScriptNameSpaceManager.cpp', 'nsStructuredCloneContainer.cpp', 'nsStubAnimationObserver.cpp', @@ -359,7 +353,6 @@ SOURCES += [ 'ResponsiveImageSelector.cpp', 'SameProcessMessageQueue.cpp', 'ScreenOrientation.cpp', - 'ScriptSettings.cpp', 'ShadowRoot.cpp', 'StructuredCloneHolder.cpp', 'StyleSheetList.cpp', diff --git a/dom/base/nsContentPermissionHelper.cpp b/dom/base/nsContentPermissionHelper.cpp index c57fc6233..eaaec2a41 100644 --- a/dom/base/nsContentPermissionHelper.cpp +++ b/dom/base/nsContentPermissionHelper.cpp @@ -29,9 +29,8 @@ #include "nsIDocument.h" #include "nsIDOMEvent.h" #include "nsWeakPtr.h" -#include "ScriptSettings.h" -using mozilla::Unused; // +using mozilla::Unused; using namespace mozilla::dom; using namespace mozilla; diff --git a/dom/base/nsContentSink.cpp b/dom/base/nsContentSink.cpp index 490f0ec17..1e6465a1b 100644 --- a/dom/base/nsContentSink.cpp +++ b/dom/base/nsContentSink.cpp @@ -10,7 +10,6 @@ */ #include "nsContentSink.h" -#include "nsScriptLoader.h" #include "nsIDocument.h" #include "nsIDOMDocument.h" #include "mozilla/css/Loader.h" @@ -49,6 +48,7 @@ #include "nsHTMLDNSPrefetch.h" #include "nsIObserverService.h" #include "mozilla/Preferences.h" +#include "mozilla/dom/ScriptLoader.h" #include "nsParserConstants.h" #include "nsSandboxFlags.h" diff --git a/dom/base/nsContentSink.h b/dom/base/nsContentSink.h index b1a758874..2d914a8d7 100644 --- a/dom/base/nsContentSink.h +++ b/dom/base/nsContentSink.h @@ -36,13 +36,16 @@ class nsIAtom; class nsIChannel; class nsIContent; class nsNodeInfoManager; -class nsScriptLoader; class nsIApplicationCache; namespace mozilla { namespace css { class Loader; } // namespace css + +namespace dom { +class ScriptLoader; +} // namespace dom } // namespace mozilla #ifdef DEBUG @@ -273,7 +276,7 @@ protected: nsCOMPtr mDocShell; RefPtr mCSSLoader; RefPtr mNodeInfoManager; - RefPtr mScriptLoader; + RefPtr mScriptLoader; // back off timer notification after count int32_t mBackoffCount; diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index 40bfa97e2..dc4b23f2c 100644 --- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -1834,7 +1834,7 @@ nsDocument::Init() mScopeObject = do_GetWeakReference(global); MOZ_ASSERT(mScopeObject); - mScriptLoader = new nsScriptLoader(this); + mScriptLoader = new dom::ScriptLoader(this); mozilla::HoldJSObjects(this); @@ -4623,7 +4623,7 @@ nsDocument::GetWindowInternal() const return win; } -nsScriptLoader* +ScriptLoader* nsDocument::ScriptLoader() { return mScriptLoader; diff --git a/dom/base/nsDocument.h b/dom/base/nsDocument.h index 9d7b0aafd..502ba0f13 100644 --- a/dom/base/nsDocument.h +++ b/dom/base/nsDocument.h @@ -32,7 +32,6 @@ #include "nsJSThingHashtable.h" #include "nsIScriptObjectPrincipal.h" #include "nsIURI.h" -#include "nsScriptLoader.h" #include "nsIRadioGroupContainer.h" #include "nsILayoutHistoryState.h" #include "nsIRequest.h" @@ -61,6 +60,7 @@ #include "mozilla/MemoryReporting.h" #include "mozilla/PendingAnimationTracker.h" #include "mozilla/dom/DOMImplementation.h" +#include "mozilla/dom/ScriptLoader.h" #include "mozilla/dom/StyleSheetList.h" #include "nsDataHashtable.h" #include "mozilla/TimeStamp.h" @@ -491,7 +491,7 @@ public: /** * Get the script loader for this document */ - virtual nsScriptLoader* ScriptLoader() override; + virtual mozilla::dom::ScriptLoader* ScriptLoader() override; /** * Add/Remove an element to the document's id and name hashes @@ -1205,7 +1205,7 @@ protected: public: RefPtr mListenerManager; RefPtr mStyleSheetSetList; - RefPtr mScriptLoader; + RefPtr mScriptLoader; nsDocHeaderData* mHeaderData; nsClassHashtable mRadioGroups; diff --git a/dom/base/nsFrameMessageManager.cpp b/dom/base/nsFrameMessageManager.cpp index bba4232aa..331931f19 100644 --- a/dom/base/nsFrameMessageManager.cpp +++ b/dom/base/nsFrameMessageManager.cpp @@ -19,7 +19,6 @@ #include "nsJSUtils.h" #include "nsJSPrincipals.h" #include "nsNetUtil.h" -#include "nsScriptLoader.h" #include "nsFrameLoader.h" #include "nsIXULRuntime.h" #include "nsIScriptError.h" @@ -38,6 +37,7 @@ #include "mozilla/dom/PermissionMessageUtils.h" #include "mozilla/dom/ProcessGlobal.h" #include "mozilla/dom/SameProcessMessageQueue.h" +#include "mozilla/dom/ScriptLoader.h" #include "mozilla/dom/ScriptSettings.h" #include "mozilla/dom/ipc/BlobChild.h" #include "mozilla/dom/ipc/BlobParent.h" @@ -1786,9 +1786,9 @@ nsMessageManagerScriptExecutor::TryCacheLoadAndCompileScript( if (NS_FAILED(NS_ReadInputStreamToString(input, buffer, avail))) { return; } - nsScriptLoader::ConvertToUTF16(channel, (uint8_t*)buffer.get(), avail, - EmptyString(), nullptr, - dataStringBuf, dataStringLength); + ScriptLoader::ConvertToUTF16(channel, (uint8_t*)buffer.get(), avail, + EmptyString(), nullptr, + dataStringBuf, dataStringLength); } JS::SourceBufferHolder srcBuf(dataStringBuf, dataStringLength, diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 69643762c..acd596a44 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -62,7 +62,7 @@ #include "nsReadableUtils.h" #include "nsDOMClassInfo.h" #include "nsJSEnvironment.h" -#include "ScriptSettings.h" +#include "mozilla/dom/ScriptSettings.h" #include "mozilla/Preferences.h" #include "mozilla/Likely.h" #include "mozilla/Sprintf.h" diff --git a/dom/base/nsIDocument.h b/dom/base/nsIDocument.h index d88db8423..33aac3a3d 100644 --- a/dom/base/nsIDocument.h +++ b/dom/base/nsIDocument.h @@ -93,7 +93,6 @@ class nsIVariant; class nsViewManager; class nsPresContext; class nsRange; -class nsScriptLoader; class nsSMILAnimationController; class nsTextNode; class nsWindowSizes; @@ -153,6 +152,7 @@ enum class OrientationType : uint32_t; class ProcessingInstruction; class Promise; class Selection; +class ScriptLoader; class StyleSheetList; class SVGDocument; class SVGSVGElement; @@ -1278,7 +1278,7 @@ public: /** * Get the script loader for this document */ - virtual nsScriptLoader* ScriptLoader() = 0; + virtual mozilla::dom::ScriptLoader* ScriptLoader() = 0; /** * Add/Remove an element to the document's id and name hashes diff --git a/dom/base/nsIScriptElement.h b/dom/base/nsIScriptElement.h deleted file mode 100644 index 470d51c94..000000000 --- a/dom/base/nsIScriptElement.h +++ /dev/null @@ -1,329 +0,0 @@ -/* -*- 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 nsIScriptElement_h___ -#define nsIScriptElement_h___ - -#include "nsISupports.h" -#include "nsIURI.h" -#include "nsCOMPtr.h" -#include "nsIScriptLoaderObserver.h" -#include "nsWeakPtr.h" -#include "nsIParser.h" -#include "nsContentCreatorFunctions.h" -#include "nsIDOMHTMLScriptElement.h" -#include "mozilla/CORSMode.h" - -#define NS_ISCRIPTELEMENT_IID \ -{ 0xe60fca9b, 0x1b96, 0x4e4e, \ - { 0xa9, 0xb4, 0xdc, 0x98, 0x4f, 0x88, 0x3f, 0x9c } } - -/** - * Internal interface implemented by script elements - */ -class nsIScriptElement : public nsIScriptLoaderObserver { -public: - NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISCRIPTELEMENT_IID) - - explicit nsIScriptElement(mozilla::dom::FromParser aFromParser) - : mLineNumber(1), - mAlreadyStarted(false), - mMalformed(false), - mDoneAddingChildren(aFromParser == mozilla::dom::NOT_FROM_PARSER || - aFromParser == mozilla::dom::FROM_PARSER_FRAGMENT), - mForceAsync(aFromParser == mozilla::dom::NOT_FROM_PARSER || - aFromParser == mozilla::dom::FROM_PARSER_FRAGMENT), - mFrozen(false), - mDefer(false), - mAsync(false), - mExternal(false), - mParserCreated(aFromParser == mozilla::dom::FROM_PARSER_FRAGMENT ? - mozilla::dom::NOT_FROM_PARSER : aFromParser), - // Fragment parser-created scripts (if executable) - // behave like script-created scripts. - mCreatorParser(nullptr) - { - } - - /** - * Content type identifying the scripting language. Can be empty, in - * which case javascript will be assumed. - * Return false if type attribute is not found. - */ - virtual bool GetScriptType(nsAString& type) = 0; - - /** - * Location of script source text. Can return null, in which case - * this is assumed to be an inline script element. - */ - nsIURI* GetScriptURI() - { - NS_PRECONDITION(mFrozen, "Not ready for this call yet!"); - return mUri; - } - - /** - * Script source text for inline script elements. - */ - virtual void GetScriptText(nsAString& text) = 0; - - virtual void GetScriptCharset(nsAString& charset) = 0; - - /** - * Freezes the return values of GetScriptDeferred(), GetScriptAsync() and - * GetScriptURI() so that subsequent modifications to the attributes don't - * change execution behavior. - */ - virtual void FreezeUriAsyncDefer() = 0; - - /** - * Is the script deferred. Currently only supported by HTML scripts. - */ - bool GetScriptDeferred() - { - NS_PRECONDITION(mFrozen, "Not ready for this call yet!"); - return mDefer; - } - - /** - * Is the script async. Currently only supported by HTML scripts. - */ - bool GetScriptAsync() - { - NS_PRECONDITION(mFrozen, "Not ready for this call yet!"); - return mAsync; - } - - /** - * Is the script an external script? - */ - bool GetScriptExternal() - { - NS_PRECONDITION(mFrozen, "Not ready for this call yet!"); - return mExternal; - } - - /** - * Returns how the element was created. - */ - mozilla::dom::FromParser GetParserCreated() - { - return mParserCreated; - } - - void SetScriptLineNumber(uint32_t aLineNumber) - { - mLineNumber = aLineNumber; - } - uint32_t GetScriptLineNumber() - { - return mLineNumber; - } - - void SetIsMalformed() - { - mMalformed = true; - } - bool IsMalformed() - { - return mMalformed; - } - - void PreventExecution() - { - mAlreadyStarted = true; - } - - void LoseParserInsertedness() - { - mFrozen = false; - mUri = nullptr; - mCreatorParser = nullptr; - mParserCreated = mozilla::dom::NOT_FROM_PARSER; - bool async = false; - nsCOMPtr htmlScript = do_QueryInterface(this); - if (htmlScript) { - htmlScript->GetAsync(&async); - } - mForceAsync = !async; - } - - void SetCreatorParser(nsIParser* aParser) - { - mCreatorParser = do_GetWeakReference(aParser); - } - - /** - * Unblocks the creator parser - */ - void UnblockParser() - { - nsCOMPtr parser = do_QueryReferent(mCreatorParser); - if (parser) { - parser->UnblockParser(); - } - } - - /** - * Attempts to resume parsing asynchronously - */ - void ContinueParserAsync() - { - nsCOMPtr parser = do_QueryReferent(mCreatorParser); - if (parser) { - parser->ContinueInterruptedParsingAsync(); - } - } - - /** - * Informs the creator parser that the evaluation of this script is starting - */ - void BeginEvaluating() - { - nsCOMPtr parser = do_QueryReferent(mCreatorParser); - if (parser) { - parser->PushDefinedInsertionPoint(); - } - } - - /** - * Informs the creator parser that the evaluation of this script is ending - */ - void EndEvaluating() - { - nsCOMPtr parser = do_QueryReferent(mCreatorParser); - if (parser) { - parser->PopDefinedInsertionPoint(); - } - } - - /** - * Retrieves a pointer to the creator parser if this has one or null if not - */ - already_AddRefed GetCreatorParser() - { - nsCOMPtr parser = do_QueryReferent(mCreatorParser); - return parser.forget(); - } - - /** - * This method is called when the parser finishes creating the script - * element's children, if any are present. - * - * @return whether the parser will be blocked while this script is being - * loaded - */ - bool AttemptToExecute() - { - mDoneAddingChildren = true; - bool block = MaybeProcessScript(); - if (!mAlreadyStarted) { - // Need to lose parser-insertedness here to allow another script to cause - // execution later. - LoseParserInsertedness(); - } - return block; - } - - /** - * Get the CORS mode of the script element - */ - virtual mozilla::CORSMode GetCORSMode() const - { - /* Default to no CORS */ - return mozilla::CORS_NONE; - } - - /** - * Fire an error event - */ - virtual nsresult FireErrorEvent() = 0; - -protected: - /** - * Processes the script if it's in the document-tree and links to or - * contains a script. Once it has been evaluated there is no way to make it - * reevaluate the script, you'll have to create a new element. This also means - * that when adding a src attribute to an element that already contains an - * inline script, the script referenced by the src attribute will not be - * loaded. - * - * In order to be able to use multiple childNodes, or to use the - * fallback mechanism of using both inline script and linked script you have - * to add all attributes and childNodes before adding the element to the - * document-tree. - * - * @return whether the parser will be blocked while this script is being - * loaded - */ - virtual bool MaybeProcessScript() = 0; - - /** - * The start line number of the script. - */ - uint32_t mLineNumber; - - /** - * The "already started" flag per HTML5. - */ - bool mAlreadyStarted; - - /** - * The script didn't have an end tag. - */ - bool mMalformed; - - /** - * False if parser-inserted but the parser hasn't triggered running yet. - */ - bool mDoneAddingChildren; - - /** - * If true, the .async property returns true instead of reflecting the - * content attribute. - */ - bool mForceAsync; - - /** - * Whether src, defer and async are frozen. - */ - bool mFrozen; - - /** - * The effective deferredness. - */ - bool mDefer; - - /** - * The effective asyncness. - */ - bool mAsync; - - /** - * The effective externalness. A script can be external with mUri being null - * if the src attribute contained an invalid URL string. - */ - bool mExternal; - - /** - * Whether this element was parser-created. - */ - mozilla::dom::FromParser mParserCreated; - - /** - * The effective src (or null if no src). - */ - nsCOMPtr mUri; - - /** - * The creator parser of a non-defer, non-async parser-inserted script. - */ - nsWeakPtr mCreatorParser; -}; - -NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptElement, NS_ISCRIPTELEMENT_IID) - -#endif // nsIScriptElement_h___ diff --git a/dom/base/nsIScriptLoaderObserver.idl b/dom/base/nsIScriptLoaderObserver.idl deleted file mode 100644 index ed7196525..000000000 --- a/dom/base/nsIScriptLoaderObserver.idl +++ /dev/null @@ -1,47 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "nsISupports.idl" - -interface nsIScriptElement; -interface nsIURI; - -[scriptable, uuid(7b787204-76fb-4764-96f1-fb7a666db4f4)] -interface nsIScriptLoaderObserver : nsISupports { - - /** - * The script is available for evaluation. For inline scripts, this - * method will be called synchronously. For externally loaded scripts, - * this method will be called when the load completes. - * - * @param aResult A result code representing the result of loading - * a script. If this is a failure code, script evaluation - * will not occur. - * @param aElement The element being processed. - * @param aIsInline Is this an inline script or externally loaded? - * @param aURI What is the URI of the script (the document URI if - * it is inline). - * @param aLineNo At what line does the script appear (generally 1 - * if it is a loaded script). - */ - void scriptAvailable(in nsresult aResult, - in nsIScriptElement aElement, - in boolean aIsInline, - in nsIURI aURI, - in int32_t aLineNo); - - /** - * The script has been evaluated. - * - * @param aResult A result code representing the success or failure of - * the script evaluation. - * @param aElement The element being processed. - * @param aIsInline Is this an inline script or externally loaded? - */ - void scriptEvaluated(in nsresult aResult, - in nsIScriptElement aElement, - in boolean aIsInline); - -}; diff --git a/dom/base/nsInProcessTabChildGlobal.cpp b/dom/base/nsInProcessTabChildGlobal.cpp index 9885b41a8..4cc3c9ce9 100644 --- a/dom/base/nsInProcessTabChildGlobal.cpp +++ b/dom/base/nsInProcessTabChildGlobal.cpp @@ -11,13 +11,13 @@ #include "nsIComponentManager.h" #include "nsIServiceManager.h" #include "nsComponentManagerUtils.h" -#include "nsScriptLoader.h" #include "nsFrameLoader.h" #include "xpcpublic.h" #include "nsIMozBrowserFrame.h" #include "nsDOMClassInfoID.h" #include "mozilla/EventDispatcher.h" #include "mozilla/dom/SameProcessMessageQueue.h" +#include "mozilla/dom/ScriptLoader.h" using namespace mozilla; using namespace mozilla::dom; diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index efea3ee40..605b1917f 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -37,7 +37,6 @@ #include "nsXPCOMCIDInternal.h" #include "nsIXULRuntime.h" #include "nsTextFormatter.h" -#include "ScriptSettings.h" #include "xpcpublic.h" @@ -55,6 +54,7 @@ #include "mozilla/dom/DOMException.h" #include "mozilla/dom/DOMExceptionBinding.h" #include "mozilla/dom/ErrorEvent.h" +#include "mozilla/dom/ScriptSettings.h" #include "nsAXPCNativeCallContext.h" #include "mozilla/CycleCollectedJSContext.h" #include "mozilla/Telemetry.h" diff --git a/dom/base/nsScriptElement.cpp b/dom/base/nsScriptElement.cpp deleted file mode 100644 index ebeb18f81..000000000 --- a/dom/base/nsScriptElement.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/* -*- 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 "nsScriptElement.h" -#include "mozilla/BasicEvents.h" -#include "mozilla/EventDispatcher.h" -#include "mozilla/dom/Element.h" -#include "nsContentUtils.h" -#include "nsPresContext.h" -#include "nsScriptLoader.h" -#include "nsIParser.h" -#include "nsGkAtoms.h" -#include "nsContentSink.h" - -using namespace mozilla; -using namespace mozilla::dom; - -NS_IMETHODIMP -nsScriptElement::ScriptAvailable(nsresult aResult, - nsIScriptElement *aElement, - bool aIsInline, - nsIURI *aURI, - int32_t aLineNo) -{ - if (!aIsInline && NS_FAILED(aResult)) { - nsCOMPtr parser = do_QueryReferent(mCreatorParser); - if (parser) { - parser->PushDefinedInsertionPoint(); - } - nsresult rv = FireErrorEvent(); - if (parser) { - parser->PopDefinedInsertionPoint(); - } - return rv; - } - return NS_OK; -} - -/* virtual */ nsresult -nsScriptElement::FireErrorEvent() -{ - nsCOMPtr cont = - do_QueryInterface((nsIScriptElement*) this); - - return nsContentUtils::DispatchTrustedEvent(cont->OwnerDoc(), - cont, - NS_LITERAL_STRING("error"), - false /* bubbles */, - false /* cancelable */); -} - -NS_IMETHODIMP -nsScriptElement::ScriptEvaluated(nsresult aResult, - nsIScriptElement *aElement, - bool aIsInline) -{ - nsresult rv = NS_OK; - if (!aIsInline) { - nsCOMPtr cont = - do_QueryInterface((nsIScriptElement*) this); - - RefPtr presContext = - nsContentUtils::GetContextForContent(cont); - - nsEventStatus status = nsEventStatus_eIgnore; - EventMessage message = NS_SUCCEEDED(aResult) ? eLoad : eLoadError; - WidgetEvent event(true, message); - // Load event doesn't bubble. - event.mFlags.mBubbles = (message != eLoad); - - EventDispatcher::Dispatch(cont, presContext, &event, nullptr, &status); - } - - return rv; -} - -void -nsScriptElement::CharacterDataChanged(nsIDocument *aDocument, - nsIContent* aContent, - CharacterDataChangeInfo* aInfo) -{ - MaybeProcessScript(); -} - -void -nsScriptElement::AttributeChanged(nsIDocument* aDocument, - Element* aElement, - int32_t aNameSpaceID, - nsIAtom* aAttribute, - int32_t aModType, - const nsAttrValue* aOldValue) -{ - MaybeProcessScript(); -} - -void -nsScriptElement::ContentAppended(nsIDocument* aDocument, - nsIContent* aContainer, - nsIContent* aFirstNewContent, - int32_t aNewIndexInContainer) -{ - MaybeProcessScript(); -} - -void -nsScriptElement::ContentInserted(nsIDocument *aDocument, - nsIContent* aContainer, - nsIContent* aChild, - int32_t aIndexInContainer) -{ - MaybeProcessScript(); -} - -bool -nsScriptElement::MaybeProcessScript() -{ - nsCOMPtr cont = - do_QueryInterface((nsIScriptElement*) this); - - NS_ASSERTION(cont->DebugGetSlots()->mMutationObservers.Contains(this), - "You forgot to add self as observer"); - - if (mAlreadyStarted || !mDoneAddingChildren || - !cont->GetComposedDoc() || mMalformed || !HasScriptContent()) { - return false; - } - - FreezeUriAsyncDefer(); - - mAlreadyStarted = true; - - nsIDocument* ownerDoc = cont->OwnerDoc(); - nsCOMPtr parser = ((nsIScriptElement*) this)->GetCreatorParser(); - if (parser) { - nsCOMPtr sink = parser->GetContentSink(); - if (sink) { - nsCOMPtr parserDoc = do_QueryInterface(sink->GetTarget()); - if (ownerDoc != parserDoc) { - // Willful violation of HTML5 as of 2010-12-01 - return false; - } - } - } - - RefPtr loader = ownerDoc->ScriptLoader(); - return loader->ProcessScriptElement(this); -} diff --git a/dom/base/nsScriptElement.h b/dom/base/nsScriptElement.h deleted file mode 100644 index 4a2a584ac..000000000 --- a/dom/base/nsScriptElement.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -*- 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 nsScriptElement_h -#define nsScriptElement_h - -#include "mozilla/Attributes.h" -#include "nsIScriptLoaderObserver.h" -#include "nsIScriptElement.h" -#include "nsStubMutationObserver.h" - -/** - * Baseclass useful for script elements (such as and - * ). Currently the class assumes that only the 'src' - * attribute and the children of the class affect what script to execute. - */ - -class nsScriptElement : public nsIScriptElement, - public nsStubMutationObserver -{ -public: - // nsIScriptLoaderObserver - NS_DECL_NSISCRIPTLOADEROBSERVER - - // nsIMutationObserver - NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED - NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED - NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED - NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED - - explicit nsScriptElement(mozilla::dom::FromParser aFromParser) - : nsIScriptElement(aFromParser) - { - } - - virtual nsresult FireErrorEvent() override; - -protected: - // Internal methods - - /** - * Check if this element contains any script, linked or inline - */ - virtual bool HasScriptContent() = 0; - - virtual bool MaybeProcessScript() override; -}; - -#endif // nsScriptElement_h diff --git a/dom/base/nsScriptLoader.cpp b/dom/base/nsScriptLoader.cpp deleted file mode 100644 index 25482fe7b..000000000 --- a/dom/base/nsScriptLoader.cpp +++ /dev/null @@ -1,3061 +0,0 @@ -/* -*- 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/. */ - -/* - * A class that handles loading and evaluation of