Backed out 4 changesets (bug 1948254) for causing build bustages @ NavigateEvent.h
Backed out changeset 14269121caf3 (bug 1948254) Backed out changeset e327d067c6a0 (bug 1948254) Backed out changeset d13b8e53fb78 (bug 1948254) Backed out changeset 3c4be02a9115 (bug 1948254)
This commit is contained in:
@@ -607,15 +607,15 @@ bool WindowContext::HasValidHistoryActivation() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/interaction.html#consume-history-action-user-activation
|
// https://html.spec.whatwg.org/multipage/interaction.html#consume-history-action-user-activation
|
||||||
void WindowContext::ConsumeHistoryActivation() {
|
bool WindowContext::ConsumeHistoryActivation() {
|
||||||
MOZ_ASSERT(IsInProcess());
|
MOZ_ASSERT(IsInProcess());
|
||||||
|
|
||||||
if (!HasValidHistoryActivation()) {
|
if (!HasValidHistoryActivation()) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mHistoryActivation = mUserGestureStart;
|
mHistoryActivation = mUserGestureStart;
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WindowContext::GetTransientUserGestureActivationModifiers(
|
bool WindowContext::GetTransientUserGestureActivationModifiers(
|
||||||
|
|||||||
@@ -229,8 +229,9 @@ class WindowContext : public nsISupports, public nsWrapperCache {
|
|||||||
// Return true if its corresponding window has history activation.
|
// Return true if its corresponding window has history activation.
|
||||||
bool HasValidHistoryActivation() const;
|
bool HasValidHistoryActivation() const;
|
||||||
|
|
||||||
// Consume the history-action user activation.
|
// Return true if the corresponding window has valid history activation
|
||||||
void ConsumeHistoryActivation();
|
// and the history activation had been consumed successfully.
|
||||||
|
bool ConsumeHistoryActivation();
|
||||||
|
|
||||||
bool GetTransientUserGestureActivationModifiers(
|
bool GetTransientUserGestureActivationModifiers(
|
||||||
UserActivation::Modifiers* aModifiers);
|
UserActivation::Modifiers* aModifiers);
|
||||||
|
|||||||
@@ -11353,20 +11353,6 @@ nsDocShell::AddState(JS::Handle<JS::Value> aData, const nsAString& aTitle,
|
|||||||
|
|
||||||
} // end of same-origin check
|
} // end of same-origin check
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/#shared-history-push/replace-state-steps
|
|
||||||
// Step 8
|
|
||||||
if (nsCOMPtr<nsPIDOMWindowInner> window = document->GetInnerWindow()) {
|
|
||||||
if (RefPtr<Navigation> navigation = window->Navigation();
|
|
||||||
navigation &&
|
|
||||||
navigation->FirePushReplaceReloadNavigateEvent(
|
|
||||||
aReplace ? NavigationType::Replace : NavigationType::Push, newURI,
|
|
||||||
/* aIsSameDocument */ true, /* aUserInvolvement */ Nothing(),
|
|
||||||
/* aSourceElement */ nullptr, /* aFormDataEntryList */ Nothing(),
|
|
||||||
/* aNavigationAPIState */ nullptr, scContainer)) {
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 8: call "URL and history update steps"
|
// Step 8: call "URL and history update steps"
|
||||||
rv = UpdateURLAndHistory(document, newURI, scContainer,
|
rv = UpdateURLAndHistory(document, newURI, scContainer,
|
||||||
aReplace ? NavigationHistoryBehavior::Replace
|
aReplace ? NavigationHistoryBehavior::Replace
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ interface nsIDocShell : nsIDocShellTreeItem
|
|||||||
* Do either a history.pushState() or history.replaceState() operation,
|
* Do either a history.pushState() or history.replaceState() operation,
|
||||||
* depending on the value of aReplace.
|
* depending on the value of aReplace.
|
||||||
*/
|
*/
|
||||||
[implicit_jscontext, can_run_script]
|
[implicit_jscontext]
|
||||||
void addState(in jsval aData, in AString aTitle,
|
void addState(in jsval aData, in AString aTitle,
|
||||||
in AString aURL, in boolean aReplace);
|
in AString aURL, in boolean aReplace);
|
||||||
|
|
||||||
|
|||||||
@@ -365,7 +365,7 @@ nsresult FormData::GetSendInfo(nsIInputStream** aBody, uint64_t* aContentLength,
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<FormData> FormData::Clone() const {
|
already_AddRefed<FormData> FormData::Clone() {
|
||||||
RefPtr<FormData> formData = new FormData(*this);
|
RefPtr<FormData> formData = new FormData(*this);
|
||||||
return formData.forget();
|
return formData.forget();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ class FormData final : public nsISupports,
|
|||||||
NotNull<const Encoding*> aEncoding = UTF_8_ENCODING,
|
NotNull<const Encoding*> aEncoding = UTF_8_ENCODING,
|
||||||
Element* aSubmitter = nullptr);
|
Element* aSubmitter = nullptr);
|
||||||
|
|
||||||
already_AddRefed<FormData> Clone() const;
|
already_AddRefed<FormData> Clone();
|
||||||
|
|
||||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||||
NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(FormData)
|
NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(FormData)
|
||||||
|
|||||||
@@ -50,14 +50,10 @@ class nsHistory final : public nsISupports, public nsWrapperCache {
|
|||||||
mozilla::ErrorResult& aRv);
|
mozilla::ErrorResult& aRv);
|
||||||
void Back(mozilla::dom::CallerType aCallerType, mozilla::ErrorResult& aRv);
|
void Back(mozilla::dom::CallerType aCallerType, mozilla::ErrorResult& aRv);
|
||||||
void Forward(mozilla::dom::CallerType aCallerType, mozilla::ErrorResult& aRv);
|
void Forward(mozilla::dom::CallerType aCallerType, mozilla::ErrorResult& aRv);
|
||||||
|
|
||||||
MOZ_CAN_RUN_SCRIPT
|
|
||||||
void PushState(JSContext* aCx, JS::Handle<JS::Value> aData,
|
void PushState(JSContext* aCx, JS::Handle<JS::Value> aData,
|
||||||
const nsAString& aTitle, const nsAString& aUrl,
|
const nsAString& aTitle, const nsAString& aUrl,
|
||||||
mozilla::dom::CallerType aCallerType,
|
mozilla::dom::CallerType aCallerType,
|
||||||
mozilla::ErrorResult& aRv);
|
mozilla::ErrorResult& aRv);
|
||||||
|
|
||||||
MOZ_CAN_RUN_SCRIPT
|
|
||||||
void ReplaceState(JSContext* aCx, JS::Handle<JS::Value> aData,
|
void ReplaceState(JSContext* aCx, JS::Handle<JS::Value> aData,
|
||||||
const nsAString& aTitle, const nsAString& aUrl,
|
const nsAString& aTitle, const nsAString& aUrl,
|
||||||
mozilla::dom::CallerType aCallerType,
|
mozilla::dom::CallerType aCallerType,
|
||||||
@@ -66,7 +62,6 @@ class nsHistory final : public nsISupports, public nsWrapperCache {
|
|||||||
protected:
|
protected:
|
||||||
virtual ~nsHistory();
|
virtual ~nsHistory();
|
||||||
|
|
||||||
MOZ_CAN_RUN_SCRIPT
|
|
||||||
void PushOrReplaceState(JSContext* aCx, JS::Handle<JS::Value> aData,
|
void PushOrReplaceState(JSContext* aCx, JS::Handle<JS::Value> aData,
|
||||||
const nsAString& aTitle, const nsAString& aUrl,
|
const nsAString& aTitle, const nsAString& aUrl,
|
||||||
mozilla::dom::CallerType aCallerType,
|
mozilla::dom::CallerType aCallerType,
|
||||||
|
|||||||
@@ -27,7 +27,6 @@
|
|||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
#include "js/Value.h"
|
#include "js/Value.h"
|
||||||
#include "mozilla/CycleCollectedUniquePtr.h"
|
|
||||||
#include "mozilla/RootedOwningNonNull.h"
|
#include "mozilla/RootedOwningNonNull.h"
|
||||||
#include "mozilla/RootedRefPtr.h"
|
#include "mozilla/RootedRefPtr.h"
|
||||||
|
|
||||||
@@ -88,6 +87,12 @@ inline std::enable_if_t<is_dom_dictionary<T>, void> ImplCycleCollectionTraverse(
|
|||||||
aDictionary.TraverseForCC(aCallback, aFlags);
|
aDictionary.TraverseForCC(aCallback, aFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline std::enable_if_t<is_dom_dictionary<T>, void> ImplCycleCollectionUnlink(
|
||||||
|
UniquePtr<T>& aDictionary) {
|
||||||
|
aDictionary.reset();
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline std::enable_if_t<is_dom_dictionary<T>, void> ImplCycleCollectionTraverse(
|
inline std::enable_if_t<is_dom_dictionary<T>, void> ImplCycleCollectionTraverse(
|
||||||
nsCycleCollectionTraversalCallback& aCallback, UniquePtr<T>& aDictionary,
|
nsCycleCollectionTraversalCallback& aCallback, UniquePtr<T>& aDictionary,
|
||||||
|
|||||||
@@ -19267,15 +19267,6 @@ class CGBindingRoot(CGThing):
|
|||||||
|
|
||||||
for d in dictionaries:
|
for d in dictionaries:
|
||||||
addPrefHeadersForDictionary(bindingHeaders, d)
|
addPrefHeadersForDictionary(bindingHeaders, d)
|
||||||
try:
|
|
||||||
if CGDictionary.dictionaryNeedsCycleCollection(d):
|
|
||||||
bindingDeclareHeaders["nsCycleCollectionParticipant.h"] = True
|
|
||||||
except CycleCollectionUnsupported:
|
|
||||||
# We have some member that we don't know how to CC. Don't output
|
|
||||||
# our cycle collection overloads, so attempts to CC us will fail to
|
|
||||||
# compile instead of misbehaving.
|
|
||||||
pass
|
|
||||||
|
|
||||||
for d in descriptors:
|
for d in descriptors:
|
||||||
interface = d.interface
|
interface = d.interface
|
||||||
addPrefHeaderForObject(bindingHeaders, interface)
|
addPrefHeaderForObject(bindingHeaders, interface)
|
||||||
|
|||||||
@@ -4,302 +4,16 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "nsGlobalWindowInner.h"
|
|
||||||
|
|
||||||
#include "mozilla/HoldDropJSObjects.h"
|
|
||||||
|
|
||||||
#include "mozilla/dom/AbortController.h"
|
|
||||||
#include "mozilla/dom/NavigateEvent.h"
|
#include "mozilla/dom/NavigateEvent.h"
|
||||||
#include "mozilla/dom/NavigateEventBinding.h"
|
#include "mozilla/dom/NavigateEventBinding.h"
|
||||||
#include "mozilla/dom/Navigation.h"
|
|
||||||
|
|
||||||
namespace mozilla::dom {
|
namespace mozilla::dom {
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_INHERITED_WITH_JS_MEMBERS(NavigateEvent, Event,
|
|
||||||
(mDestination, mSignal,
|
|
||||||
mFormData, mSourceElement,
|
|
||||||
mNavigationHandlerList,
|
|
||||||
mAbortController),
|
|
||||||
(mInfo))
|
|
||||||
|
|
||||||
NS_IMPL_ADDREF_INHERITED(NavigateEvent, Event)
|
|
||||||
NS_IMPL_RELEASE_INHERITED(NavigateEvent, Event)
|
|
||||||
|
|
||||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(NavigateEvent)
|
|
||||||
NS_INTERFACE_MAP_END_INHERITING(Event)
|
|
||||||
|
|
||||||
JSObject* NavigateEvent::WrapObjectInternal(JSContext* aCx,
|
|
||||||
JS::Handle<JSObject*> aGivenProto) {
|
|
||||||
return NavigateEvent_Binding::Wrap(aCx, this, aGivenProto);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
already_AddRefed<NavigateEvent> NavigateEvent::Constructor(
|
already_AddRefed<NavigateEvent> NavigateEvent::Constructor(
|
||||||
const GlobalObject& aGlobal, const nsAString& aType,
|
const GlobalObject& aGlobal, const nsAString& aType,
|
||||||
const NavigateEventInit& aEventInitDict) {
|
const NavigateEventInit& aEventInitDict) {
|
||||||
nsCOMPtr<mozilla::dom::EventTarget> eventTarget =
|
return {};
|
||||||
do_QueryInterface(aGlobal.GetAsSupports());
|
|
||||||
return Constructor(eventTarget, aType, aEventInitDict);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */
|
|
||||||
already_AddRefed<NavigateEvent> NavigateEvent::Constructor(
|
|
||||||
EventTarget* aEventTarget, const nsAString& aType,
|
|
||||||
const NavigateEventInit& aEventInitDict) {
|
|
||||||
RefPtr<NavigateEvent> event = new NavigateEvent(aEventTarget);
|
|
||||||
bool trusted = event->Init(aEventTarget);
|
|
||||||
event->InitEvent(
|
|
||||||
aType, aEventInitDict.mBubbles ? CanBubble::eYes : CanBubble::eNo,
|
|
||||||
aEventInitDict.mCancelable ? Cancelable::eYes : Cancelable::eNo,
|
|
||||||
aEventInitDict.mComposed ? Composed::eYes : Composed::eNo);
|
|
||||||
event->InitNavigateEvent(aEventInitDict);
|
|
||||||
event->SetTrusted(trusted);
|
|
||||||
return event.forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* static */
|
|
||||||
already_AddRefed<NavigateEvent> NavigateEvent::Constructor(
|
|
||||||
EventTarget* aEventTarget, const nsAString& aType,
|
|
||||||
const NavigateEventInit& aEventInitDict,
|
|
||||||
nsIStructuredCloneContainer* aClassicHistoryAPIState,
|
|
||||||
AbortController* aAbortController) {
|
|
||||||
RefPtr<NavigateEvent> event =
|
|
||||||
Constructor(aEventTarget, aType, aEventInitDict);
|
|
||||||
|
|
||||||
event->mAbortController = aAbortController;
|
|
||||||
MOZ_DIAGNOSTIC_ASSERT(event->mSignal == aAbortController->Signal());
|
|
||||||
|
|
||||||
event->mClassicHistoryAPIState = aClassicHistoryAPIState;
|
|
||||||
|
|
||||||
return event.forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
NavigationType NavigateEvent::NavigationType() const { return mNavigationType; }
|
|
||||||
|
|
||||||
already_AddRefed<NavigationDestination> NavigateEvent::Destination() const {
|
|
||||||
return do_AddRef(mDestination);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NavigateEvent::CanIntercept() const { return mCanIntercept; }
|
|
||||||
|
|
||||||
bool NavigateEvent::UserInitiated() const { return mUserInitiated; }
|
|
||||||
|
|
||||||
bool NavigateEvent::HashChange() const { return mHashChange; }
|
|
||||||
|
|
||||||
AbortSignal* NavigateEvent::Signal() const { return mSignal; }
|
|
||||||
|
|
||||||
already_AddRefed<FormData> NavigateEvent::GetFormData() const {
|
|
||||||
return do_AddRef(mFormData);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NavigateEvent::GetDownloadRequest(nsAString& aDownloadRequest) const {
|
|
||||||
aDownloadRequest = mDownloadRequest;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NavigateEvent::GetInfo(JSContext* aCx,
|
|
||||||
JS::MutableHandle<JS::Value> aInfo) const {
|
|
||||||
aInfo.set(mInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NavigateEvent::HasUAVisualTransition() const {
|
|
||||||
return mHasUAVisualTransition;
|
|
||||||
}
|
|
||||||
|
|
||||||
Element* NavigateEvent::GetSourceElement() const { return mSourceElement; }
|
|
||||||
|
|
||||||
void NavigateEvent::Intercept(const NavigationInterceptOptions& aOptions,
|
|
||||||
ErrorResult& aRv) {
|
|
||||||
// This will be implemented in Bug 1897439.
|
|
||||||
}
|
|
||||||
|
|
||||||
void NavigateEvent::Scroll(ErrorResult& aRv) {
|
|
||||||
// This will be implemented in Bug 1897439.
|
|
||||||
}
|
|
||||||
|
|
||||||
NavigateEvent::NavigateEvent(EventTarget* aOwner)
|
|
||||||
: Event(aOwner, nullptr, nullptr) {
|
|
||||||
mozilla::HoldJSObjects(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
NavigateEvent::~NavigateEvent() { DropJSObjects(this); }
|
|
||||||
|
|
||||||
void NavigateEvent::InitNavigateEvent(const NavigateEventInit& aEventInitDict) {
|
|
||||||
mNavigationType = aEventInitDict.mNavigationType;
|
|
||||||
mDestination = aEventInitDict.mDestination;
|
|
||||||
mCanIntercept = aEventInitDict.mCanIntercept;
|
|
||||||
mUserInitiated = aEventInitDict.mUserInitiated;
|
|
||||||
mHashChange = aEventInitDict.mHashChange;
|
|
||||||
mSignal = aEventInitDict.mSignal;
|
|
||||||
mFormData = aEventInitDict.mFormData;
|
|
||||||
mDownloadRequest = aEventInitDict.mDownloadRequest;
|
|
||||||
mInfo = aEventInitDict.mInfo;
|
|
||||||
mHasUAVisualTransition = aEventInitDict.mHasUAVisualTransition;
|
|
||||||
mSourceElement = aEventInitDict.mSourceElement;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NavigateEvent::SetCanIntercept(bool aCanIntercept) {
|
|
||||||
mCanIntercept = aCanIntercept;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum NavigateEvent::InterceptionState NavigateEvent::InterceptionState() const {
|
|
||||||
return mInterceptionState;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NavigateEvent::SetInterceptionState(
|
|
||||||
enum InterceptionState aInterceptionState) {
|
|
||||||
mInterceptionState = aInterceptionState;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsIStructuredCloneContainer* NavigateEvent::ClassicHistoryAPIState() const {
|
|
||||||
return mClassicHistoryAPIState;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsTArray<RefPtr<NavigationInterceptHandler>>&
|
|
||||||
NavigateEvent::NavigationHandlerList() {
|
|
||||||
return mNavigationHandlerList;
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/#navigateevent-finish
|
|
||||||
void NavigateEvent::Finish(bool aDidFulfill) {
|
|
||||||
switch (mInterceptionState) {
|
|
||||||
// Step 1
|
|
||||||
case InterceptionState::Intercepted:
|
|
||||||
case InterceptionState::Finished:
|
|
||||||
MOZ_DIAGNOSTIC_ASSERT(false);
|
|
||||||
break;
|
|
||||||
// Step 2
|
|
||||||
case InterceptionState::None:
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 3
|
|
||||||
PotentiallyResetFocus();
|
|
||||||
|
|
||||||
// Step 4
|
|
||||||
if (aDidFulfill) {
|
|
||||||
PotentiallyProcessScrollBehavior();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 5
|
|
||||||
mInterceptionState = InterceptionState::Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/#potentially-reset-the-focus
|
|
||||||
void NavigateEvent::PotentiallyResetFocus() {
|
|
||||||
// Step 1
|
|
||||||
MOZ_DIAGNOSTIC_ASSERT(mInterceptionState == InterceptionState::Committed ||
|
|
||||||
mInterceptionState == InterceptionState::Scrolled);
|
|
||||||
|
|
||||||
// Step 2
|
|
||||||
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(GetParentObject());
|
|
||||||
|
|
||||||
// If we don't have a window here, there's not much we can do. This could
|
|
||||||
// potentially happen in a chrome context, and in the end it's just better to
|
|
||||||
// be sure and null check.
|
|
||||||
if (NS_WARN_IF(!window)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Navigation* navigation = window->Navigation();
|
|
||||||
|
|
||||||
// Step 3
|
|
||||||
bool focusChanged = navigation->FocusedChangedDuringOngoingNavigation();
|
|
||||||
|
|
||||||
// Step 4
|
|
||||||
navigation->SetFocusedChangedDuringOngoingNavigation(false);
|
|
||||||
|
|
||||||
// Step 5
|
|
||||||
if (focusChanged) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 6
|
|
||||||
if (mFocusResetBehavior &&
|
|
||||||
*mFocusResetBehavior == NavigationFocusReset::Manual) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 7
|
|
||||||
Document* document = window->GetExtantDoc();
|
|
||||||
|
|
||||||
// If we don't have a document here, there's not much we can do.
|
|
||||||
if (NS_WARN_IF(!document)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 8
|
|
||||||
Element* focusTarget = document->GetDocumentElement();
|
|
||||||
if (focusTarget) {
|
|
||||||
focusTarget =
|
|
||||||
focusTarget->GetAutofocusDelegate(mozilla::IsFocusableFlags(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 9
|
|
||||||
if (!focusTarget) {
|
|
||||||
focusTarget = document->GetBody();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 10
|
|
||||||
if (!focusTarget) {
|
|
||||||
focusTarget = document->GetDocumentElement();
|
|
||||||
}
|
|
||||||
|
|
||||||
// The remaining steps will be implemented in Bug 1948253.
|
|
||||||
|
|
||||||
// Step 11: Run the focusing steps for focusTarget, with document's viewport
|
|
||||||
// as the fallback target.
|
|
||||||
// Step 12: Move the sequential focus navigation starting point to
|
|
||||||
// focusTarget.
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/#potentially-process-scroll-behavior
|
|
||||||
void NavigateEvent::PotentiallyProcessScrollBehavior() {
|
|
||||||
// Step 1
|
|
||||||
MOZ_DIAGNOSTIC_ASSERT(mInterceptionState == InterceptionState::Committed ||
|
|
||||||
mInterceptionState == InterceptionState::Scrolled);
|
|
||||||
|
|
||||||
// Step 2
|
|
||||||
if (mInterceptionState == InterceptionState::Scrolled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 3
|
|
||||||
if (mScrollBehavior && *mScrollBehavior == NavigationScrollBehavior::Manual) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process 4
|
|
||||||
ProcessScrollBehavior();
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/#process-scroll-behavior
|
|
||||||
void NavigateEvent::ProcessScrollBehavior() {
|
|
||||||
// Step 1
|
|
||||||
MOZ_DIAGNOSTIC_ASSERT(mInterceptionState == InterceptionState::Committed);
|
|
||||||
|
|
||||||
// Step 2
|
|
||||||
mInterceptionState = InterceptionState::Scrolled;
|
|
||||||
|
|
||||||
switch (mNavigationType) {
|
|
||||||
// Step 3
|
|
||||||
case NavigationType::Traverse:
|
|
||||||
case NavigationType::Reload:
|
|
||||||
// Restore scroll position data given event's relevant global object's
|
|
||||||
// navigable's active session history entry.
|
|
||||||
|
|
||||||
// The remaining steps will be implemented in Bug 1948249.
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
// Step 4
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The remaining steps will be implemented in Bug 1948249.
|
|
||||||
|
|
||||||
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(GetParentObject());
|
|
||||||
// Step 4.1
|
|
||||||
/* Document* document = */ Unused << window->GetExtantDoc();
|
|
||||||
}
|
|
||||||
} // namespace mozilla::dom
|
} // namespace mozilla::dom
|
||||||
|
|||||||
@@ -7,136 +7,56 @@
|
|||||||
#ifndef mozilla_dom_NavigateEvent_h___
|
#ifndef mozilla_dom_NavigateEvent_h___
|
||||||
#define mozilla_dom_NavigateEvent_h___
|
#define mozilla_dom_NavigateEvent_h___
|
||||||
|
|
||||||
#include "js/RootingAPI.h"
|
#include "js/TypeDecls.h"
|
||||||
#include "js/Value.h"
|
|
||||||
#include "mozilla/AlreadyAddRefed.h"
|
|
||||||
#include "mozilla/RefPtr.h"
|
|
||||||
#include "mozilla/dom/AbortController.h"
|
|
||||||
#include "mozilla/dom/BindingDeclarations.h"
|
#include "mozilla/dom/BindingDeclarations.h"
|
||||||
#include "mozilla/dom/Event.h"
|
#include "mozilla/dom/Event.h"
|
||||||
#include "mozilla/dom/NavigateEventBinding.h"
|
#include "mozilla/dom/NavigateEventBinding.h"
|
||||||
#include "nsCycleCollectionParticipant.h"
|
#include "mozilla/dom/NavigationBinding.h"
|
||||||
|
|
||||||
namespace mozilla::dom {
|
namespace mozilla::dom {
|
||||||
|
|
||||||
class AbortController;
|
|
||||||
class AbortSignal;
|
class AbortSignal;
|
||||||
class FormData;
|
class FormData;
|
||||||
class NavigationDestination;
|
class NavigationDestination;
|
||||||
struct NavigationInterceptOptions;
|
struct NavigationInterceptOptions;
|
||||||
|
|
||||||
enum class NavigationType : uint8_t;
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/#the-navigateevent-interface
|
|
||||||
class NavigateEvent final : public Event {
|
class NavigateEvent final : public Event {
|
||||||
public:
|
public:
|
||||||
NS_DECL_ISUPPORTS_INHERITED
|
NS_INLINE_DECL_REFCOUNTING_INHERITED(NavigateEvent, Event)
|
||||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(NavigateEvent, Event)
|
|
||||||
|
|
||||||
virtual JSObject* WrapObjectInternal(
|
|
||||||
JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
|
||||||
|
|
||||||
static already_AddRefed<NavigateEvent> Constructor(
|
static already_AddRefed<NavigateEvent> Constructor(
|
||||||
const GlobalObject& aGlobal, const nsAString& aType,
|
const GlobalObject& aGlobal, const nsAString& aType,
|
||||||
const NavigateEventInit& aEventInitDict);
|
const NavigateEventInit& aEventInitDict);
|
||||||
|
|
||||||
static already_AddRefed<NavigateEvent> Constructor(
|
enum NavigationType NavigationType() const { return {}; }
|
||||||
EventTarget* aEventTarget, const nsAString& aType,
|
|
||||||
const NavigateEventInit& aEventInitDict);
|
|
||||||
|
|
||||||
static already_AddRefed<NavigateEvent> Constructor(
|
already_AddRefed<NavigationDestination> Destination() const { return {}; }
|
||||||
EventTarget* aEventTarget, const nsAString& aType,
|
|
||||||
const NavigateEventInit& aEventInitDict,
|
|
||||||
nsIStructuredCloneContainer* aClassicHistoryAPIState,
|
|
||||||
AbortController* aAbortController);
|
|
||||||
|
|
||||||
NavigationType NavigationType() const;
|
bool CanIntercept() const { return {}; }
|
||||||
|
|
||||||
already_AddRefed<NavigationDestination> Destination() const;
|
bool UserInitiated() const { return {}; }
|
||||||
|
|
||||||
bool CanIntercept() const;
|
bool HashChange() const { return {}; }
|
||||||
|
|
||||||
bool UserInitiated() const;
|
already_AddRefed<AbortSignal> Signal() const { return {}; }
|
||||||
|
|
||||||
bool HashChange() const;
|
already_AddRefed<FormData> GetFormData() const { return {}; }
|
||||||
|
|
||||||
AbortSignal* Signal() const;
|
void GetDownloadRequest(nsString& aRetVal) const {}
|
||||||
|
|
||||||
already_AddRefed<FormData> GetFormData() const;
|
void GetInfo(JSContext* aCx, JS::MutableHandle<JS::Value> aRetVal) const {}
|
||||||
|
|
||||||
void GetDownloadRequest(nsAString& aDownloadRequest) const;
|
bool HasUAVisualTransition() const { return {}; }
|
||||||
|
|
||||||
void GetInfo(JSContext* aCx, JS::MutableHandle<JS::Value> aInfo) const;
|
void Intercept(const NavigationInterceptOptions& aOptions, ErrorResult& aRv) {
|
||||||
|
}
|
||||||
|
|
||||||
bool HasUAVisualTransition() const;
|
void Scroll(ErrorResult& aRv) {}
|
||||||
|
|
||||||
Element* GetSourceElement() const;
|
bool IsTrusted() const { return {}; }
|
||||||
|
|
||||||
void Intercept(const NavigationInterceptOptions& aOptions, ErrorResult& aRv);
|
|
||||||
|
|
||||||
void Scroll(ErrorResult& aRv);
|
|
||||||
|
|
||||||
void InitNavigateEvent(const NavigateEventInit& aEventInitDict);
|
|
||||||
|
|
||||||
void SetCanIntercept(bool aCanIntercept);
|
|
||||||
|
|
||||||
enum class InterceptionState : uint8_t {
|
|
||||||
None,
|
|
||||||
Intercepted,
|
|
||||||
Committed,
|
|
||||||
Scrolled,
|
|
||||||
Finished
|
|
||||||
};
|
|
||||||
|
|
||||||
InterceptionState InterceptionState() const;
|
|
||||||
|
|
||||||
void SetInterceptionState(enum InterceptionState aInterceptionState);
|
|
||||||
|
|
||||||
nsIStructuredCloneContainer* ClassicHistoryAPIState() const;
|
|
||||||
|
|
||||||
nsTArray<RefPtr<NavigationInterceptHandler>>& NavigationHandlerList();
|
|
||||||
|
|
||||||
void Finish(bool aDidFulfill);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void PotentiallyResetFocus();
|
~NavigateEvent() = default;
|
||||||
|
|
||||||
void PotentiallyProcessScrollBehavior();
|
|
||||||
|
|
||||||
void ProcessScrollBehavior();
|
|
||||||
|
|
||||||
explicit NavigateEvent(EventTarget* aOwner);
|
|
||||||
~NavigateEvent();
|
|
||||||
|
|
||||||
enum NavigationType mNavigationType {};
|
|
||||||
RefPtr<NavigationDestination> mDestination;
|
|
||||||
bool mCanIntercept = false;
|
|
||||||
bool mUserInitiated = false;
|
|
||||||
bool mHashChange = false;
|
|
||||||
RefPtr<AbortSignal> mSignal;
|
|
||||||
RefPtr<FormData> mFormData;
|
|
||||||
nsString mDownloadRequest;
|
|
||||||
JS::Heap<JS::Value> mInfo;
|
|
||||||
bool mHasUAVisualTransition = false;
|
|
||||||
RefPtr<Element> mSourceElement;
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#the-navigateevent-interface:navigateevent-2
|
|
||||||
enum InterceptionState mInterceptionState = InterceptionState::None;
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#the-navigateevent-interface:navigateevent-3
|
|
||||||
nsTArray<RefPtr<NavigationInterceptHandler>> mNavigationHandlerList;
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#the-navigateevent-interface:navigateevent-4
|
|
||||||
Maybe<NavigationFocusReset> mFocusResetBehavior;
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#the-navigateevent-interface:navigateevent-5
|
|
||||||
Maybe<NavigationScrollBehavior> mScrollBehavior;
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#the-navigateevent-interface:navigateevent-6
|
|
||||||
RefPtr<AbortController> mAbortController;
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#the-navigateevent-interface:navigateevent-7
|
|
||||||
nsCOMPtr<nsIStructuredCloneContainer> mClassicHistoryAPIState;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace mozilla::dom
|
} // namespace mozilla::dom
|
||||||
|
|||||||
@@ -6,99 +6,38 @@
|
|||||||
|
|
||||||
#include "mozilla/dom/Navigation.h"
|
#include "mozilla/dom/Navigation.h"
|
||||||
|
|
||||||
#include "nsContentUtils.h"
|
|
||||||
#include "nsCycleCollectionParticipant.h"
|
|
||||||
#include "nsDocShell.h"
|
|
||||||
#include "nsGlobalWindowInner.h"
|
|
||||||
#include "nsIStructuredCloneContainer.h"
|
|
||||||
#include "nsIXULRuntime.h"
|
|
||||||
#include "nsNetUtil.h"
|
|
||||||
#include "nsTHashtable.h"
|
|
||||||
|
|
||||||
#include "mozilla/CycleCollectedJSContext.h"
|
#include "mozilla/CycleCollectedJSContext.h"
|
||||||
#include "mozilla/CycleCollectedUniquePtr.h"
|
|
||||||
#include "mozilla/HoldDropJSObjects.h"
|
|
||||||
#include "mozilla/Logging.h"
|
#include "mozilla/Logging.h"
|
||||||
#include "mozilla/StaticPrefs_dom.h"
|
|
||||||
#include "mozilla/UniquePtr.h"
|
|
||||||
|
|
||||||
#include "mozilla/dom/Document.h"
|
#include "mozilla/dom/Document.h"
|
||||||
#include "mozilla/dom/Event.h"
|
#include "mozilla/dom/Event.h"
|
||||||
#include "mozilla/dom/FeaturePolicy.h"
|
#include "mozilla/dom/FeaturePolicy.h"
|
||||||
#include "mozilla/dom/NavigationActivation.h"
|
|
||||||
#include "mozilla/dom/NavigationCurrentEntryChangeEvent.h"
|
#include "mozilla/dom/NavigationCurrentEntryChangeEvent.h"
|
||||||
#include "mozilla/dom/NavigationHistoryEntry.h"
|
#include "mozilla/dom/NavigationHistoryEntry.h"
|
||||||
#include "mozilla/dom/NavigationTransition.h"
|
|
||||||
#include "mozilla/dom/NavigationUtils.h"
|
|
||||||
#include "mozilla/dom/SessionHistoryEntry.h"
|
#include "mozilla/dom/SessionHistoryEntry.h"
|
||||||
#include "mozilla/dom/WindowContext.h"
|
#include "mozilla/StaticPrefs_dom.h"
|
||||||
|
#include "mozilla/dom/Document.h"
|
||||||
|
#include "mozilla/dom/NavigationCurrentEntryChangeEvent.h"
|
||||||
|
#include "mozilla/dom/NavigationHistoryEntry.h"
|
||||||
|
#include "mozilla/dom/SessionHistoryEntry.h"
|
||||||
|
#include "nsContentUtils.h"
|
||||||
|
#include "nsIXULRuntime.h"
|
||||||
|
#include "nsNetUtil.h"
|
||||||
|
|
||||||
mozilla::LazyLogModule gNavigationLog("Navigation");
|
mozilla::LazyLogModule gNavigationLog("Navigation");
|
||||||
|
|
||||||
namespace mozilla::dom {
|
namespace mozilla::dom {
|
||||||
|
|
||||||
struct NavigationAPIMethodTracker {
|
NS_IMPL_CYCLE_COLLECTION_INHERITED(Navigation, DOMEventTargetHelper, mEntries);
|
||||||
RefPtr<Navigation> mNavigationObject;
|
|
||||||
Maybe<nsID> mKey;
|
|
||||||
JS::Heap<JS::Value> mInfo;
|
|
||||||
RefPtr<nsStructuredCloneContainer> mSerializedState;
|
|
||||||
RefPtr<NavigationHistoryEntry> mCommittedToEntry;
|
|
||||||
RefPtr<Promise> mFinishedPromise;
|
|
||||||
};
|
|
||||||
|
|
||||||
// This ignore is because the following ImplCycleCollectionTraverse and
|
|
||||||
// ImplCycleCollectionTrace are being called by the cycle collection machinery
|
|
||||||
// through a visitor pattern, that fools clangd a bit, since we're not directly
|
|
||||||
// calling them here but instead they get called from either the overloads for
|
|
||||||
// UniquePtr or nsTHashtable.
|
|
||||||
#ifdef __clang__
|
|
||||||
# pragma clang diagnostic push
|
|
||||||
# pragma clang diagnostic ignored "-Wunused-function"
|
|
||||||
#endif // __clang__
|
|
||||||
|
|
||||||
static void ImplCycleCollectionTraverse(
|
|
||||||
nsCycleCollectionTraversalCallback& cb,
|
|
||||||
const NavigationAPIMethodTracker& aField, const char* aName,
|
|
||||||
uint32_t aFlags) {
|
|
||||||
const NavigationAPIMethodTracker* tmp = &aField;
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNavigationObject);
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSerializedState);
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCommittedToEntry);
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFinishedPromise);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ImplCycleCollectionTrace(const TraceCallbacks& aCallbacks,
|
|
||||||
NavigationAPIMethodTracker& aField,
|
|
||||||
const char* aName, void* aClosure) {
|
|
||||||
ImplCycleCollectionTrace(aCallbacks, aField.mInfo, aName, aClosure);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __clang__
|
|
||||||
# pragma clang diagnostic pop
|
|
||||||
#endif // __clang__
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_INHERITED_WITH_JS_MEMBERS(
|
|
||||||
Navigation, DOMEventTargetHelper,
|
|
||||||
(mEntries, mOngoingNavigateEvent, mTransition, mActivation,
|
|
||||||
mOngoingAPIMethodTracker, mUpcomingNonTraverseAPIMethodTracker,
|
|
||||||
mUpcomingTraverseAPIMethodTrackers),
|
|
||||||
(mOngoingAPIMethodTracker, mUpcomingNonTraverseAPIMethodTracker,
|
|
||||||
mUpcomingTraverseAPIMethodTrackers));
|
|
||||||
NS_IMPL_ADDREF_INHERITED(Navigation, DOMEventTargetHelper)
|
NS_IMPL_ADDREF_INHERITED(Navigation, DOMEventTargetHelper)
|
||||||
NS_IMPL_RELEASE_INHERITED(Navigation, DOMEventTargetHelper)
|
NS_IMPL_RELEASE_INHERITED(Navigation, DOMEventTargetHelper)
|
||||||
|
|
||||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Navigation)
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Navigation)
|
||||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||||
|
|
||||||
Navigation::Navigation(nsPIDOMWindowInner* aWindow)
|
Navigation::Navigation(nsPIDOMWindowInner* aWindow) : mWindow(aWindow) {
|
||||||
: DOMEventTargetHelper(aWindow) {
|
|
||||||
MOZ_ASSERT(aWindow);
|
MOZ_ASSERT(aWindow);
|
||||||
|
|
||||||
mozilla::HoldJSObjects(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Navigation::~Navigation() { mozilla::DropJSObjects(this); }
|
|
||||||
|
|
||||||
JSObject* Navigation::WrapObject(JSContext* aCx,
|
JSObject* Navigation::WrapObject(JSContext* aCx,
|
||||||
JS::Handle<JSObject*> aGivenProto) {
|
JS::Handle<JSObject*> aGivenProto) {
|
||||||
return Navigation_Binding::Wrap(aCx, this, aGivenProto);
|
return Navigation_Binding::Wrap(aCx, this, aGivenProto);
|
||||||
@@ -133,7 +72,7 @@ already_AddRefed<NavigationHistoryEntry> Navigation::GetCurrentEntry() const {
|
|||||||
return entry.forget();
|
return entry.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/#dom-navigation-updatecurrententry
|
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-navigation-updatecurrententry
|
||||||
void Navigation::UpdateCurrentEntry(
|
void Navigation::UpdateCurrentEntry(
|
||||||
JSContext* aCx, const NavigationUpdateCurrentEntryOptions& aOptions,
|
JSContext* aCx, const NavigationUpdateCurrentEntryOptions& aOptions,
|
||||||
ErrorResult& aRv) {
|
ErrorResult& aRv) {
|
||||||
@@ -164,20 +103,16 @@ void Navigation::UpdateCurrentEntry(
|
|||||||
DispatchEvent(*event);
|
DispatchEvent(*event);
|
||||||
}
|
}
|
||||||
|
|
||||||
NavigationTransition* Navigation::GetTransition() const { return mTransition; }
|
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#has-entries-and-events-disabled
|
||||||
|
|
||||||
NavigationActivation* Navigation::GetActivation() const { return mActivation; }
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/#has-entries-and-events-disabled
|
|
||||||
bool Navigation::HasEntriesAndEventsDisabled() const {
|
bool Navigation::HasEntriesAndEventsDisabled() const {
|
||||||
Document* doc = GetDocumentIfCurrent();
|
Document* doc = mWindow->GetDoc();
|
||||||
return !doc || !doc->IsCurrentActiveDocument() ||
|
return !doc->IsCurrentActiveDocument() ||
|
||||||
(NS_IsAboutBlankAllowQueryAndFragment(doc->GetDocumentURI()) &&
|
(NS_IsAboutBlankAllowQueryAndFragment(doc->GetDocumentURI()) &&
|
||||||
doc->IsInitialDocument()) ||
|
doc->IsInitialDocument()) ||
|
||||||
doc->GetPrincipal()->GetIsNullPrincipal();
|
doc->GetPrincipal()->GetIsNullPrincipal();
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/#initialize-the-navigation-api-entries-for-a-new-document
|
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#initialize-the-navigation-api-entries-for-a-new-document
|
||||||
void Navigation::InitializeHistoryEntries(
|
void Navigation::InitializeHistoryEntries(
|
||||||
mozilla::Span<const SessionHistoryInfo> aNewSHInfos,
|
mozilla::Span<const SessionHistoryInfo> aNewSHInfos,
|
||||||
const SessionHistoryInfo* aInitialSHInfo) {
|
const SessionHistoryInfo* aInitialSHInfo) {
|
||||||
@@ -188,8 +123,8 @@ void Navigation::InitializeHistoryEntries(
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (auto i = 0ul; i < aNewSHInfos.Length(); i++) {
|
for (auto i = 0ul; i < aNewSHInfos.Length(); i++) {
|
||||||
mEntries.AppendElement(MakeRefPtr<NavigationHistoryEntry>(
|
mEntries.AppendElement(
|
||||||
GetOwnerGlobal(), &aNewSHInfos[i], i));
|
MakeRefPtr<NavigationHistoryEntry>(mWindow, &aNewSHInfos[i], i));
|
||||||
if (aNewSHInfos[i].NavigationKey() == aInitialSHInfo->NavigationKey()) {
|
if (aNewSHInfos[i].NavigationKey() == aInitialSHInfo->NavigationKey()) {
|
||||||
mCurrentEntryIndex = Some(i);
|
mCurrentEntryIndex = Some(i);
|
||||||
}
|
}
|
||||||
@@ -204,7 +139,7 @@ void Navigation::InitializeHistoryEntries(
|
|||||||
("aInitialSHInfo: %s %s\n", key.ToString().get(), id.ToString().get()));
|
("aInitialSHInfo: %s %s\n", key.ToString().get(), id.ToString().get()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/#update-the-navigation-api-entries-for-a-same-document-navigation
|
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#update-the-navigation-api-entries-for-a-same-document-navigation
|
||||||
void Navigation::UpdateEntriesForSameDocumentNavigation(
|
void Navigation::UpdateEntriesForSameDocumentNavigation(
|
||||||
SessionHistoryInfo* aDestinationSHE, NavigationType aNavigationType) {
|
SessionHistoryInfo* aDestinationSHE, NavigationType aNavigationType) {
|
||||||
// Step 1.
|
// Step 1.
|
||||||
@@ -239,7 +174,7 @@ void Navigation::UpdateEntriesForSameDocumentNavigation(
|
|||||||
disposedEntries.AppendElement(mEntries.PopLastElement());
|
disposedEntries.AppendElement(mEntries.PopLastElement());
|
||||||
}
|
}
|
||||||
mEntries.AppendElement(MakeRefPtr<NavigationHistoryEntry>(
|
mEntries.AppendElement(MakeRefPtr<NavigationHistoryEntry>(
|
||||||
GetOwnerGlobal(), aDestinationSHE, *mCurrentEntryIndex));
|
mWindow, aDestinationSHE, *mCurrentEntryIndex));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NavigationType::Replace:
|
case NavigationType::Replace:
|
||||||
@@ -247,7 +182,7 @@ void Navigation::UpdateEntriesForSameDocumentNavigation(
|
|||||||
disposedEntries.AppendElement(oldCurrentEntry);
|
disposedEntries.AppendElement(oldCurrentEntry);
|
||||||
aDestinationSHE->NavigationKey() = oldCurrentEntry->Key();
|
aDestinationSHE->NavigationKey() = oldCurrentEntry->Key();
|
||||||
mEntries[*mCurrentEntryIndex] = MakeRefPtr<NavigationHistoryEntry>(
|
mEntries[*mCurrentEntryIndex] = MakeRefPtr<NavigationHistoryEntry>(
|
||||||
GetOwnerGlobal(), aDestinationSHE, *mCurrentEntryIndex);
|
mWindow, aDestinationSHE, *mCurrentEntryIndex);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NavigationType::Reload:
|
case NavigationType::Reload:
|
||||||
@@ -259,7 +194,7 @@ void Navigation::UpdateEntriesForSameDocumentNavigation(
|
|||||||
// Steps 9-12.
|
// Steps 9-12.
|
||||||
{
|
{
|
||||||
nsAutoMicroTask mt;
|
nsAutoMicroTask mt;
|
||||||
AutoEntryScript aes(GetOwnerGlobal(),
|
AutoEntryScript aes(mWindow->AsGlobal(),
|
||||||
"UpdateEntriesForSameDocumentNavigation");
|
"UpdateEntriesForSameDocumentNavigation");
|
||||||
|
|
||||||
ScheduleEventsFromNavigation(aNavigationType, oldCurrentEntry,
|
ScheduleEventsFromNavigation(aNavigationType, oldCurrentEntry,
|
||||||
@@ -267,7 +202,7 @@ void Navigation::UpdateEntriesForSameDocumentNavigation(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/#update-the-navigation-api-entries-for-reactivation
|
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#update-the-navigation-api-entries-for-reactivation
|
||||||
void Navigation::UpdateForReactivation(SessionHistoryInfo* aReactivatedEntry) {
|
void Navigation::UpdateForReactivation(SessionHistoryInfo* aReactivatedEntry) {
|
||||||
// NAV-TODO
|
// NAV-TODO
|
||||||
}
|
}
|
||||||
@@ -324,526 +259,6 @@ void LogEntry(NavigationHistoryEntry* aEntry, uint64_t aIndex, uint64_t aTotal,
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/#fire-a-traverse-navigate-event
|
|
||||||
bool Navigation::FireTraverseNavigateEvent(
|
|
||||||
SessionHistoryInfo* aDestinationSessionHistoryInfo,
|
|
||||||
Maybe<UserNavigationInvolvement> aUserInvolvement) {
|
|
||||||
// aDestinationSessionHistoryInfo corresponds to
|
|
||||||
// https://html.spec.whatwg.org/#fire-navigate-traverse-destinationshe
|
|
||||||
|
|
||||||
// To not unnecessarily create an event that's never used, step 1 and step 2
|
|
||||||
// in #fire-a-traverse-navigate-event have been moved to after step 25 in
|
|
||||||
// #inner-navigate-event-firing-algorithm in our implementation.
|
|
||||||
|
|
||||||
// Step 5
|
|
||||||
RefPtr<NavigationHistoryEntry> destinationNHE =
|
|
||||||
FindNavigationHistoryEntry(aDestinationSessionHistoryInfo);
|
|
||||||
|
|
||||||
// Step 6.2 and step 7.2
|
|
||||||
RefPtr<nsStructuredCloneContainer> state =
|
|
||||||
destinationNHE ? destinationNHE->GetNavigationState() : nullptr;
|
|
||||||
|
|
||||||
// Step 8
|
|
||||||
bool isSameDocument =
|
|
||||||
ToMaybeRef(
|
|
||||||
nsDocShell::Cast(nsContentUtils::GetDocShellForEventTarget(this)))
|
|
||||||
.andThen([](auto& aDocShell) {
|
|
||||||
return ToMaybeRef(aDocShell.GetLoadingSessionHistoryInfo());
|
|
||||||
})
|
|
||||||
.map([aDestinationSessionHistoryInfo](auto& aSessionHistoryInfo) {
|
|
||||||
return aDestinationSessionHistoryInfo->SharesDocumentWith(
|
|
||||||
aSessionHistoryInfo.mInfo);
|
|
||||||
})
|
|
||||||
.valueOr(false);
|
|
||||||
|
|
||||||
// Step 3, step 4, step 6.1, and step 7.1.
|
|
||||||
RefPtr<NavigationDestination> destination =
|
|
||||||
MakeAndAddRef<NavigationDestination>(
|
|
||||||
GetOwnerGlobal(), aDestinationSessionHistoryInfo->GetURI(),
|
|
||||||
destinationNHE, state, isSameDocument);
|
|
||||||
|
|
||||||
// Step 9
|
|
||||||
return InnerFireNavigateEvent(
|
|
||||||
NavigationType::Traverse, destination,
|
|
||||||
aUserInvolvement.valueOr(UserNavigationInvolvement::None),
|
|
||||||
/* aSourceElement */ nullptr,
|
|
||||||
/* aFormDataEntryList*/ Nothing(),
|
|
||||||
/* aClassicHistoryAPIState */ nullptr,
|
|
||||||
/* aDownloadRequestFilename */ u""_ns);
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/#fire-a-push/replace/reload-navigate-event
|
|
||||||
bool Navigation::FirePushReplaceReloadNavigateEvent(
|
|
||||||
NavigationType aNavigationType, nsIURI* aDestinationURL,
|
|
||||||
bool aIsSameDocument, Maybe<UserNavigationInvolvement> aUserInvolvement,
|
|
||||||
Element* aSourceElement, Maybe<const FormData&> aFormDataEntryList,
|
|
||||||
nsStructuredCloneContainer* aNavigationAPIState,
|
|
||||||
nsIStructuredCloneContainer* aClassicHistoryAPIState) {
|
|
||||||
// To not unnecessarily create an event that's never used, step 1 and step 2
|
|
||||||
// in #fire-a-push/replace/reload-navigate-event have been moved to after step
|
|
||||||
// 25 in #inner-navigate-event-firing-algorithm in our implementation.
|
|
||||||
|
|
||||||
// Step 3 to step 7
|
|
||||||
RefPtr<NavigationDestination> destination =
|
|
||||||
MakeAndAddRef<NavigationDestination>(GetOwnerGlobal(), aDestinationURL,
|
|
||||||
/* aEntry */ nullptr,
|
|
||||||
/* aState */ nullptr,
|
|
||||||
aIsSameDocument);
|
|
||||||
|
|
||||||
// Step 8
|
|
||||||
return InnerFireNavigateEvent(
|
|
||||||
aNavigationType, destination,
|
|
||||||
aUserInvolvement.valueOr(UserNavigationInvolvement::None), aSourceElement,
|
|
||||||
aFormDataEntryList, aClassicHistoryAPIState,
|
|
||||||
/* aDownloadRequestFilename */ u""_ns);
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/#fire-a-download-request-navigate-event
|
|
||||||
bool Navigation::FireDownloadRequestNavigateEvent(
|
|
||||||
nsIURI* aDestinationURL, UserNavigationInvolvement aUserInvolvement,
|
|
||||||
Element* aSourceElement, const nsAString& aFilename) {
|
|
||||||
// To not unnecessarily create an event that's never used, step 1 and step 2
|
|
||||||
// in #fire-a-download-request-navigate-event have been moved to after step
|
|
||||||
// 25 in #inner-navigate-event-firing-algorithm in our implementation.
|
|
||||||
|
|
||||||
// Step 3 to step 7
|
|
||||||
RefPtr<NavigationDestination> destination =
|
|
||||||
MakeAndAddRef<NavigationDestination>(GetOwnerGlobal(), aDestinationURL,
|
|
||||||
/* aEntry */ nullptr,
|
|
||||||
/* aState */ nullptr,
|
|
||||||
/* aIsSameDocument */ false);
|
|
||||||
|
|
||||||
// Step 8
|
|
||||||
return InnerFireNavigateEvent(
|
|
||||||
NavigationType::Push, destination, aUserInvolvement, aSourceElement,
|
|
||||||
/* aFormDataEntryList */ Nothing(),
|
|
||||||
/* aClassicHistoryAPIState */ nullptr, aFilename);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implementation of this will be done in Bug 1948596.
|
|
||||||
// https://html.spec.whatwg.org/#can-have-its-url-rewritten
|
|
||||||
static bool CanBeRewritten(nsIURI* aURI, nsIURI* aOtherURI) { return false; }
|
|
||||||
|
|
||||||
static bool HasHistoryActionActivation(
|
|
||||||
Maybe<nsGlobalWindowInner&> aRelevantGlobalObject) {
|
|
||||||
return aRelevantGlobalObject
|
|
||||||
.map([](auto& aRelevantGlobalObject) {
|
|
||||||
WindowContext* windowContext = aRelevantGlobalObject.GetWindowContext();
|
|
||||||
return windowContext && windowContext->HasValidHistoryActivation();
|
|
||||||
})
|
|
||||||
.valueOr(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ConsumeHistoryActionUserActivation(
|
|
||||||
Maybe<nsGlobalWindowInner&> aRelevantGlobalObject) {
|
|
||||||
aRelevantGlobalObject.apply([](auto& aRelevantGlobalObject) {
|
|
||||||
if (WindowContext* windowContext =
|
|
||||||
aRelevantGlobalObject.GetWindowContext()) {
|
|
||||||
windowContext->ConsumeHistoryActivation();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implementation of this will be done in Bug 1948593.
|
|
||||||
static bool HasUAVisualTransition(Maybe<Document&>) { return false; }
|
|
||||||
|
|
||||||
static bool EqualsExceptRef(nsIURI* aURI, nsIURI* aOtherURI) {
|
|
||||||
bool equalsExceptRef = false;
|
|
||||||
return aURI && aOtherURI &&
|
|
||||||
NS_SUCCEEDED(aURI->EqualsExceptRef(aOtherURI, &equalsExceptRef));
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool HasIdenticalFragment(nsIURI* aURI, nsIURI* aOtherURI) {
|
|
||||||
nsAutoCString ref;
|
|
||||||
|
|
||||||
if (NS_FAILED(aURI->GetRef(ref))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsAutoCString otherRef;
|
|
||||||
if (NS_FAILED(aOtherURI->GetRef(otherRef))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ref.Equals(otherRef);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult Navigation::FireEvent(const nsAString& aName) {
|
|
||||||
RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
|
|
||||||
// it doesn't bubble, and it isn't cancelable
|
|
||||||
event->InitEvent(aName, false, false);
|
|
||||||
event->SetTrusted(true);
|
|
||||||
ErrorResult rv;
|
|
||||||
DispatchEvent(*event, rv);
|
|
||||||
return rv.StealNSResult();
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/#inner-navigate-event-firing-algorithm
|
|
||||||
bool Navigation::InnerFireNavigateEvent(
|
|
||||||
NavigationType aNavigationType, NavigationDestination* aDestination,
|
|
||||||
UserNavigationInvolvement aUserInvolvement, Element* aSourceElement,
|
|
||||||
Maybe<const FormData&> aFormDataEntryList,
|
|
||||||
nsIStructuredCloneContainer* aClassicHistoryAPIState,
|
|
||||||
const nsAString& aDownloadRequestFilename) {
|
|
||||||
// Step 1
|
|
||||||
if (HasEntriesAndEventsDisabled()) {
|
|
||||||
// Step 1.1 to step 1.3
|
|
||||||
MOZ_DIAGNOSTIC_ASSERT(!mOngoingAPIMethodTracker);
|
|
||||||
MOZ_DIAGNOSTIC_ASSERT(!mUpcomingNonTraverseAPIMethodTracker);
|
|
||||||
MOZ_DIAGNOSTIC_ASSERT(mUpcomingTraverseAPIMethodTrackers.IsEmpty());
|
|
||||||
|
|
||||||
// Step 1.4
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
NavigateEventInit init;
|
|
||||||
|
|
||||||
// Step 2
|
|
||||||
Maybe<nsID> destinationKey;
|
|
||||||
|
|
||||||
// Step 3
|
|
||||||
if (auto* entry = aDestination->GetEntry()) {
|
|
||||||
destinationKey.emplace(entry->Key());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 4
|
|
||||||
MOZ_DIAGNOSTIC_ASSERT(!destinationKey || destinationKey->Equals(nsID{}));
|
|
||||||
|
|
||||||
// Step 5
|
|
||||||
PromoteUpcomingAPIMethodTrackerToOngoing(std::move(destinationKey));
|
|
||||||
|
|
||||||
// Step 6
|
|
||||||
NavigationAPIMethodTracker* apiMethodTracker = mOngoingAPIMethodTracker.get();
|
|
||||||
|
|
||||||
// Step 7
|
|
||||||
Maybe<BrowsingContext&> navigable =
|
|
||||||
ToMaybeRef(GetOwnerWindow()).andThen([](auto& aWindow) {
|
|
||||||
return ToMaybeRef(aWindow.GetBrowsingContext());
|
|
||||||
});
|
|
||||||
|
|
||||||
// Step 8
|
|
||||||
Document* document =
|
|
||||||
navigable.map([](auto& aNavigable) { return aNavigable.GetDocument(); })
|
|
||||||
.valueOr(nullptr);
|
|
||||||
|
|
||||||
// Step 9
|
|
||||||
init.mCanIntercept =
|
|
||||||
document &&
|
|
||||||
CanBeRewritten(document->GetDocumentURI(), aDestination->GetURI()) &&
|
|
||||||
(aDestination->SameDocument() ||
|
|
||||||
aNavigationType != NavigationType::Traverse);
|
|
||||||
|
|
||||||
// Step 10 and step 11
|
|
||||||
init.mCancelable =
|
|
||||||
navigable->IsTop() && aDestination->SameDocument() &&
|
|
||||||
(aUserInvolvement != UserNavigationInvolvement::BrowserUI ||
|
|
||||||
HasHistoryActionActivation(ToMaybeRef(GetOwnerWindow())));
|
|
||||||
|
|
||||||
// Step 13
|
|
||||||
init.mNavigationType = aNavigationType;
|
|
||||||
|
|
||||||
// Step 14
|
|
||||||
init.mDestination = aDestination;
|
|
||||||
|
|
||||||
// Step 15
|
|
||||||
init.mDownloadRequest = aDownloadRequestFilename;
|
|
||||||
|
|
||||||
// Step 16
|
|
||||||
// init.mInfo = std::move(apiMethodTracker->mInfo);
|
|
||||||
|
|
||||||
// Step 17
|
|
||||||
init.mHasUAVisualTransition =
|
|
||||||
HasUAVisualTransition(ToMaybeRef(GetDocumentIfCurrent()));
|
|
||||||
|
|
||||||
// Step 18
|
|
||||||
init.mSourceElement = aSourceElement;
|
|
||||||
|
|
||||||
// Step 19
|
|
||||||
RefPtr<AbortController> abortController =
|
|
||||||
new AbortController(GetOwnerGlobal());
|
|
||||||
|
|
||||||
// Step 20
|
|
||||||
init.mSignal = abortController->Signal();
|
|
||||||
|
|
||||||
// step 21
|
|
||||||
nsCOMPtr<nsIURI> currentURL = document->GetDocumentURI();
|
|
||||||
|
|
||||||
// step 22
|
|
||||||
init.mHashChange = !aClassicHistoryAPIState && aDestination->SameDocument() &&
|
|
||||||
EqualsExceptRef(aDestination->GetURI(), currentURL) &&
|
|
||||||
!HasIdenticalFragment(aDestination->GetURI(), currentURL);
|
|
||||||
|
|
||||||
// Step 23
|
|
||||||
init.mUserInitiated = aUserInvolvement != UserNavigationInvolvement::None;
|
|
||||||
|
|
||||||
// Step 24
|
|
||||||
init.mFormData = aFormDataEntryList ? aFormDataEntryList->Clone() : nullptr;
|
|
||||||
|
|
||||||
// Step 25
|
|
||||||
MOZ_DIAGNOSTIC_ASSERT(!mOngoingNavigateEvent);
|
|
||||||
|
|
||||||
// We now have everything we need to fully initialize the NavigateEvent, so
|
|
||||||
// we'll go ahead and create it now. This is done by the spec in step 1 and
|
|
||||||
// step 2 of #fire-a-traverse-navigate-event,
|
|
||||||
// #fire-a-push/replace/reload-navigate-event, or
|
|
||||||
// #fire-a-download-request-navigate-event, but there's no reason to not
|
|
||||||
// delay it until here.
|
|
||||||
RefPtr<NavigateEvent> event = NavigateEvent::Constructor(
|
|
||||||
this, u"navigate"_ns, init, aClassicHistoryAPIState, abortController);
|
|
||||||
|
|
||||||
// Step 26
|
|
||||||
mOngoingNavigateEvent = event;
|
|
||||||
|
|
||||||
// Step 27
|
|
||||||
mFocusChangedDUringOngoingNavigation = false;
|
|
||||||
|
|
||||||
// Step 28
|
|
||||||
mSuppressNormalScrollRestorationDuringOngoingNavigation = false;
|
|
||||||
|
|
||||||
// Step 29 and step 30
|
|
||||||
if (!DispatchEvent(*event, CallerType::NonSystem, IgnoreErrors())) {
|
|
||||||
// Step 30.1
|
|
||||||
if (aNavigationType == NavigationType::Traverse) {
|
|
||||||
ConsumeHistoryActionUserActivation(ToMaybeRef(GetOwnerWindow()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 30.2
|
|
||||||
if (!abortController->Signal()->Aborted()) {
|
|
||||||
AbortOngoingNavigation();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 30.3
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
using InterceptionState = enum NavigateEvent::InterceptionState;
|
|
||||||
// Step 31
|
|
||||||
bool endResultIsSameDocument =
|
|
||||||
event->InterceptionState() != InterceptionState::None ||
|
|
||||||
aDestination->SameDocument();
|
|
||||||
|
|
||||||
// Step 32 (and the destructor of this is step 36)
|
|
||||||
nsAutoMicroTask mt;
|
|
||||||
|
|
||||||
// Step 33
|
|
||||||
if (event->InterceptionState() != InterceptionState::None) {
|
|
||||||
// Step 33.1
|
|
||||||
event->SetInterceptionState(InterceptionState::Committed);
|
|
||||||
|
|
||||||
// Step 33.2
|
|
||||||
RefPtr<NavigationHistoryEntry> fromNHE = GetCurrentEntry();
|
|
||||||
|
|
||||||
// Step 33.3
|
|
||||||
MOZ_DIAGNOSTIC_ASSERT(fromNHE);
|
|
||||||
|
|
||||||
// Step 33.4
|
|
||||||
RefPtr<Promise> promise = Promise::CreateInfallible(GetOwnerGlobal());
|
|
||||||
mTransition = MakeAndAddRef<NavigationTransition>(
|
|
||||||
GetOwnerGlobal(), aNavigationType, fromNHE, promise);
|
|
||||||
|
|
||||||
// Step 33.5
|
|
||||||
MOZ_ALWAYS_TRUE(promise->SetAnyPromiseIsHandled());
|
|
||||||
|
|
||||||
switch (aNavigationType) {
|
|
||||||
case NavigationType::Traverse:
|
|
||||||
// Step 33.6
|
|
||||||
mSuppressNormalScrollRestorationDuringOngoingNavigation = true;
|
|
||||||
break;
|
|
||||||
case NavigationType::Push:
|
|
||||||
case NavigationType::Replace: {
|
|
||||||
// Step 33.7
|
|
||||||
nsDocShell* docShell = nsDocShell::Cast(document->GetDocShell());
|
|
||||||
docShell->UpdateURLAndHistory(
|
|
||||||
document, aDestination->GetURI(), event->ClassicHistoryAPIState(),
|
|
||||||
*NavigationUtils::NavigationHistoryBehavior(aNavigationType),
|
|
||||||
document->GetDocumentURI(), aDestination->SameDocument());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 34
|
|
||||||
if (endResultIsSameDocument) {
|
|
||||||
// Step 34.1
|
|
||||||
AutoTArray<RefPtr<Promise>, 16> promiseList;
|
|
||||||
// Step 34.2
|
|
||||||
for (auto& handler : event->NavigationHandlerList().Clone()) {
|
|
||||||
// Step 34.2.1
|
|
||||||
promiseList.AppendElement(MOZ_KnownLive(handler)->Call());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 34.3
|
|
||||||
if (promiseList.IsEmpty()) {
|
|
||||||
promiseList.AppendElement(Promise::CreateResolvedWithUndefined(
|
|
||||||
GetOwnerGlobal(), IgnoredErrorResult()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 34.4
|
|
||||||
Promise::WaitForAll(
|
|
||||||
GetOwnerGlobal(), promiseList,
|
|
||||||
[self = RefPtr(this), event,
|
|
||||||
apiMethodTracker](const Span<JS::Heap<JS::Value>>&) {
|
|
||||||
// Success steps
|
|
||||||
// Step 1
|
|
||||||
if (nsCOMPtr<nsPIDOMWindowInner> window =
|
|
||||||
do_QueryInterface(event->GetParentObject());
|
|
||||||
window && !window->IsFullyActive()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 2
|
|
||||||
if (AbortSignal* signal = event->Signal(); signal->Aborted()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 3
|
|
||||||
MOZ_DIAGNOSTIC_ASSERT(event == self->mOngoingNavigateEvent);
|
|
||||||
|
|
||||||
// Step 4
|
|
||||||
self->mOngoingNavigateEvent = nullptr;
|
|
||||||
|
|
||||||
// Step 5
|
|
||||||
event->Finish(true);
|
|
||||||
|
|
||||||
// Step 6
|
|
||||||
self->FireEvent(u"navigatesuccess"_ns);
|
|
||||||
|
|
||||||
// Step 7
|
|
||||||
if (apiMethodTracker) {
|
|
||||||
apiMethodTracker->mFinishedPromise->MaybeResolveWithUndefined();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 8
|
|
||||||
if (self->mTransition) {
|
|
||||||
self->mTransition->Finished()->MaybeResolveWithUndefined();
|
|
||||||
}
|
|
||||||
|
|
||||||
self->mTransition = nullptr;
|
|
||||||
},
|
|
||||||
[self = RefPtr(this), event,
|
|
||||||
apiMethodTracker](JS::Handle<JS::Value> aRejectionReason) {
|
|
||||||
// Failure steps
|
|
||||||
// Step 1
|
|
||||||
if (nsCOMPtr<nsPIDOMWindowInner> window =
|
|
||||||
do_QueryInterface(event->GetParentObject());
|
|
||||||
window && !window->IsFullyActive()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 2
|
|
||||||
if (AbortSignal* signal = event->Signal(); signal->Aborted()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 3
|
|
||||||
MOZ_DIAGNOSTIC_ASSERT(event == self->mOngoingNavigateEvent);
|
|
||||||
|
|
||||||
// Step 4
|
|
||||||
self->mOngoingNavigateEvent = nullptr;
|
|
||||||
|
|
||||||
// Step 5
|
|
||||||
event->Finish(false);
|
|
||||||
|
|
||||||
// Step 6 and step 7 will be implemented in Bug 1949499.
|
|
||||||
// Step 6: Let errorInfo be the result of extracting error
|
|
||||||
// information from rejectionReason.
|
|
||||||
|
|
||||||
// Step 7: Fire an event named navigateerror at navigation using
|
|
||||||
// ErrorEvent, with additional attributes initialized according to
|
|
||||||
// errorInfo.
|
|
||||||
|
|
||||||
// Step 8
|
|
||||||
if (apiMethodTracker) {
|
|
||||||
apiMethodTracker->mFinishedPromise->MaybeReject(aRejectionReason);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 9
|
|
||||||
if (self->mTransition) {
|
|
||||||
self->mTransition->Finished()->MaybeReject(aRejectionReason);
|
|
||||||
}
|
|
||||||
|
|
||||||
self->mTransition = nullptr;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 35
|
|
||||||
if (apiMethodTracker) {
|
|
||||||
CleanUp(apiMethodTracker);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 37 and step 38
|
|
||||||
return event->InterceptionState() == InterceptionState::None;
|
|
||||||
}
|
|
||||||
|
|
||||||
NavigationHistoryEntry* Navigation::FindNavigationHistoryEntry(
|
|
||||||
SessionHistoryInfo* aSessionHistoryInfo) const {
|
|
||||||
for (const auto& navigationHistoryEntry : mEntries) {
|
|
||||||
if (navigationHistoryEntry->IsSameEntry(aSessionHistoryInfo)) {
|
|
||||||
return navigationHistoryEntry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/#promote-an-upcoming-api-method-tracker-to-ongoing
|
|
||||||
void Navigation::PromoteUpcomingAPIMethodTrackerToOngoing(
|
|
||||||
Maybe<nsID>&& aDestinationKey) {
|
|
||||||
MOZ_DIAGNOSTIC_ASSERT(!mOngoingAPIMethodTracker);
|
|
||||||
if (aDestinationKey) {
|
|
||||||
MOZ_DIAGNOSTIC_ASSERT(!mUpcomingNonTraverseAPIMethodTracker);
|
|
||||||
Maybe<NavigationAPIMethodTracker&> tracker(NavigationAPIMethodTracker);
|
|
||||||
if (auto entry =
|
|
||||||
mUpcomingTraverseAPIMethodTrackers.Extract(*aDestinationKey)) {
|
|
||||||
mOngoingAPIMethodTracker = std::move(*entry);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mOngoingAPIMethodTracker = std::move(mUpcomingNonTraverseAPIMethodTracker);
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/#navigation-api-method-tracker-clean-up
|
|
||||||
/* static */ void Navigation::CleanUp(
|
|
||||||
NavigationAPIMethodTracker* aNavigationAPIMethodTracker) {
|
|
||||||
// Step 1
|
|
||||||
RefPtr<Navigation> navigation =
|
|
||||||
aNavigationAPIMethodTracker->mNavigationObject;
|
|
||||||
|
|
||||||
// Step 2
|
|
||||||
if (navigation->mOngoingAPIMethodTracker == aNavigationAPIMethodTracker) {
|
|
||||||
navigation->mOngoingAPIMethodTracker = nullptr;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 3.1
|
|
||||||
Maybe<nsID> key = aNavigationAPIMethodTracker->mKey;
|
|
||||||
|
|
||||||
// Step 3.2
|
|
||||||
MOZ_DIAGNOSTIC_ASSERT(key);
|
|
||||||
|
|
||||||
// Step 3.3
|
|
||||||
MOZ_DIAGNOSTIC_ASSERT(
|
|
||||||
navigation->mUpcomingTraverseAPIMethodTrackers.Contains(*key));
|
|
||||||
|
|
||||||
navigation->mUpcomingTraverseAPIMethodTrackers.Remove(*key);
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/#abort-the-ongoing-navigation
|
|
||||||
void Navigation::AbortOngoingNavigation() {}
|
|
||||||
|
|
||||||
bool Navigation::FocusedChangedDuringOngoingNavigation() const {
|
|
||||||
return mFocusChangedDUringOngoingNavigation;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Navigation::SetFocusedChangedDuringOngoingNavigation(
|
|
||||||
bool aFocusChangedDUringOngoingNavigation) {
|
|
||||||
mFocusChangedDUringOngoingNavigation = aFocusChangedDUringOngoingNavigation;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Navigation::LogHistory() const {
|
void Navigation::LogHistory() const {
|
||||||
if (!MOZ_LOG_TEST(gNavigationLog, LogLevel::Debug)) {
|
if (!MOZ_LOG_TEST(gNavigationLog, LogLevel::Debug)) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -7,25 +7,12 @@
|
|||||||
#ifndef mozilla_dom_Navigation_h___
|
#ifndef mozilla_dom_Navigation_h___
|
||||||
#define mozilla_dom_Navigation_h___
|
#define mozilla_dom_Navigation_h___
|
||||||
|
|
||||||
#include "nsHashtablesFwd.h"
|
|
||||||
#include "nsStringFwd.h"
|
|
||||||
#include "nsStructuredCloneContainer.h"
|
|
||||||
|
|
||||||
#include "mozilla/AlreadyAddRefed.h"
|
|
||||||
#include "mozilla/DOMEventTargetHelper.h"
|
#include "mozilla/DOMEventTargetHelper.h"
|
||||||
#include "mozilla/Maybe.h"
|
|
||||||
#include "mozilla/RefPtr.h"
|
|
||||||
|
|
||||||
#include "mozilla/dom/NavigateEvent.h"
|
|
||||||
#include "mozilla/dom/NavigationBinding.h"
|
#include "mozilla/dom/NavigationBinding.h"
|
||||||
|
|
||||||
class nsIDHashKey;
|
|
||||||
|
|
||||||
namespace mozilla::dom {
|
namespace mozilla::dom {
|
||||||
|
|
||||||
class FormData;
|
|
||||||
class NavigationActivation;
|
class NavigationActivation;
|
||||||
class NavigationDestination;
|
|
||||||
class NavigationHistoryEntry;
|
class NavigationHistoryEntry;
|
||||||
struct NavigationNavigateOptions;
|
struct NavigationNavigateOptions;
|
||||||
struct NavigationOptions;
|
struct NavigationOptions;
|
||||||
@@ -36,13 +23,10 @@ struct NavigationResult;
|
|||||||
|
|
||||||
class SessionHistoryInfo;
|
class SessionHistoryInfo;
|
||||||
|
|
||||||
struct NavigationAPIMethodTracker;
|
|
||||||
|
|
||||||
class Navigation final : public DOMEventTargetHelper {
|
class Navigation final : public DOMEventTargetHelper {
|
||||||
public:
|
public:
|
||||||
NS_DECL_ISUPPORTS_INHERITED
|
NS_DECL_ISUPPORTS_INHERITED
|
||||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(Navigation,
|
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(Navigation, DOMEventTargetHelper)
|
||||||
DOMEventTargetHelper)
|
|
||||||
|
|
||||||
explicit Navigation(nsPIDOMWindowInner* aWindow);
|
explicit Navigation(nsPIDOMWindowInner* aWindow);
|
||||||
|
|
||||||
@@ -53,8 +37,8 @@ class Navigation final : public DOMEventTargetHelper {
|
|||||||
void UpdateCurrentEntry(JSContext* aCx,
|
void UpdateCurrentEntry(JSContext* aCx,
|
||||||
const NavigationUpdateCurrentEntryOptions& aOptions,
|
const NavigationUpdateCurrentEntryOptions& aOptions,
|
||||||
ErrorResult& aRv);
|
ErrorResult& aRv);
|
||||||
NavigationTransition* GetTransition() const;
|
already_AddRefed<NavigationTransition> GetTransition() { return {}; }
|
||||||
NavigationActivation* GetActivation() const;
|
already_AddRefed<NavigationActivation> GetActivation() { return {}; }
|
||||||
|
|
||||||
bool CanGoBack() {
|
bool CanGoBack() {
|
||||||
return !HasEntriesAndEventsDisabled() && mCurrentEntryIndex &&
|
return !HasEntriesAndEventsDisabled() && mCurrentEntryIndex &&
|
||||||
@@ -105,33 +89,8 @@ class Navigation final : public DOMEventTargetHelper {
|
|||||||
static bool IsAPIEnabled(JSContext* /* unused */ = nullptr,
|
static bool IsAPIEnabled(JSContext* /* unused */ = nullptr,
|
||||||
JSObject* /* unused */ = nullptr);
|
JSObject* /* unused */ = nullptr);
|
||||||
|
|
||||||
// Wrapper algorithms for firing the navigate event.
|
|
||||||
// https://html.spec.whatwg.org/#navigate-event-firing
|
|
||||||
|
|
||||||
MOZ_CAN_RUN_SCRIPT bool FireTraverseNavigateEvent(
|
|
||||||
SessionHistoryInfo* aDestinationSessionHistoryInfo,
|
|
||||||
Maybe<UserNavigationInvolvement> aUserInvolvement);
|
|
||||||
|
|
||||||
MOZ_CAN_RUN_SCRIPT bool FirePushReplaceReloadNavigateEvent(
|
|
||||||
NavigationType aNavigationType, nsIURI* aDestinationURL,
|
|
||||||
bool aIsSameDocument, Maybe<UserNavigationInvolvement> aUserInvolvement,
|
|
||||||
Element* aSourceElement, Maybe<const FormData&> aFormDataEntryList,
|
|
||||||
nsStructuredCloneContainer* aNavigationAPIState,
|
|
||||||
nsIStructuredCloneContainer* aClassicHistoryAPIState);
|
|
||||||
|
|
||||||
MOZ_CAN_RUN_SCRIPT bool FireDownloadRequestNavigateEvent(
|
|
||||||
nsIURI* aDestinationURL, UserNavigationInvolvement aUserInvolvement,
|
|
||||||
Element* aSourceElement, const nsAString& aFilename);
|
|
||||||
|
|
||||||
bool FocusedChangedDuringOngoingNavigation() const;
|
|
||||||
void SetFocusedChangedDuringOngoingNavigation(
|
|
||||||
bool aFocusChangedDUringOngoingNavigation);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using UpcomingTraverseAPIMethodTrackers =
|
~Navigation() = default;
|
||||||
nsTHashMap<nsIDHashKey, UniquePtr<NavigationAPIMethodTracker>>;
|
|
||||||
|
|
||||||
~Navigation();
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#has-entries-and-events-disabled
|
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#has-entries-and-events-disabled
|
||||||
bool HasEntriesAndEventsDisabled() const;
|
bool HasEntriesAndEventsDisabled() const;
|
||||||
@@ -141,56 +100,13 @@ class Navigation final : public DOMEventTargetHelper {
|
|||||||
const RefPtr<NavigationHistoryEntry>& aPreviousEntry,
|
const RefPtr<NavigationHistoryEntry>& aPreviousEntry,
|
||||||
nsTArray<RefPtr<NavigationHistoryEntry>>&& aDisposedEntries);
|
nsTArray<RefPtr<NavigationHistoryEntry>>&& aDisposedEntries);
|
||||||
|
|
||||||
nsresult FireEvent(const nsAString& aName);
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/#inner-navigate-event-firing-algorithm
|
|
||||||
MOZ_CAN_RUN_SCRIPT bool InnerFireNavigateEvent(
|
|
||||||
NavigationType aNavigationType, NavigationDestination* aDestination,
|
|
||||||
UserNavigationInvolvement aUserInvolvement, Element* aSourceElement,
|
|
||||||
Maybe<const FormData&> aFormDataEntryList,
|
|
||||||
nsIStructuredCloneContainer* aClassicHistoryAPIState,
|
|
||||||
const nsAString& aDownloadRequestFilename);
|
|
||||||
|
|
||||||
NavigationHistoryEntry* FindNavigationHistoryEntry(
|
|
||||||
SessionHistoryInfo* aSessionHistoryInfo) const;
|
|
||||||
|
|
||||||
void PromoteUpcomingAPIMethodTrackerToOngoing(Maybe<nsID>&& aDestinationKey);
|
|
||||||
|
|
||||||
static void CleanUp(NavigationAPIMethodTracker* aNavigationAPIMethodTracker);
|
|
||||||
|
|
||||||
void AbortOngoingNavigation();
|
|
||||||
|
|
||||||
void LogHistory() const;
|
void LogHistory() const;
|
||||||
|
|
||||||
|
nsCOMPtr<nsPIDOMWindowInner> mWindow;
|
||||||
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#navigation-entry-list
|
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#navigation-entry-list
|
||||||
nsTArray<RefPtr<NavigationHistoryEntry>> mEntries;
|
nsTArray<RefPtr<NavigationHistoryEntry>> mEntries;
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#navigation-current-entry
|
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#navigation-current-entry
|
||||||
Maybe<uint64_t> mCurrentEntryIndex;
|
Maybe<uint64_t> mCurrentEntryIndex;
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/#ongoing-navigation-tracking:navigateevent-2
|
|
||||||
RefPtr<NavigateEvent> mOngoingNavigateEvent;
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#focus-changed-during-ongoing-navigation
|
|
||||||
bool mFocusChangedDUringOngoingNavigation = false;
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#suppress-normal-scroll-restoration-during-ongoing-navigation
|
|
||||||
bool mSuppressNormalScrollRestorationDuringOngoingNavigation = false;
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#ongoing-api-method-tracker
|
|
||||||
UniquePtr<NavigationAPIMethodTracker> mOngoingAPIMethodTracker;
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#upcoming-non-traverse-api-method-tracker
|
|
||||||
UniquePtr<NavigationAPIMethodTracker> mUpcomingNonTraverseAPIMethodTracker;
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#upcoming-traverse-api-method-trackers
|
|
||||||
UpcomingTraverseAPIMethodTrackers mUpcomingTraverseAPIMethodTrackers;
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/#concept-navigation-transition
|
|
||||||
RefPtr<NavigationTransition> mTransition;
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/#navigation-activation
|
|
||||||
RefPtr<NavigationActivation> mActivation;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace mozilla::dom
|
} // namespace mozilla::dom
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
#ifndef mozilla_dom_NavigationActivation_h___
|
#ifndef mozilla_dom_NavigationActivation_h___
|
||||||
#define mozilla_dom_NavigationActivation_h___
|
#define mozilla_dom_NavigationActivation_h___
|
||||||
|
|
||||||
#include "nsISupports.h"
|
|
||||||
#include "nsWrapperCache.h"
|
#include "nsWrapperCache.h"
|
||||||
|
|
||||||
class nsIGlobalObject;
|
class nsIGlobalObject;
|
||||||
|
|||||||
@@ -104,10 +104,4 @@ JSObject* NavigationDestination::WrapObject(JSContext* aCx,
|
|||||||
|
|
||||||
nsIGlobalObject* NavigationDestination::GetParentObject() { return mGlobal; }
|
nsIGlobalObject* NavigationDestination::GetParentObject() { return mGlobal; }
|
||||||
|
|
||||||
NavigationHistoryEntry* NavigationDestination::GetEntry() const {
|
|
||||||
return mEntry;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsIURI* NavigationDestination::GetURI() const { return mURL; }
|
|
||||||
|
|
||||||
} // namespace mozilla::dom
|
} // namespace mozilla::dom
|
||||||
|
|||||||
@@ -48,9 +48,6 @@ class NavigationDestination final : public nsISupports, public nsWrapperCache {
|
|||||||
JS::Handle<JSObject*> aGivenProto) override;
|
JS::Handle<JSObject*> aGivenProto) override;
|
||||||
nsIGlobalObject* GetParentObject();
|
nsIGlobalObject* GetParentObject();
|
||||||
|
|
||||||
NavigationHistoryEntry* GetEntry() const;
|
|
||||||
nsIURI* GetURI() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
~NavigationDestination() = default;
|
~NavigationDestination() = default;
|
||||||
|
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ extern mozilla::LazyLogModule gNavigationLog;
|
|||||||
|
|
||||||
namespace mozilla::dom {
|
namespace mozilla::dom {
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(NavigationHistoryEntry,
|
NS_IMPL_CYCLE_COLLECTION_INHERITED(NavigationHistoryEntry, DOMEventTargetHelper,
|
||||||
DOMEventTargetHelper);
|
mWindow);
|
||||||
NS_IMPL_ADDREF_INHERITED(NavigationHistoryEntry, DOMEventTargetHelper)
|
NS_IMPL_ADDREF_INHERITED(NavigationHistoryEntry, DOMEventTargetHelper)
|
||||||
NS_IMPL_RELEASE_INHERITED(NavigationHistoryEntry, DOMEventTargetHelper)
|
NS_IMPL_RELEASE_INHERITED(NavigationHistoryEntry, DOMEventTargetHelper)
|
||||||
|
|
||||||
@@ -24,22 +24,19 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(NavigationHistoryEntry)
|
|||||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||||
|
|
||||||
NavigationHistoryEntry::NavigationHistoryEntry(
|
NavigationHistoryEntry::NavigationHistoryEntry(
|
||||||
nsIGlobalObject* aGlobal, const SessionHistoryInfo* aSHInfo, int64_t aIndex)
|
nsPIDOMWindowInner* aWindow, const SessionHistoryInfo* aSHInfo,
|
||||||
: DOMEventTargetHelper(aGlobal),
|
int64_t aIndex)
|
||||||
|
: mWindow(aWindow),
|
||||||
mSHInfo(MakeUnique<SessionHistoryInfo>(*aSHInfo)),
|
mSHInfo(MakeUnique<SessionHistoryInfo>(*aSHInfo)),
|
||||||
mIndex(aIndex) {}
|
mIndex(aIndex) {}
|
||||||
|
|
||||||
NavigationHistoryEntry::~NavigationHistoryEntry() = default;
|
NavigationHistoryEntry::~NavigationHistoryEntry() = default;
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/#dom-navigationhistoryentry-url
|
|
||||||
void NavigationHistoryEntry::GetUrl(nsAString& aResult) const {
|
void NavigationHistoryEntry::GetUrl(nsAString& aResult) const {
|
||||||
if (!HasActiveDocument()) {
|
if (!GetCurrentDocument()->IsCurrentActiveDocument()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasActiveDocument implies that GetCurrentDocument returns non-null.
|
|
||||||
MOZ_DIAGNOSTIC_ASSERT(GetCurrentDocument());
|
|
||||||
|
|
||||||
if (!SameDocument()) {
|
if (!SameDocument()) {
|
||||||
auto referrerPolicy = GetCurrentDocument()->ReferrerPolicy();
|
auto referrerPolicy = GetCurrentDocument()->ReferrerPolicy();
|
||||||
if (referrerPolicy == ReferrerPolicy::No_referrer ||
|
if (referrerPolicy == ReferrerPolicy::No_referrer ||
|
||||||
@@ -56,9 +53,8 @@ void NavigationHistoryEntry::GetUrl(nsAString& aResult) const {
|
|||||||
CopyUTF8toUTF16(uriSpec, aResult);
|
CopyUTF8toUTF16(uriSpec, aResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/#dom-navigationhistoryentry-key
|
|
||||||
void NavigationHistoryEntry::GetKey(nsAString& aResult) const {
|
void NavigationHistoryEntry::GetKey(nsAString& aResult) const {
|
||||||
if (!HasActiveDocument()) {
|
if (!GetCurrentDocument()->IsCurrentActiveDocument()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,9 +63,8 @@ void NavigationHistoryEntry::GetKey(nsAString& aResult) const {
|
|||||||
CopyUTF8toUTF16(Substring(keyString.get() + 1, NSID_LENGTH - 3), aResult);
|
CopyUTF8toUTF16(Substring(keyString.get() + 1, NSID_LENGTH - 3), aResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/#dom-navigationhistoryentry-id
|
|
||||||
void NavigationHistoryEntry::GetId(nsAString& aResult) const {
|
void NavigationHistoryEntry::GetId(nsAString& aResult) const {
|
||||||
if (!HasActiveDocument()) {
|
if (!GetCurrentDocument()->IsCurrentActiveDocument()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,30 +73,20 @@ void NavigationHistoryEntry::GetId(nsAString& aResult) const {
|
|||||||
CopyUTF8toUTF16(Substring(idString.get() + 1, NSID_LENGTH - 3), aResult);
|
CopyUTF8toUTF16(Substring(idString.get() + 1, NSID_LENGTH - 3), aResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/#dom-navigationhistoryentry-index
|
|
||||||
int64_t NavigationHistoryEntry::Index() const {
|
int64_t NavigationHistoryEntry::Index() const {
|
||||||
MOZ_ASSERT(mSHInfo);
|
MOZ_ASSERT(mSHInfo);
|
||||||
if (!HasActiveDocument()) {
|
if (!GetCurrentDocument()->IsCurrentActiveDocument()) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return mIndex;
|
return mIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/#dom-navigationhistoryentry-samedocument
|
|
||||||
bool NavigationHistoryEntry::SameDocument() const {
|
bool NavigationHistoryEntry::SameDocument() const {
|
||||||
if (!HasActiveDocument()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// HasActiveDocument implies that GetCurrentDocument returns non-null.
|
|
||||||
MOZ_DIAGNOSTIC_ASSERT(GetCurrentDocument());
|
|
||||||
|
|
||||||
MOZ_ASSERT(mSHInfo);
|
MOZ_ASSERT(mSHInfo);
|
||||||
auto* docShell = nsDocShell::Cast(GetCurrentDocument()->GetDocShell());
|
auto* docShell = static_cast<nsDocShell*>(mWindow->GetDocShell());
|
||||||
return docShell && docShell->IsSameDocumentAsActiveEntry(*mSHInfo);
|
return docShell->IsSameDocumentAsActiveEntry(*mSHInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/#dom-navigationhistoryentry-getstate
|
|
||||||
void NavigationHistoryEntry::GetState(JSContext* aCx,
|
void NavigationHistoryEntry::GetState(JSContext* aCx,
|
||||||
JS::MutableHandle<JS::Value> aResult,
|
JS::MutableHandle<JS::Value> aResult,
|
||||||
ErrorResult& aRv) const {
|
ErrorResult& aRv) const {
|
||||||
@@ -122,10 +107,8 @@ void NavigationHistoryEntry::GetState(JSContext* aCx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void NavigationHistoryEntry::SetState(nsStructuredCloneContainer* aState) {
|
void NavigationHistoryEntry::SetState(nsStructuredCloneContainer* aState) {
|
||||||
if (RefPtr<nsStructuredCloneContainer> state =
|
RefPtr<nsStructuredCloneContainer> state = mSHInfo->GetNavigationState();
|
||||||
mSHInfo->GetNavigationState()) {
|
state->Copy(*aState);
|
||||||
state->Copy(*aState);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NavigationHistoryEntry::IsSameEntry(
|
bool NavigationHistoryEntry::IsSameEntry(
|
||||||
@@ -144,27 +127,11 @@ JSObject* NavigationHistoryEntry::WrapObject(
|
|||||||
}
|
}
|
||||||
|
|
||||||
Document* NavigationHistoryEntry::GetCurrentDocument() const {
|
Document* NavigationHistoryEntry::GetCurrentDocument() const {
|
||||||
return GetDocumentIfCurrent();
|
return mWindow->GetDoc();
|
||||||
}
|
|
||||||
|
|
||||||
bool NavigationHistoryEntry::HasActiveDocument() const {
|
|
||||||
if (auto* document = GetCurrentDocument()) {
|
|
||||||
return document->IsCurrentActiveDocument();
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const nsID& NavigationHistoryEntry::Key() const {
|
const nsID& NavigationHistoryEntry::Key() const {
|
||||||
return mSHInfo->NavigationKey();
|
return mSHInfo->NavigationKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
nsStructuredCloneContainer* NavigationHistoryEntry::GetNavigationState() const {
|
|
||||||
if (!mSHInfo) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return mSHInfo->GetNavigationState();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace mozilla::dom
|
} // namespace mozilla::dom
|
||||||
|
|||||||
@@ -9,21 +9,19 @@
|
|||||||
|
|
||||||
#include "mozilla/DOMEventTargetHelper.h"
|
#include "mozilla/DOMEventTargetHelper.h"
|
||||||
|
|
||||||
class nsIGlobalObject;
|
|
||||||
class nsStructuredCloneContainer;
|
class nsStructuredCloneContainer;
|
||||||
|
|
||||||
namespace mozilla::dom {
|
namespace mozilla::dom {
|
||||||
|
|
||||||
class SessionHistoryInfo;
|
class SessionHistoryInfo;
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/#navigationhistoryentry
|
|
||||||
class NavigationHistoryEntry final : public DOMEventTargetHelper {
|
class NavigationHistoryEntry final : public DOMEventTargetHelper {
|
||||||
public:
|
public:
|
||||||
NS_DECL_ISUPPORTS_INHERITED
|
NS_DECL_ISUPPORTS_INHERITED
|
||||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(NavigationHistoryEntry,
|
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(NavigationHistoryEntry,
|
||||||
DOMEventTargetHelper)
|
DOMEventTargetHelper)
|
||||||
|
|
||||||
NavigationHistoryEntry(nsIGlobalObject* aGlobal,
|
NavigationHistoryEntry(nsPIDOMWindowInner* aWindow,
|
||||||
const SessionHistoryInfo* aSHInfo, int64_t aIndex);
|
const SessionHistoryInfo* aSHInfo, int64_t aIndex);
|
||||||
|
|
||||||
void GetUrl(nsAString& aResult) const;
|
void GetUrl(nsAString& aResult) const;
|
||||||
@@ -47,16 +45,12 @@ class NavigationHistoryEntry final : public DOMEventTargetHelper {
|
|||||||
|
|
||||||
const nsID& Key() const;
|
const nsID& Key() const;
|
||||||
|
|
||||||
nsStructuredCloneContainer* GetNavigationState() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
~NavigationHistoryEntry();
|
~NavigationHistoryEntry();
|
||||||
|
|
||||||
Document* GetCurrentDocument() const;
|
Document* GetCurrentDocument() const;
|
||||||
|
|
||||||
bool HasActiveDocument() const;
|
nsCOMPtr<nsPIDOMWindowInner> mWindow;
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/#nhe-she
|
|
||||||
UniquePtr<SessionHistoryInfo> mSHInfo;
|
UniquePtr<SessionHistoryInfo> mSHInfo;
|
||||||
int64_t mIndex;
|
int64_t mIndex;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* vim: set ts=2 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/NavigationBinding.h"
|
|
||||||
#include "mozilla/dom/NavigationUtils.h"
|
|
||||||
|
|
||||||
namespace mozilla::dom {
|
|
||||||
|
|
||||||
/* static */ Maybe<NavigationHistoryBehavior>
|
|
||||||
NavigationUtils::NavigationHistoryBehavior(NavigationType aNavigationType) {
|
|
||||||
switch (aNavigationType) {
|
|
||||||
case NavigationType::Push:
|
|
||||||
return Some(NavigationHistoryBehavior::Push);
|
|
||||||
case NavigationType::Replace:
|
|
||||||
return Some(NavigationHistoryBehavior::Replace);
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return Nothing();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace mozilla::dom
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* vim: set ts=2 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 mozilla_dom_NavigationUtils_h___
|
|
||||||
#define mozilla_dom_NavigationUtils_h___
|
|
||||||
|
|
||||||
#include "mozilla/Maybe.h"
|
|
||||||
|
|
||||||
namespace mozilla::dom {
|
|
||||||
enum class NavigationType : uint8_t;
|
|
||||||
enum class NavigationHistoryBehavior : uint8_t;
|
|
||||||
|
|
||||||
class NavigationUtils {
|
|
||||||
public:
|
|
||||||
static Maybe<NavigationHistoryBehavior> NavigationHistoryBehavior(
|
|
||||||
NavigationType aNavigationType);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace mozilla::dom
|
|
||||||
|
|
||||||
#endif // mozilla_dom_NavigationUtils_h___
|
|
||||||
@@ -13,7 +13,6 @@ EXPORTS.mozilla.dom += [
|
|||||||
"NavigationDestination.h",
|
"NavigationDestination.h",
|
||||||
"NavigationHistoryEntry.h",
|
"NavigationHistoryEntry.h",
|
||||||
"NavigationTransition.h",
|
"NavigationTransition.h",
|
||||||
"NavigationUtils.h",
|
|
||||||
"UserNavigationInvolvement.h",
|
"UserNavigationInvolvement.h",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -23,7 +22,6 @@ UNIFIED_SOURCES += [
|
|||||||
"NavigationDestination.cpp",
|
"NavigationDestination.cpp",
|
||||||
"NavigationHistoryEntry.cpp",
|
"NavigationHistoryEntry.cpp",
|
||||||
"NavigationTransition.cpp",
|
"NavigationTransition.cpp",
|
||||||
"NavigationUtils.cpp",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
FINAL_LIBRARY = "xul"
|
FINAL_LIBRARY = "xul"
|
||||||
|
|||||||
@@ -42,7 +42,6 @@
|
|||||||
#include "nsDebug.h"
|
#include "nsDebug.h"
|
||||||
#include "nsGlobalWindowInner.h"
|
#include "nsGlobalWindowInner.h"
|
||||||
#include "nsIScriptObjectPrincipal.h"
|
#include "nsIScriptObjectPrincipal.h"
|
||||||
#include "nsISupportsImpl.h"
|
|
||||||
#include "nsJSEnvironment.h"
|
#include "nsJSEnvironment.h"
|
||||||
#include "nsJSPrincipals.h"
|
#include "nsJSPrincipals.h"
|
||||||
#include "nsJSUtils.h"
|
#include "nsJSUtils.h"
|
||||||
@@ -219,119 +218,6 @@ already_AddRefed<Promise> Promise::All(
|
|||||||
return CreateFromExisting(global, result, aPropagateUserInteraction);
|
return CreateFromExisting(global, result, aPropagateUserInteraction);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct WaitForAllEmptyTask : public MicroTaskRunnable {
|
|
||||||
WaitForAllEmptyTask(
|
|
||||||
nsIGlobalObject* aGlobal,
|
|
||||||
const std::function<void(const Span<JS::Heap<JS::Value>>&)>& aCallback)
|
|
||||||
: mGlobal(aGlobal), mCallback(aCallback) {}
|
|
||||||
|
|
||||||
private:
|
|
||||||
virtual void Run(AutoSlowOperation&) override { mCallback({}); }
|
|
||||||
|
|
||||||
virtual bool Suppressed() override { return mGlobal->IsInSyncOperation(); }
|
|
||||||
|
|
||||||
nsCOMPtr<nsIGlobalObject> mGlobal;
|
|
||||||
const std::function<void(const Span<JS::Heap<JS::Value>>&)> mCallback;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Initializing WaitForAllResults also performs step 1 and step 2 of
|
|
||||||
// #wait-for-all.
|
|
||||||
struct WaitForAllResults {
|
|
||||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WaitForAllResults)
|
|
||||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WaitForAllResults)
|
|
||||||
|
|
||||||
explicit WaitForAllResults(size_t aSize) : mResult(aSize) {
|
|
||||||
HoldJSObjects(this);
|
|
||||||
|
|
||||||
mResult.EnsureLengthAtLeast(aSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 1
|
|
||||||
size_t mFullfilledCount = 0;
|
|
||||||
|
|
||||||
// Step 2
|
|
||||||
bool mRejected = false;
|
|
||||||
|
|
||||||
nsTArray<JS::Heap<JS::Value>> mResult;
|
|
||||||
|
|
||||||
private:
|
|
||||||
~WaitForAllResults() { DropJSObjects(this); };
|
|
||||||
};
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_WITH_JS_MEMBERS(WaitForAllResults, (), (mResult))
|
|
||||||
|
|
||||||
// https://webidl.spec.whatwg.org/#wait-for-all
|
|
||||||
/* static */
|
|
||||||
void Promise::WaitForAll(
|
|
||||||
nsIGlobalObject* aGlobal, const Span<RefPtr<Promise>>& aPromises,
|
|
||||||
const std::function<void(const Span<JS::Heap<JS::Value>>&)>& aSuccessSteps,
|
|
||||||
const std::function<void(JS::Handle<JS::Value>)>& aFailureSteps) {
|
|
||||||
// Step 1 and step 2 are in WaitForAllResults.
|
|
||||||
|
|
||||||
// Step 3
|
|
||||||
const auto& rejectionHandlerSteps =
|
|
||||||
[aFailureSteps](JSContext* aCx, JS::Handle<JS::Value> aArg,
|
|
||||||
ErrorResult& aRv,
|
|
||||||
const RefPtr<WaitForAllResults>& aResult) {
|
|
||||||
// Step 3.1
|
|
||||||
if (aResult->mRejected) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
// Step 3.2
|
|
||||||
aResult->mRejected = true;
|
|
||||||
// Step 3.3
|
|
||||||
aFailureSteps(aArg);
|
|
||||||
return nullptr;
|
|
||||||
};
|
|
||||||
// Step 5
|
|
||||||
const size_t total = aPromises.size();
|
|
||||||
// Step 6
|
|
||||||
if (!total) {
|
|
||||||
CycleCollectedJSContext* context = CycleCollectedJSContext::Get();
|
|
||||||
if (context) {
|
|
||||||
RefPtr<MicroTaskRunnable> microTask =
|
|
||||||
new WaitForAllEmptyTask(aGlobal, aSuccessSteps);
|
|
||||||
// Step 6.1
|
|
||||||
context->DispatchToMicroTask(microTask.forget());
|
|
||||||
}
|
|
||||||
// Step 6.2
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Step 7
|
|
||||||
size_t index = 0;
|
|
||||||
// Step 8
|
|
||||||
// Since we'll be passing an nsTArray to several invocations to
|
|
||||||
// fulfillmentHandlerSteps we wrap it into a cycle collecting and tracing
|
|
||||||
// object.
|
|
||||||
RefPtr result = MakeAndAddRef<WaitForAllResults>(total);
|
|
||||||
// Step 9
|
|
||||||
for (const auto& promise : aPromises) {
|
|
||||||
// Step 9.1 and step 9.2
|
|
||||||
const auto& fulfillmentHandlerSteps =
|
|
||||||
[aSuccessSteps, promiseIndex = index](
|
|
||||||
JSContext* aCx, JS::Handle<JS::Value> aArg, ErrorResult& aRv,
|
|
||||||
const RefPtr<WaitForAllResults>& aResult)
|
|
||||||
-> already_AddRefed<Promise> {
|
|
||||||
// Step 9.2.1
|
|
||||||
aResult->mResult[promiseIndex].set(aArg.get());
|
|
||||||
// Step 9.2.2
|
|
||||||
aResult->mFullfilledCount++;
|
|
||||||
// Step 9.2.3.
|
|
||||||
// aResult->mResult.Length() is by definition equals to total.
|
|
||||||
if (aResult->mFullfilledCount == aResult->mResult.Length()) {
|
|
||||||
aSuccessSteps(aResult->mResult);
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
};
|
|
||||||
// Step 9.4 (and actually also step 4 and step 9.3)
|
|
||||||
(void)promise->ThenCatchWithCycleCollectedArgs(
|
|
||||||
fulfillmentHandlerSteps, rejectionHandlerSteps, result);
|
|
||||||
|
|
||||||
// Step 9.5
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void SettlePromise(Promise* aSettlingPromise, Promise* aCallbackPromise,
|
static void SettlePromise(Promise* aSettlingPromise, Promise* aCallbackPromise,
|
||||||
ErrorResult& aRv) {
|
ErrorResult& aRv) {
|
||||||
if (!aSettlingPromise) {
|
if (!aSettlingPromise) {
|
||||||
@@ -504,11 +390,11 @@ namespace {
|
|||||||
class PromiseNativeHandlerShim final : public PromiseNativeHandler {
|
class PromiseNativeHandlerShim final : public PromiseNativeHandler {
|
||||||
RefPtr<PromiseNativeHandler> mInner;
|
RefPtr<PromiseNativeHandler> mInner;
|
||||||
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
|
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
|
||||||
enum InnerState {
|
enum InnerState{
|
||||||
NotCleared,
|
NotCleared,
|
||||||
ClearedFromResolve,
|
ClearedFromResolve,
|
||||||
ClearedFromReject,
|
ClearedFromReject,
|
||||||
ClearedFromCC,
|
ClearedFromCC,
|
||||||
};
|
};
|
||||||
InnerState mState = NotCleared;
|
InnerState mState = NotCleared;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -261,12 +261,6 @@ class Promise : public SupportsWeakPtr {
|
|||||||
PropagateUserInteraction aPropagateUserInteraction =
|
PropagateUserInteraction aPropagateUserInteraction =
|
||||||
eDontPropagateUserInteraction);
|
eDontPropagateUserInteraction);
|
||||||
|
|
||||||
static void WaitForAll(
|
|
||||||
nsIGlobalObject* aGlobal, const Span<RefPtr<Promise>>& aPromises,
|
|
||||||
const std::function<void(const Span<JS::Heap<JS::Value>>&)>&
|
|
||||||
aSuccessSteps,
|
|
||||||
const std::function<void(JS::Handle<JS::Value>)>& aFailureSteps);
|
|
||||||
|
|
||||||
template <typename Callback, typename... Args>
|
template <typename Callback, typename... Args>
|
||||||
using IsHandlerCallback =
|
using IsHandlerCallback =
|
||||||
std::is_same<already_AddRefed<Promise>,
|
std::is_same<already_AddRefed<Promise>,
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ interface NavigateEvent : Event {
|
|||||||
readonly attribute DOMString? downloadRequest;
|
readonly attribute DOMString? downloadRequest;
|
||||||
readonly attribute any info;
|
readonly attribute any info;
|
||||||
readonly attribute boolean hasUAVisualTransition;
|
readonly attribute boolean hasUAVisualTransition;
|
||||||
readonly attribute Element? sourceElement;
|
|
||||||
|
|
||||||
[Throws] undefined intercept(optional NavigationInterceptOptions options = {});
|
[Throws] undefined intercept(optional NavigationInterceptOptions options = {});
|
||||||
[Throws] undefined scroll();
|
[Throws] undefined scroll();
|
||||||
@@ -38,7 +37,6 @@ dictionary NavigateEventInit : EventInit {
|
|||||||
DOMString? downloadRequest = null;
|
DOMString? downloadRequest = null;
|
||||||
any info;
|
any info;
|
||||||
boolean hasUAVisualTransition = false;
|
boolean hasUAVisualTransition = false;
|
||||||
Element? sourceElement = null;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
dictionary NavigationInterceptOptions {
|
dictionary NavigationInterceptOptions {
|
||||||
|
|||||||
@@ -65,7 +65,6 @@ EXPORTS += [
|
|||||||
"nsCOMPtr.h",
|
"nsCOMPtr.h",
|
||||||
"nscore.h",
|
"nscore.h",
|
||||||
"nsCRTGlue.h",
|
"nsCRTGlue.h",
|
||||||
"nsCycleCollectionContainerParticipant.h",
|
|
||||||
"nsCycleCollectionNoteChild.h",
|
"nsCycleCollectionNoteChild.h",
|
||||||
"nsCycleCollectionNoteRootCallback.h",
|
"nsCycleCollectionNoteRootCallback.h",
|
||||||
"nsCycleCollectionParticipant.h",
|
"nsCycleCollectionParticipant.h",
|
||||||
|
|||||||
@@ -1,60 +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 nsCycleCollectionContainerParticipant_h__
|
|
||||||
#define nsCycleCollectionContainerParticipant_h__
|
|
||||||
|
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* To be able to implement ImplCycleCollectionIndexedContainer, we need to
|
|
||||||
* handle const vs non-const. ImplCycleCollectionTrace requires that the the
|
|
||||||
* value traced is non-const, and historically ImplCycleCollectionTraverse has
|
|
||||||
* been declared to take either const or non-const values. This poses a problem
|
|
||||||
* for containers, since it's not possible to define one
|
|
||||||
* ImplCycleCollectionIndexedContainer for both the const and non-const case
|
|
||||||
* with a templated parameter for the type contained by the container. The
|
|
||||||
* reason for this is how overload resolution works when it sees non-generic
|
|
||||||
* types with different constness. The standard solution for this is to use a
|
|
||||||
* universal reference, but we can't do this only because suddenly our
|
|
||||||
* ImplCycleCollectionIndexedContainer would be valid for any type. To make this
|
|
||||||
* work we need a way to constrain the type and we need it to be a constraint on
|
|
||||||
* the container type, not the type contained.
|
|
||||||
*
|
|
||||||
* This is pretty much the proposal for std::is_specialization_of, but with
|
|
||||||
* names from the unofficial cycle collector namespace. We use this to be able
|
|
||||||
* to do partial specialization to overload containers whose contents we wish to
|
|
||||||
* have participate in cycle collection. `template <typename Container>
|
|
||||||
* EnableCycleCollectionIf<Container, SomeContainer>` allows us to restrict an
|
|
||||||
* overload to only happen for a type SomeContainer<T>, which we then can use to
|
|
||||||
* make sure that an ImplCycleCollectionIndexedContainer overload is for a
|
|
||||||
* particular container, const or not.
|
|
||||||
*
|
|
||||||
* Example:
|
|
||||||
*
|
|
||||||
* template <typename Container, typename Callback,
|
|
||||||
* EnableCycleCollectionIf<Container, nsTHashtable> = nullptr>
|
|
||||||
* inline void ImplCycleCollectionContainer(Container&& aField,
|
|
||||||
* Callback&& aCallback) {
|
|
||||||
* // Implementation goes here
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
template <typename, template <typename...> typename>
|
|
||||||
struct ImplCycleCollectionIsContainerT : std::false_type {};
|
|
||||||
|
|
||||||
template <template <typename...> typename Container, typename... Args>
|
|
||||||
struct ImplCycleCollectionIsContainerT<Container<Args...>, Container>
|
|
||||||
: std::true_type {};
|
|
||||||
|
|
||||||
template <typename T, template <typename...> typename Container>
|
|
||||||
constexpr bool ImplCycleCollectionIsContainer = ImplCycleCollectionIsContainerT<
|
|
||||||
std::remove_cv_t<std::remove_reference_t<T>>, Container>::value;
|
|
||||||
|
|
||||||
template <typename T, template <typename...> typename Container>
|
|
||||||
using EnableCycleCollectionIf =
|
|
||||||
typename std::enable_if_t<ImplCycleCollectionIsContainer<T, Container>>*;
|
|
||||||
|
|
||||||
#endif // nsCycleCollectionContainerParticipant_h__
|
|
||||||
@@ -21,8 +21,12 @@
|
|||||||
* is a hack and is intentional in order to speed up the comparison inside
|
* is a hack and is intentional in order to speed up the comparison inside
|
||||||
* NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED.
|
* NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED.
|
||||||
*/
|
*/
|
||||||
#define NS_XPCOMCYCLECOLLECTIONPARTICIPANT_IID \
|
#define NS_XPCOMCYCLECOLLECTIONPARTICIPANT_IID \
|
||||||
{0xc61eac14, 0x5f7a, 0x4481, {0x96, 0x5e, 0x7e, 0xaa, 0x6e, 0xff, 0xa8, 0x5e}}
|
{ \
|
||||||
|
0xc61eac14, 0x5f7a, 0x4481, { \
|
||||||
|
0x96, 0x5e, 0x7e, 0xaa, 0x6e, 0xff, 0xa8, 0x5e \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Special IID to get at the base nsISupports for a class. Usually this is the
|
* Special IID to get at the base nsISupports for a class. Usually this is the
|
||||||
@@ -31,8 +35,12 @@
|
|||||||
* to have separate nsCycleCollectionParticipant's for tearoffs or aggregated
|
* to have separate nsCycleCollectionParticipant's for tearoffs or aggregated
|
||||||
* classes.
|
* classes.
|
||||||
*/
|
*/
|
||||||
#define NS_CYCLECOLLECTIONISUPPORTS_IID \
|
#define NS_CYCLECOLLECTIONISUPPORTS_IID \
|
||||||
{0xc61eac14, 0x5f7a, 0x4481, {0x96, 0x5e, 0x7e, 0xaa, 0x6e, 0xff, 0xa8, 0x5f}}
|
{ \
|
||||||
|
0xc61eac14, 0x5f7a, 0x4481, { \
|
||||||
|
0x96, 0x5e, 0x7e, 0xaa, 0x6e, 0xff, 0xa8, 0x5f \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
enum class CCReason : uint8_t {
|
enum class CCReason : uint8_t {
|
||||||
@@ -190,109 +198,6 @@ struct TraceCallbackFunc : public TraceCallbacks {
|
|||||||
Func mCallback;
|
Func mCallback;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T,
|
|
||||||
typename = std::enable_if_t<
|
|
||||||
std::is_same_v<
|
|
||||||
void, decltype(std::declval<TraceCallbacks*>()->Trace(
|
|
||||||
std::declval<T*>(), std::declval<const char*>(),
|
|
||||||
std::declval<void*>()))>,
|
|
||||||
void>>
|
|
||||||
using TraceableType = T;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Default implementation for traceable types.
|
|
||||||
*/
|
|
||||||
template <typename T>
|
|
||||||
inline void ImplCycleCollectionTrace(const TraceCallbacks& aCallbacks,
|
|
||||||
TraceableType<T>& aField,
|
|
||||||
const char* aName, void* aClosure) {
|
|
||||||
aCallbacks.Trace(&aField, aName, aClosure);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Default implementations for containers.
|
|
||||||
*
|
|
||||||
* To participate either define `ImplCycleCollectionContainer` or
|
|
||||||
* `ImplCycleCollectionIndexedContainer` for the container type. The latter
|
|
||||||
* should be chosen when edges should be decorated as an indexed container. Use
|
|
||||||
* `EnableCycleCollectionIf` from nsCycleCollectionContainerParticipant.h to
|
|
||||||
* restrict allowed types. For example:
|
|
||||||
*
|
|
||||||
* template <typename T>
|
|
||||||
* struct MyContainer {
|
|
||||||
* T mT;
|
|
||||||
* };
|
|
||||||
*
|
|
||||||
* template <typename Container, typename Callback,
|
|
||||||
* EnableCycleCollectionIf<Container, MyContainer> = nullptr>
|
|
||||||
* inline void ImplCycleCollectionContainer(Container&& aField,
|
|
||||||
* Callback&& aCallback) {
|
|
||||||
* aCallback(aField.mT);
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
|
|
||||||
template <typename T, typename = void>
|
|
||||||
struct ImplCycleCollectionNonIndexedContainerT : std::false_type {};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct ImplCycleCollectionNonIndexedContainerT<
|
|
||||||
T,
|
|
||||||
std::void_t<decltype(ImplCycleCollectionContainer(std::declval<T&>(), 0))>>
|
|
||||||
: std::true_type {};
|
|
||||||
|
|
||||||
template <typename T, typename = void>
|
|
||||||
struct ImplCycleCollectionIndexedContainerT : std::false_type {};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct ImplCycleCollectionIndexedContainerT<
|
|
||||||
T, std::void_t<decltype(ImplCycleCollectionIndexedContainer(
|
|
||||||
std::declval<T&>(), 0))>> : std::true_type {};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
constexpr bool ImplCycleCollectionCollectNonIndexedContainer =
|
|
||||||
ImplCycleCollectionNonIndexedContainerT<T>::value;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
constexpr bool ImplCycleCollectionCollectIndexedContainer =
|
|
||||||
ImplCycleCollectionIndexedContainerT<T>::value;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
constexpr bool ImplCycleCollectionCollectContainer =
|
|
||||||
ImplCycleCollectionNonIndexedContainerT<T>::value ||
|
|
||||||
ImplCycleCollectionIndexedContainerT<T>::value;
|
|
||||||
|
|
||||||
template <typename T, typename = std::enable_if_t<
|
|
||||||
ImplCycleCollectionCollectContainer<T>, void>>
|
|
||||||
void ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
|
|
||||||
T& aField, const char* aName,
|
|
||||||
uint32_t aFlags = 0) {
|
|
||||||
if constexpr (ImplCycleCollectionIndexedContainerT<T>::value) {
|
|
||||||
aFlags |= CycleCollectionEdgeNameArrayFlag;
|
|
||||||
ImplCycleCollectionIndexedContainer(aField, [&](auto& aFieldMember) {
|
|
||||||
ImplCycleCollectionTraverse(aCallback, aFieldMember, aName, aFlags);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
ImplCycleCollectionContainer(aField, [&](auto& aFieldMember) {
|
|
||||||
ImplCycleCollectionTraverse(aCallback, aFieldMember, aName, aFlags);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, typename = std::enable_if_t<
|
|
||||||
ImplCycleCollectionCollectContainer<T>, void>>
|
|
||||||
void ImplCycleCollectionTrace(const TraceCallbacks& aCallbacks, T& aField,
|
|
||||||
const char* aName, void* aClosure) {
|
|
||||||
if constexpr (ImplCycleCollectionIndexedContainerT<T>::value) {
|
|
||||||
ImplCycleCollectionIndexedContainer(aField, [&](auto& aFieldMember) {
|
|
||||||
ImplCycleCollectionTrace(aCallbacks, aFieldMember, aName, aClosure);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
ImplCycleCollectionContainer(aField, [&](auto& aFieldMember) {
|
|
||||||
ImplCycleCollectionTrace(aCallbacks, aFieldMember, aName, aClosure);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Participant implementation classes
|
* Participant implementation classes
|
||||||
*/
|
*/
|
||||||
@@ -715,7 +620,7 @@ T* DowncastCCParticipant(void* aPtr) {
|
|||||||
NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::Trace(s, aCallbacks, aClosure);
|
NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::Trace(s, aCallbacks, aClosure);
|
||||||
|
|
||||||
#define NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(_field) \
|
#define NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(_field) \
|
||||||
ImplCycleCollectionTrace(aCallbacks, tmp->_field, #_field, aClosure);
|
aCallbacks.Trace(&tmp->_field, #_field, aClosure);
|
||||||
|
|
||||||
// NB: The (void)tmp; hack in the TRACE_END macro exists to support
|
// NB: The (void)tmp; hack in the TRACE_END macro exists to support
|
||||||
// implementations that don't need to do anything in their Trace method.
|
// implementations that don't need to do anything in their Trace method.
|
||||||
|
|||||||
@@ -1,29 +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 mozilla_CycleCollectedUniquePtr_h__
|
|
||||||
#define mozilla_CycleCollectedUniquePtr_h__
|
|
||||||
|
|
||||||
#include "mozilla/UniquePtr.h"
|
|
||||||
#include "nsCycleCollectionContainerParticipant.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
template <typename T>
|
|
||||||
inline void ImplCycleCollectionUnlink(mozilla::UniquePtr<T>& aField) {
|
|
||||||
aField.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Container, typename Callback,
|
|
||||||
EnableCycleCollectionIf<Container, mozilla::UniquePtr> = nullptr>
|
|
||||||
inline void ImplCycleCollectionContainer(Container&& aField,
|
|
||||||
Callback&& aCallback) {
|
|
||||||
if (aField) {
|
|
||||||
aCallback(*aField);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // namespace mozilla
|
|
||||||
|
|
||||||
#endif // mozilla_CycleCollectedUniquePtr_h__
|
|
||||||
@@ -91,7 +91,6 @@ EXPORTS.mozilla += [
|
|||||||
"ArrayAlgorithm.h",
|
"ArrayAlgorithm.h",
|
||||||
"ArrayIterator.h",
|
"ArrayIterator.h",
|
||||||
"AtomArray.h",
|
"AtomArray.h",
|
||||||
"CycleCollectedUniquePtr.h",
|
|
||||||
"Dafsa.h",
|
"Dafsa.h",
|
||||||
"IncrementalTokenizer.h",
|
"IncrementalTokenizer.h",
|
||||||
"Observer.h",
|
"Observer.h",
|
||||||
|
|||||||
@@ -288,12 +288,6 @@ class nsBaseHashtable
|
|||||||
const nsBaseHashtable<KC, DT, UDT, C>&, const char* aName,
|
const nsBaseHashtable<KC, DT, UDT, C>&, const char* aName,
|
||||||
uint32_t aFlags);
|
uint32_t aFlags);
|
||||||
|
|
||||||
template <typename KC, typename DT, typename UDT, typename C>
|
|
||||||
friend inline void ImplCycleCollectionTrace(const TraceCallbacks& aCallbacks,
|
|
||||||
nsBaseHashtable<KC, DT, UDT, C>&,
|
|
||||||
const char* aName,
|
|
||||||
void* aClosure);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef typename KeyClass::KeyType KeyType;
|
typedef typename KeyClass::KeyType KeyType;
|
||||||
typedef nsBaseHashtableET<KeyClass, DataType> EntryType;
|
typedef nsBaseHashtableET<KeyClass, DataType> EntryType;
|
||||||
@@ -1063,41 +1057,4 @@ inline void ImplCycleCollectionTraverse(
|
|||||||
ImplCycleCollectionTraverse(aCallback, aField.GetData(), aName, aFlags);
|
ImplCycleCollectionTraverse(aCallback, aField.GetData(), aName, aFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class KeyClass, class DataType, class UserDataType, class Converter>
|
|
||||||
inline void ImplCycleCollectionTrace(
|
|
||||||
const TraceCallbacks& aCallbacks,
|
|
||||||
nsBaseHashtable<KeyClass, DataType, UserDataType, Converter>& aField,
|
|
||||||
const char* aName, void* aClosure) {
|
|
||||||
ImplCycleCollectionTrace(
|
|
||||||
aCallbacks,
|
|
||||||
static_cast<nsTHashtable<nsBaseHashtableET<KeyClass, DataType>>&>(aField),
|
|
||||||
aName, aClosure);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace mozilla::detail {
|
|
||||||
template <typename T, typename = void>
|
|
||||||
constexpr bool kCanTrace = false;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
constexpr bool
|
|
||||||
kCanTrace<T, std::void_t<decltype(ImplCycleCollectionTrace(
|
|
||||||
std::declval<TraceCallbacks>(), std::declval<T&>(),
|
|
||||||
std::declval<const char*>(), std::declval<void*>()))>> =
|
|
||||||
true;
|
|
||||||
} // namespace mozilla::detail
|
|
||||||
|
|
||||||
template <typename KeyClass, typename DataType>
|
|
||||||
inline void ImplCycleCollectionTrace(
|
|
||||||
const TraceCallbacks& aCallbacks,
|
|
||||||
nsBaseHashtableET<KeyClass, DataType>& aField, const char* aName,
|
|
||||||
void* aClosure) {
|
|
||||||
static_assert(!mozilla::detail::kCanTrace<KeyClass&>,
|
|
||||||
"Don't use traceable values as KeyClass");
|
|
||||||
static_assert(mozilla::detail::kCanTrace<DataType&>,
|
|
||||||
"Can't trace values of type DataType");
|
|
||||||
|
|
||||||
ImplCycleCollectionTrace(aCallbacks, *aField.GetModifiableData(), aName,
|
|
||||||
aClosure);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // nsBaseHashtable_h__
|
#endif // nsBaseHashtable_h__
|
||||||
|
|||||||
@@ -21,3 +21,7 @@ bool IsTwiceTheRequiredBytesRepresentableAsUint32(size_t aCapacity,
|
|||||||
using mozilla::CheckedUint32;
|
using mozilla::CheckedUint32;
|
||||||
return ((CheckedUint32(aCapacity) * aElemSize) * 2).isValid();
|
return ((CheckedUint32(aCapacity) * aElemSize) * 2).isValid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ::detail::SetCycleCollectionArrayFlag(uint32_t& aFlags) {
|
||||||
|
aFlags |= CycleCollectionEdgeNameArrayFlag;
|
||||||
|
}
|
||||||
|
|||||||
@@ -43,7 +43,6 @@ class Heap;
|
|||||||
} /* namespace JS */
|
} /* namespace JS */
|
||||||
|
|
||||||
class nsCycleCollectionTraversalCallback;
|
class nsCycleCollectionTraversalCallback;
|
||||||
struct TraceCallbacks;
|
|
||||||
class nsRegion;
|
class nsRegion;
|
||||||
|
|
||||||
namespace mozilla::a11y {
|
namespace mozilla::a11y {
|
||||||
@@ -2686,11 +2685,21 @@ inline void ImplCycleCollectionUnlink(nsTArray_Impl<E, Alloc>& aField) {
|
|||||||
aField.Clear();
|
aField.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename E, typename Alloc, typename Callback>
|
namespace detail {
|
||||||
inline void ImplCycleCollectionIndexedContainer(nsTArray_Impl<E, Alloc>& aField,
|
// This is defined in the cpp file to avoid including
|
||||||
Callback&& aCallback) {
|
// nsCycleCollectionNoteChild.h in this header file.
|
||||||
for (auto& value : aField) {
|
void SetCycleCollectionArrayFlag(uint32_t& aFlags);
|
||||||
aCallback(value);
|
} // namespace detail
|
||||||
|
|
||||||
|
template <typename E, typename Alloc>
|
||||||
|
inline void ImplCycleCollectionTraverse(
|
||||||
|
nsCycleCollectionTraversalCallback& aCallback,
|
||||||
|
nsTArray_Impl<E, Alloc>& aField, const char* aName, uint32_t aFlags = 0) {
|
||||||
|
::detail::SetCycleCollectionArrayFlag(aFlags);
|
||||||
|
size_t length = aField.Length();
|
||||||
|
E* elements = aField.Elements();
|
||||||
|
for (size_t i = 0; i < length; ++i) {
|
||||||
|
ImplCycleCollectionTraverse(aCallback, elements[i], aName, aFlags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,6 @@
|
|||||||
#include "mozilla/fallible.h"
|
#include "mozilla/fallible.h"
|
||||||
#include "nsPointerHashKeys.h"
|
#include "nsPointerHashKeys.h"
|
||||||
#include "nsTArrayForwardDeclare.h"
|
#include "nsTArrayForwardDeclare.h"
|
||||||
#include "nsCycleCollectionContainerParticipant.h"
|
|
||||||
|
|
||||||
template <class EntryType>
|
template <class EntryType>
|
||||||
class nsTHashtable;
|
class nsTHashtable;
|
||||||
@@ -431,8 +430,8 @@ class MOZ_NEEDS_NO_VTABLE_TYPE nsTHashtable {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <class F>
|
template <class F>
|
||||||
auto WithEntryHandle(KeyType aKey, F&& aFunc)
|
auto WithEntryHandle(KeyType aKey,
|
||||||
-> std::invoke_result_t<F, EntryHandle&&> {
|
F&& aFunc) -> std::invoke_result_t<F, EntryHandle&&> {
|
||||||
return this->mTable.WithEntryHandle(
|
return this->mTable.WithEntryHandle(
|
||||||
EntryType::KeyToPointer(aKey),
|
EntryType::KeyToPointer(aKey),
|
||||||
[&aKey, &aFunc](auto entryHandle) -> decltype(auto) {
|
[&aKey, &aFunc](auto entryHandle) -> decltype(auto) {
|
||||||
@@ -723,21 +722,20 @@ void nsTHashtable<EntryType>::s_ClearEntry(PLDHashTable* aTable,
|
|||||||
}
|
}
|
||||||
|
|
||||||
class nsCycleCollectionTraversalCallback;
|
class nsCycleCollectionTraversalCallback;
|
||||||
struct TraceCallbacks;
|
|
||||||
|
|
||||||
template <class EntryType>
|
template <class EntryType>
|
||||||
inline void ImplCycleCollectionUnlink(nsTHashtable<EntryType>& aField) {
|
inline void ImplCycleCollectionUnlink(nsTHashtable<EntryType>& aField) {
|
||||||
aField.Clear();
|
aField.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function template constrained to types that are (possibly const)
|
template <class EntryType>
|
||||||
// nsTHashtable.
|
inline void ImplCycleCollectionTraverse(
|
||||||
template <typename Container, typename Callback,
|
nsCycleCollectionTraversalCallback& aCallback,
|
||||||
EnableCycleCollectionIf<Container, nsTHashtable> = nullptr>
|
const nsTHashtable<EntryType>& aField, const char* aName,
|
||||||
inline void ImplCycleCollectionContainer(Container&& aField,
|
uint32_t aFlags = 0) {
|
||||||
Callback&& aCallback) {
|
for (auto iter = aField.ConstIter(); !iter.Done(); iter.Next()) {
|
||||||
for (auto& entry : aField) {
|
const EntryType* entry = iter.Get();
|
||||||
aCallback(entry);
|
ImplCycleCollectionTraverse(aCallback, *entry, aName, aFlags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -878,8 +876,8 @@ class nsTHashtable<nsPtrHashKey<T>>
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <class F>
|
template <class F>
|
||||||
auto WithEntryHandle(KeyType aKey, F aFunc)
|
auto WithEntryHandle(KeyType aKey,
|
||||||
-> std::invoke_result_t<F, EntryHandle&&> {
|
F aFunc) -> std::invoke_result_t<F, EntryHandle&&> {
|
||||||
return Base::WithEntryHandle(aKey, [&aFunc](auto entryHandle) {
|
return Base::WithEntryHandle(aKey, [&aFunc](auto entryHandle) {
|
||||||
return aFunc(EntryHandle{std::move(entryHandle)});
|
return aFunc(EntryHandle{std::move(entryHandle)});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user