Skip to content

compilePackages: module.exports = class loses the class method table — static AND prototype methods read undefined (breaks stack-utils → ink) #4933

Description

@proggeramlug

Summary

A compiled (compilePackages) CommonJS module that exports a class via module.exports = SomeClass loses the class's entire method table — both static methods and prototype (instance) methods come back undefined. The class is importable and callable as a constructor, but it's effectively bare.

Concretely with stack-utils@2.x (a transitive dep of ink via <ErrorOverview>):

import StackUtils from 'stack-utils';
console.log(typeof StackUtils);                    // 'function'    ✓
console.log(typeof StackUtils.nodeInternals);      // 'undefined'   ✗  (static method)
console.log(typeof StackUtils.prototype?.clean);   // 'undefined'   ✗  (instance/prototype method)
new StackUtils();                                  // TypeError: undefined is not iterable

Node prints function / function / function, and new StackUtils() succeeds.

stack-utils/index.js is a textbook shape:

class StackUtils {
  constructor (opts) {
    ...
    if ('internals' in opts === false) {
      opts.internals = StackUtils.nodeInternals();   // ← static call from ctor
    }
    ...
  }
  static nodeInternals () { return [...natives]; }
  clean (stack, indent = 0) { ... }
  // ...more instance methods...
}
module.exports = StackUtils;   // line 344 — CJS default-export of the class

Because StackUtils.nodeInternals is undefined, the constructor's internal call collapses to spreading undefined, surfacing as TypeError: undefined is not iterable during new StackUtils().

How it surfaced (ink end-to-end, #348)

This is the ink wall immediately after the react-reconciler SIGBUS fix (#4902). Module-init eval-order tracing through ink stops at ink/build/components/ErrorOverview.js, whose top level runs:

const stackUtils = new StackUtils({ cwd: cwd(), internals: StackUtils.nodeInternals() });

undefined is not iterable, before any user code. So importing ink throws at init.

Minimal repro environment

Scope / suggested triage

  • The breakage is method access on the class object (both Ctor.staticFn and Ctor.prototype.method read back undefined), not the constructor itself — new runs the ctor body. So the class's static + prototype method tables aren't attached to the object that module.exports = Ctor publishes.
  • Likely specific to the CJS module.exports = <class> export path (the class is defined at top level, exported at the bottom). Worth checking whether the exported binding is a re-wrapped/forwarded copy of the class that drops its method side-tables, vs. the original class identity.
  • Probably the same family as compiled-package instance methods not callable (dayjs.format, chalk.green) — prototype-method dispatch gap #838 (compiled-package instance methods not callable — dayjs/chalk prototype-dispatch gap), but here the methods are entirely absent (typeof … === 'undefined'), not merely non-dispatching, and statics are affected too.

Impact

Related

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