partytown icon indicating copy to clipboard operation
partytown copied to clipboard

loadScriptsOnMainThread regex stringify bug

Open azurre99 opened this issue 1 year ago • 2 comments

There seems to be a problem with how regex is being serialized in the partytown/src/module.ts. As showed on first picture I pass to partytown config two regular expressions, however on second picture these two regular expressions get converted to empty objects, when inspecting inside the browser.

Current workaround is to include full urls of all the scripts you want to run on the main thread, but this is not optimal, as these are scripts controlled by GTM in my case, and URLs can change, so regex would be really nice here.

Image Image

azurre99 avatar Oct 22 '24 12:10 azurre99

can u give a minimal reproducible example?

muhsin-life avatar Dec 09 '24 13:12 muhsin-life

I'm experiencing the same issue.

First, loadScriptsOnMainThread is not whitelisted in this context. https://github.com/nuxt-modules/partytown/blob/4c534d941d7e132b9cedb7fc02c3ff0fda5db9a5/src/module.ts#L61

As a result, the following code causes RegExp value to be serialized as {} : https://github.com/nuxt-modules/partytown/blob/4c534d941d7e132b9cedb7fc02c3ff0fda5db9a5/src/module.ts#L64

JSON.stringify(['https://example.com', /https:\/\/example\.com/])
// '["https://example.com",{}]'

However, even if loadScriptsOnMainThread is added to whitelist, the problem persists. It seems that genObjectFromRawEntries method in knitwork does not support RegExp code generation.

https://github.com/nuxt-modules/partytown/blob/4c534d941d7e132b9cedb7fc02c3ff0fda5db9a5/src/module.ts#L66

Here's a relevant test case setup (in knitwork):

import { expect, describe, it } from "vitest";
import { genObjectFromRawEntries } from "../src";
import { genTestTitle } from "./_utils";

const genObjectFromRawTests = [
  {
    obj: {
      resolveUrl: "https://example.com",
      loadScriptsOnMainThread: [
        "https://example.com",
        /https:\/\/example\.com/,
      ],
    },
    code: [
      "{",
      "  resolveUrl: https://example.com,",
      "  loadScriptsOnMainThread: [",
      "    https://example.com,",
      "    /https:\\/\\/example\\.com\\/,",
      "  ]",
      "}",
    ].join("\n"),
  },
];

describe("genObjectFromRawEntries", () => {
  for (const t of genObjectFromRawTests) {
    it(genTestTitle(t.code), () => {
      const code = genObjectFromRawEntries(Object.entries(t.obj));
      expect(code).to.equal(t.code);
    });
  }
});

Test results:

FAIL  test/regexp.test.ts > genObjectFromRawEntries > {   resolveUrl: https://example.com,   loadScriptsOnMainThread: [     https://example.com,     /https:\/\/example\.com\/,   ] }
AssertionError: expected '{\n  resolveUrl: https://example.com,…' to equal '{\n  resolveUrl: https://example.com,…'

- Expected
+ Received

  {
    resolveUrl: https://example.com,
    loadScriptsOnMainThread: [
      https://example.com,
-     /https:\/\/example\.com\/,
+     {}
    ]
  }

I hope this information helps in resolving the issue.

elcih17 avatar May 13 '25 06:05 elcih17