#798·cyclejs

Proposed Breaking Change: PR #796, fix(dom): do not duplicate root element with no id

Author: bloodyKnucklesCreated Apr 2, 2018Updated Sep 10, 2026
Labelsissue is breaking suggestionpriority 3 (should)scope: dom

PR #796: fix(dom): do not duplicate root element with no id

It was discovered when targeting the HEAD element, discussed here, that the DOM driver is duplicating the target container when no ID is provided with it. For example, targeting the HEAD tag:

function main () {
  return {
    head: xs.of(head([
      title('About Page'),
      script({attrs: {src: '/assets/client.js'}})
    ]))
  }
}
run(main, {
  head: makeDOMDriver('head')
}

...currently results in:

<head>
  <head>
    <title>About Page</title>
    <script src="/assets/client.js"></script>
  </head>
</head>

This, of course, is not limited to the HEAD tag but any same-name tag that has an ID provided to neither the target container nor the root VDOM element. For example, given:

<!DOCTYPE html>
<html>
<body>
<main></main>
<script src="bundle.js"></script>
</body>
</html>

...and

function mainFunc () {
  return {
    DOM: xs.of(main([
      h3('About Page'),
      div('page content')
    ]))
  }
}
run(mainFunc, {
  DOM: makeDOMDriver('main')
}

...currently results in:

<body>
<main>
  <main>
    <h3>About Page</h3>
    <div>page content</div>
  </main>
</main>
...

Right now this can be overcome by including an empty string ID with the root VDOM object (whether head or main, or div...):

    DOM: xs.of(main('#', [
      h3('About Page'),
      div('page content')
    ]))

This breaking change DOES NOT affect situations where the target container and root VDOM have different tag names. Given the fix proposed in PR #796, and:

<!DOCTYPE html>
<html>
<body>
<div></div>
<script src="bundle.js"></script>
</body>
</html>

...and

function main () {
  return {
    DOM: xs.of(p('page content'))
  }
}
run(main, {
  DOM: makeDOMDriver('div')
}

...results in:

<body>
<div>
  <p>page content</p>
</div>
...

And this breaking change DOES NOT affect situations where the target container OR root VDOM have an ID set. Given the fix proposed in PR #796, and:

<!DOCTYPE html>
<html>
<body>
<div id="app"></div>
<script src="bundle.js"></script>
</body>
</html>

...and

function main () {
  return {
    DOM: xs.of(div('page content'))
  }
}
run(main, {
  DOM: makeDOMDriver('#app')
}

...results in:

<body>
<div id="app">
  <div>page content</div>
</div>
...

...and

function main () {
  return {
    DOM: xs.of(div('#app', 'page content'))
  }
}
run(main, {
  DOM: makeDOMDriver('#app')
}

...results in:

<body>
<div id="app">page content</div>
...

This breaking change DOES affect situations where the target container and root VDOM have the same tag name and neither have an ID set. For example, given the fix proposed in PR #796, and:

<!DOCTYPE html>
<html>
<body>
<div></div>
<script src="bundle.js"></script>
</body>
</html>

...and

function main () {
  return {
    DOM: xs.of(div('page content'))
  }
}
run(main, {
  DOM: makeDOMDriver('div')
}

...results in:

<body>
<div>page content</div>
...

...compared to WITHOUT the proposed fix results in:

<body>
<div>
  <div>page content</div>
</div>
...