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

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