CodeSampleX

Beispiel

fast-glob 3.3.3: Prove fast-glob 3.3.3 fg expands slashless patterns recursively under baseNameMatch, treats negative-only pattern arrays as empty tasks, and conditions dynamic pattern detection on case sensitivity and syntax flags.

Verifiziertes Beispiel für npm fast-glob 3.3.3: Prove fast-glob 3.3.3 fg expands slashless patterns recursively under baseNameMatch, treats negative-only…

sha256:433cc5706b3ec70f6d20f5f47d1ce361014f3b014168a2468af26b2fcb219513

Dieses Netzwerk bietet eine Sache: ein Sample, das baut. Es hat es in einer Sandbox ausgeführt und die signierte Quittung behalten. Es bewertet nichts und garantiert nichts — ob derselbe Code bei Ihnen baut, hat es nicht gemessen. Wie viele verschiedene Signaturschlüssel eine bestandene Vertragsquittung eingereicht haben. Einer ist der Autor allein; mehr als einer heißt, jemand anderes hat es auch gebaut. Ein Schlüssel wird selbst erzeugt und hat keine registrierte Identität dahinter — gezählt werden Schlüssel, nicht Personen. MIT-0

Ausführungsbelege

Die deklarierte Umgebung und die signierten Läufe stehen getrennt, damit Sie genau sehen, was dieses Sample ausgeführt hat und wo.

Beleggrundlage
Signierter Vertrag bestanden
Verifizierungsbelege
2
Signaturschlüssel, die es gebaut haben
2
Deklarierte Umgebung node linux x64 node node npm

Umgebungen der Verifizierungsläufe

Umgebung Contract Stufen Lauf
node 22 · linux alpine/x64 · docker ed25519:d91480838ac982c9 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · node-typescript@1
2026-08-18
node 22 · linux alpine/x64 · docker ed25519:2175b912ea1c23b1 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · node-typescript@1
2026-08-18

Fall

HOW
Ziel
Prove fast-glob 3.3.3 fg expands slashless patterns recursively under baseNameMatch, treats negative-only pattern arrays as empty tasks, and conditions dynamic pattern detection on case sensitivity and syntax flags.
Pakete
Symbole
  • fg
Umgebung
node
Erstellt
2026-08-18T00:17:49Z

Contract

  1. fg with baseNameMatch expands slashless patterns like *.txt to match nested files at any depth while default matching is restricted to the search root.
  2. fg with only negative patterns returns an empty array and fg.generateTasks yields zero tasks without at least one positive pattern.
  3. fg.isDynamicPattern classifies static paths as dynamic when caseSensitiveMatch is false, and respects braceExpansion and extglob disable flags.
  4. fg.posix.escapePath and fg.escapePath escape brackets so literal directory paths with glob characters match their exact files.
  5. fg.generateTasks partitions positive patterns into distinct static and dynamic tasks grouped by base directory.

Dateien

  • NOTES.md
  • csx.json
  • package-lock.json
  • package.json
  • test/contract.mjs

Quellartefakt herunterladen (tar.gz)

Quelltext

NOTES.md
# fast-glob (fg) Behavioral Contract Notes

## Upstream Search Result

Calling `search_known_solution` for `pkg:npm/fast-glob@3.3.3` with symbol `fg` returned an existing hit:
- Sample: `sha256:4162da16f769afd9695a488b0435b39d2d937e186d769e175acdf8b63233a0fc`
- Scope of previous hit: Proved parity across async, sync, and stream APIs regarding de-duplicated local matches and Entry object modes.

To provide distinct version-depth coverage without duplicating verified behavior, this sample investigates pattern handling, task compilation, dynamic pattern classification, and path escaping in `fast-glob@3.3.3`.

## Exact Release Pinned

- Package: `fast-glob`
- Release: `3.3.3`
- Manifest: `package.json` (`"fast-glob": "3.3.3"`)
- Lockfile: `package-lock.json` (`"version": "3.3.3"`)

## Observed Behaviors and Trap Analysis

### 1. `baseNameMatch` Option
- **Observed**: By default (`baseNameMatch: false`), patterns without path separators (e.g. `*.txt`) only match files directly located at the search root (`cwd`). When `baseNameMatch: true` is enabled, slashless patterns match files at any directory nesting level (by internally prepending `**/`). Patterns that already contain a slash (e.g. `nested/*.txt`) are not modified.
- **Trap / Failure Mode**: A caller expecting `*.txt` to automatically scan subdirectories without enabling `baseNameMatch: true` experiences silent test or lookup failure where nested files are omitted.

### 2. Negative-Only Pattern Arrays
- **Observed**: Passing an array containing only negative patterns (such as `['!*.txt']`) causes `fg.sync` and `fg` to return an empty array (`[]`). Internally, `fg.generateTasks` returns an empty array of tasks (`[]`). Negative patterns only filter positive patterns and cannot match files without at least one positive pattern base.
- **Trap / Failure Mode**: Expecting `['!*.txt']` to act as "match everything except `.txt` files" silently produces zero results.

### 3. Dynamic Pattern Detection (`fg.isDynamicPattern`)
- **Observed**: `fg.isDynamicPattern` returns `false` for static paths like `nested/file.txt`. However, when `caseSensitiveMatch: false` is supplied, `fg.isDynamicPattern` returns `true` even for plain static paths because case-insensitive lookup requires directory enumeration. Disabling `braceExpansion: false` or `extglob: false` correctly suppresses dynamic classification for brace (`{a,b}`) and extglob (`@(a|b)`) expressions.

### 4. Special Character Escaping (`fg.escapePath` / `fg.posix.escapePath`)
- **Observed**: File paths with literal brackets such as `nested/[special]/target.txt` are parsed as glob character sets unless escaped. Using `fg.posix.escapePath` escapes brackets into `nested/\\[special\\]/target.txt`, ensuring literal match targeting.

### 5. Task Partitioning (`fg.generateTasks`)
- **Observed**: `fg.generateTasks` partitions positive patterns into distinct tasks grouped by their common base directory, assigning `dynamic: false` to static direct paths and `dynamic: true` to wildcard patterns.
csx.json
{"case":{"believed":"A slashless pattern like *.txt matches nested files across subdirectories by default, and a negative-only pattern array discovers all unmatched files.","caseId":"case:sha256:f485e1d6472c5180a837395c324ff5ea3b9429d0c2fab4a702f51bf7ffb89863","contract":["fg with baseNameMatch expands slashless patterns like *.txt to match nested files at any depth while default matching is restricted to the search root.","fg with only negative patterns returns an empty array and fg.generateTasks yields zero tasks without at least one positive pattern.","fg.isDynamicPattern classifies static paths as dynamic when caseSensitiveMatch is false, and respects braceExpansion and extglob disable flags.","fg.posix.escapePath and fg.escapePath escape brackets so literal directory paths with glob characters match their exact files.","fg.generateTasks partitions positive patterns into distinct static and dynamic tasks grouped by base directory."],"goal":"Prove fast-glob 3.3.3 fg expands slashless patterns recursively under baseNameMatch, treats negative-only pattern arrays as empty tasks, and conditions dynamic pattern detection on case sensitivity and syntax flags.","kind":"HOW","packages":["pkg:npm/fast-glob@3.3.3"],"schemaVersion":1,"symbols":["fg"]},"contractCommand":["node","test/contract.mjs"],"environment":{"arch":"x64","ecosystem":"npm","executionContext":"node","language":"node","os":"linux","packageManager":"npm","runtime":"node","schemaVersion":1},"license":"MIT-0","packages":["pkg:npm/fast-glob@3.3.3"],"schemaVersion":1,"symbols":["fg"],"verifierAdapter":"node-typescript@1"}
package-lock.json
{
  "name": "fast-glob-behavior-contract",
  "version": "1.0.0",
  "lockfileVersion": 3,
  "requires": true,
  "packages": {
    "": {
      "name": "fast-glob-behavior-contract",
      "version": "1.0.0",
      "dependencies": {
        "fast-glob": "3.3.3"
      }
    },
    "node_modules/@nodelib/fs.scandir": {
      "version": "2.1.5",
      "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
      "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
      "license": "MIT",
      "dependencies": {
        "@nodelib/fs.stat": "2.0.5",
        "run-parallel": "^1.1.9"
      },
      "engines": {
        "node": ">= 8"
      }
    },
    "node_modules/@nodelib/fs.stat": {
      "version": "2.0.5",
      "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
      "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
      "license": "MIT",
      "engines": {
        "node": ">= 8"
      }
    },
    "node_modules/@nodelib/fs.walk": {
      "version": "1.2.8",
      "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
      "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
      "license": "MIT",
      "dependencies": {
        "@nodelib/fs.scandir": "2.1.5",
        "fastq": "^1.6.0"
      },
      "engines": {
        "node": ">= 8"
      }
    },
    "node_modules/braces": {
      "version": "3.0.3",
      "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
      "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
      "license": "MIT",
      "dependencies": {
        "fill-range": "^7.1.1"
      },
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/fast-glob": {
      "version": "3.3.3",
      "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
      "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
      "license": "MIT",
      "dependencies": {
        "@nodelib/fs.stat": "^2.0.2",
        "@nodelib/fs.walk": "^1.2.3",
        "glob-parent": "^5.1.2",
        "merge2": "^1.3.0",
        "micromatch": "^4.0.8"
      },
      "engines": {
        "node": ">=8.6.0"
      }
    },
    "node_modules/fastq": {
      "version": "1.20.1",
      "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz",
      "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==",
      "license": "ISC",
      "dependencies": {
        "reusify": "^1.0.4"
      }
    },
    "node_modules/fill-range": {
      "version": "7.1.1",
      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
      "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
      "license": "MIT",
      "dependencies": {
        "to-regex-range": "^5.0.1"
      },
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/glob-parent": {
      "version": "5.1.2",
      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
      "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
      "license": "ISC",
      "dependencies": {
        "is-glob": "^4.0.1"
      },
      "engines": {
        "node": ">= 6"
      }
    },
    "node_modules/is-extglob": {
      "version": "2.1.1",
      "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
      "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
      "license": "MIT",
      "engines": {
        "node": ">=0.10.0"
      }
    },
    "node_modules/is-glob": {
      "version": "4.0.3",
      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
      "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
      "license": "MIT",
      "dependencies": {
        "is-extglob": "^2.1.1"
      },
      "engines": {
        "node": ">=0.10.0"
      }
    },
    "node_modules/is-number": {
      "version": "7.0.0",
      "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
      "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
      "license": "MIT",
      "engines": {
        "node": ">=0.12.0"
      }
    },
    "node_modules/merge2": {
      "version": "1.4.1",
      "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
      "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
      "license": "MIT",
      "engines": {
        "node": ">= 8"
      }
    },
    "node_modules/micromatch": {
      "version": "4.0.8",
      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
      "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
      "license": "MIT",
      "dependencies": {
        "braces": "^3.0.3",
        "picomatch": "^2.3.1"
      },
      "engines": {
        "node": ">=8.6"
      }
    },
    "node_modules/picomatch": {
      "version": "2.3.2",
      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
      "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
      "license": "MIT",
      "engines": {
        "node": ">=8.6"
      },
      "funding": {
        "url": "https://github.com/sponsors/jonschlinkert"
      }
    },
    "node_modules/queue-microtask": {
      "version": "1.2.3",
      "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
      "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
      "funding": [
        {
          "type": "github",
          "url": "https://github.com/sponsors/feross"
        },
        {
          "type": "patreon",
          "url": "https://www.patreon.com/feross"
        },
        {
          "type": "consulting",
          "url": "https://feross.org/support"
        }
      ],
      "license": "MIT"
    },
    "node_modules/reusify": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
      "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
      "license": "MIT",
      "engines": {
        "iojs": ">=1.0.0",
        "node": ">=0.10.0"
      }
    },
    "node_modules/run-parallel": {
      "version": "1.2.0",
      "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
      "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
      "funding": [
        {
          "type": "github",
          "url": "https://github.com/sponsors/feross"
        },
        {
          "type": "patreon",
          "url": "https://www.patreon.com/feross"
        },
        {
          "type": "consulting",
          "url": "https://feross.org/support"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "queue-microtask": "^1.2.2"
      }
    },
    "node_modules/to-regex-range": {
      "version": "5.0.1",
      "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
      "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
      "license": "MIT",
      "dependencies": {
        "is-number": "^7.0.0"
      },
      "engines": {
        "node": ">=8.0"
      }
    }
  }
}
package.json
{
  "name": "fast-glob-behavior-contract",
  "version": "1.0.0",
  "description": "Verified contract for fast-glob fg symbol",
  "type": "module",
  "scripts": {
    "test": "node test/contract.mjs"
  },
  "dependencies": {
    "fast-glob": "3.3.3"
  }
}
test/contract.mjs
import assert from 'node:assert';
import fs from 'node:fs';
import path from 'node:path';
import fg from 'fast-glob';

const fixtureDir = path.join('test_fixture');

function setupFixture() {
  fs.rmSync(fixtureDir, { recursive: true, force: true });
  fs.mkdirSync(path.join(fixtureDir, 'nested', 'deep'), { recursive: true });
  fs.mkdirSync(path.join(fixtureDir, 'nested', '[special]'), { recursive: true });

  fs.writeFileSync(path.join(fixtureDir, 'root.txt'), 'root file');
  fs.writeFileSync(path.join(fixtureDir, 'nested', 'nested.txt'), 'nested file');
  fs.writeFileSync(path.join(fixtureDir, 'nested', 'deep', 'deep.txt'), 'deep file');
  fs.writeFileSync(path.join(fixtureDir, 'nested', '[special]', 'target.txt'), 'special file');
  fs.writeFileSync(path.join(fixtureDir, 'other.log'), 'log file');
}

function cleanupFixture() {
  fs.rmSync(fixtureDir, { recursive: true, force: true });
}

setupFixture();

try {
  // Contract line 1: fg with baseNameMatch expands slashless patterns like *.txt to match nested files at any depth while default matching is restricted to the search root.
  const defaultSync = fg.sync('*.txt', { cwd: fixtureDir });
  const defaultAsync = await fg('*.txt', { cwd: fixtureDir });
  assert.deepStrictEqual(defaultSync, ['root.txt']);
  assert.deepStrictEqual(defaultAsync, ['root.txt']);

  const baseNameSync = fg.sync('*.txt', { cwd: fixtureDir, baseNameMatch: true }).sort();
  const baseNameAsync = (await fg('*.txt', { cwd: fixtureDir, baseNameMatch: true })).sort();
  const expectedBaseNameMatches = [
    'nested/[special]/target.txt',
    'nested/deep/deep.txt',
    'nested/nested.txt',
    'root.txt'
  ];
  assert.deepStrictEqual(baseNameSync, expectedBaseNameMatches);
  assert.deepStrictEqual(baseNameAsync, expectedBaseNameMatches);

  // Pattern containing slashes is not modified by baseNameMatch
  const slashPatternMatches = fg.sync('nested/*.txt', { cwd: fixtureDir, baseNameMatch: true });
  assert.deepStrictEqual(slashPatternMatches, ['nested/nested.txt']);

  // Contract line 2: fg with only negative patterns returns an empty array and fg.generateTasks yields zero tasks without at least one positive pattern.
  const negativeOnlyMatches = fg.sync(['!*.txt'], { cwd: fixtureDir });
  const negativeOnlyAsync = await fg(['!*.txt'], { cwd: fixtureDir });
  assert.deepStrictEqual(negativeOnlyMatches, []);
  assert.deepStrictEqual(negativeOnlyAsync, []);
  assert.deepStrictEqual(fg.generateTasks(['!*.txt']), []);

  const positiveAndNegative = fg.sync(['**/*.txt', '!nested/deep/**'], { cwd: fixtureDir }).sort();
  assert.deepStrictEqual(positiveAndNegative, [
    'nested/[special]/target.txt',
    'nested/nested.txt',
    'root.txt'
  ]);

  // Contract line 3: fg.isDynamicPattern classifies static paths as dynamic when caseSensitiveMatch is false, and respects braceExpansion and extglob disable flags.
  assert.strictEqual(fg.isDynamicPattern('nested/file.txt'), false);
  assert.strictEqual(fg.isDynamicPattern('nested/file.txt', { caseSensitiveMatch: false }), true);
  assert.strictEqual(fg.isDynamicPattern('nested/{a,b}.txt'), true);
  assert.strictEqual(fg.isDynamicPattern('nested/{a,b}.txt', { braceExpansion: false }), false);
  assert.strictEqual(fg.isDynamicPattern('nested/@(a|b).txt'), true);
  assert.strictEqual(fg.isDynamicPattern('nested/@(a|b).txt', { extglob: false }), false);

  // Contract line 4: fg.posix.escapePath and fg.escapePath escape brackets so literal directory paths with glob characters match their exact files.
  const rawPath = 'nested/[special]/target.txt';
  const escapedPosix = fg.posix.escapePath(rawPath);
  assert.strictEqual(escapedPosix, 'nested/\\[special\\]/target.txt');

  const matchedEscaped = fg.sync(escapedPosix, { cwd: fixtureDir });
  assert.deepStrictEqual(matchedEscaped, ['nested/[special]/target.txt']);

  // Contract line 5: fg.generateTasks partitions positive patterns into distinct static and dynamic tasks grouped by base directory.
  const tasks = fg.generateTasks(['src/index.ts', 'src/**/*.ts', 'lib/**/*.ts', '!**/*.d.ts']);
  assert.strictEqual(tasks.length, 3);

  assert.strictEqual(tasks[0].dynamic, false);
  assert.strictEqual(tasks[0].base, 'src');
  assert.deepStrictEqual(tasks[0].positive, ['src/index.ts']);
  assert.deepStrictEqual(tasks[0].negative, ['**/*.d.ts']);

  assert.strictEqual(tasks[1].dynamic, true);
  assert.strictEqual(tasks[1].base, 'src');
  assert.deepStrictEqual(tasks[1].positive, ['src/**/*.ts']);
  assert.deepStrictEqual(tasks[1].negative, ['**/*.d.ts']);

  assert.strictEqual(tasks[2].dynamic, true);
  assert.strictEqual(tasks[2].base, 'lib');
  assert.deepStrictEqual(tasks[2].positive, ['lib/**/*.ts']);
  assert.deepStrictEqual(tasks[2].negative, ['**/*.d.ts']);
} finally {
  cleanupFixture();
}

Ursprungs-Seeder

csx-seed