Skip to content

perry-codegen: Buffer.isBuffer() not lowered (BufferIsBuffer expression) #78

Description

@proggeramlug

Environment

  • perry 0.5.92
  • macOS arm64 (darwin 25.4.0)
  • Node v25.8.0 (reference runtime)

Problem

Buffer.isBuffer(x) fails to compile under the LLVM backend:

Error compiling module '.../connection.ts' with --backend llvm:
  lowering function 'encodeParam': lowering body of 'encodeParam':
  perry-codegen Phase 2: expression BufferIsBuffer not yet supported

The compile still produces a binary because Perry emits an empty stub for the module ("linking with empty stubs"), but the resulting main references _perry_fn_src_connection_ts__connect which doesn't exist, so ld fails:

Undefined symbols for architecture arm64:
  "_perry_fn_src_connection_ts__connect", referenced from: _main
  "_src_connection_ts__init", referenced from: _main
ld: symbol(s) not found for architecture arm64

Node and Bun compile + run the same source cleanly.

Minimal repro

// minrepro.ts
function describe(v: unknown): string {
    if (Buffer.isBuffer(v)) {
        return 'buffer of length ' + v.length;
    }
    return typeof v;
}
console.log(describe(Buffer.from([1, 2, 3])));
console.log(describe('hi'));
perry compile minrepro.ts -o /tmp/minrepro
# → perry-codegen Phase 2: expression BufferIsBuffer not yet supported

Hit in real code

Found by @perry/mysql in encodeParam() — the branch that picked BLOB vs VAR_STRING for prepared-statement parameters. Worked around with a duck-type check:

function isBufferLike(v: unknown): boolean {
    if (v === null || typeof v !== 'object') return false;
    const a = v as { readUInt8?: unknown; length?: unknown };
    return typeof a.readUInt8 === 'function' && typeof a.length === 'number';
}

but the native idiom should Just Work — it's one of the most common Node patterns for Buffer-vs-anything-else dispatch.

Expected

Buffer.isBuffer(x) lowers to the runtime's existing Buffer-tag identity check.

Related

perry check --check-deps reported "Compilation is guaranteed to succeed" despite this expression — separate issue filed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugConfirmed defect or regressionparityCompatibility gap with Node.js, ECMAScript, or the supported ecosystem

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions