Skip to content

runtime: implement ES Set composition methods #2872

Description

@andrewtdiz

Summary

Node exposes the ES Set composition methods on Set.prototype, but Perry does not implement dispatch/runtime behavior for them:

  • union(other)
  • intersection(other)
  • difference(other)
  • symmetricDifference(other)
  • isSubsetOf(other)
  • isSupersetOf(other)
  • isDisjointFrom(other)

These are now part of the modern JS runtime surface and are used by newer libraries that target current Node.

Expected Node behavior

Local Node v25.9.0 probe:

for (const m of [
  "union",
  "intersection",
  "difference",
  "symmetricDifference",
  "isSubsetOf",
  "isSupersetOf",
  "isDisjointFrom",
]) {
  console.log(m, typeof Set.prototype[m]);
}

const a = new Set([1, 2]);
const b = new Set([2, 3]);
console.log([...a.union(b)]);                // [1, 2, 3]
console.log([...a.intersection(b)]);         // [2]
console.log([...a.difference(b)]);           // [1]
console.log([...a.symmetricDifference(b)]);  // [1, 3]
console.log(a.isSubsetOf(new Set([1, 2, 3]))); // true
console.log(a.isSupersetOf(new Set([1])));     // true
console.log(a.isDisjointFrom(new Set([4])));   // true

Current Perry behavior in source

docs/typescript-parity-gaps.md still lists these Set methods as missing.

crates/perry-codegen/src/expr/literals_vars.rs::is_set_method_name() includes the ES2024 composition names so property-value reads can look function-like:

"union"
| "intersection"
| "difference"
| "symmetricDifference"
| "isSubsetOf"
| "isSupersetOf"
| "isDisjointFrom"

However, source search found no corresponding HIR variants, no typed lowering in crates/perry-codegen/src/lower_call/property_get.rs, no crates/perry-runtime/src/set.rs helpers, and no dynamic branches in crates/perry-runtime/src/object/native_call_method.rs for these methods. That means the names may be visible as prototype method values, but actual calls do not have Node-compatible behavior.

Suggested tests

Add parity coverage for the basic Set inputs:

const a = new Set([1, 2]);
const b = new Set([2, 3]);
expect([...a.union(b)]).toEqual([1, 2, 3]);
expect([...a.intersection(b)]).toEqual([2]);
expect([...a.difference(b)]).toEqual([1]);
expect([...a.symmetricDifference(b)]).toEqual([1, 3]);
expect(a.isSubsetOf(new Set([1, 2, 3]))).toBe(true);
expect(a.isSupersetOf(new Set([1]))).toBe(true);
expect(a.isDisjointFrom(new Set([4]))).toBe(true);

Follow-up tests should cover set-like objects and TypeError cases once the basic Set-to-Set behavior is wired.

Scope / non-goals

This is scoped to exposing and dispatching the ES Set composition methods with Node-compatible basic behavior. Iterator object shape for existing keys / values / entries remains separate (#2856), and Set insertion-order preservation after delete is tracked in #2831.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions