Skip to content

Comments

Add polyfills for new Set methods (union, intersection, difference, symmetricDifference, isSubsetOf, isSupersetOf, isDisjointFrom)#110

Merged
mattcosta7 merged 2 commits intomainfrom
copilot/add-set-methods-polyfill
Feb 23, 2026
Merged

Add polyfills for new Set methods (union, intersection, difference, symmetricDifference, isSubsetOf, isSupersetOf, isDisjointFrom)#110
mattcosta7 merged 2 commits intomainfrom
copilot/add-set-methods-polyfill

Conversation

Copy link
Contributor

Copilot AI commented Feb 23, 2026

Safari 16.4 lacks support for the seven newly-baseline Set methods available in ES2024/TypeScript's es2024 lib. This adds polyfills so they can be used safely today.

Changes

  • src/set-methods.ts — New polyfill module implementing all seven methods against a SetLike<T> interface (has, keys, size) per TC39 spec, including spec-aligned optimizations (e.g. isSubsetOf short-circuits when this.size > other.size; isDisjointFrom iterates the smaller set). Follows the standard isSupported() / isPolyfilled() / apply() pattern.
  • src/index.ts — Registers setMethods alongside existing polyfills.
  • test/set-methods.js — Tests for all seven methods covering common cases and edge cases (empty sets, disjoint sets, identical sets).

Usage

import { apply } from '@github/browser-support/set-methods'
apply() // no-op if natively supported

const a = new Set([1, 2, 3])
const b = new Set([2, 3, 4])

a.union(b)               // Set {1, 2, 3, 4}
a.intersection(b)        // Set {2, 3}
a.difference(b)          // Set {1}
a.symmetricDifference(b) // Set {1, 4}
a.isSubsetOf(b)          // false
a.isSupersetOf(b)        // false
a.isDisjointFrom(b)      // false

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • accounts.google.com
    • Triggering command: /proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --disable-dev-shm-usage --use-angle=swiftshader-webgl --mute-audio --crashpad-handler-pid=4006 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/puppeteer_dev_chrome_profile-z0xwaJ --change-stack-guard-on-fork=enable --shared-files=v8_context_snapshot_data:100 --field-trial-handle=3,i,16526546639982034433,11159440813740539228,262144 --enable-features=PdfOopif --disable-features=AcceptCHFrame,IsolateSandboxedIframes,MediaRouter,OptimizationHints,PaintHolding,ProcessPerSiteUpToMainFrameThreshold,Translate --variations-seed-version --trace-process-track-uuid=3190708989122997041 (dns block)
    • Triggering command: /opt/google/chrome/chrome /usr/bin/google-chrome-stable --allow-pre-commit-input --disable-REDACTED-networking --disable-REDACTED-timer-throttling --disable-REDACTEDing-occluded-windows --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-REDACTED-pages --disable-crash-reporter --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-hang-monitor --disable-infobars --disable-ipc-flooding-protection --disable-popup-blocking --disable-prompt-on-repost --disable-renderer-REDACTEDing --disable-search-engine-choice-screen --disable-sync (dns block)
    • Triggering command: /proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --disable-dev-shm-usage --use-angle=swiftshader-webgl --mute-audio --crashpad-handler-pid=4258 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/puppeteer_dev_chrome_profile-IkdZcd --change-stack-guard-on-fork=enable --shared-files=v8_context_snapshot_data:100 --field-trial-handle=3,i,4382833278840495840,8209209942178505960,262144 --enable-features=PdfOopif --disable-features=AcceptCHFrame,IsolateSandboxedIframes,MediaRouter,OptimizationHints,PaintHolding,ProcessPerSiteUpToMainFrameThreshold,Translate --variations-seed-version --trace-process-track-uuid=3190708989122997041 (dns block)
  • api.openweathermap.org
    • Triggering command: /home/REDACTED/work/_temp/ghcca-node/node/bin/node node /home/REDACTED/.npm/_npx/60193c364be7f30b/node_modules/.bin/wtr test/set-methods.js --node-resolve (dns block)
  • clients2.google.com
    • Triggering command: /proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --disable-dev-shm-usage --use-angle=swiftshader-webgl --mute-audio --crashpad-handler-pid=4006 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/puppeteer_dev_chrome_profile-z0xwaJ --change-stack-guard-on-fork=enable --shared-files=v8_context_snapshot_data:100 --field-trial-handle=3,i,16526546639982034433,11159440813740539228,262144 --enable-features=PdfOopif --disable-features=AcceptCHFrame,IsolateSandboxedIframes,MediaRouter,OptimizationHints,PaintHolding,ProcessPerSiteUpToMainFrameThreshold,Translate --variations-seed-version --trace-process-track-uuid=3190708989122997041 (dns block)
    • Triggering command: /opt/google/chrome/chrome /usr/bin/google-chrome-stable --allow-pre-commit-input --disable-REDACTED-networking --disable-REDACTED-timer-throttling --disable-REDACTEDing-occluded-windows --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-REDACTED-pages --disable-crash-reporter --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-hang-monitor --disable-infobars --disable-ipc-flooding-protection --disable-popup-blocking --disable-prompt-on-repost --disable-renderer-REDACTEDing --disable-search-engine-choice-screen --disable-sync (dns block)
    • Triggering command: /proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --disable-dev-shm-usage --use-angle=swiftshader-webgl --mute-audio --crashpad-handler-pid=4258 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/puppeteer_dev_chrome_profile-IkdZcd --change-stack-guard-on-fork=enable --shared-files=v8_context_snapshot_data:100 --field-trial-handle=3,i,4382833278840495840,8209209942178505960,262144 --enable-features=PdfOopif --disable-features=AcceptCHFrame,IsolateSandboxedIframes,MediaRouter,OptimizationHints,PaintHolding,ProcessPerSiteUpToMainFrameThreshold,Translate --variations-seed-version --trace-process-track-uuid=3190708989122997041 (dns block)
  • safebrowsingohttpgateway.googleapis.com
    • Triggering command: /proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --disable-dev-shm-usage --use-angle=swiftshader-webgl --mute-audio --crashpad-handler-pid=4006 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/puppeteer_dev_chrome_profile-z0xwaJ --change-stack-guard-on-fork=enable --shared-files=v8_context_snapshot_data:100 --field-trial-handle=3,i,16526546639982034433,11159440813740539228,262144 --enable-features=PdfOopif --disable-features=AcceptCHFrame,IsolateSandboxedIframes,MediaRouter,OptimizationHints,PaintHolding,ProcessPerSiteUpToMainFrameThreshold,Translate --variations-seed-version --trace-process-track-uuid=3190708989122997041 (dns block)
    • Triggering command: /opt/google/chrome/chrome /usr/bin/google-chrome-stable --allow-pre-commit-input --disable-REDACTED-networking --disable-REDACTED-timer-throttling --disable-REDACTEDing-occluded-windows --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-REDACTED-pages --disable-crash-reporter --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-hang-monitor --disable-infobars --disable-ipc-flooding-protection --disable-popup-blocking --disable-prompt-on-repost --disable-renderer-REDACTEDing --disable-search-engine-choice-screen --disable-sync (dns block)
    • Triggering command: /proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --disable-dev-shm-usage --use-angle=swiftshader-webgl --mute-audio --crashpad-handler-pid=4258 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/puppeteer_dev_chrome_profile-IkdZcd --change-stack-guard-on-fork=enable --shared-files=v8_context_snapshot_data:100 --field-trial-handle=3,i,4382833278840495840,8209209942178505960,262144 --enable-features=PdfOopif --disable-features=AcceptCHFrame,IsolateSandboxedIframes,MediaRouter,OptimizationHints,PaintHolding,ProcessPerSiteUpToMainFrameThreshold,Translate --variations-seed-version --trace-process-track-uuid=3190708989122997041 (dns block)
  • www.google.com
    • Triggering command: /proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --disable-dev-shm-usage --use-angle=swiftshader-webgl --mute-audio --crashpad-handler-pid=4006 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/puppeteer_dev_chrome_profile-z0xwaJ --change-stack-guard-on-fork=enable --shared-files=v8_context_snapshot_data:100 --field-trial-handle=3,i,16526546639982034433,11159440813740539228,262144 --enable-features=PdfOopif --disable-features=AcceptCHFrame,IsolateSandboxedIframes,MediaRouter,OptimizationHints,PaintHolding,ProcessPerSiteUpToMainFrameThreshold,Translate --variations-seed-version --trace-process-track-uuid=3190708989122997041 (dns block)
    • Triggering command: /opt/google/chrome/chrome /usr/bin/google-chrome-stable --allow-pre-commit-input --disable-REDACTED-networking --disable-REDACTED-timer-throttling --disable-REDACTEDing-occluded-windows --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-REDACTED-pages --disable-crash-reporter --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-hang-monitor --disable-infobars --disable-ipc-flooding-protection --disable-popup-blocking --disable-prompt-on-repost --disable-renderer-REDACTEDing --disable-search-engine-choice-screen --disable-sync (dns block)
    • Triggering command: /proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --disable-dev-shm-usage --use-angle=swiftshader-webgl --mute-audio --crashpad-handler-pid=4258 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/puppeteer_dev_chrome_profile-IkdZcd --change-stack-guard-on-fork=enable --shared-files=v8_context_snapshot_data:100 --field-trial-handle=3,i,4382833278840495840,8209209942178505960,262144 --enable-features=PdfOopif --disable-features=AcceptCHFrame,IsolateSandboxedIframes,MediaRouter,OptimizationHints,PaintHolding,ProcessPerSiteUpToMainFrameThreshold,Translate --variations-seed-version --trace-process-track-uuid=3190708989122997041 (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

This section details on the original issue you should resolve

<issue_title>Add polyfill for newly available Set methods</issue_title>
<issue_description>when using typescript es2024 Set method types are available, but Safari 16.4 still doesn't support them (they're baselines newly available). we shouldpolyfill and remove once they fall off support

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/intersection
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/difference
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/isDisjointFrom
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/isSubsetOf
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/isSupersetOf
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/symmetricDifference
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/union

</issue_description>

Comments on the Issue (you are @copilot in this section)


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

…ce, symmetricDifference, isSubsetOf, isSupersetOf, isDisjointFrom)

Co-authored-by: mattcosta7 <8616962+mattcosta7@users.noreply.github.com>
Copilot AI changed the title [WIP] Add polyfill for newly available Set methods Add polyfills for new Set methods (union, intersection, difference, symmetricDifference, isSubsetOf, isSupersetOf, isDisjointFrom) Feb 23, 2026
@mattcosta7 mattcosta7 marked this pull request as ready for review February 23, 2026 16:39
@mattcosta7 mattcosta7 requested a review from a team as a code owner February 23, 2026 16:39
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds an ES2024 Set-methods polyfill module so consumers can safely use the newly-baseline Set APIs (e.g. union, intersection) in browsers like Safari 16.4 that lack native support, and registers it in the library’s aggregated polyfill entrypoint.

Changes:

  • Added src/set-methods.ts implementing union, intersection, difference, symmetricDifference, isSubsetOf, isSupersetOf, isDisjointFrom plus isSupported() / isPolyfilled() / apply().
  • Registered the new polyfill under polyfills in src/index.ts.
  • Added test/set-methods.js with unit tests for the exported implementations.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
src/set-methods.ts New polyfill module implementing and installing the ES2024 Set methods.
src/index.ts Registers setMethods in the global polyfills list.
test/set-methods.js Adds tests for the new Set-method implementations.
Comments suppressed due to low confidence (3)

src/set-methods.ts:101

  • isSupported() only checks property existence via 'name' in Set.prototype, which can return true even if a non-function value is present (or something is inherited). This can cause apply() to be skipped while the methods still aren't callable. Consider also checking typeof Set.prototype.union === 'function' (and the rest) like the other polyfills do.
export function isSupported(): boolean {
  return (
    'union' in Set.prototype &&
    'intersection' in Set.prototype &&
    'difference' in Set.prototype &&
    'symmetricDifference' in Set.prototype &&
    'isSubsetOf' in Set.prototype &&
    'isSupersetOf' in Set.prototype &&
    'isDisjointFrom' in Set.prototype
  )

src/set-methods.ts:129

  • apply() installs all 7 methods whenever any of them are missing. In environments with partial native support, this will overwrite the native implementations (and potentially change behavior/perf). Prefer installing each method only if it's missing (similar to iterator-helpers.ts), so native methods are preserved.
export function apply(): void {
  if (!isSupported()) {
    Object.assign(Set.prototype, {
      union,
      intersection,
      difference,
      symmetricDifference,
      isSubsetOf,
      isSupersetOf,
      isDisjointFrom,
    })

test/set-methods.js:23

  • Tests currently exercise the exported functions via .call(...) but don't verify apply() actually installs the methods on Set.prototype (e.g., new Set([1]).union(...)) or that isPolyfilled() becomes true after applying. Adding at least one prototype-level test would cover the primary integration path.
  it('has standard isSupported, isPolyfilled, apply API', () => {
    expect(isSupported).to.be.a('function')
    expect(isPolyfilled).to.be.a('function')
    expect(apply).to.be.a('function')
    expect(isSupported()).to.be.a('boolean')
    expect(isPolyfilled()).to.equal(false)
  })

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

const proto = Set.prototype as unknown as Record<string, unknown>
return (
'union' in Set.prototype &&
proto['union'] === union &&
Copy link
Contributor

Choose a reason for hiding this comment

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

We are not adding this check: proto['union'] === union && to isSupported. Is that intended?

Copy link
Member

Choose a reason for hiding this comment

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

yep, I believe that's right, if I understand it correctly?

isSupported supports both polyfilled and not, so it should cover both cases (once the polyfill is applied), while isPolyfilled validates whether the support came from the polyfill applied or by built in support (which I think for us is everything but safari 16 or 17)

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh I see, yeah that makes sense!

@mattcosta7 mattcosta7 merged commit 6578b5b into main Feb 23, 2026
9 checks passed
@mattcosta7 mattcosta7 deleted the copilot/add-set-methods-polyfill branch February 23, 2026 21:53
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.

Add polyfill for newly available Set methods

3 participants