Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[BUG] Fails with "Execution context was destroyed" when iframes are removed #64

@mccahan

Description

@mccahan

Describe the bug
I have a page that uses html2canvas to "screenshot" part of the page to use as a texture with ThreeJS for a particular effect. When html2canvas runs, it creates an iframe with a copy of the page, takes its screenshot, and then destroys the iframe. Running timecut and timesnap on a page that removes an iframe results in a fatal error as it attempts to execute the time overwriting on an invalid execution context:

Error: Execution context was destroyed, most likely because of a navigation.
    at rewriteError (/Volumes/Projects/timesnap/node_modules/puppeteer/lib/ExecutionContext.js:167:15)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async ExecutionContext._evaluateInternal (/Volumes/Projects/timesnap/node_modules/puppeteer/lib/ExecutionContext.js:120:56)
    at async ExecutionContext.evaluate (/Volumes/Projects/timesnap/node_modules/puppeteer/lib/ExecutionContext.js:48:12)
    at async Promise.all (index 1)
    at async run (/Volumes/Projects/timesnap/index.js:251:9)
    at async module.exports (/Volumes/Projects/timesnap/index.js:285:5)
  -- ASYNC --
    at ExecutionContext.<anonymous> (/Volumes/Projects/timesnap/node_modules/puppeteer/lib/helper.js:111:15)
    at DOMWorld.evaluate (/Volumes/Projects/timesnap/node_modules/puppeteer/lib/DOMWorld.js:112:20)
  -- ASYNC --
    at Frame.<anonymous> (/Volumes/Projects/timesnap/node_modules/puppeteer/lib/helper.js:111:15)
    at /Volumes/Projects/timesnap/lib/overwrite-time.js:56:18
    at Array.map (<anonymous>)
    at Object.goToTimeAndAnimate (/Volumes/Projects/timesnap/lib/overwrite-time.js:55:36)
    at run (/Volumes/Projects/timesnap/index.js:251:27)
    at async module.exports (/Volumes/Projects/timesnap/index.js:285:5)
node:internal/process/promises:246
          triggerUncaughtException(err, true /* fromPromise */);
          ^

On the first captured frame after the iframe is removed, Puppeteer throws the "Execution context was destroyed" exception message. If we catch that exception, a captured frame or two later Puppeteer will throw a different exception that the (browser) frame has been detached:

Error: Execution Context is not available in detached frame "https://tungs.github.io/amuse/truchet-tiles/" (are you trying to evaluate?)
    at DOMWorld.executionContext (/Volumes/Projects/timesnap/node_modules/puppeteer/lib/DOMWorld.js:91:13)
    at DOMWorld.evaluate (/Volumes/Projects/timesnap/node_modules/puppeteer/lib/DOMWorld.js:111:32)
    at Frame.evaluate (/Volumes/Projects/timesnap/node_modules/puppeteer/lib/FrameManager.js:439:28)
    at Frame.<anonymous> (/Volumes/Projects/timesnap/node_modules/puppeteer/lib/helper.js:112:23)
    at /Volumes/Projects/timesnap/lib/overwrite-time.js:60:18
    at Array.map (<anonymous>)
    at Object.goToTimeAndAnimate (/Volumes/Projects/timesnap/lib/overwrite-time.js:55:36)
    at run (/Volumes/Projects/timesnap/index.js:251:27)
    at async module.exports (/Volumes/Projects/timesnap/index.js:291:5)
node:internal/process/promises:246
          triggerUncaughtException(err, true /* fromPromise */);

I do have my own version of a fix at https://github.com/mccahan/timesnap/pull/1/files if you'd like me to Pull Request it - I didn't want to assume where you might want to catch the exception.

Checking the exception message for the string "Execution context was destroyed" feels flimsy, but it mirrors the check that Puppeteer uses internally. I was unable to find a way to determine ahead of time whether the context was destroyed, the only way I could find to test for it is to try and catch an exception afterwards.

I also added in a check to skip processing on (browser) frames that are marked as detached. This negates the second fatal exception.

To Reproduce

  1. Create file remove-iframe.html with the contents from the Attachments section below
  2. Run node cli.js remove-iframe.html
  3. After 1-2 successful frame captures, it will throw an exception and die

Expected behavior
Expected it to gracefully handle (intentional) removals of iframes, continuing to capture.

Attachments and Screenshots

Simplest sample recreation page:

<html>
<body>
  <iframe src="https://tungs.github.io/amuse/truchet-tiles/#autoplay=true&switchStyle=random"></iframe>
  <script>
    setTimeout(() => {
      document.querySelector('iframe').remove()
    }, 20)
  </script>
</body>
</html>

Desktop (please complete the following information):

  • OS: macOS 12.0.1 (M1 Mac)
  • Node Version v17.3.0
  • Timesnap Version 0.3.3-prerelease, 0.3.2

Additional context
I hit the same issue in timecut, but it seems this is the appropriate repo to address it?

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions