Closed jeremyroman closed 5 years ago
Hmm, on further thought, what should happen if you set src
on a portal that has a guest BC but is not yet inserted? I think it should navigate, but it's kinda weird regardless.
onportalactivate = e => {
let portal = e.adoptPredecessor();
portal.src = 'https://somewhere.else/';
/* ... */
};
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 adoptPredecessor
more explicit.
I've been avoiding it because it's kind of indirect, but maybe it's semantically nicer. Something like:
A \<portal> element has lifetime reasons, which is an ordered set of strings that is initially « ».
To extend element's lifetime due to reason, append reason to element's lifetime reasons. To discontinue element's lifetime due to reason, remove reason from element's lifetime reasons. If this causes element's lifetime reasons to become empty, then discard element's guest browsing context and set it to null.
Whenever a portal element element becomes browsing-context connected, run the following steps:
- Extend element's lifetime due to
"browsing-context-connected"
.- (Set the source URL if appropriate, etc.)
Whenever a portal element element becomes browsing-context disconnected, run the following steps:
- Discontinue element's lifetime due to
"browsing-context-connected"
.
Plus wording to give an additional reason, say "predecessor-just-adopted"
, in adoptPredecessor
, which is discontinued at the end of the steps to activate a portal browsing context.
This would imply that for the duration of the portalactivate
event, you can treat the portal element the same as if it were BC-connected (you can set its source to invalid and invalid values, post messages, and so on). I think that's probably nicer than having the two cases be different, even if it seems to demand a little abstraction overhead.
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™.
Doing some more edge-case thinking here. What about this:
onportalactivate = e => { let portal = e.adoptPredecessor(); // Does this drop the existing BC? portal.src = '';
I'd argue that yes, this does drop the BC.
// If so, does this recreate it, or did the above forfeit the special status? portal.src = 'https://somewhere.else/'; }
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.
I'm leaning toward making the concept of specially-extended lifetime for the result of
adoptPredecessor
more explicit.I've been avoiding it because it's kind of indirect, but maybe it's semantically nicer. Something like:
A
element has lifetime reasons, which is an ordered set of strings that is initially « ». To extend element's lifetime due to reason, append reason to element's lifetime reasons. To discontinue element's lifetime due to reason, remove reason from element's lifetime reasons. If this causes element's lifetime reasons to become empty, then discard element's guest browsing context and set it to null. Whenever a portal element element becomes browsing-context connected, run the following steps:
- Extend element's lifetime due to
"browsing-context-connected"
.- (Set the source URL if appropriate, etc.)
Whenever a portal element element becomes browsing-context disconnected, run the following steps:
- Discontinue element's lifetime due to
"browsing-context-connected"
.Plus wording to give an additional reason, say
"predecessor-just-adopted"
, inadoptPredecessor
, which is discontinued at the end of the steps to activate a portal browsing context.This would imply that for the duration of the
portalactivate
event, you can treat the portal element the same as if it were BC-connected (you can set its source to invalid and invalid values, post messages, and so on). I think that's probably nicer than having the two cases be different, even if it seems to demand a little abstraction overhead.WDYT (before I go to the effort of making such changes)?
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.
@domenic might also want to comment since I'm kinda proposing to make this more complicated in the name of Internal Consistency™.
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.
The special status is only achievable by calling the adoptPredecessor API, once it's dropped, it's no possible to get it back.
I'm not claiming it can be recovered, I'm wondering whether setting src
forfeited it early. The special status is ordinarily forfeited at the end of the portalactivate
event.
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.
I'm not sure "has a BC" can be expressed without reference to state created just for that purpose, because if you invoke activate
, nothing about its state changes except that it loses its BC. There's a similar case of being adopted by another document, which needs to discard the BC. Forcibly changing content attributes in such a case seems strange.
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 <portal>
definitely has no BC, but not stronger than that.
The lifetime-reasons thing could also be spelled as an algorithm that explicitly checks all of the possible reasons. The portalactivate
reason would require an explicit boolean of state at least, so it didn't seem shorter. It'd look something like:
To check the lifetime of a
<portal>
element element, perform the following steps:
- If element is browsing-context connected, then return.
- If element's just-adopted flag is true, then return.
- Discard element's guest browsing context.
- Set element's guest browsing context to null.
This would be invoked at all points which could make one of the conditions false (BC disconnection, end of portalactivate
dispatch).
Hmm, tried to incorporate some of this feedback into the latest version of this PR. PTAL?
Resolves #137.
PTAL and let me know if you agree that this is the right behavior.
Preview | Diff