Skip to content

Instantly share code, notes, and snippets.

@JamieMason
Last active May 9, 2019 15:19
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JamieMason/ac07a1975ed8a1c0363c to your computer and use it in GitHub Desktop.
Save JamieMason/ac07a1975ed8a1c0363c to your computer and use it in GitHub Desktop.
Create a new JavaScript execution context, to safely extend hosts/natives for example.

Create a new JavaScript execution context

Source

const getNewExecutionContext = markup =>
  new Promise(resolve => {
    const iframe = document.createElement('iframe');
    iframe.style.display = 'none';
    iframe.setAttribute('src', 'about:blank');

    const intervalID = window.setInterval(() => {
      const context = iframe.contentDocument || iframe.contentWindow.document;
      if (context.readyState === 'complete') {
        clearInterval(intervalID);
        context.defaultView.document.write(markup);
        resolve({
          window: context.defaultView,
          destroy() {
            document.documentElement.removeChild(iframe);
          },
        });
      }
    }, 5);
    document.documentElement.appendChild(iframe);
  });

Example Usage

test('renders a valid doctype', async () => {
  const markup = renderHtmlString();
  const context = await getNewExecutionContext(markup);
  expect(context.window.doctype).toEqual('<!DOCTYPE html>');
  context.destroy();
});
@joshnesbitt
Copy link

Really nice work.

@joshnesbitt
Copy link

One suggestion though, would is be better to call onLoad with apply/call to ensure this is set to the correct scope?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment