Re: [whatwg/dom] Proposal: A Range.prototype.replaceContents(...) (#837)

@annevk so this is a very basic test case you can test right away in your machine too:

```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Custom Elements Callbacks Cost</title>
  <style>
  custom-element {
    display: block;
  }
  </style>
  <script>
  class NoCBElement extends HTMLElement {
    get value() {
      return this.textContent;
    }
    set value(value) {
      this.textContent = value;
    }
  }
  class CBElement extends NoCBElement {
    connectedCallback() {
      this.connected = (this.connected || 0) + 1;
      this.setAttribute('connected', this.connected);
    }
    disconnectedCallback() {
      this.disconnected = (this.disconnected || 0) + 1;
      this.setAttribute('disconnected', this.disconnected);
    }
  }
  customElements.define(
    'custom-element',
    /^\?callbacks?/.test(location.search) ?
      CBElement : NoCBElement
  );
  this.onload = function () {
    var container = document.body;
    var items = [];
    console.time('creation');
    for (var i = 0; i < 1000; i++)
      items.push(
        container.appendChild(
          create('custom-element', {value: 'Item ' + i})
        )
      );
    console.timeEnd('creation');
    setInterval(
      function shuffle(randomly) {
        var before = items.slice(0);
        console.time('shuffling');

        //* single pass
        items.sort(randomly);
        for (var i = 0; i < 1000; i++) {
          before[i] = before[i].nextSibling;
          container.insertBefore(items[i], before[i]);
        }
        //*/

        /* multi pass
        for (var i = 0; i < 1000; i++)
          container.removeChild(items[i]);
        items.sort(randomly);
        for (var i = 0; i < 1000; i++)
          container.appendChild(items[i]);
        //*/

        console.timeEnd('shuffling');
      },
      2000,
      function randomly() {
        return Math.random() - Math.random();
      }
    );
  };
  function create(name, attributes) {
    return Object.assign(document.createElement(name), attributes);
  }
  </script>
</head>
</html>
```

There is a commented version of the test that explicitly drops all nodes and append back, but I'd like to focus on the _single pass_ case where nodes don't ever actually even leave their container, they are just moved around.

The `connectedCallback` and `disconnectedCallback` trigger each time this movement happens, which is undesired for the "_shuffling_" or general reordering purpose, as it's simple enough to eventually manually dispatch an event to their container after the shuffling happen, if knowing that such shuffling is important.

To trigger the callback version simply pass `?callback` or `?callbacks` to the URL, and check results out.

### No Callbacks Triggered

![Screenshot from 2020-03-02 17-19-42](https://user-images.githubusercontent.com/85749/75695553-8c85dc00-5caa-11ea-8cd2-9631353e4cbe.png)


### With Callbacks Triggered

![Screenshot from 2020-03-02 17-18-48](https://user-images.githubusercontent.com/85749/75695568-93acea00-5caa-11ea-91b4-de133a8f9fce.png)

### Conclusions
Of course the cost of each callback is also important, but the point is that one cannot possibly know what the `connected` and `disconnected` callbacks do, but most of the time do much more than simply updating an attribute (add events, clear events, add listeners, clear listeners, *fetch* content on connected, etcetera)

I hope this was useful.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/whatwg/dom/issues/837#issuecomment-593488340

Received on Monday, 2 March 2020 16:25:59 UTC