Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(patchUrlMappings): recreate script elements when patching their src attribute #242

Merged
merged 2 commits into from
Aug 13, 2024

Conversation

elainemckinley
Copy link
Contributor

@elainemckinley elainemckinley commented Aug 10, 2024

Currently, when a new script tag is created via an imported JavaScript package, we are changing the src attribute for that script tag when it goes through the normal MutationObserver flow. However, a refetch doesn't happen; MutationObserver only goes off when the HTML element is added, but never stops the outgoing request.

With this change, if the MutationObserver sees that it's modifying a <script src= attribute, it'll instead create a new script tag in the DOM next to the one it would have modified, and then destroy the original. Unfortunately this will still show the error from the request blocked by the CSP, but it will go off separately and make the new request with the second script tag as well, loading in the content.

I'd be curious to collect thoughts on this solution. It's obviously destructive to do this for things like img tags (since React for instance would break when it goes to rerender), but I'm hoping this will solve the problem for script tags.

Includes the change from #239, since it was needed to fix my local test case as well.

@@ -11,3 +11,4 @@ To test changes to the SDK, locally, with either of these projects, you must do

1. From terminal, navigate to the root of either project's directory, (i.e. examples/discord-application-start or examples/sdk-playground)
2. Start up the example's web server with `pnpm dev`.
3. Start up the SDK's development pipeline with `pnpm dev`.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🙃

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great callout. We may want to clarify this one is run from the root of the repo

function attemptRecreateScriptNode(node: HTMLElement, {url, mappings}: RemapInput) {
const newUrl = attemptRemap({url, mappings});
if (url.toString() !== newUrl.toString()) {
const newNode = document.createElement(node.tagName);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I couldn't node.clone() here because script nodes have internal state on whether or not the node has started its fetch. See https://html.spec.whatwg.org/multipage/scripting.html and search the page for "already started", or this StackOverflow answer.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great. Thanks for calling out how we got here. It may be worth leaving a comment to explain the motivation

Well done 👏🏻

Comment on lines 119 to 120
attemptSetNodeSrc(node, mappings);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copying my feedback from Andrew's PR

Super-opinionated-pedantic nit

We should rename the function to recursivelyRemapNodeAndChildNodes

or we can call attemptSetNodeSrc inside the original mutation's added nodes

  if (patchSrcAttributes) {
    const callback: MutationCallback = function (mutationsList) {
      for (const mutation of mutationsList) {
        if (mutation.type === 'attributes' && mutation.attributeName === 'src') {
          attemptSetNodeSrc(mutation.target, mappings);
        } else if (mutation.type === 'childList') {
          mutation.addedNodes.forEach((node) => {
            attemptSetNodeSrc(node, mappings);  // Heres the added line
            recursivelyRemapChildNodes(node, mappings);
          });
        }
      }
    };

Either works. I'm pro the code-snippet above as it should result in less function calls. But we should double-check that it still solves the core issue

Copy link
Contributor

@matthova matthova left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks great! 🚢

@elainemckinley elainemckinley merged commit b915ebf into main Aug 13, 2024
1 check passed
@elainemckinley elainemckinley deleted the elaine/fix-dynamic-script-load-mappings branch August 13, 2024 18:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants