question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. ItΒ collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Modifying globals within module leaks to global with Node >=10

See original GitHub issue

When running the test suite with Node 10 or higher, the test should not influence other modules when injecting mocks in the shared test cases fails. This happens because __set__ing a global in moduleA.js doesn’t set that global only within that module, but globally (so also in moduleB.js and in the test suite itself). This should not happen, since it leaks to other tests and can have various unwanted effects. It did not happen with Node 9 (which is why Travis also didn’t pick this up - it tests with Node 6, 8 and 9), and I do not know why this happens using higher versions (Node 10, 11 and 12 all have this behaviour, starting from the very first v10.0.0).

What makes this case even more mysterious, is that since that test (should not influence ...) sets console to a dummy mock { } (which should only have effect in moduleA, but because of this bug also changes the global console), all further Mocha output (which uses console.log) is suppressed. It took me a while therefore, to actually notice this test was failing!

All other tests seem to pass fine – it.skip the failing test, and you see the other tests pass:

63 passing (1s)
1 pending

This is also the easiest way to check that Mocha actually ran the other tests.

How to reproduce

I use nvm to switch between node versions. (I left out some of the test results, as marked by ...)

$ nvm use 9
Now using node v9.11.2 (npm v5.6.0)

$ npm test
> rewire@4.0.1 test /Users/Rens/Dev/rewire
> mocha -R spec

  __get__
    βœ“ should return the initial value
      ...

  ...

  rewire
    βœ“ should work like require() (101ms)
    βœ“ should return a fresh instance of the module
    βœ“ should not cache the rewired module
    βœ“ should modify the module so it provides the __set__ - function (45ms)
    βœ“ should modify the module so it provides the __get__ - function (57ms)
    βœ“ should modify the module so it provides the __with__ - function (55ms)
    βœ“ should provide __get__ as a non-enumerable property
    βœ“ should provide __get__ as a writable property
    βœ“ should provide __set__ as a non-enumerable property
    βœ“ should provide __set__ as a writable property
    βœ“ should provide __with__ as a non-enumerable property
    βœ“ should provide __with__ as a writable property
    βœ“ should not influence other modules
    βœ“ should not override/influence global objects by default
    βœ“ should provide a working __set__ method
    βœ“ should provide a working __get__ method
    βœ“ should provide a working __with__ method
    βœ“ should provide the ability to inject mocks
    βœ“ should not influence other modules when injecting mocks
    βœ“ should provide the ability to mock global objects just within the module (41ms)
    βœ“ should be possible to mock global objects that are added on runtime
    βœ“ should not be a problem to have a comment on file end
    βœ“ should not be a problem to have a module that exports a boolean
    βœ“ should not be a problem to have a module that exports null
    βœ“ should not be a problem to have a module that exports a sealed object
    βœ“ should not be a problem to have a module that uses object spread operator
    βœ“ should not be a problem to have a module that uses object rest operator
    βœ“ should not influence the original require if nothing has been required within the rewired module
    βœ“ subsequent calls of rewire should always return a new instance (46ms)
    βœ“ should preserve the strict mode
    βœ“ should not modify line numbers in stack traces
    βœ“ should be possible to set implicit globals
    βœ“ should throw a TypeError if the path is not a string
    βœ“ should also revert nested changes (with dot notation)
    βœ“ should be possible to mock undefined, implicit globals
    βœ“ should be possible to mock and revert JSON.parse (see #40)
    βœ“ should be possible to set a const variable
    βœ“ should fail with a helpful TypeError when const is re-assigned
    βœ“ should also work with CoffeeScript (43ms)


  64 passing (1s)

$ nvm use 10
Now using node v10.16.0 (npm v6.9.0)

$ npm test
> rewire@4.0.1 test /Users/Rens/Dev/rewire
> mocha -R spec

  __get__
    βœ“ should return the initial value
      ...

  ...

  rewire
    βœ“ should work like require() (86ms)
    βœ“ should return a fresh instance of the module
    βœ“ should not cache the rewired module
    βœ“ should modify the module so it provides the __set__ - function (54ms)
    βœ“ should modify the module so it provides the __get__ - function (49ms)
    βœ“ should modify the module so it provides the __with__ - function (45ms)
    βœ“ should provide __get__ as a non-enumerable property
    βœ“ should provide __get__ as a writable property
    βœ“ should provide __set__ as a non-enumerable property
    βœ“ should provide __set__ as a writable property
    βœ“ should provide __with__ as a non-enumerable property
    βœ“ should provide __with__ as a writable property
    βœ“ should not influence other modules
    βœ“ should not override/influence global objects by default
    βœ“ should provide a working __set__ method
    βœ“ should provide a working __get__ method
    βœ“ should provide a working __with__ method
    βœ“ should provide the ability to inject mocks
    βœ“ should not influence other modules when injecting mocks

Note that the last 20-or-so tests disappeared, and there was no test result β€˜x passing’.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:2
  • Comments:13 (10 by maintainers)

github_iconTop GitHub Comments

2reactions
rensbaardmancommented, Jul 12, 2019

So, process is still global, it is only not part of the enumerable keys of global. You can check this with

$ nvm use 12
$ node
> Object.getOwnPropertyNames(global).indexOf('process')

which should return an integer (for me, it is 60) indicating it is in that list.

But indeed, the same bug is the cause of your problems. I have a fork that fixes it. I also submitted it as a PR, but it has been a long time since the last PR in this repo was merged.

Note, though, that the workaround to __set__ process.exit directly is strongly discouraged. Are you sure you are not simply modifying the global process?

1reaction
jhnnscommented, Dec 19, 2021

Published as v6.0.0 πŸš€

Read more comments on GitHub >

github_iconTop Results From Across the Web

Global objects | Node.js v19.3.0 Documentation
These objects are available in all modules. The following variables may appear to be global but are not. They exist only in the...
Read more >
Sharing & modifying a variable between multiple files node.js
Sometimes I'd like to sharing variables between multiple files because I love modular style eg. separating controller, function, models in ...
Read more >
Node.js Global Objects - GeeksforGeeks
Global Objects are built-in objects that are part of the JavaScript and can be used directly in the application without importing any particularΒ ......
Read more >
Using Global Variables in Node.js - Stack Abuse
To set up a global variable, we need to create it on the global object. The global object is what gives us the...
Read more >
Learn Globals in Node.js - Frontend Masters
Scott gives an overview of process, require, __dirname, module, and global, that are all global variables provided to apps by Node.js.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found