Cloned <script> tags do not execute. Why?
<script id="hello"> console.log("hello execution count ", window.helloCount++); </script> <script id="action"> document.body.appendChild( document.getElementById('hello').cloneNode(true)); console.log('cloned the script'); </script>
After execution, there are two hello scripts in the document, but only one has executed.
This is part of a larger problem I am working on, so I know it is a dumb thing to do.
This behavior is required by the W3C HTML5 specification.
<script> element has a property flag called "already started". The specification says:
Initially, script elements must have this flag unset (script blocks, when created, are not "already started"). The cloning steps for script elements must set the "already started" flag on the copy if it is set on the element being cloned.
And then, later:
If the script element is marked as having "already started", then the user agent must abort these steps at this point. The script is not executed.
The solution is simply not to clone script elements, but to create completely new elements that are populated with the same content.
I don't know why it doesn't work with
cloneNode, but you can achieve the same result by copying the
innerHTML to a new script node.
var clone = document.createElement('script'); clone.innerHTML = document.getElementById('hello').innerHTML; document.body.appendChild(clone); console.log('copied the script');
<script> window.helloCount = 1; </script> <script id="hello"> console.log("hello execution count ", window.helloCount++); </script> <div>Copied scripts do execute</div>
In principle browser does the following when it executes
<script> on the page:
<script> was not executed before it does the following:
<script>DOM node as executed;
When you clone the node it gets that internal "executed" flag too, it prevents the script from further executions.
Solution: if you want script to be re-executed do steps #1 and #2. Cloning is not required in this case.
©2020 All rights reserved.