Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp
Warning:line 913, column 5
Value stored to 'rv' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name PrototypeDocumentContentSink.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dom/prototype -fcoverage-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dom/prototype -resource-dir /usr/lib/llvm-18/lib/clang/18 -include /var/lib/jenkins/workspace/firefox-scan-build/config/gcc_hidden.h -include /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /var/lib/jenkins/workspace/firefox-scan-build/dom/prototype -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dom/prototype -I /var/lib/jenkins/workspace/firefox-scan-build/dom/base -I /var/lib/jenkins/workspace/firefox-scan-build/dom/xul -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/backward -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-deprecated-this-capture -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -fdeprecated-macro -ferror-limit 19 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-aligned-allocation -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-07-27-022226-2793976-1 -x c++ /var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp
1/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3/* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
6
7#include "nsCOMPtr.h"
8#include "mozilla/dom/PrototypeDocumentContentSink.h"
9#include "nsIParser.h"
10#include "mozilla/dom/Document.h"
11#include "mozilla/dom/URL.h"
12#include "nsIContent.h"
13#include "nsIURI.h"
14#include "nsNetUtil.h"
15#include "nsHTMLParts.h"
16#include "nsCRT.h"
17#include "mozilla/StyleSheetInlines.h"
18#include "mozilla/css/Loader.h"
19#include "nsGkAtoms.h"
20#include "nsContentUtils.h"
21#include "nsDocElementCreatedNotificationRunner.h"
22#include "nsIScriptContext.h"
23#include "nsNameSpaceManager.h"
24#include "nsIScriptError.h"
25#include "prtime.h"
26#include "mozilla/Logging.h"
27#include "nsRect.h"
28#include "nsIScriptElement.h"
29#include "nsReadableUtils.h"
30#include "nsUnicharUtils.h"
31#include "nsIChannel.h"
32#include "nsNodeInfoManager.h"
33#include "nsContentCreatorFunctions.h"
34#include "nsIContentPolicy.h"
35#include "nsContentPolicyUtils.h"
36#include "nsError.h"
37#include "nsIScriptGlobalObject.h"
38#include "mozAutoDocUpdate.h"
39#include "nsMimeTypes.h"
40#include "nsHtml5SVGLoadDispatcher.h"
41#include "nsTextNode.h"
42#include "mozilla/dom/AutoEntryScript.h"
43#include "mozilla/dom/CDATASection.h"
44#include "mozilla/dom/Comment.h"
45#include "mozilla/dom/DocumentType.h"
46#include "mozilla/dom/Element.h"
47#include "mozilla/dom/HTMLTemplateElement.h"
48#include "mozilla/dom/ProcessingInstruction.h"
49#include "mozilla/dom/XMLStylesheetProcessingInstruction.h"
50#include "mozilla/dom/ScriptLoader.h"
51#include "mozilla/LoadInfo.h"
52#include "mozilla/PresShell.h"
53#include "mozilla/ProfilerLabels.h"
54#include "mozilla/RefPtr.h"
55#include "mozilla/Try.h"
56
57#include "nsXULPrototypeCache.h"
58#include "nsXULElement.h"
59#include "mozilla/CycleCollectedJSContext.h"
60#include "js/CompilationAndEvaluation.h"
61#include "js/experimental/JSStencil.h"
62#include "js/Utility.h" // JS::FreePolicy
63
64using namespace mozilla;
65using namespace mozilla::dom;
66
67LazyLogModule PrototypeDocumentContentSink::gLog("PrototypeDocument");
68
69nsresult NS_NewPrototypeDocumentContentSink(nsIContentSink** aResult,
70 Document* aDoc, nsIURI* aURI,
71 nsISupports* aContainer,
72 nsIChannel* aChannel) {
73 MOZ_ASSERT(nullptr != aResult, "null ptr")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(nullptr != aResult)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(nullptr != aResult))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("nullptr != aResult"
" (" "null ptr" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 73); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nullptr != aResult"
") (" "null ptr" ")"); do { *((volatile int*)__null) = 73; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
74 if (nullptr == aResult) {
75 return NS_ERROR_NULL_POINTER;
76 }
77 RefPtr<PrototypeDocumentContentSink> it = new PrototypeDocumentContentSink();
78
79 nsresult rv = it->Init(aDoc, aURI, aContainer, aChannel);
80 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 80); return rv; } } while (false)
;
81
82 it.forget(aResult);
83 return NS_OK;
84}
85
86namespace mozilla::dom {
87
88PrototypeDocumentContentSink::PrototypeDocumentContentSink()
89 : mNextSrcLoadWaiter(nullptr),
90 mCurrentScriptProto(nullptr),
91 mOffThreadCompiling(false),
92 mStillWalking(false),
93 mPendingSheets(0) {}
94
95PrototypeDocumentContentSink::~PrototypeDocumentContentSink() {
96 NS_ASSERTION(do { if (!(mNextSrcLoadWaiter == nullptr)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "unreferenced document still waiting for script source to load?"
, "mNextSrcLoadWaiter == nullptr", "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 98); MOZ_PretendNoReturn(); } } while (0)
97 mNextSrcLoadWaiter == nullptr,do { if (!(mNextSrcLoadWaiter == nullptr)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "unreferenced document still waiting for script source to load?"
, "mNextSrcLoadWaiter == nullptr", "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 98); MOZ_PretendNoReturn(); } } while (0)
98 "unreferenced document still waiting for script source to load?")do { if (!(mNextSrcLoadWaiter == nullptr)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "unreferenced document still waiting for script source to load?"
, "mNextSrcLoadWaiter == nullptr", "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 98); MOZ_PretendNoReturn(); } } while (0)
;
99}
100
101nsresult PrototypeDocumentContentSink::Init(Document* aDoc, nsIURI* aURI,
102 nsISupports* aContainer,
103 nsIChannel* aChannel) {
104 MOZ_ASSERT(aDoc, "null ptr")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDoc)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aDoc))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aDoc" " (" "null ptr" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 104); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDoc" ") (" "null ptr"
")"); do { *((volatile int*)__null) = 104; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
105 MOZ_ASSERT(aURI, "null ptr")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aURI)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aURI))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aURI" " (" "null ptr" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 105); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") (" "null ptr"
")"); do { *((volatile int*)__null) = 105; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
106
107 mDocument = aDoc;
108
109 mDocument->SetDelayFrameLoaderInitialization(true);
110 mDocument->SetMayStartLayout(false);
111
112 // Get the URI. this should match the uri used for the OnNewURI call in
113 // nsDocShell::CreateDocumentViewer.
114 nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(mDocumentURI));
115 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 115); return rv; } } while (false)
;
116
117 mScriptLoader = mDocument->ScriptLoader();
118
119 return NS_OK;
120}
121
122NS_IMPL_CYCLE_COLLECTION(PrototypeDocumentContentSink, mParser, mDocumentURI,PrototypeDocumentContentSink::cycleCollection PrototypeDocumentContentSink
::_cycleCollectorGlobal; void PrototypeDocumentContentSink::cycleCollection
::Unlink(void* p) { PrototypeDocumentContentSink* tmp = DowncastCCParticipant
<PrototypeDocumentContentSink>(p); ImplCycleCollectionUnlink
(tmp->mParser); ImplCycleCollectionUnlink(tmp->mDocumentURI
); ImplCycleCollectionUnlink(tmp->mDocument); ImplCycleCollectionUnlink
(tmp->mScriptLoader); ImplCycleCollectionUnlink(tmp->mContextStack
); ImplCycleCollectionUnlink(tmp->mCurrentPrototype); (void
)tmp; } nsresult PrototypeDocumentContentSink::cycleCollection
::TraverseNative( void* p, nsCycleCollectionTraversalCallback
& cb) { PrototypeDocumentContentSink* tmp = DowncastCCParticipant
<PrototypeDocumentContentSink>(p); cb.DescribeRefCountedNode
(tmp->mRefCnt.get(), "PrototypeDocumentContentSink"); ImplCycleCollectionTraverse
(cb, tmp->mParser, "mParser", 0); ImplCycleCollectionTraverse
(cb, tmp->mDocumentURI, "mDocumentURI", 0); ImplCycleCollectionTraverse
(cb, tmp->mDocument, "mDocument", 0); ImplCycleCollectionTraverse
(cb, tmp->mScriptLoader, "mScriptLoader", 0); ImplCycleCollectionTraverse
(cb, tmp->mContextStack, "mContextStack", 0); ImplCycleCollectionTraverse
(cb, tmp->mCurrentPrototype, "mCurrentPrototype", 0); (void
)tmp; return NS_OK; }
123 mDocument, mScriptLoader, mContextStack,PrototypeDocumentContentSink::cycleCollection PrototypeDocumentContentSink
::_cycleCollectorGlobal; void PrototypeDocumentContentSink::cycleCollection
::Unlink(void* p) { PrototypeDocumentContentSink* tmp = DowncastCCParticipant
<PrototypeDocumentContentSink>(p); ImplCycleCollectionUnlink
(tmp->mParser); ImplCycleCollectionUnlink(tmp->mDocumentURI
); ImplCycleCollectionUnlink(tmp->mDocument); ImplCycleCollectionUnlink
(tmp->mScriptLoader); ImplCycleCollectionUnlink(tmp->mContextStack
); ImplCycleCollectionUnlink(tmp->mCurrentPrototype); (void
)tmp; } nsresult PrototypeDocumentContentSink::cycleCollection
::TraverseNative( void* p, nsCycleCollectionTraversalCallback
& cb) { PrototypeDocumentContentSink* tmp = DowncastCCParticipant
<PrototypeDocumentContentSink>(p); cb.DescribeRefCountedNode
(tmp->mRefCnt.get(), "PrototypeDocumentContentSink"); ImplCycleCollectionTraverse
(cb, tmp->mParser, "mParser", 0); ImplCycleCollectionTraverse
(cb, tmp->mDocumentURI, "mDocumentURI", 0); ImplCycleCollectionTraverse
(cb, tmp->mDocument, "mDocument", 0); ImplCycleCollectionTraverse
(cb, tmp->mScriptLoader, "mScriptLoader", 0); ImplCycleCollectionTraverse
(cb, tmp->mContextStack, "mContextStack", 0); ImplCycleCollectionTraverse
(cb, tmp->mCurrentPrototype, "mCurrentPrototype", 0); (void
)tmp; return NS_OK; }
124 mCurrentPrototype)PrototypeDocumentContentSink::cycleCollection PrototypeDocumentContentSink
::_cycleCollectorGlobal; void PrototypeDocumentContentSink::cycleCollection
::Unlink(void* p) { PrototypeDocumentContentSink* tmp = DowncastCCParticipant
<PrototypeDocumentContentSink>(p); ImplCycleCollectionUnlink
(tmp->mParser); ImplCycleCollectionUnlink(tmp->mDocumentURI
); ImplCycleCollectionUnlink(tmp->mDocument); ImplCycleCollectionUnlink
(tmp->mScriptLoader); ImplCycleCollectionUnlink(tmp->mContextStack
); ImplCycleCollectionUnlink(tmp->mCurrentPrototype); (void
)tmp; } nsresult PrototypeDocumentContentSink::cycleCollection
::TraverseNative( void* p, nsCycleCollectionTraversalCallback
& cb) { PrototypeDocumentContentSink* tmp = DowncastCCParticipant
<PrototypeDocumentContentSink>(p); cb.DescribeRefCountedNode
(tmp->mRefCnt.get(), "PrototypeDocumentContentSink"); ImplCycleCollectionTraverse
(cb, tmp->mParser, "mParser", 0); ImplCycleCollectionTraverse
(cb, tmp->mDocumentURI, "mDocumentURI", 0); ImplCycleCollectionTraverse
(cb, tmp->mDocument, "mDocument", 0); ImplCycleCollectionTraverse
(cb, tmp->mScriptLoader, "mScriptLoader", 0); ImplCycleCollectionTraverse
(cb, tmp->mContextStack, "mContextStack", 0); ImplCycleCollectionTraverse
(cb, tmp->mCurrentPrototype, "mCurrentPrototype", 0); (void
)tmp; return NS_OK; }
125
126NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PrototypeDocumentContentSink)nsresult PrototypeDocumentContentSink::QueryInterface(const nsIID
& aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) {
NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 126); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface
; if (TopThreeWordsEquals( aIID, (nsXPCOMCycleCollectionParticipant
::COMTypeInfo<nsXPCOMCycleCollectionParticipant, void>::
kIID), (nsCycleCollectionISupports::COMTypeInfo<nsCycleCollectionISupports
, void>::kIID)) && (LowWordEquals(aIID, (nsXPCOMCycleCollectionParticipant
::COMTypeInfo<nsXPCOMCycleCollectionParticipant, void>::
kIID)) || LowWordEquals(aIID, (nsCycleCollectionISupports::COMTypeInfo
<nsCycleCollectionISupports, void>::kIID)))) { if (LowWordEquals
(aIID, (nsXPCOMCycleCollectionParticipant::COMTypeInfo<nsXPCOMCycleCollectionParticipant
, void>::kIID))) { *aInstancePtr = PrototypeDocumentContentSink
::cycleCollection::GetParticipant(); return NS_OK; } if (LowWordEquals
(aIID, (nsCycleCollectionISupports::COMTypeInfo<nsCycleCollectionISupports
, void>::kIID))) { *aInstancePtr = PrototypeDocumentContentSink
::cycleCollection::Upcast(this); return NS_OK; } foundInterface
= nullptr; } else
127 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContentSink)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupports>)) foundInterface = static_cast
<nsISupports*>(static_cast<nsIContentSink*>(this)
); else
128 NS_INTERFACE_MAP_ENTRY(nsIContentSink)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIContentSink>)) foundInterface =
static_cast<nsIContentSink*>(this); else
129 NS_INTERFACE_MAP_ENTRY(nsIStreamLoaderObserver)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIStreamLoaderObserver>)) foundInterface
= static_cast<nsIStreamLoaderObserver*>(this); else
130 NS_INTERFACE_MAP_ENTRY(nsICSSLoaderObserver)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsICSSLoaderObserver>)) foundInterface
= static_cast<nsICSSLoaderObserver*>(this); else
131 NS_INTERFACE_MAP_ENTRY(nsIOffThreadScriptReceiver)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIOffThreadScriptReceiver>)) foundInterface
= static_cast<nsIOffThreadScriptReceiver*>(this); else
132NS_INTERFACE_MAP_ENDfoundInterface = 0; nsresult status; if (!foundInterface) { do
{ static_assert( mozilla::detail::AssertionConditionType<
decltype(!aIID.Equals((nsISupports::COMTypeInfo<nsISupports
, void>::kIID)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aIID.Equals((nsISupports::COMTypeInfo
<nsISupports, void>::kIID))))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("!aIID.Equals((nsISupports::COMTypeInfo<nsISupports, void>::kIID))"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 132); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIID.Equals((nsISupports::COMTypeInfo<nsISupports, void>::kIID))"
")"); do { *((volatile int*)__null) = 132; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); status = NS_NOINTERFACE
; } else { (foundInterface)->AddRef(); status = NS_OK; } *
aInstancePtr = foundInterface; return status; }
133
134NS_IMPL_CYCLE_COLLECTING_ADDREF(PrototypeDocumentContentSink)MozExternalRefCountType PrototypeDocumentContentSink::AddRef(
void) { static_assert(!std::is_destructible_v<PrototypeDocumentContentSink
>, "Reference-counted class " "PrototypeDocumentContentSink"
" should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 134); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
134; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); _mOwningThread.AssertOwnership("PrototypeDocumentContentSink"
" not thread-safe"); nsISupports* base = PrototypeDocumentContentSink
::cycleCollection::Upcast(this); nsrefcnt count = mRefCnt.incr
(base); NS_LogAddRef((this), (count), ("PrototypeDocumentContentSink"
), (uint32_t)(sizeof(*this))); return count; }
135NS_IMPL_CYCLE_COLLECTING_RELEASE(PrototypeDocumentContentSink)MozExternalRefCountType PrototypeDocumentContentSink::Release
(void) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 135); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 135
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); _mOwningThread.AssertOwnership("PrototypeDocumentContentSink"
" not thread-safe"); nsISupports* base = PrototypeDocumentContentSink
::cycleCollection::Upcast(this); nsrefcnt count = mRefCnt.decr
(base); NS_LogRelease((this), (count), ("PrototypeDocumentContentSink"
)); return count; } void PrototypeDocumentContentSink::DeleteCycleCollectable
(void) { delete (this); }
136
137//----------------------------------------------------------------------
138//
139// nsIContentSink interface
140//
141
142void PrototypeDocumentContentSink::SetDocumentCharset(
143 NotNull<const Encoding*> aEncoding) {
144 if (mDocument) {
145 mDocument->SetDocumentCharacterSet(aEncoding);
146 }
147}
148
149nsISupports* PrototypeDocumentContentSink::GetTarget() {
150 return ToSupports(mDocument);
151}
152
153bool PrototypeDocumentContentSink::IsScriptExecuting() {
154 return !!mScriptLoader->GetCurrentScript();
155}
156
157NS_IMETHODIMPnsresult
158PrototypeDocumentContentSink::SetParser(nsParserBase* aParser) {
159 MOZ_ASSERT(aParser, "Should have a parser here!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aParser)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aParser))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aParser" " (" "Should have a parser here!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 159); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParser" ") ("
"Should have a parser here!" ")"); do { *((volatile int*)__null
) = 159; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
160 mParser = aParser;
161 return NS_OK;
162}
163
164nsIParser* PrototypeDocumentContentSink::GetParser() {
165 return static_cast<nsIParser*>(mParser.get());
166}
167
168void PrototypeDocumentContentSink::ContinueInterruptedParsingIfEnabled() {
169 if (mParser && mParser->IsParserEnabled()) {
170 GetParser()->ContinueInterruptedParsing();
171 }
172}
173
174void PrototypeDocumentContentSink::ContinueInterruptedParsingAsync() {
175 nsCOMPtr<nsIRunnable> ev = NewRunnableMethod(
176 "PrototypeDocumentContentSink::ContinueInterruptedParsingIfEnabled", this,
177 &PrototypeDocumentContentSink::ContinueInterruptedParsingIfEnabled);
178 mDocument->Dispatch(ev.forget());
179}
180
181//----------------------------------------------------------------------
182//
183// PrototypeDocumentContentSink::ContextStack
184//
185
186PrototypeDocumentContentSink::ContextStack::ContextStack()
187 : mTop(nullptr), mDepth(0) {}
188
189PrototypeDocumentContentSink::ContextStack::~ContextStack() { Clear(); }
190
191void PrototypeDocumentContentSink::ContextStack::Traverse(
192 nsCycleCollectionTraversalCallback& aCallback, const char* aName,
193 uint32_t aFlags) {
194 aFlags |= CycleCollectionEdgeNameArrayFlag;
195 Entry* current = mTop;
196 while (current) {
197 CycleCollectionNoteChild(aCallback, current->mElement, aName, aFlags);
198 current = current->mNext;
199 }
200}
201
202void PrototypeDocumentContentSink::ContextStack::Clear() {
203 while (mTop) {
204 Entry* doomed = mTop;
205 mTop = mTop->mNext;
206 NS_IF_RELEASE(doomed->mElement)do { if (doomed->mElement) { (doomed->mElement)->Release
(); (doomed->mElement) = 0; } } while (0)
;
207 delete doomed;
208 }
209 mDepth = 0;
210}
211
212nsresult PrototypeDocumentContentSink::ContextStack::Push(
213 nsXULPrototypeElement* aPrototype, nsIContent* aElement) {
214 Entry* entry = new Entry;
215 entry->mPrototype = aPrototype;
216 entry->mElement = aElement;
217 NS_IF_ADDREF(entry->mElement)ns_if_addref(entry->mElement);
218 entry->mIndex = 0;
219
220 entry->mNext = mTop;
221 mTop = entry;
222
223 ++mDepth;
224 return NS_OK;
225}
226
227nsresult PrototypeDocumentContentSink::ContextStack::Pop() {
228 if (mDepth == 0) return NS_ERROR_UNEXPECTED;
229
230 Entry* doomed = mTop;
231 mTop = mTop->mNext;
232 --mDepth;
233
234 NS_IF_RELEASE(doomed->mElement)do { if (doomed->mElement) { (doomed->mElement)->Release
(); (doomed->mElement) = 0; } } while (0)
;
235 delete doomed;
236 return NS_OK;
237}
238
239nsresult PrototypeDocumentContentSink::ContextStack::Peek(
240 nsXULPrototypeElement** aPrototype, nsIContent** aElement,
241 int32_t* aIndex) {
242 if (mDepth == 0) return NS_ERROR_UNEXPECTED;
243
244 *aPrototype = mTop->mPrototype;
245 *aElement = mTop->mElement;
246 NS_IF_ADDREF(*aElement)ns_if_addref(*aElement);
247 *aIndex = mTop->mIndex;
248
249 return NS_OK;
250}
251
252nsresult PrototypeDocumentContentSink::ContextStack::SetTopIndex(
253 int32_t aIndex) {
254 if (mDepth == 0) return NS_ERROR_UNEXPECTED;
255
256 mTop->mIndex = aIndex;
257 return NS_OK;
258}
259
260//----------------------------------------------------------------------
261//
262// Content model walking routines
263//
264
265nsresult PrototypeDocumentContentSink::OnPrototypeLoadDone(
266 nsXULPrototypeDocument* aPrototype) {
267 mCurrentPrototype = aPrototype;
268 mDocument->SetPrototypeDocument(aPrototype);
269
270 nsresult rv = PrepareToWalk();
271 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 271); return rv; } } while (false)
;
272
273 rv = ResumeWalk();
274
275 return rv;
276}
277
278nsresult PrototypeDocumentContentSink::PrepareToWalk() {
279 MOZ_ASSERT(mCurrentPrototype)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mCurrentPrototype)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mCurrentPrototype))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mCurrentPrototype"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 279); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCurrentPrototype"
")"); do { *((volatile int*)__null) = 279; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
280 nsresult rv;
281
282 mStillWalking = true;
283
284 // Notify document that the load is beginning
285 mDocument->BeginLoad();
286
287 // Get the prototype's root element and initialize the context
288 // stack for the prototype walk.
289 nsXULPrototypeElement* proto = mCurrentPrototype->GetRootElement();
290
291 if (!proto) {
292 if (MOZ_LOG_TEST(gLog, LogLevel::Error)(__builtin_expect(!!(mozilla::detail::log_test(gLog, LogLevel
::Error)), 0))
) {
293 nsCOMPtr<nsIURI> url = mCurrentPrototype->GetURI();
294
295 nsAutoCString urlspec;
296 rv = url->GetSpec(urlspec);
297 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
298
299 MOZ_LOG(gLog, LogLevel::Error,do { const ::mozilla::LogModule* moz_real_module = gLog; if (
(__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Error)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Error, "prototype: error parsing '%s'", urlspec.get
()); } } while (0)
300 ("prototype: error parsing '%s'", urlspec.get()))do { const ::mozilla::LogModule* moz_real_module = gLog; if (
(__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Error)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Error, "prototype: error parsing '%s'", urlspec.get
()); } } while (0)
;
301 }
302
303 return NS_OK;
304 }
305
306 nsINode* nodeToInsertBefore = mDocument->GetFirstChild();
307
308 const nsTArray<RefPtr<nsXULPrototypePI> >& processingInstructions =
309 mCurrentPrototype->GetProcessingInstructions();
310
311 uint32_t total = processingInstructions.Length();
312 for (uint32_t i = 0; i < total; ++i) {
313 rv = CreateAndInsertPI(processingInstructions[i], mDocument,
314 nodeToInsertBefore);
315 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
316 }
317
318 // Do one-time initialization.
319 RefPtr<Element> root;
320
321 // Add the root element
322 rv = CreateElementFromPrototype(proto, getter_AddRefs(root), nullptr);
323 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
324
325 ErrorResult error;
326 mDocument->AppendChildTo(root, false, error);
327 if (error.Failed()) {
328 return error.StealNSResult();
329 }
330
331 // TODO(emilio): Should this really notify? We don't notify of appends anyhow,
332 // and we just appended the root so no styles can possibly depend on it.
333 mDocument->UpdateDocumentStates(DocumentState::RTL_LOCALE, true);
334
335 nsContentUtils::AddScriptRunner(
336 new nsDocElementCreatedNotificationRunner(mDocument));
337
338 // There'd better not be anything on the context stack at this
339 // point! This is the basis case for our "induction" in
340 // ResumeWalk(), below, which'll assume that there's always a
341 // content element on the context stack if we're in the document.
342 NS_ASSERTION(mContextStack.Depth() == 0,do { if (!(mContextStack.Depth() == 0)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "something's on the context stack already", "mContextStack.Depth() == 0"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 343); MOZ_PretendNoReturn(); } } while (0)
343 "something's on the context stack already")do { if (!(mContextStack.Depth() == 0)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "something's on the context stack already", "mContextStack.Depth() == 0"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 343); MOZ_PretendNoReturn(); } } while (0)
;
344 if (mContextStack.Depth() != 0) return NS_ERROR_UNEXPECTED;
345
346 rv = mContextStack.Push(proto, root);
347 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
348
349 return NS_OK;
350}
351
352nsresult PrototypeDocumentContentSink::CreateAndInsertPI(
353 const nsXULPrototypePI* aProtoPI, nsINode* aParent, nsINode* aBeforeThis) {
354 MOZ_ASSERT(aProtoPI, "null ptr")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aProtoPI)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aProtoPI))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aProtoPI" " (" "null ptr"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 354); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aProtoPI" ") ("
"null ptr" ")"); do { *((volatile int*)__null) = 354; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
355 MOZ_ASSERT(aParent, "null ptr")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aParent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aParent))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aParent" " (" "null ptr"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 355); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent" ") ("
"null ptr" ")"); do { *((volatile int*)__null) = 355; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
356
357 RefPtr<ProcessingInstruction> node =
358 NS_NewXMLProcessingInstruction(aParent->OwnerDoc()->NodeInfoManager(),
359 aProtoPI->mTarget, aProtoPI->mData);
360
361 nsresult rv;
362 if (aProtoPI->mTarget.EqualsLiteral("xml-stylesheet")) {
363 MOZ_ASSERT(LinkStyle::FromNode(*node),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(LinkStyle::FromNode(*node))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(LinkStyle::FromNode(*node)))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("LinkStyle::FromNode(*node)"
" (" "XML Stylesheet node does not implement LinkStyle!" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 364); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LinkStyle::FromNode(*node)"
") (" "XML Stylesheet node does not implement LinkStyle!" ")"
); do { *((volatile int*)__null) = 364; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
364 "XML Stylesheet node does not implement LinkStyle!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(LinkStyle::FromNode(*node))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(LinkStyle::FromNode(*node)))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("LinkStyle::FromNode(*node)"
" (" "XML Stylesheet node does not implement LinkStyle!" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 364); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LinkStyle::FromNode(*node)"
") (" "XML Stylesheet node does not implement LinkStyle!" ")"
); do { *((volatile int*)__null) = 364; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
365 auto* pi = static_cast<XMLStylesheetProcessingInstruction*>(node.get());
366 rv = InsertXMLStylesheetPI(aProtoPI, aParent, aBeforeThis, pi);
367 } else {
368 // No special processing, just add the PI to the document.
369 ErrorResult error;
370 aParent->InsertChildBefore(node->AsContent(),
371 aBeforeThis ? aBeforeThis->AsContent() : nullptr,
372 false, error);
373 rv = error.StealNSResult();
374 }
375
376 return rv;
377}
378
379nsresult PrototypeDocumentContentSink::InsertXMLStylesheetPI(
380 const nsXULPrototypePI* aProtoPI, nsINode* aParent, nsINode* aBeforeThis,
381 XMLStylesheetProcessingInstruction* aPINode) {
382 // We want to be notified when the style sheet finishes loading, so
383 // disable style sheet loading for now.
384 aPINode->DisableUpdates();
385 aPINode->OverrideBaseURI(mCurrentPrototype->GetURI());
386
387 ErrorResult rv;
388 aParent->InsertChildBefore(
389 aPINode, aBeforeThis ? aBeforeThis->AsContent() : nullptr, false, rv);
390 if (rv.Failed()) {
391 return rv.StealNSResult();
392 }
393
394 // load the stylesheet if necessary, passing ourselves as
395 // nsICSSObserver
396 auto result = aPINode->EnableUpdatesAndUpdateStyleSheet(this);
397 if (result.isErr()) {
398 // Ignore errors from UpdateStyleSheet; we don't want failure to
399 // do that to break the XUL document load. But do propagate out
400 // NS_ERROR_OUT_OF_MEMORY.
401 if (result.unwrapErr() == NS_ERROR_OUT_OF_MEMORY) {
402 return result.unwrapErr();
403 }
404 return NS_OK;
405 }
406
407 auto update = result.unwrap();
408 if (update.ShouldBlock()) {
409 ++mPendingSheets;
410 }
411
412 return NS_OK;
413}
414
415void PrototypeDocumentContentSink::CloseElement(Element* aElement,
416 bool aHadChildren) {
417 if (nsIContent::RequiresDoneAddingChildren(
418 aElement->NodeInfo()->NamespaceID(),
419 aElement->NodeInfo()->NameAtom())) {
420 aElement->DoneAddingChildren(false);
421 }
422
423 if (auto* linkStyle = LinkStyle::FromNode(*aElement)) {
424 auto result = linkStyle->EnableUpdatesAndUpdateStyleSheet(this);
425 if (result.isOk() && result.unwrap().ShouldBlock()) {
426 ++mPendingSheets;
427 }
428 return;
429 }
430
431 if (!aHadChildren) {
432 return;
433 }
434
435 // See bug 370111 and bug 1495946. We don't cache inline styles nor module
436 // scripts in the prototype cache, and we don't notify on node insertion, so
437 // we need to do this for the stylesheet / script to be properly processed.
438 // This kinda sucks, but notifying was a pretty sizeable perf regression so...
439 if (aElement->IsHTMLElement(nsGkAtoms::script) ||
440 aElement->IsSVGElement(nsGkAtoms::script)) {
441 nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(aElement);
442 MOZ_ASSERT(sele, "Node didn't QI to script.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sele)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(sele))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("sele" " (" "Node didn't QI to script."
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 442); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sele" ") (" "Node didn't QI to script."
")"); do { *((volatile int*)__null) = 442; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
443 if (sele->GetScriptIsModule()) {
444 DebugOnly<bool> block = sele->AttemptToExecute();
445 MOZ_ASSERT(!block, "<script type=module> shouldn't block the parser")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!block)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(!block))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!block" " (" "<script type=module> shouldn't block the parser"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 445); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!block" ") ("
"<script type=module> shouldn't block the parser" ")")
; do { *((volatile int*)__null) = 445; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
446 }
447 }
448}
449
450nsresult PrototypeDocumentContentSink::ResumeWalk() {
451 nsresult rv = ResumeWalkInternal();
452 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
453 nsContentUtils::ReportToConsoleNonLocalized(
454 u"Failed to load document from prototype document."_ns,
455 nsIScriptError::errorFlag, "Prototype Document"_ns, mDocument,
456 mDocumentURI);
457 }
458 return rv;
459}
460
461nsresult PrototypeDocumentContentSink::ResumeWalkInternal() {
462 MOZ_ASSERT(mStillWalking)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mStillWalking)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mStillWalking))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("mStillWalking",
"/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 462); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mStillWalking"
")"); do { *((volatile int*)__null) = 462; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
463 // Walk the prototype and build the delegate content model. The
464 // walk is performed in a top-down, left-to-right fashion. That
465 // is, a parent is built before any of its children; a node is
466 // only built after all of its siblings to the left are fully
467 // constructed.
468 //
469 // It is interruptable so that transcluded documents (e.g.,
470 // <html:script src="..." />) can be properly re-loaded if the
471 // cached copy of the document becomes stale.
472 nsresult rv;
473 nsCOMPtr<nsIURI> docURI =
474 mCurrentPrototype ? mCurrentPrototype->GetURI() : nullptr;
475
476 while (true) {
477 // Begin (or resume) walking the current prototype.
478
479 while (mContextStack.Depth() > 0) {
480 // Look at the top of the stack to determine what we're
481 // currently working on.
482 // This will always be a node already constructed and
483 // inserted to the actual document.
484 nsXULPrototypeElement* proto;
485 nsCOMPtr<nsIContent> element;
486 nsCOMPtr<nsIContent> nodeToPushTo;
487 int32_t indx; // all children of proto before indx (not
488 // inclusive) have already been constructed
489 rv = mContextStack.Peek(&proto, getter_AddRefs(element), &indx);
490 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
491
492 if (indx >= (int32_t)proto->mChildren.Length()) {
493 if (element) {
494 // We've processed all of the prototype's children.
495 CloseElement(element->AsElement(), /* aHadChildren = */ true);
496 }
497 // Now pop the context stack back up to the parent
498 // element and continue the prototype walk.
499 mContextStack.Pop();
500 continue;
501 }
502
503 nodeToPushTo = element;
504 // For template elements append the content to the template's document
505 // fragment.
506 if (auto* templateElement = HTMLTemplateElement::FromNode(element)) {
507 nodeToPushTo = templateElement->Content();
508 }
509
510 // Grab the next child, and advance the current context stack
511 // to the next sibling to our right.
512 nsXULPrototypeNode* childproto = proto->mChildren[indx];
513 mContextStack.SetTopIndex(++indx);
514
515 switch (childproto->mType) {
516 case nsXULPrototypeNode::eType_Element: {
517 // An 'element', which may contain more content.
518 auto* protoele = static_cast<nsXULPrototypeElement*>(childproto);
519
520 RefPtr<Element> child;
521 MOZ_TRY(CreateElementFromPrototype(protoele, getter_AddRefs(child),do { auto mozTryTempResult_ = ::mozilla::ToResult(CreateElementFromPrototype
(protoele, getter_AddRefs(child), nodeToPushTo)); if ((__builtin_expect
(!!(mozTryTempResult_.isErr()), 0))) { return mozTryTempResult_
.propagateErr(); } } while (0)
522 nodeToPushTo))do { auto mozTryTempResult_ = ::mozilla::ToResult(CreateElementFromPrototype
(protoele, getter_AddRefs(child), nodeToPushTo)); if ((__builtin_expect
(!!(mozTryTempResult_.isErr()), 0))) { return mozTryTempResult_
.propagateErr(); } } while (0)
;
523
524 if (auto* linkStyle = LinkStyle::FromNode(*child)) {
525 linkStyle->DisableUpdates();
526 }
527
528 // ...and append it to the content model.
529 ErrorResult error;
530 nodeToPushTo->AppendChildTo(child, false, error);
531 if (error.Failed()) {
532 return error.StealNSResult();
533 }
534
535 if (nsIContent::RequiresDoneCreatingElement(
536 protoele->mNodeInfo->NamespaceID(),
537 protoele->mNodeInfo->NameAtom())) {
538 child->DoneCreatingElement();
539 }
540
541 // If it has children, push the element onto the context
542 // stack and begin to process them.
543 if (protoele->mChildren.Length() > 0) {
544 rv = mContextStack.Push(protoele, child);
545 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
546 } else {
547 // If there are no children, close the element immediately.
548 CloseElement(child, /* aHadChildren = */ false);
549 }
550 } break;
551
552 case nsXULPrototypeNode::eType_Script: {
553 // A script reference. Execute the script immediately;
554 // this may have side effects in the content model.
555 auto* scriptproto = static_cast<nsXULPrototypeScript*>(childproto);
556 if (scriptproto->mSrcURI) {
557 // A transcluded script reference; this may
558 // "block" our prototype walk if the script isn't
559 // cached, or the cached copy of the script is
560 // stale and must be reloaded.
561 bool blocked;
562 rv = LoadScript(scriptproto, &blocked);
563 // If the script cannot be loaded, just keep going!
564
565 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && blocked) return NS_OK;
566 } else if (scriptproto->HasStencil()) {
567 // An inline script
568 rv = ExecuteScript(scriptproto);
569 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
570 }
571 } break;
572
573 case nsXULPrototypeNode::eType_Text: {
574 nsNodeInfoManager* nim = nodeToPushTo->NodeInfo()->NodeInfoManager();
575 // A simple text node.
576 RefPtr<nsTextNode> text = new (nim) nsTextNode(nim);
577
578 auto* textproto = static_cast<nsXULPrototypeText*>(childproto);
579 text->SetText(textproto->mValue, false);
580
581 ErrorResult error;
582 nodeToPushTo->AppendChildTo(text, false, error);
583 if (error.Failed()) {
584 return error.StealNSResult();
585 }
586 } break;
587
588 case nsXULPrototypeNode::eType_PI: {
589 auto* piProto = static_cast<nsXULPrototypePI*>(childproto);
590
591 // <?xml-stylesheet?> doesn't have an effect
592 // outside the prolog, like it used to. Issue a warning.
593
594 if (piProto->mTarget.EqualsLiteral("xml-stylesheet")) {
595 AutoTArray<nsString, 1> params = {piProto->mTarget};
596
597 nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
598 "XUL Document"_ns, nullptr,
599 nsContentUtils::eXUL_PROPERTIES,
600 "PINotInProlog", params, docURI);
601 }
602
603 nsIContent* parent = element.get();
604 if (parent) {
605 // an inline script could have removed the root element
606 rv = CreateAndInsertPI(piProto, parent, nullptr);
607 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 607); return rv; } } while (false)
;
608 }
609 } break;
610
611 default:
612 MOZ_ASSERT_UNREACHABLE("Unexpected nsXULPrototypeNode::Type")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Unexpected nsXULPrototypeNode::Type" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 612); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Unexpected nsXULPrototypeNode::Type"
")"); do { *((volatile int*)__null) = 612; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
613 }
614 }
615
616 // Once we get here, the context stack will have been
617 // depleted. That means that the entire prototype has been
618 // walked and content has been constructed.
619 break;
620 }
621
622 mStillWalking = false;
623 return MaybeDoneWalking();
624}
625
626void PrototypeDocumentContentSink::InitialTranslationCompleted() {
627 MaybeDoneWalking();
628}
629
630nsresult PrototypeDocumentContentSink::MaybeDoneWalking() {
631 if (mPendingSheets > 0 || mStillWalking) {
632 return NS_OK;
633 }
634
635 if (mDocument->HasPendingInitialTranslation()) {
636 mDocument->OnParsingCompleted();
637 return NS_OK;
638 }
639
640 return DoneWalking();
641}
642
643nsresult PrototypeDocumentContentSink::DoneWalking() {
644 MOZ_ASSERT(mPendingSheets == 0, "there are sheets to be loaded")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mPendingSheets == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mPendingSheets == 0))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("mPendingSheets == 0"
" (" "there are sheets to be loaded" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 644); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPendingSheets == 0"
") (" "there are sheets to be loaded" ")"); do { *((volatile
int*)__null) = 644; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
645 MOZ_ASSERT(!mStillWalking, "walk not done")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mStillWalking)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mStillWalking))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!mStillWalking"
" (" "walk not done" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 645); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mStillWalking"
") (" "walk not done" ")"); do { *((volatile int*)__null) = 645
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
646 MOZ_ASSERT(!mDocument->HasPendingInitialTranslation(), "translation pending")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mDocument->HasPendingInitialTranslation())>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!mDocument->HasPendingInitialTranslation()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("!mDocument->HasPendingInitialTranslation()"
" (" "translation pending" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 646); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mDocument->HasPendingInitialTranslation()"
") (" "translation pending" ")"); do { *((volatile int*)__null
) = 646; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
647
648 if (mDocument) {
649 MOZ_ASSERT(mDocument->GetReadyStateEnum() == Document::READYSTATE_LOADING,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDocument->GetReadyStateEnum() == Document::READYSTATE_LOADING
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mDocument->GetReadyStateEnum() == Document::READYSTATE_LOADING
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mDocument->GetReadyStateEnum() == Document::READYSTATE_LOADING"
" (" "Bad readyState" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 650); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDocument->GetReadyStateEnum() == Document::READYSTATE_LOADING"
") (" "Bad readyState" ")"); do { *((volatile int*)__null) =
650; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false)
650 "Bad readyState")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDocument->GetReadyStateEnum() == Document::READYSTATE_LOADING
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mDocument->GetReadyStateEnum() == Document::READYSTATE_LOADING
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mDocument->GetReadyStateEnum() == Document::READYSTATE_LOADING"
" (" "Bad readyState" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 650); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDocument->GetReadyStateEnum() == Document::READYSTATE_LOADING"
") (" "Bad readyState" ")"); do { *((volatile int*)__null) =
650; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false)
;
651 mDocument->SetReadyStateInternal(Document::READYSTATE_INTERACTIVE);
652 mDocument->NotifyPossibleTitleChange(false);
653
654 nsContentUtils::DispatchEventOnlyToChrome(mDocument, mDocument,
655 u"MozBeforeInitialXULLayout"_ns,
656 CanBubble::eYes, Cancelable::eNo);
657 }
658
659 if (mScriptLoader) {
660 mScriptLoader->ParsingComplete(false);
661 mScriptLoader->DeferCheckpointReached();
662 }
663
664 StartLayout();
665
666 if (IsChromeURI(mDocumentURI) &&
667 nsXULPrototypeCache::GetInstance()->IsEnabled()) {
668 bool isCachedOnDisk;
669 nsXULPrototypeCache::GetInstance()->HasPrototype(mDocumentURI,
670 &isCachedOnDisk);
671 if (!isCachedOnDisk) {
672 if (!mDocument->GetDocumentElement() ||
673 (mDocument->GetDocumentElement()->NodeInfo()->Equals(
674 nsGkAtoms::parsererror) &&
675 mDocument->GetDocumentElement()->NodeInfo()->NamespaceEquals(
676 nsDependentAtomString(nsGkAtoms::nsuri_parsererror)))) {
677 nsXULPrototypeCache::GetInstance()->RemovePrototype(mDocumentURI);
678 } else {
679 nsXULPrototypeCache::GetInstance()->WritePrototype(mCurrentPrototype);
680 }
681 }
682 }
683
684 mDocument->SetDelayFrameLoaderInitialization(false);
685 RefPtr<Document> doc = mDocument;
686 doc->MaybeInitializeFinalizeFrameLoaders();
687
688 // If the document we are loading has a reference or it is a
689 // frameset document, disable the scroll bars on the views.
690
691 doc->SetScrollToRef(mDocument->GetDocumentURI());
692
693 doc->EndLoad();
694
695 return NS_OK;
696}
697
698void PrototypeDocumentContentSink::StartLayout() {
699 AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING(mozilla::Maybe<nsAutoCString> autoCStr; mozilla::Maybe<
mozilla::AutoProfilerLabel> raiiObjectNsCString; if (profiler_is_active
()) { autoCStr.emplace(mDocumentURI->GetSpecOrDefault()); raiiObjectNsCString
.emplace("PrototypeDocumentContentSink::StartLayout", autoCStr
->get(), JS::ProfilingCategoryPair::LAYOUT); }
700 "PrototypeDocumentContentSink::StartLayout", LAYOUT,mozilla::Maybe<nsAutoCString> autoCStr; mozilla::Maybe<
mozilla::AutoProfilerLabel> raiiObjectNsCString; if (profiler_is_active
()) { autoCStr.emplace(mDocumentURI->GetSpecOrDefault()); raiiObjectNsCString
.emplace("PrototypeDocumentContentSink::StartLayout", autoCStr
->get(), JS::ProfilingCategoryPair::LAYOUT); }
701 mDocumentURI->GetSpecOrDefault())mozilla::Maybe<nsAutoCString> autoCStr; mozilla::Maybe<
mozilla::AutoProfilerLabel> raiiObjectNsCString; if (profiler_is_active
()) { autoCStr.emplace(mDocumentURI->GetSpecOrDefault()); raiiObjectNsCString
.emplace("PrototypeDocumentContentSink::StartLayout", autoCStr
->get(), JS::ProfilingCategoryPair::LAYOUT); }
;
702 mDocument->SetMayStartLayout(true);
703 RefPtr<PresShell> presShell = mDocument->GetPresShell();
704 if (presShell && !presShell->DidInitialize()) {
705 nsresult rv = presShell->Initialize();
706 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
707 return;
708 }
709 }
710}
711
712NS_IMETHODIMPnsresult
713PrototypeDocumentContentSink::StyleSheetLoaded(StyleSheet* aSheet,
714 bool aWasDeferred,
715 nsresult aStatus) {
716 if (!aWasDeferred) {
717 // Don't care about when alternate sheets finish loading
718 MOZ_ASSERT(mPendingSheets > 0, "Unexpected StyleSheetLoaded notification")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mPendingSheets > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mPendingSheets > 0))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("mPendingSheets > 0"
" (" "Unexpected StyleSheetLoaded notification" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 718); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPendingSheets > 0"
") (" "Unexpected StyleSheetLoaded notification" ")"); do { *
((volatile int*)__null) = 718; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
719
720 --mPendingSheets;
721
722 return MaybeDoneWalking();
723 }
724
725 return NS_OK;
726}
727
728nsresult PrototypeDocumentContentSink::LoadScript(
729 nsXULPrototypeScript* aScriptProto, bool* aBlock) {
730 // Load a transcluded script
731 nsresult rv;
732
733 bool isChromeDoc = IsChromeURI(mDocumentURI);
734
735 if (isChromeDoc && aScriptProto->HasStencil()) {
736 rv = ExecuteScript(aScriptProto);
737
738 // Ignore return value from execution, and don't block
739 *aBlock = false;
740 return NS_OK;
741 }
742
743 // Try the XUL script cache, in case two XUL documents source the same
744 // .js file (e.g., strres.js from navigator.xul and utilityOverlay.xul).
745 // XXXbe the cache relies on aScriptProto's GC root!
746 bool useXULCache = nsXULPrototypeCache::GetInstance()->IsEnabled();
747
748 if (isChromeDoc && useXULCache) {
749 RefPtr<JS::Stencil> newStencil =
750 nsXULPrototypeCache::GetInstance()->GetStencil(aScriptProto->mSrcURI);
751 if (newStencil) {
752 // The script language for a proto must remain constant - we
753 // can't just change it for this unexpected language.
754 aScriptProto->Set(newStencil);
755 }
756
757 if (aScriptProto->HasStencil()) {
758 rv = ExecuteScript(aScriptProto);
759
760 // Ignore return value from execution, and don't block
761 *aBlock = false;
762 return NS_OK;
763 }
764 }
765
766 // Release stencil from FastLoad since we decided against using them
767 aScriptProto->Set(nullptr);
768
769 // Set the current script prototype so that OnStreamComplete can report
770 // the right file if there are errors in the script.
771 NS_ASSERTION(!mCurrentScriptProto,do { if (!(!mCurrentScriptProto)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "still loading a script when starting another load?", "!mCurrentScriptProto"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 772); MOZ_PretendNoReturn(); } } while (0)
772 "still loading a script when starting another load?")do { if (!(!mCurrentScriptProto)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "still loading a script when starting another load?", "!mCurrentScriptProto"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 772); MOZ_PretendNoReturn(); } } while (0)
;
773 mCurrentScriptProto = aScriptProto;
774
775 if (isChromeDoc && aScriptProto->mSrcLoading) {
776 // Another document load has started, which is still in progress.
777 // Remember to ResumeWalk this document when the load completes.
778 mNextSrcLoadWaiter = aScriptProto->mSrcLoadWaiters;
779 aScriptProto->mSrcLoadWaiters = this;
780 NS_ADDREF_THIS()AddRef();
781 } else {
782 nsCOMPtr<nsILoadGroup> group =
783 mDocument
784 ->GetDocumentLoadGroup(); // found in
785 // mozilla::dom::Document::SetScriptGlobalObject
786
787 // Note: the loader will keep itself alive while it's loading.
788 nsCOMPtr<nsIStreamLoader> loader;
789 rv = NS_NewStreamLoader(
790 getter_AddRefs(loader), aScriptProto->mSrcURI,
791 this, // aObserver
792 mDocument, // aRequestingContext
793 nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_INHERITS_SEC_CONTEXT,
794 nsIContentPolicy::TYPE_INTERNAL_SCRIPT, group);
795
796 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
797 mCurrentScriptProto = nullptr;
798 return rv;
799 }
800
801 aScriptProto->mSrcLoading = true;
802 }
803
804 // Block until OnStreamComplete resumes us.
805 *aBlock = true;
806 return NS_OK;
807}
808
809NS_IMETHODIMPnsresult
810PrototypeDocumentContentSink::OnStreamComplete(nsIStreamLoader* aLoader,
811 nsISupports* context,
812 nsresult aStatus,
813 uint32_t stringLen,
814 const uint8_t* string) {
815 nsCOMPtr<nsIRequest> request;
816 aLoader->GetRequest(getter_AddRefs(request));
817 nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
818
819#ifdef DEBUG1
820 // print a load error on bad status
821 if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) {
822 if (channel) {
823 nsCOMPtr<nsIURI> uri;
824 channel->GetURI(getter_AddRefs(uri));
825 if (uri) {
826 printf("Failed to load %s\n", uri->GetSpecOrDefault().get());
827 }
828 }
829 }
830#endif
831
832 // This is the completion routine that will be called when a
833 // transcluded script completes. Compile and execute the script
834 // if the load was successful, then continue building content
835 // from the prototype.
836 nsresult rv = aStatus;
837
838 NS_ASSERTION(mCurrentScriptProto && mCurrentScriptProto->mSrcLoading,do { if (!(mCurrentScriptProto && mCurrentScriptProto
->mSrcLoading)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "script source not loading on unichar stream complete?"
, "mCurrentScriptProto && mCurrentScriptProto->mSrcLoading"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 839); MOZ_PretendNoReturn(); } } while (0)
839 "script source not loading on unichar stream complete?")do { if (!(mCurrentScriptProto && mCurrentScriptProto
->mSrcLoading)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "script source not loading on unichar stream complete?"
, "mCurrentScriptProto && mCurrentScriptProto->mSrcLoading"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 839); MOZ_PretendNoReturn(); } } while (0)
;
840 if (!mCurrentScriptProto) {
841 // XXX Wallpaper for bug 270042
842 return NS_OK;
843 }
844
845 if (NS_SUCCEEDED(aStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatus)), 1)))) {
846 // If the including document is a FastLoad document, and we're
847 // compiling an out-of-line script (one with src=...), then we must
848 // be writing a new FastLoad file. If we were reading this script
849 // from the FastLoad file, XULContentSinkImpl::OpenScript (over in
850 // nsXULContentSink.cpp) would have already deserialized a non-null
851 // script->mStencil, causing control flow at the top of LoadScript
852 // not to reach here.
853 nsCOMPtr<nsIURI> uri = mCurrentScriptProto->mSrcURI;
854
855 // XXX should also check nsIHttpChannel::requestSucceeded
856
857 MOZ_ASSERT(!mOffThreadCompiling,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mOffThreadCompiling)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mOffThreadCompiling))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("!mOffThreadCompiling"
" (" "PrototypeDocument can't load multiple scripts at once"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 858); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mOffThreadCompiling"
") (" "PrototypeDocument can't load multiple scripts at once"
")"); do { *((volatile int*)__null) = 858; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
858 "PrototypeDocument can't load multiple scripts at once")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mOffThreadCompiling)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mOffThreadCompiling))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("!mOffThreadCompiling"
" (" "PrototypeDocument can't load multiple scripts at once"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 858); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mOffThreadCompiling"
") (" "PrototypeDocument can't load multiple scripts at once"
")"); do { *((volatile int*)__null) = 858; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
859
860 UniquePtr<Utf8Unit[], JS::FreePolicy> units;
861 size_t unitsLength = 0;
862
863 rv = ScriptLoader::ConvertToUTF8(channel, string, stringLen, u""_ns,
864 mDocument, units, unitsLength);
865 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
866 rv = mCurrentScriptProto->CompileMaybeOffThread(
867 std::move(units), unitsLength, uri, 1, mDocument, this);
868 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !mCurrentScriptProto->HasStencil()) {
869 mOffThreadCompiling = true;
870 mDocument->BlockOnload();
871 return NS_OK;
872 }
873 }
874 }
875
876 return OnScriptCompileComplete(mCurrentScriptProto->GetStencil(), rv);
877}
878
879NS_IMETHODIMPnsresult
880PrototypeDocumentContentSink::OnScriptCompileComplete(JS::Stencil* aStencil,
881 nsresult aStatus) {
882 // The mCurrentScriptProto may have been cleared out by another
883 // PrototypeDocumentContentSink.
884 if (!mCurrentScriptProto) {
885 return NS_OK;
886 }
887
888 // When compiling off thread the script will not have been attached to the
889 // script proto yet.
890 if (aStencil && !mCurrentScriptProto->HasStencil()) {
891 mCurrentScriptProto->Set(aStencil);
892 }
893
894 // Allow load events to be fired once off thread compilation finishes.
895 if (mOffThreadCompiling) {
896 mOffThreadCompiling = false;
897 mDocument->UnblockOnload(false);
898 }
899
900 // Clear mCurrentScriptProto now, but save it first for use below in
901 // the execute code, and in the while loop that resumes walks of other
902 // documents that raced to load this script.
903 nsXULPrototypeScript* scriptProto = mCurrentScriptProto;
904 mCurrentScriptProto = nullptr;
905
906 // Clear the prototype's loading flag before executing the script or
907 // resuming document walks, in case any of those control flows starts a
908 // new script load.
909 scriptProto->mSrcLoading = false;
910
911 nsresult rv = aStatus;
912 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
913 rv = ExecuteScript(scriptProto);
Value stored to 'rv' is never read
914
915 // If the XUL cache is enabled, save the script object there in
916 // case different XUL documents source the same script.
917 //
918 // But don't save the script in the cache unless the master XUL
919 // document URL is a chrome: URL. It is valid for a URL such as
920 // about:config to translate into a master document URL, whose
921 // prototype document nodes -- including prototype scripts that
922 // hold GC roots protecting their mJSObject pointers -- are not
923 // cached in the XUL prototype cache. See StartDocumentLoad,
924 // the fillXULCache logic.
925 //
926 // A document such as about:config is free to load a script via
927 // a URL such as chrome://global/content/config.js, and we must
928 // not cache that script object without a prototype cache entry
929 // containing a companion nsXULPrototypeScript node that owns a
930 // GC root protecting the script object. Otherwise, the script
931 // cache entry will dangle once the uncached prototype document
932 // is released when its owning document is unloaded.
933 //
934 // (See http://bugzilla.mozilla.org/show_bug.cgi?id=98207 for
935 // the true crime story.)
936 bool useXULCache = nsXULPrototypeCache::GetInstance()->IsEnabled();
937
938 if (useXULCache && IsChromeURI(mDocumentURI) && scriptProto->HasStencil()) {
939 nsXULPrototypeCache::GetInstance()->PutStencil(scriptProto->mSrcURI,
940 scriptProto->GetStencil());
941 }
942 // ignore any evaluation errors
943 }
944
945 rv = ResumeWalk();
946
947 // Load a pointer to the prototype-script's list of documents who
948 // raced to load the same script
949 PrototypeDocumentContentSink** docp = &scriptProto->mSrcLoadWaiters;
950
951 // Resume walking other documents that waited for this one's load, first
952 // executing the script we just compiled, in each doc's script context
953 PrototypeDocumentContentSink* doc;
954 while ((doc = *docp) != nullptr) {
955 NS_ASSERTION(doc->mCurrentScriptProto == scriptProto,do { if (!(doc->mCurrentScriptProto == scriptProto)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "waiting for wrong script to load?", "doc->mCurrentScriptProto == scriptProto"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 956); MOZ_PretendNoReturn(); } } while (0)
956 "waiting for wrong script to load?")do { if (!(doc->mCurrentScriptProto == scriptProto)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "waiting for wrong script to load?", "doc->mCurrentScriptProto == scriptProto"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 956); MOZ_PretendNoReturn(); } } while (0)
;
957 doc->mCurrentScriptProto = nullptr;
958
959 // Unlink doc from scriptProto's list before executing and resuming
960 *docp = doc->mNextSrcLoadWaiter;
961 doc->mNextSrcLoadWaiter = nullptr;
962
963 if (aStatus == NS_BINDING_ABORTED && !scriptProto->HasStencil()) {
964 // If the previous doc load was aborted, we want to try loading
965 // again for the next doc. Otherwise, one abort would lead to all
966 // subsequent waiting docs to abort as well.
967 bool block = false;
968 doc->LoadScript(scriptProto, &block);
969 NS_RELEASE(doc)do { (doc)->Release(); (doc) = 0; } while (0);
970 return rv;
971 }
972
973 // Execute only if we loaded and compiled successfully, then resume
974 if (NS_SUCCEEDED(aStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatus)), 1))) && scriptProto->HasStencil()) {
975 doc->ExecuteScript(scriptProto);
976 }
977 doc->ResumeWalk();
978 NS_RELEASE(doc)do { (doc)->Release(); (doc) = 0; } while (0);
979 }
980
981 return rv;
982}
983
984nsresult PrototypeDocumentContentSink::ExecuteScript(
985 nsXULPrototypeScript* aScript) {
986 MOZ_ASSERT(aScript != nullptr, "null ptr")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aScript != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aScript != nullptr))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("aScript != nullptr"
" (" "null ptr" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 986); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aScript != nullptr"
") (" "null ptr" ")"); do { *((volatile int*)__null) = 986; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
987 NS_ENSURE_TRUE(aScript, NS_ERROR_NULL_POINTER)do { if ((__builtin_expect(!!(!(aScript)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aScript" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 987); return NS_ERROR_NULL_POINTER; } } while (false)
;
988
989 nsIScriptGlobalObject* scriptGlobalObject;
990 bool aHasHadScriptHandlingObject;
991 scriptGlobalObject =
992 mDocument->GetScriptHandlingObject(aHasHadScriptHandlingObject);
993
994 NS_ENSURE_TRUE(scriptGlobalObject, NS_ERROR_NOT_INITIALIZED)do { if ((__builtin_expect(!!(!(scriptGlobalObject)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "scriptGlobalObject" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 994); return NS_ERROR_NOT_INITIALIZED; } } while (false)
;
995
996 nsresult rv;
997 rv = scriptGlobalObject->EnsureScriptEnvironment();
998 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 998); return rv; } } while (false)
;
999
1000 // Execute the precompiled script with the given version
1001 nsAutoMicroTask mt;
1002
1003 // We're about to run script via JS_ExecuteScript, so we need an
1004 // AutoEntryScript. This is Gecko specific and not in any spec.
1005 AutoEntryScript aes(scriptGlobalObject, "precompiled XUL <script> element");
1006 JSContext* cx = aes.cx();
1007
1008 JS::Rooted<JSScript*> scriptObject(cx);
1009 rv = aScript->InstantiateScript(cx, &scriptObject);
1010 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 1010); return rv; } } while (false)
;
1011
1012 JS::Rooted<JSObject*> global(cx, JS::CurrentGlobalOrNull(cx));
1013 NS_ENSURE_TRUE(xpc::Scriptability::Get(global).Allowed(), NS_OK)do { if ((__builtin_expect(!!(!(xpc::Scriptability::Get(global
).Allowed())), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"xpc::Scriptability::Get(global).Allowed()" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 1013); return NS_OK; } } while (false)
;
1014
1015 // On failure, ~AutoScriptEntry will handle exceptions, so
1016 // there is no need to manually check the return value.
1017 JS::Rooted<JS::Value> rval(cx);
1018 Unused << JS_ExecuteScript(cx, scriptObject, &rval);
1019
1020 return NS_OK;
1021}
1022
1023nsresult PrototypeDocumentContentSink::CreateElementFromPrototype(
1024 nsXULPrototypeElement* aPrototype, Element** aResult, nsIContent* aParent) {
1025 // Create a content model element from a prototype element.
1026 MOZ_ASSERT(aPrototype, "null ptr")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPrototype)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPrototype))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aPrototype" " (" "null ptr"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 1026); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrototype"
") (" "null ptr" ")"); do { *((volatile int*)__null) = 1026;
__attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
1027 if (!aPrototype) return NS_ERROR_NULL_POINTER;
1028
1029 *aResult = nullptr;
1030 nsresult rv = NS_OK;
1031
1032 if (MOZ_LOG_TEST(gLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gLog, LogLevel
::Debug)), 0))
) {
1033 MOZ_LOG(do { const ::mozilla::LogModule* moz_real_module = gLog; if (
(__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "prototype: creating <%s> from prototype"
, NS_ConvertUTF16toUTF8(aPrototype->mNodeInfo->QualifiedName
()).get()); } } while (0)
1034 gLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gLog; if (
(__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "prototype: creating <%s> from prototype"
, NS_ConvertUTF16toUTF8(aPrototype->mNodeInfo->QualifiedName
()).get()); } } while (0)
1035 ("prototype: creating <%s> from prototype",do { const ::mozilla::LogModule* moz_real_module = gLog; if (
(__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "prototype: creating <%s> from prototype"
, NS_ConvertUTF16toUTF8(aPrototype->mNodeInfo->QualifiedName
()).get()); } } while (0)
1036 NS_ConvertUTF16toUTF8(aPrototype->mNodeInfo->QualifiedName()).get()))do { const ::mozilla::LogModule* moz_real_module = gLog; if (
(__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "prototype: creating <%s> from prototype"
, NS_ConvertUTF16toUTF8(aPrototype->mNodeInfo->QualifiedName
()).get()); } } while (0)
;
1037 }
1038
1039 RefPtr<Element> result;
1040
1041 Document* doc = aParent ? aParent->OwnerDoc() : mDocument.get();
1042 if (aPrototype->mNodeInfo->NamespaceEquals(kNameSpaceID_XUL8)) {
1043 const bool isRoot = !aParent;
1044 // If it's a XUL element, it'll be lightweight until somebody
1045 // monkeys with it.
1046 rv = nsXULElement::CreateFromPrototype(aPrototype, doc, true, isRoot,
1047 getter_AddRefs(result));
1048 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
1049 } else {
1050 // If it's not a XUL element, it's gonna be heavyweight no matter
1051 // what. So we need to copy everything out of the prototype
1052 // into the element. Get a nodeinfo from our nodeinfo manager
1053 // for this node.
1054 RefPtr<NodeInfo> newNodeInfo = doc->NodeInfoManager()->GetNodeInfo(
1055 aPrototype->mNodeInfo->NameAtom(),
1056 aPrototype->mNodeInfo->GetPrefixAtom(),
1057 aPrototype->mNodeInfo->NamespaceID(), nsINode::ELEMENT_NODE);
1058 if (!newNodeInfo) {
1059 return NS_ERROR_OUT_OF_MEMORY;
1060 }
1061 const bool isScript =
1062 newNodeInfo->Equals(nsGkAtoms::script, kNameSpaceID_XHTML3) ||
1063 newNodeInfo->Equals(nsGkAtoms::script, kNameSpaceID_SVG9);
1064 if (aPrototype->mIsAtom &&
1065 newNodeInfo->NamespaceID() == kNameSpaceID_XHTML3) {
1066 rv = NS_NewHTMLElement(getter_AddRefs(result), newNodeInfo.forget(),
1067 NOT_FROM_PARSER, aPrototype->mIsAtom);
1068 } else {
1069 rv = NS_NewElement(getter_AddRefs(result), newNodeInfo.forget(),
1070 NOT_FROM_PARSER);
1071 }
1072 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
1073
1074 rv = AddAttributes(aPrototype, result);
1075 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
1076
1077 if (isScript) {
1078 nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(result);
1079 MOZ_ASSERT(sele, "Node didn't QI to script.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sele)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(sele))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("sele" " (" "Node didn't QI to script."
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/prototype/PrototypeDocumentContentSink.cpp"
, 1079); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sele" ") ("
"Node didn't QI to script." ")"); do { *((volatile int*)__null
) = 1079; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
1080
1081 sele->FreezeExecutionAttrs(doc);
1082 // Script loading is handled by the this content sink, so prevent the
1083 // script from loading when it is bound to the document.
1084 //
1085 // NOTE(emilio): This is only done for non-module scripts, because we
1086 // don't support caching modules properly yet, see the comment in
1087 // XULContentSinkImpl::OpenScript. For non-inline scripts, this is enough,
1088 // since we can start the load when the node is inserted. Non-inline
1089 // scripts need another special-case in CloseElement.
1090 if (!sele->GetScriptIsModule()) {
1091 sele->PreventExecution();
1092 }
1093 }
1094 }
1095
1096 // FIXME(bug 1627474): Is this right if this is inside an <html:template>?
1097 if (result->HasAttr(nsGkAtoms::datal10nid)) {
1098 mDocument->mL10nProtoElements.InsertOrUpdate(result, RefPtr{aPrototype});
1099 result->SetElementCreatedFromPrototypeAndHasUnmodifiedL10n();
1100 }
1101 result.forget(aResult);
1102 return NS_OK;
1103}
1104
1105nsresult PrototypeDocumentContentSink::AddAttributes(
1106 nsXULPrototypeElement* aPrototype, Element* aElement) {
1107 nsresult rv;
1108
1109 for (size_t i = 0; i < aPrototype->mAttributes.Length(); ++i) {
1110 nsXULPrototypeAttribute* protoattr = &(aPrototype->mAttributes[i]);
1111 nsAutoString valueStr;
1112 protoattr->mValue.ToString(valueStr);
1113
1114 rv = aElement->SetAttr(protoattr->mName.NamespaceID(),
1115 protoattr->mName.LocalName(),
1116 protoattr->mName.GetPrefix(), valueStr, false);
1117 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
1118 }
1119
1120 return NS_OK;
1121}
1122
1123} // namespace mozilla::dom