Exec Script

Inject SCRIPT in execute SCRIPT in shadowDOM scope

by Danny Engelman

HTML

<template id=scriptContainer>
  <script>
    console.log("script runs in Global scope!!");

    function GlobalFunction(scope, marker) {
      scope = scope.getRootNode().host || scope;
      console.log('run', marker, 'scope:', scope);
      scope.elementMethod && scope.elementMethod();
    }

  </script>
  <img src onerror="(()=>{
    // IIFE not required
    // onerror runs async! so after Event loop and all elements are done.
    this.onerror = null;// prevent endless loop if function itself generates an error
    GlobalFunction(this,'fromIMGonerror');
    this.remove();
  })()">
</template>
<my-element id=ONE></my-element>
<my-element id=TWO></my-element>
<script>
  /* document.body.append(scriptContainer.content.cloneNode(true)); */
  console.log('START SCRIPT');
  customElements.define('my-element',
    class extends HTMLElement {
      connectedCallback() {
        console.log('connectedCallback', this.id);
        this.attachShadow({
          mode: 'open'
        }).append(scriptContainer.content.cloneNode(true));
      }
      addElement(tag, content) {
        if (typeof tag == "string") {
          tag = this.shadowRoot.appendChild(document.createElement(tag));
        } else {
        	tag = tag.shadowRoot;
        }
        typeof content == "string" ? tag.innerHTML = content : tag.append(...content);
        return tag;
      }
      elementMethod() {
        console.log('elementMethod', this.id);
        this.addElement(this,["content:", this.id]);
        this.addElement("PRE", this.shadowRoot.innerHTML.replace(/</g, "&lt;"));
        //script from first TWO.runScript is still in the DOM
        //and shown as <span in the second Element
        //because the span.remove() is done after the EventLoop is empty
        TWO.runScript(`console.log(${this.id}.id,'runs in',element.id)`); //duplicate line in console!
        TWO.runScript(`console.log(${this.id}.id,'runs in',element.id)`); //duplicate line in console!
      }
      runScript(script) {
...