Skip to content

♻️ use global URL constructor and fall back to pristine iframe only when needed - #4967

Open
BenoitZugmeyer wants to merge 2 commits into
mainfrom
benoit/url-polyfill-fallback
Open

♻️ use global URL constructor and fall back to pristine iframe only when needed#4967
BenoitZugmeyer wants to merge 2 commits into
mainfrom
benoit/url-polyfill-fallback

Conversation

@BenoitZugmeyer

Copy link
Copy Markdown
Member

Motivation

The SDK creates a hidden <iframe> on every page just to read an unpatched URL constructor, even though the global URL works correctly in the vast majority of environments. This is wasteful and can interfere with strict sandboxed contexts (e.g. Shopify Custom Pixels). We should only fall back to the iframe when the global constructor is actually patched or broken.

Changes

  • buildUrl now probes the global URL constructor with a relative-URL resolution check and uses it directly when it behaves correctly, falling back to the pristine iframe-sourced constructor only when needed.
  • Removed the HTMLIFrameElement.prototype.contentWindow shim from the Shopify sandbox patch, no longer necessary now that the iframe path is not taken by default.
  • Moved urlPolyfill.spec.ts next to its source file in js-core.

Test instructions

  • In the sandbox, load a page and confirm view URLs resolve correctly (no hidden iframe created in the DOM).
  • Temporarily override window.URL with a throwing function in the console, then trigger a navigation: URLs should still resolve via the iframe fallback.

Checklist

  • Tested locally
  • Tested on staging
  • Added unit tests for this change.
  • Added e2e/integration tests for this change.
  • Updated documentation and/or relevant AGENTS.md file

@datadog-datadog-prod-us1

datadog-datadog-prod-us1 Bot commented Aug 20, 2026

Copy link
Copy Markdown

Pipelines  Tests

Unblock PR with BitsAI

⚠️ Warnings

🚦 1 Pipeline job failed

DataDog/browser-sdk | unit-bs: [safari-desktop] — ❌ 2 tests failed · 🔧 Needs a code fix, caused by this PR

View in Datadog · View in GitLab

❌ httpRequest HttpRequestEvent observable should report failure for failing requests from Safari 14.1.2 (Mac OS 10.15.7)   View in Datadog
Expected $.length = 1 to equal 2.
Expected $[1] = undefined to equal Object({ type: &#39;success&#39;, bandwidth: Object({ ongoingByteCount: 0, ongoingRequestCount: 0 }), payload: Object({ data: &#39;{&#34;foo&#34;:&#34;barX&#34;}
{&#34;foo&#34;:&#34;barY&#34;}&#39;, bytesCount: 10, retry: Object({ count: 1, lastFailureStatus: 429 }) }) }).
&lt;Jasmine&gt;
webpack:///packages/browser-core/src/transport/httpRequest.spec.ts:199:37 &lt;- /tmp/_karma_webpack_941494/commons.js:64816:43
asyncFunctionResume@[native code]
[native code]
promiseReactionJobWithoutPromise@[native code]
promiseReactionJob@[native code]
❌ httpRequest HttpRequestEvent observable should report multiple failures when requests are retried repeatedly from Safari 14.1.2 (Mac OS 10.15.7)   View in Datadog
Expected $[1].payload.data = &#39;{&#34;foo&#34;:&#34;barX&#34;}
{&#34;foo&#34;:&#34;barY&#34;}&#39; to equal &#39;{&#34;foo&#34;:&#34;barA&#34;}
{&#34;foo&#34;:&#34;barB&#34;}&#39;.
Expected $[1].payload.retry.count = 2 to equal 1.
&lt;Jasmine&gt;
webpack:///packages/browser-core/src/transport/httpRequest.spec.ts:217:37 &lt;- /tmp/_karma_webpack_941494/commons.js:64831:43
asyncFunctionResume@[native code]
[native code]
promiseReactionJobWithoutPromise@[native code]
promiseReactionJob@[native code]

ℹ️ Info

No other issues found (see more)

❄️ No new flaky tests detected

🎯 Code Coverage (details)
Patch Coverage: 85.71%
Overall Coverage: 77.23% (+0.03%)

Useful? React with 👍 / 👎

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 0c09ad8 | Docs | View more details | Give us feedback!

@cit-pr-commenter-54b7da

cit-pr-commenter-54b7da Bot commented Aug 20, 2026

Copy link
Copy Markdown

Bundles Sizes Evolution

📦 Bundle Name Base Size Local Size 𝚫 𝚫% Status
Rum 181.20 KiB 181.31 KiB +113 B +0.06%
Rum Profiler 8.43 KiB 8.43 KiB 0 B 0.00%
Rum Recorder 21.12 KiB 21.12 KiB 0 B 0.00%
Logs 57.52 KiB 57.63 KiB +111 B +0.19%
Rum Salesforce N/A 139.33 KiB N/A N/A N/A
Rum Slim 139.21 KiB 139.32 KiB +112 B +0.08%
Worker 22.96 KiB 22.96 KiB 0 B 0.00%
Rum Shopify N/A 200.92 KiB N/A N/A N/A
Rum-shopify Profiler N/A 8.43 KiB N/A N/A N/A
Rum-shopify Recorder N/A 3.72 KiB N/A N/A N/A

@BenoitZugmeyer
BenoitZugmeyer force-pushed the benoit/url-polyfill-fallback branch 2 times, most recently from 43504fc to 86cdaa1 Compare August 20, 2026 16:12
@BenoitZugmeyer
BenoitZugmeyer marked this pull request as ready for review August 20, 2026 16:18
@BenoitZugmeyer
BenoitZugmeyer requested a review from a team as a code owner August 20, 2026 16:18

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 86cdaa17ca

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

} catch {
// ignore
}
return getPristineWindow().URL

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep the fallback safe inside Shopify pixels

issue: When this probe rejects the global constructor in a Shopify Custom Pixel, getPristineWindow() reads URL from the nested iframe's cross-origin contentWindow; that property access is outside its try block and throws a SecurityError. This commit simultaneously removes the contentWindow shim that previously prevented that access, so the advertised fallback breaks view/URL resolution precisely when a patched or partially functional URL makes it necessary. Keep the Shopify guard or make the pristine-constructor lookup safely fall back without accessing the cross-origin window.

AGENTS.md reference: packages/js-core/AGENTS.md:L33-L44

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

No, the URL should be available in shopify pixel environment, so we won't need this fallback.

Comment thread packages/js-core/src/util/urlPolyfill.ts Outdated
Comment thread packages/js-core/src/util/urlPolyfill.ts
Comment thread packages/js-core/src/util/urlPolyfill.ts Outdated
@BenoitZugmeyer
BenoitZugmeyer force-pushed the benoit/url-polyfill-fallback branch from 86cdaa1 to f1637bd Compare August 20, 2026 16:29
…hen needed

Creating a hidden iframe on every page just to read an unpatched URL
constructor is wasteful when the global one works fine. Probe it with a
relative-URL resolution check and only fall back to the iframe-sourced
constructor when it is patched or broken. This also drops the
contentWindow shim in the Shopify sandbox patch, no longer needed now
that the iframe path is not taken by default.
@BenoitZugmeyer
BenoitZugmeyer force-pushed the benoit/url-polyfill-fallback branch from f1637bd to 0c09ad8 Compare August 20, 2026 16:36
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.

1 participant