2

I have a model with a function call of util.endsWith(str, end) but I forgot to import my util file. Normally I would expect an error like:

cannot call method 'endsWith' of undefined or something like that

but the error I am getting is:

TypeError: Object #<Object> has no method 'endsWith'

which indicates that util is defined. I did a console.log of it and found that it is the same object you get from require('util').

I certainly did not require the util module in this, and I can't find anywhere in my files where I do so (not that I would expect something require-ed in another file to be in this file).

Interestingly, util is only defined if I require this module from somewhere else; if I just run the file then util is undefined.

Is this normal?


My files are not that complicated (<100 lines each) but I have not been able to replicate it with a super basic example. Maybe it has to be a couple of levels deep.

nodejs 0.10.12

PagodaJosh
  • 43
  • 4

2 Answers2

3

Most likely you forgot doing var util somewhere in a different module where util is being assigned to. This results in a global variable being created.

You may be leaking more global variables this way. You can get an overview which globals are being created by doing:

var oldGlobalNames = Object.keys(global)

at top of main script. Then do

console.log(_.difference(Object.keys(global), oldGlobalNames))

on bottom.

This uses the difference function from Underscore.

Or use https://github.com/aheckmann/gleak module.

Another idea: do a project-wide search (including node_modules dir) for util =. Get a sense of where util is being assigned to.

See also Node.js - why do I get leaks when testing with mocha and zombie?

Community
  • 1
  • 1
Myrne Stol
  • 11,222
  • 4
  • 40
  • 48
  • as I understand it, that is not how node modules work. In any case this javascript was generated by coffeescript, so it is impossible to 'forget' to put `var` – PagodaJosh Jul 09 '13 at 16:17
  • I think what you are saying is correct for the browser, but I am not in a browser. – PagodaJosh Jul 09 '13 at 16:21
  • Pagoda is correct. All node modules are executed inside a wrapper function so variables declared with `var` are within the scope of the module's wrapper function and thus not visible to other modules. – Peter Lyons Jul 09 '13 at 16:21
  • How about first establishing that the problem is indeed a global variable `util`? Is `global['util']` set at end of script? Or even more precise, is it set right after the line that produces `TypeError: Object # has no method 'endsWith'`? (if you fail to include your own util module, that is). – Myrne Stol Jul 09 '13 at 16:25
  • 1
    @PagodaJosh, if it's only 100 lines of code, just paste the code! – Mulan Jul 09 '13 at 16:26
  • 2
    If it's indeed a global that's the culprit, a third-party module could be at fault as well. It's virtually impossible to accidentally leak global variables if you use CoffeeScript throughout, I think. But still, maybe you have some regular JS code as well. – Myrne Stol Jul 09 '13 at 16:33
  • 1
    @MerynStol I owe you an apology; it **was** a third party js module that was leaking stuff. I was under the impression that global variables could not be created in nodejs, so I did not investigate that at first. – PagodaJosh Jul 09 '13 at 16:53
  • No problem. I'm glad this one mystery is solved! Do file an issue (or do a pull request) with the owner of the misbehaving module. That potentially saves a headache for some future developers. :) In projects with lots of dependencies, I think the origin of such a leak could be hard to track down. – Myrne Stol Jul 09 '13 at 18:40
1

I think this is a repl vs script interpreter thing. When you run the repl (either node or coffee), indeed util is available as a pre-imported module it seems. However, when you run them and pass a script argument, util is not there:

node -e 'console.log(util)'

[eval]:1
console.log(util)
            ^
ReferenceError: util is not defined
    at [eval]:1:13
    at Object.<anonymous> ([eval]-wrapper:6:22)
    at Module._compile (module.js:456:26)
    at evalScript (node.js:532:25)
    at startup (node.js:80:7)
    at node.js:901:3

However, with the repl:

node
> util
{ format: [Function],
  deprecate: [Function],
  print: [Function],
  puts: [Function],......
Peter Lyons
  • 142,938
  • 30
  • 279
  • 274
  • yes, I had noticed that all the regular modules are global in the node REPL, but I am launching my code with `node myfile.js` so I don't think that it is. – PagodaJosh Jul 09 '13 at 16:36
  • @PagodaJosh I thought you said you were using coffeescript? So why not `coffee myfile.coffee` ? – Mulan Jul 09 '13 at 16:48