-
Notifications
You must be signed in to change notification settings - Fork 378
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
The way to access current script or current root, from Shadow DOM #717
Comments
Using encapsulation in a different way from how we use it for shadow trees makes this issue very confusing to read. I'm pretty sure we're not going to change what we decided on |
What is the way we use it for shadow trees? How my encapsulation differs? Per spec:
That's what I actually try to state here. I need a Speaking of whatwg/html#1013, it's for modules only, isn't it? I think the case of regular scripts are way simpler as they do not introduce problems like multiple imports |
The specific problem with enabling |
The last time we discussed this there was no particular interest in enabling this for classic scripts. And I don't think we have a hook of sorts we could use for them either. I suspect that hasn't changed? |
I don't think we'd be interested in exposing |
As @annevk 's #717 (comment), I don't think we revert the If we pursue function getCurrentScript() {
var root = document;
while (root != root.currentScriptRoot)
root = root.currentScriptRoot;
return root.currentScript;
} which is a similar approach to But similar to what @rniwa stated above, I feel reluctant to add new features to classic script. |
@TakayoshiKochi that would leak shadow trees outside the "blessed" open shadow root |
Ah, yes, maybe |
I'm going to close this given that something that only works for open shadow trees would not be acceptable given past discussions. |
I've been doing a deep dive into this issue and believe that the solution is not to change how
One might expect If We can kind of spoof this behavior in the following way :
But, the ShadowRoot interface is not a direct extension of the Document interface. So
This is a bit cumbersome though and, of course, manually evaluating scripts in content injected via Either way though this provides more security than allowing the scripts to run in the global scope as they do now. Exposing only a limited stub in place of the Document interface can prevent the injected scripts from accessing the outer document at all, that is, if there weren't alternate routes to it like
Ideal BehaviorUltimately, it should be possible to declaratively provide template elements in the host document which can contain scripts that use consistent Document interface syntax and get executed in the shadowRoot context avoiding this hack altogether.
Declaring those options would have to be done when creating the shadowRoot. Like this proposed example :
With the default for all options being |
@besworks I like the idea basically moving the document context to be the current custom element. I would also like to see this working for scripts other than textual but are referenced via source attribute: <script src="url.to.some.script" crossorigin type="module> |
@chrisodom that should be doable. You would just need to fetch the script and run the response through
|
Since
There is no way for a script to access the elements in its own root. That, in my opinion, breaks the idea of encapsulation, and for sure renders script elements inside shadow root useless.
At least the scripts that have something to do with the shadow root they are in.
Why do I think it breaks encapsulation?
For me, Shadow DOM was the way to encapsulate a bunch of any HTML elements into a separate tree. Therefore, (in V0) I used
<div>
elements that does not obfuscate the global tree,<style>
elements that affects only elements inside and does not bleed outside,<script>
elements that could work with smaller document fragment, where I can use small set of scoped IDs,querySelect
smaller tree and so on.JS was never strictly encapsulated as it is working in the global context. That could be good and bad but I don't want that to be part of this discussion.
However, I was at least able to use a convention to support it. I could even force it by auditing, linting the scripts I put into my shadow, make sure they do not access document or global variables.
Right now, there is no (*) way to access this encapsulated/scoped document fragment from the script, and they only can access,
querySelect
global document. That means<script>
s in "encapsulated" tree are able to access global tree, but cannot access encapsulated tree.Compare such shadow roots:
The pre-477/v0 case was working perfectly, looked pretty clean. The only downside is that you had to remember to use
document.currentScript.getRootNode()
instead ofdocument
, but as I stated above this could be good and bad that you can make this conscious decision.Then post-477 it's rather impossible to achieve such behavior. The first case simply doesn't work and most probably would make a random button beep.
The second one may work as long as you
Also, it's extremely ugly and bug-prone.
What is worse it requires you to pierce through all the shadow roots.
// @rniwa maybe you would be interested in a problem that disallows closed shadows and requires piercing
"Having
currentScript
allows you to expose shadow root and break encapsulation again"It does, but you can expose it in many other ways which are not disallowed. For example with custom elements, like in #477 (comment)
(*) "You can use custom element"
I can, but I think it's overkill. Consider the costs of cognitive load for developers, maintenance, performance, loading yet another polyfill of defining a custom element, creating an instance, considering all CE reactions just to access an element in my own scope and do something simple with it just once.
Imagine using full CustomElements machinery as an IIFE.
More use cases
I would say: all cases when you would like to do any kind of scripting in scoped encapsulated DOM. Especially those which are specific, unique, or just too simple, so where running CE machinery does not make sense.
If extrapolating the example above is not enough, and somebody would like to see more. I'm happy to provide more real-life, production-based use cases. But here I'd like to avoid blurring the picture and making the post to long to read.
Solutions
currentScript
and usegetRootNode()
.It's a simple solution from the perspective of web developer/ shadow root author. It's the same
getRootNode
that is used for any other custom or native element.I believe it should be also simple from implementers perspective, as it was there already in V0.
currentRoot
as proposed by @hayatoito.If for some reason
currentScript
is really so evil and worse from CE'sthis.getRootNode()
, or externalelement.shadowRoot
, that it has to be blocked. I think it's pretty self-explanatory and straightforward API, that would be also nice sugar on top ofdocument.currentScript.getRootNode()
. But I would expect some problems with such context-awareness, both in author developer experience as in implementation.The text was updated successfully, but these errors were encountered: