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
|
||||
void WindowContext::ConsumeHistoryActivation() {
|
||||
bool WindowContext::ConsumeHistoryActivation() {
|
||||
MOZ_ASSERT(IsInProcess());
|
||||
|
||||
if (!HasValidHistoryActivation()) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
mHistoryActivation = mUserGestureStart;
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WindowContext::GetTransientUserGestureActivationModifiers(
|
||||
|
||||
@@ -229,8 +229,9 @@ class WindowContext : public nsISupports, public nsWrapperCache {
|
||||
// Return true if its corresponding window has history activation.
|
||||
bool HasValidHistoryActivation() const;
|
||||
|
||||
// Consume the history-action user activation.
|
||||
void ConsumeHistoryActivation();
|
||||
// Return true if the corresponding window has valid history activation
|
||||
// and the history activation had been consumed successfully.
|
||||
bool ConsumeHistoryActivation();
|
||||
|
||||
bool GetTransientUserGestureActivationModifiers(
|
||||
UserActivation::Modifiers* aModifiers);
|
||||
|
||||
@@ -11353,20 +11353,6 @@ nsDocShell::AddState(JS::Handle<JS::Value> aData, const nsAString& aTitle,
|
||||
|
||||
} // 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"
|
||||
rv = UpdateURLAndHistory(document, newURI, scContainer,
|
||||
aReplace ? NavigationHistoryBehavior::Replace
|
||||
|
||||
@@ -106,7 +106,7 @@ interface nsIDocShell : nsIDocShellTreeItem
|
||||
* Do either a history.pushState() or history.replaceState() operation,
|
||||
* depending on the value of aReplace.
|
||||
*/
|
||||
[implicit_jscontext, can_run_script]
|
||||
[implicit_jscontext]
|
||||
void addState(in jsval aData, in AString aTitle,
|
||||
in AString aURL, in boolean aReplace);
|
||||
|
||||
|
||||
@@ -365,7 +365,7 @@ nsresult FormData::GetSendInfo(nsIInputStream** aBody, uint64_t* aContentLength,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
already_AddRefed<FormData> FormData::Clone() const {
|
||||
already_AddRefed<FormData> FormData::Clone() {
|
||||
RefPtr<FormData> formData = new FormData(*this);
|
||||
return formData.forget();
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ class FormData final : public nsISupports,
|
||||
NotNull<const Encoding*> aEncoding = UTF_8_ENCODING,
|
||||
Element* aSubmitter = nullptr);
|
||||
|
||||
already_AddRefed<FormData> Clone() const;
|
||||
already_AddRefed<FormData> Clone();
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(FormData)
|
||||
|
||||
@@ -50,14 +50,10 @@ class nsHistory final : public nsISupports, public nsWrapperCache {
|
||||
mozilla::ErrorResult& aRv);
|
||||
void Back(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,
|
||||
const nsAString& aTitle, const nsAString& aUrl,
|
||||
mozilla::dom::CallerType aCallerType,
|
||||
mozilla::ErrorResult& aRv);
|
||||
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
void ReplaceState(JSContext* aCx, JS::Handle<JS::Value> aData,
|
||||
const nsAString& aTitle, const nsAString& aUrl,
|
||||
mozilla::dom::CallerType aCallerType,
|
||||
@@ -66,7 +62,6 @@ class nsHistory final : public nsISupports, public nsWrapperCache {
|
||||
protected:
|
||||
virtual ~nsHistory();
|
||||
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
void PushOrReplaceState(JSContext* aCx, JS::Handle<JS::Value> aData,
|
||||
const nsAString& aTitle, const nsAString& aUrl,
|
||||
mozilla::dom::CallerType aCallerType,
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
#include <type_traits>
|
||||
|
||||
#include "js/Value.h"
|
||||
#include "mozilla/CycleCollectedUniquePtr.h"
|
||||
#include "mozilla/RootedOwningNonNull.h"
|
||||
#include "mozilla/RootedRefPtr.h"
|
||||
|
||||
@@ -88,6 +87,12 @@ inline std::enable_if_t<is_dom_dictionary<T>, void> ImplCycleCollectionTraverse(
|
||||
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>
|
||||
inline std::enable_if_t<is_dom_dictionary<T>, void> ImplCycleCollectionTraverse(
|
||||
nsCycleCollectionTraversalCallback& aCallback, UniquePtr<T>& aDictionary,
|
||||
|
||||
@@ -19267,15 +19267,6 @@ class CGBindingRoot(CGThing):
|
||||
|
||||
for d in dictionaries:
|
||||
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:
|
||||
interface = d.interface
|
||||
addPrefHeaderForObject(bindingHeaders, interface)
|
||||
|
||||
@@ -4,302 +4,16 @@
|
||||
* 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 "nsGlobalWindowInner.h"
|
||||
|
||||
#include "mozilla/HoldDropJSObjects.h"
|
||||
|
||||
#include "mozilla/dom/AbortController.h"
|
||||
#include "mozilla/dom/NavigateEvent.h"
|
||||
#include "mozilla/dom/NavigateEventBinding.h"
|
||||
#include "mozilla/dom/Navigation.h"
|
||||
|
||||
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 */
|
||||
already_AddRefed<NavigateEvent> NavigateEvent::Constructor(
|
||||
const GlobalObject& aGlobal, const nsAString& aType,
|
||||
const NavigateEventInit& aEventInitDict) {
|
||||
nsCOMPtr<mozilla::dom::EventTarget> eventTarget =
|
||||
do_QueryInterface(aGlobal.GetAsSupports());
|
||||
return Constructor(eventTarget, aType, aEventInitDict);
|
||||
return {};
|
||||
}
|
||||
|
||||
/* 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
|
||||
|
||||
@@ -7,136 +7,56 @@
|
||||
#ifndef mozilla_dom_NavigateEvent_h___
|
||||
#define mozilla_dom_NavigateEvent_h___
|
||||
|
||||
#include "js/RootingAPI.h"
|
||||
#include "js/Value.h"
|
||||
#include "mozilla/AlreadyAddRefed.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/dom/AbortController.h"
|
||||
#include "js/TypeDecls.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/dom/Event.h"
|
||||
#include "mozilla/dom/NavigateEventBinding.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "mozilla/dom/NavigationBinding.h"
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
class AbortController;
|
||||
class AbortSignal;
|
||||
class FormData;
|
||||
class NavigationDestination;
|
||||
struct NavigationInterceptOptions;
|
||||
|
||||
enum class NavigationType : uint8_t;
|
||||
|
||||
// https://html.spec.whatwg.org/#the-navigateevent-interface
|
||||
class NavigateEvent final : public Event {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(NavigateEvent, Event)
|
||||
|
||||
virtual JSObject* WrapObjectInternal(
|
||||
JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
NS_INLINE_DECL_REFCOUNTING_INHERITED(NavigateEvent, Event)
|
||||
|
||||
static already_AddRefed<NavigateEvent> Constructor(
|
||||
const GlobalObject& aGlobal, const nsAString& aType,
|
||||
const NavigateEventInit& aEventInitDict);
|
||||
|
||||
static already_AddRefed<NavigateEvent> Constructor(
|
||||
EventTarget* aEventTarget, const nsAString& aType,
|
||||
const NavigateEventInit& aEventInitDict);
|
||||
enum NavigationType NavigationType() const { return {}; }
|
||||
|
||||
static already_AddRefed<NavigateEvent> Constructor(
|
||||
EventTarget* aEventTarget, const nsAString& aType,
|
||||
const NavigateEventInit& aEventInitDict,
|
||||
nsIStructuredCloneContainer* aClassicHistoryAPIState,
|
||||
AbortController* aAbortController);
|
||||
already_AddRefed<NavigationDestination> Destination() const { return {}; }
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
bool IsTrusted() const { return {}; }
|
||||
|
||||
private:
|
||||
void PotentiallyResetFocus();
|
||||
|
||||
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;
|
||||
~NavigateEvent() = default;
|
||||
};
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
||||
@@ -6,99 +6,38 @@
|
||||
|
||||
#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/CycleCollectedUniquePtr.h"
|
||||
#include "mozilla/HoldDropJSObjects.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "mozilla/StaticPrefs_dom.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
#include "mozilla/dom/Document.h"
|
||||
#include "mozilla/dom/Event.h"
|
||||
#include "mozilla/dom/FeaturePolicy.h"
|
||||
#include "mozilla/dom/NavigationActivation.h"
|
||||
#include "mozilla/dom/NavigationCurrentEntryChangeEvent.h"
|
||||
#include "mozilla/dom/NavigationHistoryEntry.h"
|
||||
#include "mozilla/dom/NavigationTransition.h"
|
||||
#include "mozilla/dom/NavigationUtils.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");
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
struct NavigationAPIMethodTracker {
|
||||
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_CYCLE_COLLECTION_INHERITED(Navigation, DOMEventTargetHelper, mEntries);
|
||||
NS_IMPL_ADDREF_INHERITED(Navigation, DOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(Navigation, DOMEventTargetHelper)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Navigation)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||
|
||||
Navigation::Navigation(nsPIDOMWindowInner* aWindow)
|
||||
: DOMEventTargetHelper(aWindow) {
|
||||
Navigation::Navigation(nsPIDOMWindowInner* aWindow) : mWindow(aWindow) {
|
||||
MOZ_ASSERT(aWindow);
|
||||
|
||||
mozilla::HoldJSObjects(this);
|
||||
}
|
||||
|
||||
Navigation::~Navigation() { mozilla::DropJSObjects(this); }
|
||||
|
||||
JSObject* Navigation::WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) {
|
||||
return Navigation_Binding::Wrap(aCx, this, aGivenProto);
|
||||
@@ -133,7 +72,7 @@ already_AddRefed<NavigationHistoryEntry> Navigation::GetCurrentEntry() const {
|
||||
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(
|
||||
JSContext* aCx, const NavigationUpdateCurrentEntryOptions& aOptions,
|
||||
ErrorResult& aRv) {
|
||||
@@ -164,20 +103,16 @@ void Navigation::UpdateCurrentEntry(
|
||||
DispatchEvent(*event);
|
||||
}
|
||||
|
||||
NavigationTransition* Navigation::GetTransition() const { return mTransition; }
|
||||
|
||||
NavigationActivation* Navigation::GetActivation() const { return mActivation; }
|
||||
|
||||
// https://html.spec.whatwg.org/#has-entries-and-events-disabled
|
||||
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#has-entries-and-events-disabled
|
||||
bool Navigation::HasEntriesAndEventsDisabled() const {
|
||||
Document* doc = GetDocumentIfCurrent();
|
||||
return !doc || !doc->IsCurrentActiveDocument() ||
|
||||
Document* doc = mWindow->GetDoc();
|
||||
return !doc->IsCurrentActiveDocument() ||
|
||||
(NS_IsAboutBlankAllowQueryAndFragment(doc->GetDocumentURI()) &&
|
||||
doc->IsInitialDocument()) ||
|
||||
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(
|
||||
mozilla::Span<const SessionHistoryInfo> aNewSHInfos,
|
||||
const SessionHistoryInfo* aInitialSHInfo) {
|
||||
@@ -188,8 +123,8 @@ void Navigation::InitializeHistoryEntries(
|
||||
}
|
||||
|
||||
for (auto i = 0ul; i < aNewSHInfos.Length(); i++) {
|
||||
mEntries.AppendElement(MakeRefPtr<NavigationHistoryEntry>(
|
||||
GetOwnerGlobal(), &aNewSHInfos[i], i));
|
||||
mEntries.AppendElement(
|
||||
MakeRefPtr<NavigationHistoryEntry>(mWindow, &aNewSHInfos[i], i));
|
||||
if (aNewSHInfos[i].NavigationKey() == aInitialSHInfo->NavigationKey()) {
|
||||
mCurrentEntryIndex = Some(i);
|
||||
}
|
||||
@@ -204,7 +139,7 @@ void Navigation::InitializeHistoryEntries(
|
||||
("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(
|
||||
SessionHistoryInfo* aDestinationSHE, NavigationType aNavigationType) {
|
||||
// Step 1.
|
||||
@@ -239,7 +174,7 @@ void Navigation::UpdateEntriesForSameDocumentNavigation(
|
||||
disposedEntries.AppendElement(mEntries.PopLastElement());
|
||||
}
|
||||
mEntries.AppendElement(MakeRefPtr<NavigationHistoryEntry>(
|
||||
GetOwnerGlobal(), aDestinationSHE, *mCurrentEntryIndex));
|
||||
mWindow, aDestinationSHE, *mCurrentEntryIndex));
|
||||
break;
|
||||
|
||||
case NavigationType::Replace:
|
||||
@@ -247,7 +182,7 @@ void Navigation::UpdateEntriesForSameDocumentNavigation(
|
||||
disposedEntries.AppendElement(oldCurrentEntry);
|
||||
aDestinationSHE->NavigationKey() = oldCurrentEntry->Key();
|
||||
mEntries[*mCurrentEntryIndex] = MakeRefPtr<NavigationHistoryEntry>(
|
||||
GetOwnerGlobal(), aDestinationSHE, *mCurrentEntryIndex);
|
||||
mWindow, aDestinationSHE, *mCurrentEntryIndex);
|
||||
break;
|
||||
|
||||
case NavigationType::Reload:
|
||||
@@ -259,7 +194,7 @@ void Navigation::UpdateEntriesForSameDocumentNavigation(
|
||||
// Steps 9-12.
|
||||
{
|
||||
nsAutoMicroTask mt;
|
||||
AutoEntryScript aes(GetOwnerGlobal(),
|
||||
AutoEntryScript aes(mWindow->AsGlobal(),
|
||||
"UpdateEntriesForSameDocumentNavigation");
|
||||
|
||||
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) {
|
||||
// NAV-TODO
|
||||
}
|
||||
@@ -324,526 +259,6 @@ void LogEntry(NavigationHistoryEntry* aEntry, uint64_t aIndex, uint64_t aTotal,
|
||||
|
||||
} // 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 {
|
||||
if (!MOZ_LOG_TEST(gNavigationLog, LogLevel::Debug)) {
|
||||
return;
|
||||
|
||||
@@ -7,25 +7,12 @@
|
||||
#ifndef 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/Maybe.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
|
||||
#include "mozilla/dom/NavigateEvent.h"
|
||||
#include "mozilla/dom/NavigationBinding.h"
|
||||
|
||||
class nsIDHashKey;
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
class FormData;
|
||||
class NavigationActivation;
|
||||
class NavigationDestination;
|
||||
class NavigationHistoryEntry;
|
||||
struct NavigationNavigateOptions;
|
||||
struct NavigationOptions;
|
||||
@@ -36,13 +23,10 @@ struct NavigationResult;
|
||||
|
||||
class SessionHistoryInfo;
|
||||
|
||||
struct NavigationAPIMethodTracker;
|
||||
|
||||
class Navigation final : public DOMEventTargetHelper {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(Navigation,
|
||||
DOMEventTargetHelper)
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(Navigation, DOMEventTargetHelper)
|
||||
|
||||
explicit Navigation(nsPIDOMWindowInner* aWindow);
|
||||
|
||||
@@ -53,8 +37,8 @@ class Navigation final : public DOMEventTargetHelper {
|
||||
void UpdateCurrentEntry(JSContext* aCx,
|
||||
const NavigationUpdateCurrentEntryOptions& aOptions,
|
||||
ErrorResult& aRv);
|
||||
NavigationTransition* GetTransition() const;
|
||||
NavigationActivation* GetActivation() const;
|
||||
already_AddRefed<NavigationTransition> GetTransition() { return {}; }
|
||||
already_AddRefed<NavigationActivation> GetActivation() { return {}; }
|
||||
|
||||
bool CanGoBack() {
|
||||
return !HasEntriesAndEventsDisabled() && mCurrentEntryIndex &&
|
||||
@@ -105,33 +89,8 @@ class Navigation final : public DOMEventTargetHelper {
|
||||
static bool IsAPIEnabled(JSContext* /* 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:
|
||||
using UpcomingTraverseAPIMethodTrackers =
|
||||
nsTHashMap<nsIDHashKey, UniquePtr<NavigationAPIMethodTracker>>;
|
||||
|
||||
~Navigation();
|
||||
~Navigation() = default;
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#has-entries-and-events-disabled
|
||||
bool HasEntriesAndEventsDisabled() const;
|
||||
@@ -141,56 +100,13 @@ class Navigation final : public DOMEventTargetHelper {
|
||||
const RefPtr<NavigationHistoryEntry>& aPreviousEntry,
|
||||
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;
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowInner> mWindow;
|
||||
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#navigation-entry-list
|
||||
nsTArray<RefPtr<NavigationHistoryEntry>> mEntries;
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#navigation-current-entry
|
||||
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
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#ifndef mozilla_dom_NavigationActivation_h___
|
||||
#define mozilla_dom_NavigationActivation_h___
|
||||
|
||||
#include "nsISupports.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
class nsIGlobalObject;
|
||||
|
||||
@@ -104,10 +104,4 @@ JSObject* NavigationDestination::WrapObject(JSContext* aCx,
|
||||
|
||||
nsIGlobalObject* NavigationDestination::GetParentObject() { return mGlobal; }
|
||||
|
||||
NavigationHistoryEntry* NavigationDestination::GetEntry() const {
|
||||
return mEntry;
|
||||
}
|
||||
|
||||
nsIURI* NavigationDestination::GetURI() const { return mURL; }
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
||||
@@ -48,9 +48,6 @@ class NavigationDestination final : public nsISupports, public nsWrapperCache {
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
nsIGlobalObject* GetParentObject();
|
||||
|
||||
NavigationHistoryEntry* GetEntry() const;
|
||||
nsIURI* GetURI() const;
|
||||
|
||||
private:
|
||||
~NavigationDestination() = default;
|
||||
|
||||
|
||||
@@ -15,8 +15,8 @@ extern mozilla::LazyLogModule gNavigationLog;
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(NavigationHistoryEntry,
|
||||
DOMEventTargetHelper);
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(NavigationHistoryEntry, DOMEventTargetHelper,
|
||||
mWindow);
|
||||
NS_IMPL_ADDREF_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)
|
||||
|
||||
NavigationHistoryEntry::NavigationHistoryEntry(
|
||||
nsIGlobalObject* aGlobal, const SessionHistoryInfo* aSHInfo, int64_t aIndex)
|
||||
: DOMEventTargetHelper(aGlobal),
|
||||
nsPIDOMWindowInner* aWindow, const SessionHistoryInfo* aSHInfo,
|
||||
int64_t aIndex)
|
||||
: mWindow(aWindow),
|
||||
mSHInfo(MakeUnique<SessionHistoryInfo>(*aSHInfo)),
|
||||
mIndex(aIndex) {}
|
||||
|
||||
NavigationHistoryEntry::~NavigationHistoryEntry() = default;
|
||||
|
||||
// https://html.spec.whatwg.org/#dom-navigationhistoryentry-url
|
||||
void NavigationHistoryEntry::GetUrl(nsAString& aResult) const {
|
||||
if (!HasActiveDocument()) {
|
||||
if (!GetCurrentDocument()->IsCurrentActiveDocument()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// HasActiveDocument implies that GetCurrentDocument returns non-null.
|
||||
MOZ_DIAGNOSTIC_ASSERT(GetCurrentDocument());
|
||||
|
||||
if (!SameDocument()) {
|
||||
auto referrerPolicy = GetCurrentDocument()->ReferrerPolicy();
|
||||
if (referrerPolicy == ReferrerPolicy::No_referrer ||
|
||||
@@ -56,9 +53,8 @@ void NavigationHistoryEntry::GetUrl(nsAString& aResult) const {
|
||||
CopyUTF8toUTF16(uriSpec, aResult);
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/#dom-navigationhistoryentry-key
|
||||
void NavigationHistoryEntry::GetKey(nsAString& aResult) const {
|
||||
if (!HasActiveDocument()) {
|
||||
if (!GetCurrentDocument()->IsCurrentActiveDocument()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -67,9 +63,8 @@ void NavigationHistoryEntry::GetKey(nsAString& aResult) const {
|
||||
CopyUTF8toUTF16(Substring(keyString.get() + 1, NSID_LENGTH - 3), aResult);
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/#dom-navigationhistoryentry-id
|
||||
void NavigationHistoryEntry::GetId(nsAString& aResult) const {
|
||||
if (!HasActiveDocument()) {
|
||||
if (!GetCurrentDocument()->IsCurrentActiveDocument()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -78,30 +73,20 @@ void NavigationHistoryEntry::GetId(nsAString& aResult) const {
|
||||
CopyUTF8toUTF16(Substring(idString.get() + 1, NSID_LENGTH - 3), aResult);
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/#dom-navigationhistoryentry-index
|
||||
int64_t NavigationHistoryEntry::Index() const {
|
||||
MOZ_ASSERT(mSHInfo);
|
||||
if (!HasActiveDocument()) {
|
||||
if (!GetCurrentDocument()->IsCurrentActiveDocument()) {
|
||||
return -1;
|
||||
}
|
||||
return mIndex;
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/#dom-navigationhistoryentry-samedocument
|
||||
bool NavigationHistoryEntry::SameDocument() const {
|
||||
if (!HasActiveDocument()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// HasActiveDocument implies that GetCurrentDocument returns non-null.
|
||||
MOZ_DIAGNOSTIC_ASSERT(GetCurrentDocument());
|
||||
|
||||
MOZ_ASSERT(mSHInfo);
|
||||
auto* docShell = nsDocShell::Cast(GetCurrentDocument()->GetDocShell());
|
||||
return docShell && docShell->IsSameDocumentAsActiveEntry(*mSHInfo);
|
||||
auto* docShell = static_cast<nsDocShell*>(mWindow->GetDocShell());
|
||||
return docShell->IsSameDocumentAsActiveEntry(*mSHInfo);
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/#dom-navigationhistoryentry-getstate
|
||||
void NavigationHistoryEntry::GetState(JSContext* aCx,
|
||||
JS::MutableHandle<JS::Value> aResult,
|
||||
ErrorResult& aRv) const {
|
||||
@@ -122,10 +107,8 @@ void NavigationHistoryEntry::GetState(JSContext* aCx,
|
||||
}
|
||||
|
||||
void NavigationHistoryEntry::SetState(nsStructuredCloneContainer* aState) {
|
||||
if (RefPtr<nsStructuredCloneContainer> state =
|
||||
mSHInfo->GetNavigationState()) {
|
||||
state->Copy(*aState);
|
||||
}
|
||||
RefPtr<nsStructuredCloneContainer> state = mSHInfo->GetNavigationState();
|
||||
state->Copy(*aState);
|
||||
}
|
||||
|
||||
bool NavigationHistoryEntry::IsSameEntry(
|
||||
@@ -144,27 +127,11 @@ JSObject* NavigationHistoryEntry::WrapObject(
|
||||
}
|
||||
|
||||
Document* NavigationHistoryEntry::GetCurrentDocument() const {
|
||||
return GetDocumentIfCurrent();
|
||||
}
|
||||
|
||||
bool NavigationHistoryEntry::HasActiveDocument() const {
|
||||
if (auto* document = GetCurrentDocument()) {
|
||||
return document->IsCurrentActiveDocument();
|
||||
}
|
||||
|
||||
return false;
|
||||
return mWindow->GetDoc();
|
||||
}
|
||||
|
||||
const nsID& NavigationHistoryEntry::Key() const {
|
||||
return mSHInfo->NavigationKey();
|
||||
}
|
||||
|
||||
nsStructuredCloneContainer* NavigationHistoryEntry::GetNavigationState() const {
|
||||
if (!mSHInfo) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return mSHInfo->GetNavigationState();
|
||||
}
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
||||
@@ -9,21 +9,19 @@
|
||||
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
|
||||
class nsIGlobalObject;
|
||||
class nsStructuredCloneContainer;
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
class SessionHistoryInfo;
|
||||
|
||||
// https://html.spec.whatwg.org/#navigationhistoryentry
|
||||
class NavigationHistoryEntry final : public DOMEventTargetHelper {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(NavigationHistoryEntry,
|
||||
DOMEventTargetHelper)
|
||||
|
||||
NavigationHistoryEntry(nsIGlobalObject* aGlobal,
|
||||
NavigationHistoryEntry(nsPIDOMWindowInner* aWindow,
|
||||
const SessionHistoryInfo* aSHInfo, int64_t aIndex);
|
||||
|
||||
void GetUrl(nsAString& aResult) const;
|
||||
@@ -47,16 +45,12 @@ class NavigationHistoryEntry final : public DOMEventTargetHelper {
|
||||
|
||||
const nsID& Key() const;
|
||||
|
||||
nsStructuredCloneContainer* GetNavigationState() const;
|
||||
|
||||
private:
|
||||
~NavigationHistoryEntry();
|
||||
|
||||
Document* GetCurrentDocument() const;
|
||||
|
||||
bool HasActiveDocument() const;
|
||||
|
||||
// https://html.spec.whatwg.org/#nhe-she
|
||||
nsCOMPtr<nsPIDOMWindowInner> mWindow;
|
||||
UniquePtr<SessionHistoryInfo> mSHInfo;
|
||||
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",
|
||||
"NavigationHistoryEntry.h",
|
||||
"NavigationTransition.h",
|
||||
"NavigationUtils.h",
|
||||
"UserNavigationInvolvement.h",
|
||||
]
|
||||
|
||||
@@ -23,7 +22,6 @@ UNIFIED_SOURCES += [
|
||||
"NavigationDestination.cpp",
|
||||
"NavigationHistoryEntry.cpp",
|
||||
"NavigationTransition.cpp",
|
||||
"NavigationUtils.cpp",
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = "xul"
|
||||
|
||||
@@ -42,7 +42,6 @@
|
||||
#include "nsDebug.h"
|
||||
#include "nsGlobalWindowInner.h"
|
||||
#include "nsIScriptObjectPrincipal.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsJSEnvironment.h"
|
||||
#include "nsJSPrincipals.h"
|
||||
#include "nsJSUtils.h"
|
||||
@@ -219,119 +218,6 @@ already_AddRefed<Promise> Promise::All(
|
||||
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,
|
||||
ErrorResult& aRv) {
|
||||
if (!aSettlingPromise) {
|
||||
@@ -504,11 +390,11 @@ namespace {
|
||||
class PromiseNativeHandlerShim final : public PromiseNativeHandler {
|
||||
RefPtr<PromiseNativeHandler> mInner;
|
||||
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
|
||||
enum InnerState {
|
||||
NotCleared,
|
||||
ClearedFromResolve,
|
||||
ClearedFromReject,
|
||||
ClearedFromCC,
|
||||
enum InnerState{
|
||||
NotCleared,
|
||||
ClearedFromResolve,
|
||||
ClearedFromReject,
|
||||
ClearedFromCC,
|
||||
};
|
||||
InnerState mState = NotCleared;
|
||||
#endif
|
||||
|
||||
@@ -261,12 +261,6 @@ class Promise : public SupportsWeakPtr {
|
||||
PropagateUserInteraction aPropagateUserInteraction =
|
||||
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>
|
||||
using IsHandlerCallback =
|
||||
std::is_same<already_AddRefed<Promise>,
|
||||
|
||||
@@ -21,7 +21,6 @@ interface NavigateEvent : Event {
|
||||
readonly attribute DOMString? downloadRequest;
|
||||
readonly attribute any info;
|
||||
readonly attribute boolean hasUAVisualTransition;
|
||||
readonly attribute Element? sourceElement;
|
||||
|
||||
[Throws] undefined intercept(optional NavigationInterceptOptions options = {});
|
||||
[Throws] undefined scroll();
|
||||
@@ -38,7 +37,6 @@ dictionary NavigateEventInit : EventInit {
|
||||
DOMString? downloadRequest = null;
|
||||
any info;
|
||||
boolean hasUAVisualTransition = false;
|
||||
Element? sourceElement = null;
|
||||
};
|
||||
|
||||
dictionary NavigationInterceptOptions {
|
||||
|
||||
@@ -65,7 +65,6 @@ EXPORTS += [
|
||||
"nsCOMPtr.h",
|
||||
"nscore.h",
|
||||
"nsCRTGlue.h",
|
||||
"nsCycleCollectionContainerParticipant.h",
|
||||
"nsCycleCollectionNoteChild.h",
|
||||
"nsCycleCollectionNoteRootCallback.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
|
||||
* NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED.
|
||||
*/
|
||||
#define NS_XPCOMCYCLECOLLECTIONPARTICIPANT_IID \
|
||||
{0xc61eac14, 0x5f7a, 0x4481, {0x96, 0x5e, 0x7e, 0xaa, 0x6e, 0xff, 0xa8, 0x5e}}
|
||||
#define NS_XPCOMCYCLECOLLECTIONPARTICIPANT_IID \
|
||||
{ \
|
||||
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
|
||||
@@ -31,8 +35,12 @@
|
||||
* to have separate nsCycleCollectionParticipant's for tearoffs or aggregated
|
||||
* classes.
|
||||
*/
|
||||
#define NS_CYCLECOLLECTIONISUPPORTS_IID \
|
||||
{0xc61eac14, 0x5f7a, 0x4481, {0x96, 0x5e, 0x7e, 0xaa, 0x6e, 0xff, 0xa8, 0x5f}}
|
||||
#define NS_CYCLECOLLECTIONISUPPORTS_IID \
|
||||
{ \
|
||||
0xc61eac14, 0x5f7a, 0x4481, { \
|
||||
0x96, 0x5e, 0x7e, 0xaa, 0x6e, 0xff, 0xa8, 0x5f \
|
||||
} \
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
enum class CCReason : uint8_t {
|
||||
@@ -190,109 +198,6 @@ struct TraceCallbackFunc : public TraceCallbacks {
|
||||
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
|
||||
*/
|
||||
@@ -715,7 +620,7 @@ T* DowncastCCParticipant(void* aPtr) {
|
||||
NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::Trace(s, aCallbacks, aClosure);
|
||||
|
||||
#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
|
||||
// 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",
|
||||
"ArrayIterator.h",
|
||||
"AtomArray.h",
|
||||
"CycleCollectedUniquePtr.h",
|
||||
"Dafsa.h",
|
||||
"IncrementalTokenizer.h",
|
||||
"Observer.h",
|
||||
|
||||
@@ -288,12 +288,6 @@ class nsBaseHashtable
|
||||
const nsBaseHashtable<KC, DT, UDT, C>&, const char* aName,
|
||||
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:
|
||||
typedef typename KeyClass::KeyType KeyType;
|
||||
typedef nsBaseHashtableET<KeyClass, DataType> EntryType;
|
||||
@@ -1063,41 +1057,4 @@ inline void ImplCycleCollectionTraverse(
|
||||
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__
|
||||
|
||||
@@ -21,3 +21,7 @@ bool IsTwiceTheRequiredBytesRepresentableAsUint32(size_t aCapacity,
|
||||
using mozilla::CheckedUint32;
|
||||
return ((CheckedUint32(aCapacity) * aElemSize) * 2).isValid();
|
||||
}
|
||||
|
||||
void ::detail::SetCycleCollectionArrayFlag(uint32_t& aFlags) {
|
||||
aFlags |= CycleCollectionEdgeNameArrayFlag;
|
||||
}
|
||||
|
||||
@@ -43,7 +43,6 @@ class Heap;
|
||||
} /* namespace JS */
|
||||
|
||||
class nsCycleCollectionTraversalCallback;
|
||||
struct TraceCallbacks;
|
||||
class nsRegion;
|
||||
|
||||
namespace mozilla::a11y {
|
||||
@@ -2686,11 +2685,21 @@ inline void ImplCycleCollectionUnlink(nsTArray_Impl<E, Alloc>& aField) {
|
||||
aField.Clear();
|
||||
}
|
||||
|
||||
template <typename E, typename Alloc, typename Callback>
|
||||
inline void ImplCycleCollectionIndexedContainer(nsTArray_Impl<E, Alloc>& aField,
|
||||
Callback&& aCallback) {
|
||||
for (auto& value : aField) {
|
||||
aCallback(value);
|
||||
namespace detail {
|
||||
// This is defined in the cpp file to avoid including
|
||||
// nsCycleCollectionNoteChild.h in this header file.
|
||||
void SetCycleCollectionArrayFlag(uint32_t& aFlags);
|
||||
} // 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 "nsPointerHashKeys.h"
|
||||
#include "nsTArrayForwardDeclare.h"
|
||||
#include "nsCycleCollectionContainerParticipant.h"
|
||||
|
||||
template <class EntryType>
|
||||
class nsTHashtable;
|
||||
@@ -431,8 +430,8 @@ class MOZ_NEEDS_NO_VTABLE_TYPE nsTHashtable {
|
||||
};
|
||||
|
||||
template <class F>
|
||||
auto WithEntryHandle(KeyType aKey, F&& aFunc)
|
||||
-> std::invoke_result_t<F, EntryHandle&&> {
|
||||
auto WithEntryHandle(KeyType aKey,
|
||||
F&& aFunc) -> std::invoke_result_t<F, EntryHandle&&> {
|
||||
return this->mTable.WithEntryHandle(
|
||||
EntryType::KeyToPointer(aKey),
|
||||
[&aKey, &aFunc](auto entryHandle) -> decltype(auto) {
|
||||
@@ -723,21 +722,20 @@ void nsTHashtable<EntryType>::s_ClearEntry(PLDHashTable* aTable,
|
||||
}
|
||||
|
||||
class nsCycleCollectionTraversalCallback;
|
||||
struct TraceCallbacks;
|
||||
|
||||
template <class EntryType>
|
||||
inline void ImplCycleCollectionUnlink(nsTHashtable<EntryType>& aField) {
|
||||
aField.Clear();
|
||||
}
|
||||
|
||||
// Function template constrained to types that are (possibly const)
|
||||
// nsTHashtable.
|
||||
template <typename Container, typename Callback,
|
||||
EnableCycleCollectionIf<Container, nsTHashtable> = nullptr>
|
||||
inline void ImplCycleCollectionContainer(Container&& aField,
|
||||
Callback&& aCallback) {
|
||||
for (auto& entry : aField) {
|
||||
aCallback(entry);
|
||||
template <class EntryType>
|
||||
inline void ImplCycleCollectionTraverse(
|
||||
nsCycleCollectionTraversalCallback& aCallback,
|
||||
const nsTHashtable<EntryType>& aField, const char* aName,
|
||||
uint32_t aFlags = 0) {
|
||||
for (auto iter = aField.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
const EntryType* entry = iter.Get();
|
||||
ImplCycleCollectionTraverse(aCallback, *entry, aName, aFlags);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -878,8 +876,8 @@ class nsTHashtable<nsPtrHashKey<T>>
|
||||
};
|
||||
|
||||
template <class F>
|
||||
auto WithEntryHandle(KeyType aKey, F aFunc)
|
||||
-> std::invoke_result_t<F, EntryHandle&&> {
|
||||
auto WithEntryHandle(KeyType aKey,
|
||||
F aFunc) -> std::invoke_result_t<F, EntryHandle&&> {
|
||||
return Base::WithEntryHandle(aKey, [&aFunc](auto entryHandle) {
|
||||
return aFunc(EntryHandle{std::move(entryHandle)});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user