Skip to content

Commit

Permalink
Allow document.open() to desync session history and document URLs
Browse files Browse the repository at this point in the history
Closes #6556. In particular, reverts document.open() to only update the document's URL, and not the session history entry's URL, like it did before ae7cf0c. Now that they can mismatch, we need to audit the cases where this might be important, which leads to the following changes:

* Changes location.reload() to reload the current session history entry's URL, instead of the document's URL. This ensures that post-document.open() reload behavior is aligned with WebKit and Gecko, as tested by https://wpt.fyi/results/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/reload.window.html.

* Changes history.pushState()/history.replaceState() with no URL argument to default to the document's URL, instead of the current session history's URL. This ensures that post-document.open() pushState()/replaceState() behavior is aligned with all engines, as tested by web-platform-tests/wpt#28826.

This also modernizes and makes a bit more precise the location.reload() method steps. The user-initiated reload steps remain vague; #6600 will tackle those.
  • Loading branch information
domenic committed May 4, 2021
1 parent 92bf07c commit 472a856
Showing 1 changed file with 74 additions and 39 deletions.
113 changes: 74 additions & 39 deletions source
Original file line number Diff line number Diff line change
Expand Up @@ -83619,7 +83619,16 @@ interface <dfn>BarProp</dfn> {
data-x="struct item">items</span>:</p>

<ul>
<li><p><dfn data-x="she-url">URL</dfn>, a <span>URL</span></p></li>
<li>
<p><dfn data-x="she-url">URL</dfn>, a <span>URL</span></p>

<p class="warning">This <a href="#warning-document-open-url-mismatch">doesn't necessarily
match</a> the <span data-x="she-document">document</span>'s <span
data-x="concept-document-URL">URL</span>. In general, to find the "current URL" prefer using the
appropriate <code>Document</code>'s <span data-x="concept-document-URL">URL</span>; a
<span>session history entry</span>'s <span data-x="she-url">URL</span> is only to be used for
session history traversal and restoration.</p>
</li>

<li>
<p><dfn data-x="she-document">document</dfn>, a <code>Document</code> or null</p>
Expand Down Expand Up @@ -84178,8 +84187,8 @@ interface <dfn>History</dfn> {
<li><p>Let <var>serializedData</var> be
<span>StructuredSerializeForStorage</span>(<var>data</var>). Rethrow any exceptions.</p></li>

<li><p>Let <var>newURL</var> be the <span>session history</span>'s <span>current entry</span>'s
<span data-x="she-url">URL</span>.</p></li>
<li><p>Let <var>newURL</var> be <var>document</var>'s <span
data-x="concept-document-URL">URL</span>.</p></li>

<li>
<p>If <var>url</var> is not null, then:</p>
Expand Down Expand Up @@ -85086,52 +85095,56 @@ interface <dfn>Location</dfn> { // but see also <a href="#the-location-interface
<p class="note">The <code data-x="dom-location-replace">replace()</code> method intentionally has
no security check.</p>

<p>When the <dfn method for="Location"><code data-x="dom-location-reload">reload()</code></dfn>
method is invoked, the user agent must run the appropriate steps from the following list:</p>

<dl class="switch">
<dt>If this <code>Location</code> object's <span>relevant <code>Document</code></span> is
null</dt>

<dd><p>Return.</p></dd>
<p>The <dfn method for="Location"><code data-x="dom-location-reload">reload()</code></dfn> method
steps are:</p>

<dt>If this <code>Location</code> object's <span>relevant <code>Document</code></span>'s <span
data-x="concept-document-origin">origin</span> is not <span>same origin-domain</span> with the
<span>entry settings object</span>'s <span
data-x="concept-settings-object-origin">origin</span></dt>
<ol>
<li><p>Let <var>document</var> be <span>this</span>'s <span>relevant
<code>Document</code></span>.</p></li>

<dd><p>Throw a <span>"<code>SecurityError</code>"</span> <code>DOMException</code>.</p></dd>
<li><p>Let <var>browsingContext</var> be <var>document</var>'s <span
data-x="concept-document-bc">browsing context</span>.</p></li>

<dt>If the currently executing <span data-x="concept-task">task</span> is the dispatch of a <code
data-x="event-resize">resize</code> event in response to the user resizing the <span>browsing
context</span></dt>
<li><p>If <var>document</var> is null, then return.</p></li>

<dd><p>Repaint the <span>browsing context</span> and return.</p></dd> <!-- this
theoretically would have no effect but in practice can be useful to work around rendering bugs.
-->
<li><p>If <var>document</var>'s <span data-x="concept-document-origin">origin</span> is not
<span>same origin-domain</span> with the <span>entry settings object</span>'s <span
data-x="concept-settings-object-origin">origin</span>, then throw a
<span>"<code>SecurityError</code>"</span> <code>DOMException</code>.</p></li>

<dt>If the <span>browsing context</span>'s <span>active document</span> is <span>an
<code>iframe</code> <code data-x="attr-iframe-srcdoc">srcdoc</code> document</span></dt>
<li><p>If <span>this</span>'s <span>relevant agent</span>'s <span
data-x="concept-agent-event-loop">event loop</span>'s <span>currently running task</span> is the
dispatch of a <code data-x="event-resize">resize</code> event in response to the user resizing
the <span>browsing context</span>, then repaint the <span>browsing context</span> and
return.</p></li>
<!-- this theoretically would have no effect but in practice can be useful to work around
rendering bugs. -->

<dd><p><span data-x="process the iframe attributes">Reprocess the <code>iframe</code>
attributes</span> of the <span>browsing context</span>'s <span
data-x="bc-container">container</span>.</p></dd>
<li><p>If <var>document</var> is <span>an <code>iframe</code> <code
data-x="attr-iframe-srcdoc">srcdoc</code> document</span>, then <span data-x="process the iframe
attributes">reprocess the <code>iframe</code> attributes</span> of <var>browsingContext</var>'s
<span data-x="bc-container">container</span> and return.</p></li>

<dt>Otherwise</dt>
<li>
<p><span>Navigate</span><!--DONAV location.reload()--> <var>browsingContext</var> to
<var>browsingContext</var>'s <span>session history</span>'s <span>current entry</span>'s <span
data-x="she-url">URL</span>, with <var><span>exceptionsEnabled</span></var> set to true, <var
data-x="navigation-hh">historyHandling</var> set to "<code data-x="hh-reload">reload</code>",
and the <span>source browsing context</span> set to <var>browsingContext</var>.</p>

<dd><p><span>Navigate</span><!--DONAV location.reload()--> the <span>browsing context</span> to
this <code>Location</code> object's <span>relevant <code>Document</code></span>'s <span
data-x="concept-document-url">URL</span>, with <var><span>exceptionsEnabled</span></var> set to
true, <var data-x="navigation-hh">historyHandling</var> set to "<code
data-x="hh-reload">reload</code>", and the <span>source browsing context</span> set to the
<span>browsing context</span> being navigated.</p></dd>
<p class="note">This is different than navigating to <var>document</var>'s <span
data-x="concept-document-url">URL</span>, due to the potential for <a
href="#warning-document-open-url-mismatch">mismatches caused by <code
data-x="dom-document-open">document.open()</code></a>.</p>

<!-- It appears that document.reload() always uses GET and does not, e.g., re-POST. Thus the
difference between using the document's URL here, and "the same resource as that Document" below
in the user-triggered reload section. -->
<!-- It appears that document.reload() always uses GET and does not, e.g., re-POST. Thus the
difference between using the document's URL here, and "the same resource as that Document" below
in the user-triggered reload section. -->

<!-- https://software.hixie.ch/utilities/js/live-dom-viewer/?saved=141 defends the source browsing context claim; submit, eval document.referrer, reload, eval document.referrer. -->
</dl>
<!-- https://software.hixie.ch/utilities/js/live-dom-viewer/?saved=141 defends the source
browsing context claim; submit, eval document.referrer, reload, eval document.referrer. -->
</li>
</ol>

<p>When a user requests that the <span>active document</span> of a <span>browsing context</span>
be reloaded through a user interface element, the user agent should <span>navigate</span><!--DONAV
Expand Down Expand Up @@ -94075,6 +94088,28 @@ document.body.appendChild(frame)</code></pre>
<li><p>If <var>entryDocument</var> is not <var>document</var>, then set <var>newURL</var>'s
<span data-x="concept-url-fragment">fragment</span> to null.</p></li>

<li>
<p>Set <var>document</var>'s <span data-x="concept-document-url">URL</span> to
<var>newURL</var>.</p>

<div class="note">
<p>The main purpose of this step is to allow code such as the following:</p>

<pre><code class="js">const w = window.open();
w.document.open();
w.document.write("&lt;img src='image.png'>");</code></pre>

<p>to resolve the <code data-x="">image.png</code> URL relative to the caller, instead of
relative to <code>about:blank</code>.</p>
</div>

<p class="warning" id="warning-document-open-url-mismatch">This can cause
<var>document</var>'s <span data-x="concept-document-url">URL</span> to mismatch its
corresponding <span>session history entry</span>'s <span data-x="she-url">URL</span>. This
mismatch is required for web compatibility; see <a
href="https://github.com/whatwg/html/issues/6556">issue #6556</a>.</p>
</li>

<li><p>Run the <span>URL and history update steps</span> with <var>document</var> and
<var>newURL</var>.</p></li>
</ol>
Expand Down

0 comments on commit 472a856

Please sign in to comment.