async-append icon indicating copy to clipboard operation
async-append copied to clipboard

Missing DOM mutation operations

Open domenic opened this issue 9 years ago • 4 comments

@wycats has done a lot of investigation into what are the primitive DOM operations necessary to build up a tree, as part of https://github.com/whatwg/dom/issues/270.

This proposal so far has:

  • append
  • prepend
  • remove
  • insertBefore

(I think maybe append and prepend could be reduced to insertBefore in theory.)

It is missing the following:

  • setAttribute
  • removeAttribute
  • setTextData (can be semi-emulated by removing the text node and inserting a new one, but that has slightly different semantics)
  • attachShadow

There is also the following non-primitive but convenient operation:

  • insertAdjacentHTML (can be emulated with <template>.content and insertBefore on the resulting DocumentFragment)

domenic avatar Jul 01 '16 17:07 domenic

It leaves out setAttribute, etc. on purpose. Async append isn't a patch operation over the DOM, you can only insert/remove subtrees.

It should have:

append insertBefore remove innerHTML insertAdjacentHTML

It's quite complicated to do the async semantics over an attribute, text or shadow mutation. It would require us to double buffer the entire state in the engine.

esprehn avatar Jul 01 '16 23:07 esprehn

That is to say, I think we can consider operations like that someday, but it's vastly more complicated than the insert/remove operations and it's not clear to me that we wouldn't need a different API surface for it.

esprehn avatar Jul 02 '16 02:07 esprehn

Does this problem really need such as large API surface area? Aren't you really just saying: "Hey browser, give me a window of time where I can safely mutate this DOM subtree". Upon being granted that window, the user can perform any DOM mutation they wish (within this subtree scope), via the existing APIs.

window.requestMutation(element)
  .then(element => element.innerHTML = ...);

This is a driveby comment, apologies if this has been discussed prior :)

wilsonpage avatar Aug 12 '16 10:08 wilsonpage

No, the important bit here is that there's a lot of browser-side work that needs to be done in response to a mutation (rerunning selectors, figuring out styling, building the box tree, painting), and we don't want to hang the page's JS while we do it. The API presented here (ask the browser to do some async work, let me know when it's done) means that we can slice up the work into small chunks, interleaving them with page JS so it's never blocked for a large amount of time.

Your proposed API ("give me a window where I can make mutations without causing browser-side work until I'm done") doesn't let us do this - after the callback is called, there's still a potentially large chunk of work for the browser to do, and we have to do it immediately, before we run more JS (or if we do slice it up, we need to give the page a way to know when it's done, at which point you've devolved to our proposed API).

The "gimme a window" approach does help in some ways - in particular, it guarantees that interleaving read/writes won't trigger unexpected work - but that's also accomplished by our proposed API.

tabatkins avatar Aug 16 '16 00:08 tabatkins