Skip to content

RFC: Unify JSFunction and JSObject #402

@kateinoigakukun

Description

@kateinoigakukun

Problem

The current inheritance hierarchy between JSFunction and JSObject creates several design issues:

  1. Mismatch with JavaScript's dynamic callability: In JavaScript, any object can potentially be callable (through Proxy traps or other mechanisms), but our type system assumes objects and functions are mutually exclusive categories
  2. Complex Inheritance: The inheritance structure makes the codebase unnecessarily complex to maintain
  3. Inconsistent Closure Hierarchy:
    • JSClosure inherits from JSFunction
    • JSOneshotClosure inherits from JSObject
    • This inconsistency creates confusion about which base class to use
  4. Type System Gap: JSObject.global.Function.function\!.new returns a JSObject that should be callable, but it's not in our type system

Current Architecture

  • JSFunction inherits from JSObject
  • JSClosure inherits from JSFunction
  • JSOneshotClosure inherits from JSObject
  • JSValue enum has separate cases for .function and .object

Proposed Solution

Unify JSFunction and JSObject by:

  1. Merge functionality: Move all JSFunction functionality into JSObject
  2. Add callability detection: Provide runtime checks for callable objects
  3. Simplify closures: Make JS(Oneshot)Closure composition-based rather than inheritance-based
  4. Update JSValue: Remove separate function case, use single object case

Benefits

  • Aligns type system with JavaScript's dynamic callability
  • Reduces inheritance complexity
  • Provides consistent closure architecture
  • Simplifies API surface with unified object model

Migration Strategy

  1. Add deprecated JSFunction class that forwards to JSObject
  2. Update all JSFunction usage to JSObject
  3. Provide migration guide and tooling
  4. Remove deprecated JSFunction in next major version

References

  • Async test failures already hint at this issue: Tests/JavaScriptEventLoopTests/JSClosure+AsyncTests.swift:61-64
  • Current TODO comments acknowledge the need for this unification

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