summaryrefslogtreecommitdiffstats
path: root/dom/base
diff options
context:
space:
mode:
authorwolfbeast <mcwerewolf@wolfbeast.com>2019-12-22 19:57:30 +0100
committerwolfbeast <mcwerewolf@wolfbeast.com>2019-12-22 19:57:30 +0100
commitdfa7af70ce4cd662add88f5e2a881e1054d91ef2 (patch)
treecde1088a23371942359540a12a0c70bf8a85ac50 /dom/base
parent54091ecab46c93c2e1b2c689e9179a980beaabe6 (diff)
downloadUXP-dfa7af70ce4cd662add88f5e2a881e1054d91ef2.tar
UXP-dfa7af70ce4cd662add88f5e2a881e1054d91ef2.tar.gz
UXP-dfa7af70ce4cd662add88f5e2a881e1054d91ef2.tar.lz
UXP-dfa7af70ce4cd662add88f5e2a881e1054d91ef2.tar.xz
UXP-dfa7af70ce4cd662add88f5e2a881e1054d91ef2.zip
Issue #1118 - Part 5: Change the way document.open() works
This changes the work we do for document.open() in the following ways: - We no longer create a new Window when doing document.open(). We use the same Window but remove all the event listeners on the existing DOM tree and Window before removing the document's existing children to provide a clean slate document to use for .write(). - We no longer create a session history entry (previously would be a wyciwyg URI). We now replace the current one, effectively losing the entry for the original document. - We now support document.open() on windowless documents.
Diffstat (limited to 'dom/base')
-rw-r--r--dom/base/SimpleTreeIterator.h71
-rwxr-xr-xdom/base/moz.build1
-rw-r--r--dom/base/nsDocument.cpp50
-rw-r--r--dom/base/nsDocument.h33
-rw-r--r--dom/base/nsIDocument.h15
5 files changed, 147 insertions, 23 deletions
diff --git a/dom/base/SimpleTreeIterator.h b/dom/base/SimpleTreeIterator.h
new file mode 100644
index 000000000..7ca504082
--- /dev/null
+++ b/dom/base/SimpleTreeIterator.h
@@ -0,0 +1,71 @@
+/* -*- 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/. */
+
+/**
+ * This is a light-weight tree iterator for `for` loops when full iterator
+ * functionality isn't required.
+ */
+
+#ifndef mozilla_dom_SimpleTreeIterator_h
+#define mozilla_dom_SimpleTreeIterator_h
+
+#include "nsINode.h"
+#include "nsTArray.h"
+#include "mozilla/dom/Element.h"
+
+namespace mozilla {
+namespace dom {
+
+class SimpleTreeIterator {
+public:
+ /**
+ * Initialize an iterator with aRoot. After that it can be iterated with a
+ * range-based for loop. At the moment, that's the only supported form of use
+ * for this iterator.
+ */
+ explicit SimpleTreeIterator(nsINode& aRoot)
+ : mCurrent(&aRoot)
+ {
+ mTree.AppendElement(&aRoot);
+ }
+
+ // Basic support for range-based for loops.
+ // This will modify the iterator as it goes.
+ SimpleTreeIterator& begin() { return *this; }
+
+ SimpleTreeIterator end() { return SimpleTreeIterator(); }
+
+ bool operator!=(const SimpleTreeIterator& aOther) {
+ return mCurrent != aOther.mCurrent;
+ }
+
+ void operator++() { Next(); }
+
+ nsINode* operator*() { return mCurrent; }
+
+private:
+ // Constructor used only for end() to represent a drained iterator.
+ SimpleTreeIterator()
+ : mCurrent(nullptr)
+ {}
+
+ void Next() {
+ MOZ_ASSERT(mCurrent, "Don't call Next() when we have no current node");
+
+ mCurrent = mCurrent->GetNextNode(mTree.LastElement());
+ }
+
+ // The current node.
+ nsINode* mCurrent;
+
+ // The DOM tree that we're inside of right now.
+ AutoTArray<nsINode*, 1> mTree;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_SimpleTreeIterator_h
diff --git a/dom/base/moz.build b/dom/base/moz.build
index ebb76d617..75ddefded 100755
--- a/dom/base/moz.build
+++ b/dom/base/moz.build
@@ -210,6 +210,7 @@ EXPORTS.mozilla.dom += [
'ScreenOrientation.h',
'ScriptSettings.h',
'ShadowRoot.h',
+ 'SimpleTreeIterator.h',
'StructuredCloneHolder.h',
'StructuredCloneTags.h',
'StyleSheetList.h',
diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp
index e2be6b664..0f663636f 100644
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -1968,22 +1968,10 @@ nsDocument::Reset(nsIChannel* aChannel, nsILoadGroup* aLoadGroup)
}
void
-nsDocument::ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup,
- nsIPrincipal* aPrincipal)
-{
- NS_PRECONDITION(aURI, "Null URI passed to ResetToURI");
-
- if (gDocumentLeakPRLog && MOZ_LOG_TEST(gDocumentLeakPRLog, LogLevel::Debug)) {
- PR_LogPrint("DOCUMENT %p ResetToURI %s", this,
- aURI->GetSpecOrDefault().get());
- }
-
- mSecurityInfo = nullptr;
-
- mDocumentLoadGroup = nullptr;
-
+nsDocument::DisconnectNodeTree() {
// Delete references to sub-documents and kill the subdocument map,
- // if any. It holds strong references
+ // if any. This is not strictly needed, but makes the node tree
+ // teardown a bit faster.
delete mSubDocuments;
mSubDocuments = nullptr;
@@ -2019,6 +2007,22 @@ nsDocument::ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup,
"After removing all children, there should be no root elem");
}
mInUnlinkOrDeletion = oldVal;
+}
+
+void
+nsDocument::ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup,
+ nsIPrincipal* aPrincipal)
+{
+ NS_PRECONDITION(aURI, "Null URI passed to ResetToURI");
+
+ if (gDocumentLeakPRLog && MOZ_LOG_TEST(gDocumentLeakPRLog, LogLevel::Debug)) {
+ PR_LogPrint("DOCUMENT %p ResetToURI %s", this,
+ aURI->GetSpecOrDefault().get());
+ }
+
+ mSecurityInfo = nullptr;
+
+ mDocumentLoadGroup = nullptr;
// Reset our stylesheets
ResetStylesheetsToURI(aURI);
@@ -2029,6 +2033,8 @@ nsDocument::ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup,
mListenerManager = nullptr;
}
+ DisconnectNodeTree();
+
// Release the stylesheets list.
mDOMStyleSheets = nullptr;
@@ -9077,7 +9083,8 @@ nsDocument::CloneDocHelper(nsDocument* clone) const
}
void
-nsDocument::SetReadyStateInternal(ReadyState rs)
+nsDocument::SetReadyStateInternal(ReadyState rs,
+ bool updateTimingInformation)
{
mReadyState = rs;
if (rs == READYSTATE_UNINITIALIZED) {
@@ -9086,7 +9093,12 @@ nsDocument::SetReadyStateInternal(ReadyState rs)
// transition undetectable by Web content.
return;
}
- if (mTiming) {
+
+ if (updateTimingInformation && READYSTATE_LOADING == rs) {
+ mLoadingTimeStamp = mozilla::TimeStamp::Now();
+ }
+
+ if (updateTimingInformation && mTiming) {
switch (rs) {
case READYSTATE_LOADING:
mTiming->NotifyDOMLoading(nsIDocument::GetDocumentURI());
@@ -9102,10 +9114,6 @@ nsDocument::SetReadyStateInternal(ReadyState rs)
break;
}
}
- // At the time of loading start, we don't have timing object, record time.
- if (READYSTATE_LOADING == rs) {
- mLoadingTimeStamp = mozilla::TimeStamp::Now();
- }
RefPtr<AsyncEventDispatcher> asyncDispatcher =
new AsyncEventDispatcher(this, NS_LITERAL_STRING("readystatechange"),
diff --git a/dom/base/nsDocument.h b/dom/base/nsDocument.h
index ac600eb43..c2b1d3cdb 100644
--- a/dom/base/nsDocument.h
+++ b/dom/base/nsDocument.h
@@ -704,7 +704,11 @@ public:
virtual void BeginLoad() override;
virtual void EndLoad() override;
- virtual void SetReadyStateInternal(ReadyState rs) override;
+ // Set the readystate of the document. If updateTimingInformation is true,
+ // this will record relevant timestamps in the document's performance timing.
+ // Some consumers like document.open() don't want to do that.
+ virtual void SetReadyStateInternal(ReadyState rs,
+ bool updateTimingInformation = true) override;
virtual void ContentStateChanged(nsIContent* aContent,
mozilla::EventStates aStateMask)
@@ -916,6 +920,14 @@ public:
UpdateFrameRequestCallbackSchedulingState();
}
+ void SetLoadEventFiring(bool aFiring) override { mLoadEventFiring = aFiring; }
+
+ bool SkipLoadEventAfterClose() override {
+ bool skip = mSkipLoadEventAfterClose;
+ mSkipLoadEventAfterClose = false;
+ return skip;
+ }
+
virtual nsIDocument* GetTemplateContentsOwner() override;
NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsDocument,
@@ -1255,6 +1267,11 @@ protected:
*/
Element* GetTitleElement();
+ /**
+ * Perform tree disconnection needed by ResetToURI and document.open()
+ */
+ void DisconnectNodeTree();
+
public:
// Get our title
virtual void GetTitle(nsString& aTitle) override;
@@ -1458,6 +1475,20 @@ public:
// additional sheets and sheets from the nsStyleSheetService.
bool mStyleSetFilled:1;
+ // The HTML spec has a "iframe load in progress" flag, but that doesn't seem
+ // to have the right semantics. See <https://github.com/whatwg/html/issues/4292>.
+ // What we have instead is a flag that is set while the window's 'load' event is
+ // firing if this document is the window's document.
+ bool mLoadEventFiring : 1;
+
+ // The HTML spec has a "mute iframe load" flag, but that doesn't seem to have
+ // the right semantics. See <https://github.com/whatwg/html/issues/4292>.
+ // What we have instead is a flag that is set if completion of our document
+ // via document.close() should skip firing the load event. Note that this
+ // flag is only relevant for HTML documents, but lives here for reasons that
+ // are documented above on SkipLoadEventAfterClose().
+ bool mSkipLoadEventAfterClose : 1;
+
uint8_t mPendingFullscreenRequests;
uint8_t mXMLDeclarationBits;
diff --git a/dom/base/nsIDocument.h b/dom/base/nsIDocument.h
index d76a12d71..e2b34f7e3 100644
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -1448,7 +1448,7 @@ public:
virtual void EndLoad() = 0;
enum ReadyState { READYSTATE_UNINITIALIZED = 0, READYSTATE_LOADING = 1, READYSTATE_INTERACTIVE = 3, READYSTATE_COMPLETE = 4};
- virtual void SetReadyStateInternal(ReadyState rs) = 0;
+ virtual void SetReadyStateInternal(ReadyState rs, bool updateTimingInformation = true) = 0;
ReadyState GetReadyStateEnum()
{
return mReadyState;
@@ -2187,6 +2187,19 @@ public:
}
/**
+ * Flag whether we're about to fire the window's load event for this document.
+ */
+ virtual void SetLoadEventFiring(bool aFiring) = 0;
+
+ /**
+ * Test whether we should be firing a load event for this document after a
+ * document.close().
+ * This method should only be called at the point when the load event is about
+ * to be fired, since it resets `skip`.
+ */
+ virtual bool SkipLoadEventAfterClose() = 0;
+
+ /**
* Returns the template content owner document that owns the content of
* HTMLTemplateElement.
*/