-
Notifications
You must be signed in to change notification settings - Fork 66
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tie BC creation to availability of a valid src + BC connectedness. #138
Conversation
Hmm, on further thought, what should happen if you set onportalactivate = e => {
let portal = e.adoptPredecessor();
portal.src = 'https://somewhere.else/';
/* ... */
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I agree that the portal element with a portal browsing context, but not browsing context connected is a bit weird, but I also think it should navigate. Other than that LGTM.
Doing some more edge-case thinking here. What about this: onportalactivate = e => {
let portal = e.adoptPredecessor();
// Does this drop the existing BC?
portal.src = '';
// If so, does this recreate it, or did the above forfeit the special status?
portal.src = 'https://somewhere.else/';
} I'm leaning toward making the concept of specially-extended lifetime for the result of I've been avoiding it because it's kind of indirect, but maybe it's semantically nicer. Something like:
Plus wording to give an additional reason, say This would imply that for the duration of the WDYT (before I go to the effort of making such changes)? @domenic might also want to comment since I'm kinda proposing to make this more complicated in the name of Internal Consistency™. |
I'd argue that yes, this does drop the BC.
No, because at this point the portal isn't BC-connected. The special status is only achievable by calling the adoptPredecessor API, once it's dropped, it's no possible to get it back.
Overall, I think this edge case is so unlikely that it is not worth to overcomplicate the spec to accommodate it in a nicer way. I think it's reasonable to just say that the only way for the document to create the portal browsing context is by appending it to the dom and setting the source.
I'd also like to see @domenic's opinion here, but I'd prefer to keep it simple unless there's an actual use-case that would be solved by this. In fact, even if we left it unspecified, it probably still wouldn't matter, since if implementations disagree on what to do when setting the src immediately after adopting wouldn't be an issue. |
I would definitely like to not leave it unspecified; I think there's no reason not to want implementations to be compatible about what these operations do and what their preconditions are.
I'm not claiming it can be recovered, I'm wondering whether setting My aim is simplicity. A more concise way of describing what I wrote above is: a portal may have a BC while it is browsing-context connected or it is the result of adoptPredecessor during portalactivate. While that is true, it is functional; when it becomes false, it dies. I think that's simpler than needing to specify the behavior of all of the operations (set src, activate, post message) while in the adopted-but-not-connected state as distinct from both the connected state and the dead state. |
For comparison: the alternative model (closer to what's currently written) is to predicate operations on the existence of an existing associated browsing context, and if the special state of having-a-guest-but-not-being-connected is lost then the portal element becomes inert until it becomes connected. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very interesting.
I see the draw of the lifetime-reasons framework outlined in #138 (comment). In general, I do think we should have a clear statement of when a portal has a BC. We should state it somewhere as an invariant the specification upholds, and then work out spec text that makes it obvious that the invariant does hold.
I have no opinion on what that invariant should be, but I think the first step should be spelling it out precisely. I think it's not just
is browsing-context connected or it is the result of adoptPredecessor during portalactivate
because there's also some constraint on the validity of the src="" attribute, right?
But if we can state it precisely, then we could have a framework like:
- "A portal should have a browsing context if all of the following are true: ...".
- Defining this may require the lifetime-reasons framework, or at least, some sort of boolean storing whether you're going through a portalactivate.
- An "Update a portal's BC" algorithm which checks "should have a BC", and synchronizes the portal with that (either by closing or creating). Plus I guess here is where you would also navigate.
- Everything that could change "should have a BC" then calls "update a portal's BC".
This is just off the top of my head, so I'm not sure it's perfect, but that's the direction I'd be thinking here.
index.bs
Outdated
The user agent may choose to emit a warning if the author attempts to | ||
use a <{portal}> element in a nested browsing context, as this is not | ||
supported. | ||
</p> | ||
|
||
1. If |element| has no <{portal/src}> attribute specified, or its value is the empty string, | ||
then [=close a portal element|close=] |element| and abort these steps. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Drive-by nit: "return", not "abort these steps", for both.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general for all uses of the phrase "abort these steps", or is there some guidance for when each wording is preferred? If it's just an editorial change in general, maybe I should do a separate PR to globally replace the phrase.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, probably best separate. The guidance is not very clear. We use "return" to return from an algorithm, but if that algorithm has sub-steps, e.g. in parallel or a queued task, then we have stuck with "abort these steps" (i.e. "return" is reserved for "exit the whole algorithm").
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In particular, https://infra.spec.whatwg.org/#algorithm-control-flow talks about using return, but it doesn't capture the remaining uses of "abort these steps" that we've evolved. I'll work on clarifying that in Infra.
index.bs
Outdated
@@ -407,6 +417,24 @@ spec:url; type:dfn; text:scheme | |||
|
|||
1. If the [=scheme=] of |url| is not an [=HTTP(S) scheme=], then abort these steps. | |||
|
|||
<div class="issue"> | |||
Would it be more consistent to treat this like an invalid URL, and close? | |||
</div> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Making the failure case (including for being in a nested BC) uniformly close seems reasonable to me. Right now there are some cases where the algorithm returns early but doesn't close, which seems like an unnecessary complexity for the author's mental state machine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
@@ -394,9 +394,19 @@ spec:url; type:dfn; text:scheme | |||
<section algorithm="htmlportalelement-setsourceurl"> | |||
To <dfn for="HTMLPortalElement">set the source URL of a <{portal}> element</dfn> |element|, run the following steps: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"set the source URL" is feeling like a worse name for this algorithm now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure what a better name is. It's principally used when the embedder directs the portal BC to navigate by changing the src
attribute. It is also called on BC connection, mainly because we didn't navigate earlier when src
was set.
"Possibly navigate" sounds a little vague. Any suggestions?
I'm not sure "has a BC" can be expressed without reference to state created just for that purpose, because if you invoke A weaker "may have a BC" constraint can more easily be described (roughly, BC-connected or in portalactivate dispatch); it could tell you that a The lifetime-reasons thing could also be spelled as an algorithm that explicitly checks all of the possible reasons. The
This would be invoked at all points which could make one of the conditions false (BC disconnection, end of |
Hmm, tried to incorporate some of this feedback into the latest version of this PR. PTAL? |
|
||
1. Set |adoptedPredecessorElement|'s [=just-adopted flag=] to false. | ||
|
||
1. If |element| [=may have a guest browsing context|may not have a guest browsing context=] and its [=guest browsing context=] is not null, then [=discard a browsing context|discard=] it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The use of discard here vs. close below warrants a note, I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done; wdyt?
@@ -701,14 +739,17 @@ spec:url; type:dfn; text:scheme | |||
|
|||
A {{PortalActivateEvent}} has an associated <dfn for="PortalActivateEvent">predecessor browsing context</dfn>, | |||
which is a [=top-level browsing context=] or null, a <dfn for="PortalActivateEvent">successor window</dfn>, which is | |||
a {{Window}}, and an <dfn for="PortalActivateEvent">activation promise</dfn>, which is a [=promise=]. | |||
a {{Window}}, an <dfn for="PortalActivateEvent">activation promise</dfn>, which is a [=promise=], and a | |||
<dfn for="PortalActivateEvent">adopted predecessor element</dfn>, which is a <{portal}> element or null. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fact that this is an element doesn't appear to be used. A boolean would work just as well. Right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's used to clear the "just adopted" flag after portalactivate
dispatch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, my bad.
<section algorithm="htmlportalelement-may-have-guest-browsing-context"> | ||
To determine whether a <{portal}> element <dfn for="HTMLPortalElement">may have a guest browsing context</dfn>, run the following steps: | ||
|
||
1. If |element| is [=browsing-context connected=], then return true. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe also add "and its browsing context is top-level"?
Maybe this will complicate the algorithm below, but it might be worth changing, as it expresses more clearly the situations where a portal may have a browsing context.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done; PTAL?
Resolves #137.
PTAL and let me know if you agree that this is the right behavior.
Preview | Diff