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
Alternative proposal for closed shadow DOM #499
Comments
The purpose of closed is to avoid accidental dependencies on the internals of shadow trees. We do want truly isolated shadow trees at some point, but as you indicate those require a different design. They're not considered an alternative to closed shadow trees however. |
Doesn't grepping for |
None of accessibility, automation, or testing tooling should be broken as already discussed. |
Doesn't seem to be much discussion of this or any planned fixes on the Chrome side. Could you link me if I've missed it? Revisiting:
Are we really talking about carving off parts of a web developer's DOM that they are responsible for, aren't allowed to access, because they might make a mistake? Not to mention that a developer might want to create intentional dependencies on the internals of shadow trees, regardless of whether the component author intended for them to. I really can't see who's benefiting from this. |
Regarding security, Shadow DOM is not a security mechanism. That has never been a goal of Shadow DOM, either open or closed. Do not use Shadow DOM if you want a true security. Should we mention that somewhere if people are likely to misunderstand Shadow DOM's role? |
Such discussion has to happen at each browser vendor and/or for the WebDriver specification, not here.
This is precisely why closed shadow tree is needed. Because of this possibility, once a component is published and used by third parties, there is no way for component authors to know whether there is any use of a given component that depends on a particular shape of its shadow tree. Closed shadow mode makes it much less likely for any use of the component to depend on its shadow tree structure. |
Is all of the effort to try to patch all of the supposed "leaks" of information about the closed shadow DOM, plus all of the other changes to specs and implementations (e.g. webdriver) really worth the questionable benefits of the writer of some component, trying to stop the users of that component from being idiots? My experience shows that bad coders will be bad coders, regardless of how much you try to stop them from doing it, and in this case, the only people that get "hurt" are the bad coders. So why all the effort? |
I think it's rather disrespectful to name those people "idiots". They might simply have different priorities. Guarding against typical mistakes is useful and something browsers deploy all the time. Making it available to others is useful. |
First off, terms such as idiots shouldn't be used lightly per our Code of Ethics and Professional Conduct. The term is discriminatory towards people with intellectual disabilities. See campaigns like http://www.r-word.org. Now, encapsulation is the pinnacle of modern day programming. The problem here isn't so much that some developers would poke into shadow trees of various components accidentally or purposefully. It's that component authors can't have any reasonable expectation that users of their components wouldn't do so. Why is this bad? Because those components would need to be updated in the future. And when they do get updated, all those uses of older versions of components that poked into their shadow trees would break. Look no further than shadow piercing combinators, which was introduced as a convenience mechanism for developers to pierce through shadow boundaries to style elements. At the end, Blink removed this feature from the engine because authors abused it. Look no further than the fact we can't even add |
@rniwa, seeing as those comments were directed at a theoretical person and not at anyone on this list, or any identifiable group of people, I cannot see how that violates the code of conduct |
@rniwa the fact that authors used the shadow piercing combinators should have been a clue to the blink developers that maybe there is a need here that is not being met. Removing a feature, because it gets used "too much" seems to me to be the exact antithesis of agile, UX-based development. This is precisely the problem with this part of the spec, and more broadly with the HTML spec. It is too dominated by the browser vendors opinions and not focussed on the needs of the users. |
Hello first of all, as a starting point, we should consider 3rd party securitynever been an issue, because that is not what ShadowDOM (SD) is for
Integrity
automation, accessibility & testingI see no problem. You can test 3rd party the same way as you test desktop component development / usage / behaviorDesktop development (and not just desktop, but I'm thinking controls
Brona |
The shadow DOM is an amazing idea, allowing developers to package up a 'web component' in a self-contained way, so that it won't unintentionally be affected by what's outside. This is great for everyone: the component developer can develop in the knowledge that their component won't be unintentionally affected by the page, the page developer can use the component in the knowledge that it will work correctly if they use it as intended, and the component can be updated safely without breaking anything. I think we are all in agreement on this. We seem only to hit a problem when the page developer (or a third party interacting with the page) wants to intentionally change the DOM within the web component. Then, we have 2 choices:
Let me repeat, we are saying that it is more important that the web component works correctly in a developer's page than the developer being able to do what they are trying to do. This is blatantly absurd. Add to this the fact that, in order to protect the developer from themselves, we have to create an exemption in every third-party interface that should have access. (This must be nearly all of them, since it is hard to reason about a page when chunks of it are locked away from view behind myriad opaque unstandardised interfaces.) And then the page developer can easily disable closed shadow DOMs anyway, even though they are the only ones we want to lock out. This takes a bad idea and inflates it into a multi-specification disaster. I appreciate that a lot of work has gone into closed shadow DOMs, but can we please now reconsider, and begin taking steps to unwind it. |
Nobody is forcing developers to close shadow trees. It's entirely their choice. If it causes them trouble, they can easily open them in the source code and forget all about closed shadow trees. Alternatively, if they want to access closed shadow trees during testing, they can hook I, for one, am very keen on closed shadow trees. They're a safety mechanism on a footgun and they can provide comfort to developers that they can safely make changes to their components. Taking the safety off should be as inconvenient as it is, as developers who take the time to learn how to do it are likely to learn the risks in the process. If you don't like the closed flag, simply don't use it. |
Matthaw, I do not want this to become our own discussion, but I'll try to respond 1/again, we have never been able to do what we wanted on the page, This is simply both theoretically and practically correct way. B. |
@BronislavKlucka As I mentioned above, the problem is that the resulting API will be unstandardised. If the component is incomplete/doesn't satisfy your requirements, you have to modify the code for it (if the licence allows you to) or write your own from scratch. With user-agent elements, the implementations are generally pretty complete (notable exceptions include selection API for some newer For example, if a closed shadow DOM forgets to register an API for
This is the DOM, not application logic. What we're talking about here is carving off parts of the user interface that the developer isn't allowed to affect. You're being made to hand over end-to-end control of user interaction and experience with parts of your application. In my opinion, this is worlds away from hiding members of behind-the-scenes libraries in an abstract object, and is not something to be desired.
Why must it be the developers of the component that get to enforce the contract? The component exists in a vacuum without the applications that include them, and keeping or breaking the contract only breaks that application. It seems clear to me that the application developer should be the one who has control over how stable/unstable, broken/unbroken and functionality-rich/-poor their application is. The component is not more important than the application; it should be subservient to it. We seem to be rushing to forget that.
I completely agree. Problem is, "closed" looks like a big ribbon to wrap around your component when you decide that it's done. You can quite happily write a component once, to a spec that fulfils your needs, and consider your project complete. You think, because you've matched your spec, that nobody will need to get inside it. Anyway, they might break it, and you might look bad if they do. So you tie it up with the nice "closed" ribbon and send it out into the world. It might be great at what it does, end up well-tested from widespread use, and work as intended. But you've made the decision for developers using your component that it is complete, regardless of whether it does what they're actually trying to use it for. This is not the decision you should have made, and you've stripped developers of opportunities for no good reason. A more complex point is bundling. Say you've created the best spreadsheet web component ever, and you'd like to heavily brand it, or to advertise within it. By making it a "closed" web component, you're telling the application developer that they have no choice in this -- that they must allow you to show their users these in your application, regardless of whether they disagree. I want it to be that the application developer retains final creative control, whether the web component developer likes their decisions or not. |
As the developer of a component, the writer and copyright holder of a piece of software, isn't that my prerogative? You're telling me that I shouldn't be allowed to decide how my component is used?
You don't need a closed shadow tree for this, a restrictive license would be enough. Look at the FlowPlayer license, for example, and FlowPlayer's component doesn't use shadow DOM (yet). If a component is truly open source and its shadow tree is closed—and this bothers you—, fork it and do whatever you want with it. If the component is not truly open source and its shadow is closed, then you can either get around the closed tree the "hard" way and modify it while staying in the terms of the license or move on and don't use it. |
Openness is the reason the Web is as successful as it is. If the inventors of HTML and JavaScript had decided to create closed systems, we would not have half of the features we currently use every day. We would not have any of the HTML5 shims that allow us to use cool new features while still supporting older browsers for example. There are thousand of innovations we all use every day built on top of the technology that get this technology to do things that the inventors never were able to predict. ReactJS is an amazing invention. I don't think I could have invented it. The React object uses prototype to expose its functionality to users. If it were not possible to override the prototype of a third party component, I would not have been able to create this module https://github.com/dylanb/react-axe and this module https://github.com/garbles/why-did-you-update which uses the exact same technique I used, would not have been able to have been created either. The ReactJS developers are awesome! But they could not have predicted the existence of those two (and probably hundreds of other modules) that provide value they did not see. I have never once wanted more obfuscation. I have only ever wanted more transparency and more ways to look into and manipulate things other people created. For example, right now, I wish that there were a way to find all the event handlers registered on a page (without having to write an extension) because this would allow me to extend the axe-core accessibility evaluator to do things it currently cannot do in a cross browser way. I wish that this team would expose the composed tree in a way that it can be inspected using the DOM API. I wish that the accessibility mapping information of all nodes were exposed to JavaScript so that we could write automated cross-browser tests to see whether there are accessibility bugs in UA implementations. I want more openness every day, so I can do things the browser vendors have not thought of and in many cases are not interested in doing themselves. @annevk you can repeat your assertion over and over that your are not breaking the accessibility testing but that is not what @mrmr1993 has so far found as currently being discussed here #354 (comment) @andyearnshaw It is not worth sacrificing the future innovation around Web Components just so you can prevent someone using your stuff in a way you could not foresee. I agree with @mrmr1993 that it is the inadvertent use of this flag that is most dangerous. As shown by some of the comments above, developers often think they know it all and they know better and they want to control the whole world. This desire, as shown by all the great innovations that have happened because of the openness of the Web platform, is misguided. Firefox trounced IE because it was open and Chrome would never have succeeded in winning over the development community if it had been a totally closed system like old IE. Microsoft has recognized their folly and as a result, Edge is heading in a more open direction. Open systems win when there is free competition - always. Web Components will compete with other mechanisms for achieving the same things (like React for example) and if it is not open, it will lose. |
@dylanb that implementations are imperfect does not mean the feature is broken. False equivalence. |
ReactJS is open source.
I think that's more than a little extreme, to be honest. Plenty of JavaScript and HTML components have not been open, for instance those that are heavily obfuscated or use cross-origin iframes. They haven't hindered anything. While I stand by what I said about authors rights to restrict use of their software, I'm more interested in that extra barrier that means people are more likely to know the risks before modifying the component, and I could issue structural changes to fix minor issues without worrying about breaking existing live instances. If someone can easily write |
@mrmr1993 Using internals for plain object and for ShadowDOM is exactly the same. There is no difference, it is private logic, you can expose private property in object as well and face unintentional consequences, because the object never assumed that this particular property can be changed outside of internal logic. The fact that end user does not see object, but sees a control makes no difference. Let me give you example of difference between open and closed based on usage, not on what anyone wants. Let's say I have application with calendar and list of events in selected day. The event list, the list, that is displayed when day is selected is different story. It's a box with date/time of the event, name, location, description, maybe with some control buttons... It's something that in desktop programming is called frame (poor name for Web dev. though :(, component module? object view? control box? ). It has some properties of control (object). It Is instantiated more than once, in all cases it serves the same purpose but with different attributes (display of event, but different events), it has properties of its own (e.g. background) method of its own (displayEvent(Event event)), it has its internal logic (if I click delete button, event gets deleted, no need to code it outside), but there is no need do shield it. There is no need to protect internals, programming that I should not expect the DOM to exist as designed at any time (always test for existence of element, in closed, good practice, in open mandate). If "the outside" will want to change internal structure, why not... (in desktop programming the frames' controls are by default public/published). It's just a view. I hope you can see the difference based on usage / OOP theory, not whether we like some programming paradigm or not. And yes, opinion of the autor is more important, that opinion of the developer/user of the component, whether it's expressed by licence (which you cannot touch) or closed flag, which you can touch (based on licence) @dylanb |
How useful would those two modules be together if you had to modify React source code to add those features, keep syncing this with the main fork and keep updating it every time you want a change from another module or want to add a new module etc. Talk about upgrade difficulties.
Why are you so worried about backwards compatibility for people who do this? If you do |
@BronislavKlucka I am not advocating for OS licenses. What I have said through illustration with many examples is that the ability to change and see and modify all aspects of the Web page (within the limits of security) is something that has allowed great and valuable innovations to occur and when we create features that close things off, we are limiting the creative flexibility of the users of those components. This will limit innovation and lead to possibly brilliant inventions not being technically feasible at all. One aspect of your calendar that I might legitimately want to reach in and fix is to add missing accessibility information. If it is a closed source component that has a closed flag and I cannot do that, then my only options are to switch your component out, write an entirely new component or do without the calendar picker feature. All of those alternatives are very expensive and could be avoided by simply not implementing a closed flag. |
no... I can write it in open mode with closed source licence... And if I choose closed source licence and my component will not meet your need, you still have to move on.. Or do you want to force on me, the author, the licence as well?
and has been a plague over the years when trying 3rd party parts somehow not to leek out and the outside not to leak in
which should be solely in control of the author, by licence can we get back to problem at hands and not make it about author vs. developer, OS vs. closed licencing? |
You misunderstand. The users of the library aren't part of my team, nor under my control. Nor do I, or any of my immediate colleagues oversee the work they do. In many cases they're external clients and have only a basic knowledge of web technologies. These are the ones I'd like to protect from themselves. Considering that the API is used in ads and a single client could have many (many) creatives with copy/pasted code, I think it's a valid concern. Frequent backwards incompatible releases would adversely impact our support channels and require us to maintain several versions of the product simultaneously.
For custom elements using class YourElement extends MyElement {
attachShadow(o) {
o.mode = 'open';
Element.prototype.attachShadow.call(this, o);
}
}
customElements.define('my-element', YourElement); |
I don't really want to get in between you two, but I want to point out that at least as of yesterday (haven't read through the latest replies) there was a big fallacy in this thread, which was that This is never true. There is no DRM for JavaScript. Any JavaScript code that you deploy in your webapp, you have complete control over. You can modify it as you see fit, for example, by changing all occurrences of the string "closed" to "open". Yes, this can be inconvenient. Yes, it means that certain libraries will exist which you might not be able to use out of the box without changing their source code first. That's fine: there are a lot of things a library developer can do to make their library less than usable, such as using an illiberal license, or naming their public APIs with gibberish, or obfuscating their source code. Such libraries will get less uptake by people who care about such things. That's OK. The application developer is never locked out of control of their webapp by the existence of features in the browser, like |
so let me understand the argument:
|
@mrmr1993 After thinking about your proposal: As long as it supported the mechanisms through which code can be injected into the iframe from a privileged context (as used by WebDriver), it would solve all the problems I currently have with the closed flag. It would also have to solve some of the styling problems that iframes have in order to be useful though. |
@dylanb |
Following a slight tangent: is there any indication that those naughty developers making widespread use of |
@mrmr1993 to extend that line of thinking...is it really worth all the effort just to change a property access into those 4-6 lines (depending on how you're counting) plus a property access? |
I'm torn about this. I 1000% can sympathise with both sides. I work on the standard UI library for my company and have seen some pretty awful things being done to the "shadow DOM" of our components that having a closed shadow root could have helped with. That said, many of these problems were done by accident - or because the precedent we as developers have set in the industry is that this is okay up to now - and having access to the Maybe the pragmatic solution here is to have |
That would go back on implementer consensus. That was the position until last year and it basically meant that only Chrome would ever ship something resembling shadow DOM. |
So this is non-negotiable?
To clarify, are you saying that open shadow DOM -- which is widely acknowledged to be advantageous -- will not be implemented without closed shadow DOM, which variously has:
Maybe this is already written in stone and I'm just pissing in the wind, but I really can't see why there is such strong intention to have this 'feature'. |
I think it's non-negotiable, yes. I've iterated that various times throughout these issues. I disagree with your characterization of the advantages and disadvantages. The web has encapsulation, see, e.g., closures. It's not a lot of work to implement this feature. Providing APIs to bypass it to privileged APIs is fine, as we already stated. It's not accepted as unintended bad. And not allowing downstream to override things is a feature. Advantages have already been listed earlier in this thread. |
Is there a procedure for opening a negotiation in such a case?
With the availability of the workaround, the only difference with open shadow DOM is the method of access, no? AFAICT, that was the only advantage that factors in this consideration. If there were others that do factor this in and that I missed, could you briefly summarise them? |
I guess you'd have to convince the implementers.
I'm not sure what this means. As for arguments, I would consider #499 (comment) and #499 (comment) to be pretty clear. |
@annevk so what you are saying, is that the implementors' input trumps the input of users? As pointed out #354 (comment) the consensus you talk about was never documented. In other words, you did not follow W3C process and give others an opportunity to voice their concerns. I also notice that none of you have commented on my summary of the arguments #499 (comment), I assume because it is pointing out how weak the pro-position actually is. The benefits of this proposal are minuscule, yet their impact in terms of things that break and implementation cost is huge. |
@dylanb in practice, the buck ends with implementers. However, according to the W3C it's the Director, so I suppose you could appeal to them, but I don't think any of that will change much here. I didn't really reply to your summary of the arguments since I didn't quite know what to make of it. Anyway, I will unsubscribe from this issue now since I feel like I've been repeating myself too many times. |
The consensus to have no default was reached in a F2F meeting on April 24th, 2015: This was one of the most controversial and contentious bit during shadow DOM API discussion: As you can see yourself, this is a very complicated topic of which people have varying opinions. This is precisely why we added a flag to toggle the two modes and didn't force the default mode on anyone by requiring each author to specify so that we may pick the appropriate default mode once we learn how this feature gets adopted by developers. So on the contrary to what you're claiming, this is precisely the decision made to wait & honor the future feedback we get from developers (i.e. users of this API). |
@rniwa that is a very sensible approach indeed. I apologise if my comment was a bit naive. Coming from a different angle, and arguing against the automated testing angle, wouldn't these tools have to update their code anyways to use |
The "application developer" is not always a single person. The "application developer" might be a team, and the team will mix match components that the team creates in various UIs. The explicit contract in closed trees is a form of communication between the authors in the team. It encourages collaboration when the external API of a component doesn't satisfy a use case, which is much better than team members haphazardly modifying things and introducing bugs without consulting the original component author. As for 3rd-party components, that is why choice is a freedom. Want open components? Then don't use closed ones. Want to modify a closed 3rd party component? Then fork it or don't use it. More choices means more freedom of design. |
There's also my ComposedTreeProxy idea (#516) which I think might make sense for interaction scripting: if there's something a user can do on screen, then we should also be able to do it by code too (regardless of if a shadow tree is closed or not). Actual users and robot users should be treated equally, but they are not, which is the only downside to closed trees at the moment. Monkey patching to achieve this oversteps the purpose of closed trees, but the proxy idea does not overstep. If a component author puts a button inside a closed tree, and the button appears on screen, then the button is meant to be clicked. If we can't do this with code, then that is a flaw because it means part of the public API (being able to click a button that appears on screen) cannot be done via code but only via actual user interaction. Perhaps another option is that closed trees can be accessed, but when accessed the result is actually a limited proxy (for example, the proxy allows triggering a click, but not the setting of attributes). |
FWIW I predict that if there isn't a method for reading a closed tree, the community will be very quick to override |
I am triaging open issues. Let me close this issue since it looks this issue no longer gets much attention. |
Polymer has an idea called |
The
closed
flag for web components doesn't seem to have a clear purpose, and has several issues.Security:
Element.prototype.addEventListener
is an easy example, and can't be closed without some webcompat breakage.Proxy
object provides similar opportunities when hooking getters.Integrity:
Automation, accessibility & testing:
Taking these into account, it seems that a closed shadow DOM is little better than an open shadow DOM in any of the aspects it might hope to be, and causes problems for outside interaction with pages.
Proposed alternative:
ShadowRootMode
and all of its consequences from the shadow DOM spec.<component-iframe>
) with the same attributes, DOM interfaces and behaviour as<iframe>
, except<component-iframe>
are assigned to<slot>
s in the document tree of the<iframe>
using analogues of the slotting algorithm (§3.2), assigned nodes algorithm (§3.3), and distributed nodes algorithm (§3.4).<component-iframe>
'swindow
for registering API functions for the component, e.g.window.registerComponentMethod(name, apiFunction)
to add a methodwindow.unregisterComponentMethod(name, apiFunction)
to remove a previously added method (functionally similar toremoveEventListener
elsewhere).<component-iframe>
HTMLElement
for accessing the registered API, e.g.HTMLComponentIframeElement.getRegisteredComponentMethods()
to list the added methodsHTMLComponentIframeElement.NAME(...)
whereNAME
is thename
argument for a method added viaregisterComponentMethod
.<component-iframe>
should begin loading before being inserted into the documentload
method to<component-iframe>
which creates the nested browsing context (which persists after insertion into/removal from a document) and processes the iframe attributes (see iframe spec).Is this reasonable or even doable as an alternative?
/cc @dylanb, you're the major voice against closed shadow DOMs in #354. Would this proposal address your concerns/is it something you could get behind?
The text was updated successfully, but these errors were encountered: