Skip to content

vm: Script importModuleDynamically memory leak #25424

Closed
@guybedford

Description

@guybedford
  • Version: master
  • Platform: Linux
  • Subsystem: VM

While investigating #21573 I was interested in understanding why we are storing the importModuleDynamically callback in a weak map, as that surely means that it can be GC'd if there is an indeterminate time before the import() function in the module is called.

I may or may not have diagnosed the issue correctly, but the test case is a bug nonetheless:

main.js

const vm = require('vm');

var source = `

setTimeout(() => {
  import('./test.mjs');
}, 1000)

gc();

`;

new vm.Script(source, {
  importModuleDynamically (x) {
    console.log('dynamic callback');
    return import(x);
  }
}).runInThisContext();

Where test.mjs exists as an ES module.

Running with: node --experimental-modules --expose-gc main.js I get the following output:

(node:12832) ExperimentalWarning: The ESM module loader is experimental.
dynamic callback
Segmentation fault (core dumped)

If I comment out the gc() line or run the import() call without a timeout the correct output is provided.

This makes me think we should reconsider the use of weak maps as the storage for the dynamic callback, and rather accept that the dynamic callback should always have a lifecycle that is directly tied to the lifecycle of the module(s) it is referenced by.

Metadata

Metadata

Assignees

No one assigned

    Labels

    help wantedIssues that need assistance from volunteers or PRs that need help to proceed.memoryIssues and PRs related to the memory management or memory footprint.vmIssues and PRs related to the vm subsystem.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions