Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 111 additions & 37 deletions source
Original file line number Diff line number Diff line change
Expand Up @@ -11480,6 +11480,78 @@ partial interface <dfn id="document" data-lt="">Document</dfn> {
readonly attribute <span>Element</span>? <span data-x="dom-documentorshadowroot-activeElement">activeElement</span>;
};</code></pre>

<h4>Ancestor origins</h4>

<div algorithm>
<p>A <code>Document</code> object has an associated <dfn export for="Document"
data-x="concept-document-internal-ancestor-origin-objects-list">internal ancestor origin objects
list</dfn>, initially « ».</p>

<p>The <dfn>internal ancestor origin objects list creation steps</dfn> given a
<code>Document</code> object <var>innerDoc</var> are:</p>

<ol>
<li><p>Let <var>output</var> be « ».</p></li>

<li><p>Let <var>parentDoc</var> be <var>innerDoc</var>'s <span
data-x="doc-container-document">container document</span>.</p></li>

<li><p>If <var>parentDoc</var> is null, then return <var>output</var>.</p></li>

<li><p><span>Assert</span>: <var>parentDoc</var> is <span>fully active</span>.</p></li>

<li><p>Let <var>ancestorOrigins</var> be <var>parentDoc</var>'s <span
data-x="concept-document-internal-ancestor-origin-objects-list">internal ancestor origin objects
list</span>.</p></li>

<li><p><span data-x="list append">Append</span> <var>parentDoc</var>'s <span
data-x="concept-document-origin">origin</span> to <var>output</var>.</p></li>

<li>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we could use https://infra.spec.whatwg.org/#list-extend, instead of iterating manually?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#11560 would need to change back to iterating the list though.

<p><span data-x="list iterate">For each</span> <var>ancestorOrigin</var> of
<var>ancestorOrigins</var>:</p>

<ol>
<li><p><span data-x="list append">Append</span> <var>ancestorOrigin</var> to
<var>output</var>.</p></li>
</ol>
</li>

<li><p>Return <var>output</var>.</p></li>
</ol>
</div>

<div algorithm>
<p>A <code>Document</code> object has an associated <dfn export for="Document"
data-x="concept-document-ancestor-origins-list">ancestor origins list</dfn>, initially a
<code>DOMStringList</code> object whose associated list is an empty <span>list</span>.</p>

<p>The <dfn>ancestor origins list creation steps</dfn> given a <code>Document</code> object
<var>document</var> are:</p>

<ol>
<li><p>Let <var>ancestorOrigins</var> be <var>document</var>'s <span
data-x="concept-document-internal-ancestor-origin-objects-list">internal ancestor origin objects
list</span>.</p></li>

<li><p>Let <var>output</var> be « ».</p></li>

<li>
<p><span data-x="list iterate">For each</span> <var>origin</var> of
<var>ancestorOrigins</var>:</p>

<ol>
<li><p><span data-x="list append">Append</span> the <span data-x="serialization of an
origin">serialization</span> of <var>origin</Var> to <var>output</var>.</p></li>
</ol>
</li>

<li><p>Return a new <code>DOMStringList</code> object whose associated list is
<var>output</var>.</p></li>
</ol>
</div>


<h4><dfn>Resource metadata management</dfn></h4>

<dl class="domintro">
Expand Down Expand Up @@ -96799,7 +96871,7 @@ interface <dfn interface>Location</dfn> { // but see also <a href="#the-location
[<span>LegacyUnforgeable</span>] undefined <span data-x="dom-location-replace">replace</span>(USVString url);
[<span>LegacyUnforgeable</span>] undefined <span data-x="dom-location-reload">reload</span>();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not returning the same object each time from a getter seems very surprising. Why would we want that? You don't want obj.x !== obj.x (there's a rule for this in the design principles as well).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Step 1 says to return a an empty DOMStringList if this's relevant Document is null.

Since the relevant Document can change over time, I think we can't return the same object always. So options are:

  1. Cache whatever was returned the first time the getter is called. (This matches WebKit.)
  2. Return a new object every time. (Gecko, Chromium.)
  3. Maybe throw an InvalidStateError in step 1?

The current spec is wrong since it says SameObject but then in step 1 sometimes returns an empty list (not a DOMStringList).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't have to return the same object always to not violate obj.x !== obj.x. Caching or throwing would work. Caching is probably the most compatible. SameObject is indeed wrong if the returned value has to change at certain points in time though.

Can you observe the object changing in WebKit? Maybe with initial about:blank?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, for example removing an iframe. But since WebKit caches the return value from the first access, it's different if you call the getter first before or after the iframe is removed.

https://software.hixie.ch/utilities/js/live-dom-viewer/saved/14480

Maybe option 4 is to create an empty DOMStringList in step 1 but cache it, so there can be two separate objects returned.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if you navigate an iframe its Location object stays the same, but the relevant Document changes as well. (Even across a cross-origin navigation I'm pretty sure as you're holding a proxy object, essentially.) We probably want to invalidate the list each time the relevant Document changes. Not a 100% sure how to best specify this though.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't want to change the semantics of getters so drastically I think. We ought to know when the associated document changes. We'll just have to make sure it all adds up I think.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I couldn't figure out a case where the relevant Document changes from null to non-null. Is it possible?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I couldn't figure out a case where the relevant Document changes from null to non-null. Is it possible?

No it is not.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably explain in a comment or some such about why this works then as it's not entirely obvious and it's a bit of a hack.

(If we had a proper algorithmic flow here we'd be creating the object whenever we set the Location object's associated document to a new value.)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note added in a9319d4


[<span>LegacyUnforgeable</span>, SameObject] readonly attribute <span>DOMStringList</span> <span data-x="dom-location-ancestorOrigins">ancestorOrigins</span>;
[<span>LegacyUnforgeable</span>] readonly attribute <span>DOMStringList</span> <span data-x="dom-location-ancestorOrigins">ancestorOrigins</span>;
};</code></pre>

<dl class="domintro">
Expand Down Expand Up @@ -96902,38 +96974,6 @@ interface <dfn interface>Location</dfn> { // but see also <a href="#the-location
<code>Document</code></span> is non-null, and <code>about:blank</code> otherwise.</p>
</div>

<div algorithm>
<p>A <code>Location</code> object has an associated <dfn
data-x="concept-location-ancestor-origins-list">ancestor origins list</dfn>. When a
<code>Location</code> object is created, its <span
data-x="concept-location-ancestor-origins-list">ancestor origins list</span> must be set to a
<code>DOMStringList</code> object whose associated list is the <span>list</span> of strings that
the following steps would produce:</p>

<ol>
<li><p>Let <var>output</var> be a new <span>list</span> of strings.</p></li>

<li><p>Let <var>current</var> be the <code>Location</code> object's <span>relevant
<code>Document</code></span>.</p></li>

<li>
<p>While <var>current</var>'s <span data-x="doc-container-document">container document</span>
is non-null:</p>

<ol>
<li><p>Set <var>current</var> to <var>current</var>'s <span
data-x="doc-container-document">container document</span>.</p></li>

<li><p><span data-x="list append">Append</span> the <span data-x="serialization of an
origin">serialization</span> of <var>current</var>'s <span
data-x="concept-document-origin">origin</span> to <var>output</var>.</p></li>
</ol>
</li>

<li><p>Return <var>output</var>.</p></li>
</ol>
</div>

<div algorithm>
<p>To <dfn><code>Location</code>-object navigate</dfn> a <code>Location</code> object
<var>location</var> to a <span>URL</span> <var>url</var>, optionally given a <code
Expand Down Expand Up @@ -97478,22 +97518,32 @@ interface <dfn interface>Location</dfn> { // but see also <a href="#the-location

<hr>

<p>A <code>Location</code> object has an associated <dfn export for="Location"
data-x="concept-location-empty-domstringlist">empty <code>DOMStringList</code></dfn> which is a
<code>DOMStringList</code> object whose associated list is an empty <span>list</span>.</p>

<p class="note">This object cannot carry state across navigations because it is only returned
when there is no <span>relevant <code>Document</code></span>, in which case it's not possible to
navigate, and it's not possible to return to a non-null <span>relevant
<code>Document</code></span>.</p>

<div algorithm>
<p>The <dfn attribute for="Location"><code
data-x="dom-location-ancestorOrigins">ancestorOrigins</code></dfn> getter steps are:</p>

<ol>
<li><p>If <span>this</span>'s <span>relevant <code>Document</code></span> is null, then return
an empty <span>list</span>.</p></li>
<span>this</span>'s <span data-x="concept-location-empty-domstringlist">empty
<code>DOMStringList</code></span>.</p></li>

<li><p>If <span>this</span>'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>, then throw a
<span>"<code>SecurityError</code>"</span> <code>DOMException</code>.</p></li>

<li><p>Otherwise, return <span>this</span>'s <span
data-x="concept-location-ancestor-origins-list">ancestor origins list</span>.</p></li>
<li><p>Otherwise, return <span>this</span>'s <span>relevant <code>Document</code></span>'s <span
data-x="concept-document-ancestor-origins-list">ancestor origins list</span>.</p></li>
</ol>
</div>

Expand Down Expand Up @@ -104488,6 +104538,21 @@ interface <dfn interface>NotRestoredReasons</dfn> {
</dl>
</li>

<li>
<p>If <var>embedder</var> is non-null, then:</p>

<ol>
<li><p>Set <var>document</var>'s <span
data-x="concept-document-internal-ancestor-origin-objects-list">internal ancestor origin
objects list</span> to the result of running the <span>internal ancestor origin objects list
creation steps</span> given <var>document</var>.</p></li>

<li><p>Set <var>document</var>'s <span data-x="concept-document-ancestor-origins-list">ancestor
origins list</span> to the result of running the <span>ancestor origins list creation
steps</span> given <var>document</var>.</p></li>
</ol>
</li>

<li>
<p>If <var>creator</var> is non-null, then:</p>

Expand Down Expand Up @@ -111176,7 +111241,7 @@ location.href = '#foo';</code></pre>
<p class="note">This means that both the <span data-x="is initial about:blank">initial
<code>about:blank</code></span> <code>Document</code>, and the new <code>Document</code> that
is about to be created, will share the same <code>Window</code> object.</p>
</li>
</li>

<li id="create-new-agent-and-window">
<p>Otherwise:</p>
Expand Down Expand Up @@ -111316,6 +111381,15 @@ location.href = '#foo';</code></pre>
<li><p>Set <var>window</var>'s <span data-x="concept-document-window">associated
<code>Document</code></span> to <var>document</var>.</p></li>

<li><p>Set <var>document</var>'s <span
data-x="concept-document-internal-ancestor-origin-objects-list">internal ancestor origin objects
list</span> to the result of running the <span>internal ancestor origin objects list creation
steps</span> given <var>document</var>.</p></li>

<li><p>Set <var>document</var>'s <span data-x="concept-document-ancestor-origins-list">ancestor
origins list</span> to the result of running the <span>ancestor origins list creation
steps</span> given <var>document</var>.</p></li>

<li><p><span>Run CSP initialization for a <code data-x="">Document</code></span> given
<var>document</var>. <ref>CSP</ref></p>

Expand Down