Dom: Expose document fragment serialization algorithm

Created on 1 Apr 2021  路  16Comments  路  Source: whatwg/dom

This came up during TAG review of Sanitizer API.

They have a sanitize() method that returns a DocumentFragment and a sanitizeToString() which merely calls sanitize() and then serializes the fragment.

Instead of adding ad hoc methods in various Web Platform APIs to invoke the HTML fragment serialization algorithm, there should be a way to serialize document fragments directly. I imagine there are reasons not to add innerHTML to document fragments, otherwise it would already be there. Perhaps a new getter, or a method that also accepts an optional context type?

All 16 comments

Hmm I transferred this to whatwg/dom but maybe it really belongs in https://w3c.github.io/DOM-Parsing/, at least until we finish merging that spec into HTML. Sorry about that.

As you say, I have the feeling this has been previously discussed, and maybe there were web compatibility reasons why it hasn't been added. We added innerHTML to ShadowRoot after all; why did we do that instead of adding it to its base class DocumentFragment?

In https://github.com/w3c/DOM-Parsing/issues/21 there's some discussion of the problem of the context element, but I believe that only impacts the setter, not the getter. Maybe we could add a getter to DocumentFragment? Or maybe it was just compat issues...

When building the prototype Sanitizer API in Gecko, I have actually thought the same, but didn't think of (dare thinking of?) suggesting this for wider implementation.

I even used this as a short-cut in Gecko. We currently have an _internal_, C++-only getter for innerHTML that we could easily expose to the web (added in bug 1653232).

I'm a bit unsure about the compat bit and how to resolve it though..

Probably for the same reason as DocumentFragment, you can't serialize a document either (except via XMLSerializer but this forces xhtml rather than html).

The current proposal for declarative shadow dom contains a .getInnerHTML(...) function, so even if .innerHTML on DocumentFragment/Document is a web-compat issue, that could potentially be used instead.

See the following public-webapps threads:

This wasn't really prevented / motivated by the compatibility concern. It was because innerHTML on template and ShadowRoot was conceptualized as a way to be able to support setter. With DocumentFragment which is not ShadowRoot, we don't know the context element so we need to decide which parsing mode to use. It would be indeed weird & controversial to introduce innerHTML that only supports getting but not setting since that could be a compatibility concern especially if we decide to throw an exception in the setter.

Yeah, I think this is a problem with the sanitizer API. The fragment parser takes a string and a context element. Both are significant.

Yeah, I think this is a problem with the sanitizer API. The fragment parser takes a string and a context element. Both are significant.

I'm not sure how to parse this comment. Are you saying the serialization algorithm shouldn't be exposed because it's Sanitizer API's problem, or that it shouldn't accept a context element as a parameter? Or something else?

I think (willing to be convinced otherwise) HTML string sanitization needs to account for the same input parameters as HTML string parsing, i.e., the string and the context element. Otherwise it might be tricky to insert into <tr> or some such.

I think (willing to be convinced otherwise) HTML string sanitization needs to account for the same input parameters as HTML string parsing, i.e., the string and the context element. Otherwise it might be tricky to insert into <tr> or some such.

I'm still confused. Are you saying the algorithm shouldn't be exposed on the DOM side, or making a comment to inform the API shape?

API shape / model.

The sanitize API question moved (back) to https://github.com/WICG/sanitizer-api/issues/42.

With regards to OP, having considered the sanitization API more carefully, I don't think we should expose the serialization of a DocumentFragment directly (other than through innerHTML) as there is no context-free parse function that would give you back the DocumentFragment you serialized. The exception here is XML, but I don't think we should offer an API that ends up being problematic for all HTML users (which will be the majority).

(As a simple example, consider obj.innerHTML = "<td>test<td>test". If obj is an HTML body element, it will contain a Text node "testtest". If it's an HTML tr element, it will end up containing what you expect.)

So I'll leave this open for a bit to see if there is a compelling counterargument, but I'm inclined to close this given the above.

So I'll leave this open for a bit to see if there is a compelling counterargument, but I'm inclined to close this given the above.

It might be a separate issue, but could we get a way to serialize a whole document? (other than XMLSerializer which forces XHTML even if the document is HTML).

Serializing a document doesn't suffer from the context-specific deserialization/serialization issue so it should be fine to expose.

Yeah, that seems like a reasonable request to me as an issue against either DOM Parsing or the HTML Standard. Ideally it would come with some use cases. (Browsers are already forced to implement it for XMLHttpRequest come to think of it, which should make it pretty cheap to add.)

@annevk This argues that the serialization function needs to accept a (mandatory?) context parameter, not that there shouldn't be a serialization function at all, no?

@LeaVerou the serialization doesn't depend on the context, but the parsing of it does. Given that mismatch, offering context-free serialization (i.e., documentFragmentInstance.something rather than someElement.innerHTML) will likely lead to subtle problems in practice. (As you know there's no way we can annotate the string and say that it can be only be handed to innerHTML successfully when used on a tr element or some such.)

Does this mean the sanitizer API should not be offering methods that only accept the string to sanitize as input?

Yeah, I discussed that with @mozfreddyb yesterday and that's why he reopened https://github.com/WICG/sanitizer-api/issues/42 for further discussion.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

domenic picture domenic  路  8Comments

domenic picture domenic  路  8Comments

a-tarasyuk picture a-tarasyuk  路  3Comments

jakearchibald picture jakearchibald  路  11Comments

jakearchibald picture jakearchibald  路  3Comments