-
Notifications
You must be signed in to change notification settings - Fork 29.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
events: make sure console functions exist #4479
events: make sure console functions exist #4479
Conversation
if there's no global console cached, these calls will initialize it, which in some cases can cause a circular dependency, making the console received here an empty object. The program shouldn't crash in this case. Fixes nodejs#4467
A more general fix would be to always eagerly cache the global |
@nodejs/ctc |
const e = new events.EventEmitter(); | ||
e.on('hello', function() {}); | ||
|
||
assert.ok(!e._events['hello'].hasOwnProperty('warned')); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps it would be better to use a public API to check, such as:
assert.ok(!e.listeners('hello')[0].hasOwnProperty('warned'));
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The listeners()
API leaves out the warned
property: https://github.com/nodejs/node/blob/master/lib/events.js#L393.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While I agree that it's the most efficient approach, using an internal API in a test is a bit troublesome. The "correct" way to do this would likely be to direct the stderr/stdout output to a stream and apply a regex to ensure that the result is as the user should expect it to be. It's a bit of a workaround but it ensures that we're testing exactly what the user would see.
3e80ddd
to
9f8eddb
Compare
I thought up a better way to do this: now I include a reference to |
Much better approach. I always get a bit concerned when replacing bare properties with getter/setter but in this instance I cannot imagine that there'd be any issue. The actual code change LGTM but I think the test needs a bit more work to avoid using the internal API. |
Marking as a semver-minor due to the switch to using a getter/setter |
I refactored the test as per your suggestion @jasnell. |
LGTM if CI is green |
|
||
const assert = require('assert'); | ||
const events = require('events'); | ||
const leak_warning = /EventEmitter memory leak detected. 2 hello listeners/; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was this dot meant to be matched as a dot? You should escape it in that case.
LGTM besides the two nits above. |
eslint-disable required-modules escape regex dot
Good ideas @silverwind, I've incorporated them. |
LGTM pending CI: https://ci.nodejs.org/job/node-test-pull-request/1199/ |
const old_default = events.defaultMaxListeners; | ||
events.defaultMaxListeners = 1; | ||
|
||
const e = new events.EventEmitter(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Redundant EventEmitter
Thanks @thefourtheye, updated. |
CI likes it. Still LGTM. |
e.on('hello', function() {}); | ||
e.on('hello', function() {}); | ||
|
||
assert.equal(write_calls, 2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we also assert if the console
object is properly initialized by now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think there's any way we can do that without incidentally initializing it. Our prior logging would have failed if console
didn't initialize properly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about checking if console.error
function exists by the time control reaches here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Such a reference to console.error
will compile console
if it isn't already compiled.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose we could inspect require('native_module')._cache.console
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Scratch that -- Error: Cannot find module 'native_module'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm, my office time has started. I'll think about this when I find time today. Let's not block this PR because of this. Perhaps you might want to leave a TODO or something in the test for the timebeing.
else if (write_calls === 1) | ||
assert.ok(data.match(/Trace/)); | ||
else | ||
assert.ok(false, 'stderr.write should be called only twice'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is why we have assert.equal(write_calls, 2);
at the end, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure! I felt like I should have some sort of catch-all else
statement here though.
e.on('hello', function() {}); | ||
e.on('hello', function() {}); | ||
|
||
// TODO validate console |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why add the comment vs. adding the validation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As per earlier discussion (#4479 (diff)) I don't think it's actually possible to validate the console here in any significant way, but @thefourtheye requested a comment about validating it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh :-) lol completely missed that one
LGTM |
Landed in f9a59c1... @davidvgalbraith .. I squashed the commits and reworked the commit message to make sure it fit within our style guidelines. I also went ahead and expanded that TODO comment in the test case to make sure it describes exactly why we're leaving it as a TODO |
Thanks, @jasnell! I'm glad we got this one in. |
Notable changes: * events: make sure console functions exist (Dave) #4479 * fs: add autoClose option to fs.createWriteStream (Saquib) #3679 * http: improves expect header handling (Daniel Sellers) #4501 * node: allow preload modules with -i (Evan Lucas) #4696 * v8,src: expose statistics about heap spaces (`v8.getHeapSpaceStatistics()`) (Ben Ripkens) #4463 * Minor performance improvements: - lib: Use arrow functions instead of bind where possible (Minwoo Jung) #3622 - module: cache stat() results more aggressively (Ben Noordhuis) #4575 - querystring: improve parse() performance (Brian White) #4675 PR-URL: #4742
Notable changes: * events: make sure console functions exist (Dave) #4479 * fs: add autoClose option to fs.createWriteStream (Saquib) #3679 * http: improves expect header handling (Daniel Sellers) #4501 * node: allow preload modules with -i (Evan Lucas) #4696 * v8,src: expose statistics about heap spaces (`v8.getHeapSpaceStatistics()`) (Ben Ripkens) #4463 * Minor performance improvements: - lib: Use arrow functions instead of bind where possible (Minwoo Jung) #3622 - module: cache stat() results more aggressively (Ben Noordhuis) #4575 - querystring: improve parse() performance (Brian White) #4675 PR-URL: #4742
If there's no global console cached, initialize it. Fixes: nodejs#4467 PR-URL: nodejs#4479 Reviewed-By: Roman Reiss <me@silverwind.io> Reviewed-By: James M Snell <jasnell@gmail.com>
Notable changes: * events: make sure console functions exist (Dave) nodejs#4479 * fs: add autoClose option to fs.createWriteStream (Saquib) nodejs#3679 * http: improves expect header handling (Daniel Sellers) nodejs#4501 * node: allow preload modules with -i (Evan Lucas) nodejs#4696 * v8,src: expose statistics about heap spaces (`v8.getHeapSpaceStatistics()`) (Ben Ripkens) nodejs#4463 * Minor performance improvements: - lib: Use arrow functions instead of bind where possible (Minwoo Jung) nodejs#3622 - module: cache stat() results more aggressively (Ben Noordhuis) nodejs#4575 - querystring: improve parse() performance (Brian White) nodejs#4675 PR-URL: nodejs#4742
If there's no global console cached, these calls will initialize it,
which in some cases can cause a circular dependency, making the console
received here an empty object. The program shouldn't crash in this case.
Fixes #4467