I’m working on a project with over 200 image targets, and I’m using pooling to create xrextras-named-image-target dynamically. When an image target is found, a video element is attached as a child to xrextras-named-image-target, but whenever the image target is lost, and I want to remove the child from DOM, I get continuous warnings stating:
xr-simd-24.1.2.2165.js:18 WebGL: INVALID_OPERATION: useProgram: attempt to use a deleted object"
The warning propagation stops when I find an image target again. I can’t understand the erroneous code because it’s minified:
// xr-simd.js
if (Object.keys(y).forEach((function(I) {
    A[I] = function() {
        for (var g, C = arguments.length, Q = new Array(C), B = 0; B < C; B++)
Q[B] = arguments[B];
        var E = (g = H[I]).call.apply(g, [A].concat(Q));  // g IS EMPTY
        return Y.apply(void 0, [I].concat(Q)),
        E
    }
}
this: WebGL2RenderingContext
B: 1
C: 1
E: undefined
Q: [WebGLProgram]
g: undefined
Problem
Everything seems to work despite the warning, but I wonder why the warning happens, and how I get rid of it.
My code
The functionality in short:
- Image target is found,
 #imageTargetwith theec-named-image-targetcomponent is added to the scene viasceneEl.components.pool__imagetarget.requestEntity(),- The content of 
#imagetarget-video- an a-entity that plays a video, is appended to#imageTarget, - When the image target is lost, the child element 
#imagetarget-videois removed from DOM. - The warning is triggered.
 
<!-- index.html -->
<a-scene
  xrextras-loading
  pool__imagetarget="mixin: imagetarget; size: 3; dynamic: true"
  xrextras-runtime-error
  camera-feed-delegator
  renderer="colorManagement:true; webgl2: true;"
  xrweb="disableWorldTracking: true;"
>
  <a-assets>
    <img id="imagetarget-video-thumbnail" crossorigin="anonymous" src="./assets/img/thumbs/video-play-button.png" />
     <!-- "src" is set in dynamicTarget.js when an image target is found -->
    <video id="imagetarget-video-asset"
      playsinline
      crossorigin="anonymous"
      loop="false"
      src=""
    ></video>
     <!-- ec-named-image-target is a modification of xrextras-named-image-target-->
    <a-mixin id="imagetarget" ec-named-image-target></a-mixin>
  </a-assets>
<!-- This entity is injected into #imageTarget in dynamicTarget.js -->
<template id="imagetarget-video">
  <a-entity
    ec-play-video="video: #imagetarget-video-asset; thumb: #imagetarget-video-thumbnail; canstop: true;"
    geometry="primitive: plane; height: 1.38; width: 0.776;"
    material="transparent: true">
  ></a-entity>
</template>
// index.js
import { cameraFeedDelegator } from './src/js/components/image-targeting/camera-feed-delegator.js';
import { ecNamedImageTarget } from './src/js/components/image-targeting/ec-named-image-target.js';
// Register components and primitives
AFRAME.registerComponent('camera-feed-delegator', cameraFeedDelegator);
AFRAME.registerComponent('ec-named-image-target', ecNamedImageTarget);
// ecNamedImageTarget.js - just a modification of xrextras-image-target, but with the event listener for  `xrimagefound` moved to dynamicTargeting.js
const ecNamedImageTarget = {
  schema: {
    name: {type: 'string'},
    target: {type: 'string'}
  },
  init() {
    const {object3D} = this.el
    const updateImage = ({detail}) => {
      if (this.data.name === detail.name) {
        object3D.position.copy(detail.position)
        object3D.quaternion.copy(detail.rotation)
        object3D.scale.set(detail.scale, detail.scale, detail.scale)
        object3D.visible = true
      }
    }
    const removeComponent = ({detail}) => {
      if (this.data.name === detail.name) {
        this.data.name = null;
        object3D.visible = false;
        this.el.innerHTML = '';  // THIS LINE CREATES THE ERROR, when ec-named-image-target is removed from the DOM.
        
        this.el.sceneEl.components.pool__imagetarget.returnEntity(this.el);
      }
    }
    this.el.sceneEl.addEventListener('xrimageupdated', updateImage);
    this.el.sceneEl.addEventListener('xrimagelost', removeComponent);
  },
}
export {ecNamedImageTarget}
// cameraFeedDelegator.js
const cameraFeedDelegator = {
  init() {
    const dynamicTargeting = new DynamicTargeting();
    // sets all the target images that the app should loop through. Not relevant for this case.
    dynamicTargeting.updateTargetElements() 
    window.addEventListener('xrimagefound', ({detail}) => {
        dynamicTargeting.foundTarget(detail.name, this.el.sceneEl);
    });
  
    window.addEventListener('xrimagelost', ({detail}) => {
      dynamicTargeting.lostTarget(detail.name, this.el.sceneEl);
    });
  }
}
export {cameraFeedDelegator}
// dynamicTargeting.js
export default class DynamicTargeting {
    targets = [];
    found = new Set();
    constructor() {
      this.videoEl = document.getElementById("imagetarget-video").content.firstElementChild;
      this.videoAssetEl = document.getElementById("imagetarget-video-asset");
    }
    updateTargetElements(imageTargets) {
        // ... code for looping through image targets, using this.found and this.targets.
    }
    /**
     * Adds ec-named-image-target from the pool to a-scene
     * Always making sure that the found image target is being scanned
     */
    foundTarget(imageTargetName, sceneEl) {
        this.found.add(imageTargetName);
        this.targets.splice(this.targets.indexOf(imageTargetName), 1);
  
        let imageTargetEl = sceneEl.components.pool__imagetarget.requestEntity();
        imageTargetEl.innerHTML = '';  // REMOVING THE CHILD HERE doesn't trigger the error.
  
        imageTargetEl.appendChild(childEl);
        // Sets the name of the image target that is being tracked.
        imageTargetEl.setAttribute('ec-named-image-target', `name: ${imageTargetName}`);
      }
    }
    /**
     * Restores this.targets if the image target is lost.
     */
    lostTarget(imageTargetName, sceneEl) {
      this.found.delete(name);
      this.targets.push(name);
    }
}