Skip to content

path module — 4 remaining gaps (follow-ups to #681) #741

Description

@proggeramlug

Repro

import * as path from "node:path";
console.log("dirname /:", path.dirname("/"));
console.log("join with trailing:", path.join("/foo/", "/bar/", "baz"));
console.log("matchesGlob:", path.matchesGlob("foo.txt", "*.txt"));
console.log("toNamespacedPath:", path.toNamespacedPath("/foo/bar"));
console.log("after toNamespacedPath:", "still alive");

Actual (Perry v0.5.894)

dirname /: 
join with trailing: /bar/baz
matchesGlob: undefined
TypeError: value is not a function
    at <anonymous>

(Then exits. The after toNamespacedPath line never prints.)

Expected (Node)

dirname /: /
join with trailing: /foo/bar/baz
matchesGlob: true
toNamespacedPath: /foo/bar
after toNamespacedPath: still alive

Four distinct bugs

1. path.dirname("/") returns empty string instead of "/"

Per spec, the dirname of the root is the root itself. Perry returns "".

2. path.join("/foo/", "/bar/", "baz") resets on absolute paths in the middle

Node returns /foo/bar/baz (trailing slashes are consumed, then all segments joined). Perry returns /bar/baz — looks like it resets on the second absolute segment.

Closely related to #681, which fixed the zero-args case (path.join()"."). The non-zero-args trailing-slash case still differs.

3. path.matchesGlob(path, pattern) is undefined

Newer API (Node 22.5+). Perry doesn't have it. Calling it throws TypeError.

4. path.toNamespacedPath(path) throws TypeError: value is not a function, terminating the script

This is the worst of the four. Calling path.toNamespacedPath("/foo/bar") should be a no-op on POSIX (Windows-only effect) and return its input. Instead Perry throws an unhandled TypeError that terminates the script — so any code after it (including unrelated probes) is silently dropped.

This is what makes test-files/test_parity_path.ts end at 37 of 42 expected lines today: lines 38-42 (the path.delimiter / path.sep / posix.* / win32.* checks) never run because the throw escapes upward.

Impact

The first three are normal "method not implemented" gaps. The fourth is a footgun: any consumer who calls path.toNamespacedPath expecting a no-op gets their program terminated. Common in cross-platform path-handling code.

Together these four are the entire remaining diff in test-files/test_parity_path.ts. Fix them and the parity test reaches full byte-for-byte PASS (diff = 0, joining test_parity_os as the second module to fully match).

Acceptance

The 5-line repro above prints output matching Node, including the final "after toNamespacedPath" line proving the throw is gone.

Related

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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