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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions