Skip to content

exports are empty when ESM loader loads a cjs package which uses a quibbled module #111

@stixx200

Description

@stixx200

I want to fake the fs package using memfs. My production code uses fs-extra.

The require-stack looks like:
app.js (ESM) -> fs-extra (CJS) -> graceful-fs (CJS) -> fs (Built-In)

Reproduction

Example:

import quibble from "quibble";
import { vol, fs as fsm } from "memfs";

vol.fromJSON({
    "foo.txt": "foo",
});

quibble("fs", { ...fsm });

const fse = (await import("fs-extra")).default;
await fse.stat("foo.txt");

In this use case, the ESM-Loader loads the fs-extra module with it's internal cjs loader. Because quibble restores the Module._cache entry, the cjs loader only returns an empty object for the exports:
TypeError: fse.stat is not a function

Hint:

If I remove the line delete Module._cache[filename] (in doAndRestoreCache) my use-case works.
I think the ESM Loader reads the exports from the cached value after quibble deleted it.

If I use require to load fs-extra, there is no problem:

const require = createRequire(import.meta.url);
const fse = require("fs-extra");
// ...

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