Conversation
Per https://github.com/tc39/proposal-global, the global value `global` should be configurable, writable, and non-enumerable. `node` has always provided it as configurable, writable, and enumerable. The plan is to make it non-enumerable, and barring strong evidence that node can not ship `global` as non-enumerable, this will be how it lands as stage 4 (in the spec).
|
@ljharb is there a summary on why it's not enumerable? I think it currently is here which mean this should probably be considered a breaking change...? |
|
@Fishrock123 |
|
@ljharb Here's a minimal test you can add to 'use strict';
require('../common');
const assert = require('assert');
assert(!Object.keys(global).includes('global'),
'global should be non-enumerable');Adding additional tests to that for |
|
Thanks to you both; I'll update the commit message as well as add a test. @Fishrock123 it's non-enumerable because things shouldn't be enumerable unless there's a good reason for there to be so - the proposal was made stage 3 with the understanding that if node decided making it non-enumerable was untenable, that the spec would change to make it enumerable. I think semver-major is appropriate, although I very much doubt the change will actually break anyone. |
lib/internal/bootstrap_node.js
Outdated
There was a problem hiding this comment.
By the time this code is run, the global property of the global object is already defined, and this line redefines it to be non-enumerable. This works, but I'm wondering if there's a less roundabout way to do it. (I assume it would be related to this, but I'm not sure about the specifics of how to make a property non-enumerable from the C++ side.)
There was a problem hiding this comment.
Thanks, I can explore that file, thanks for the pointer.
There was a problem hiding this comment.
(I'd definitely prefer to define it as non-enumerable in C++ instead, to be sure)
There was a problem hiding this comment.
k, figured this out, new commit incoming
|
Enumerability makes it easier for modules like https://github.com/sindresorhus/globals to discover the available globals, just saying. |
|
@silverwind This only applies to one property: the As far as libraries like https://github.com/sindresorhus/globals are concerned, I assume they use |
|
@silverwind indeed, this doesn't affect the enumerability of all global variables, just of the global variable |
|
Okay, sounds good. |
Ummm. I'm not ok with that?? I've used this for debugging certain things and finding things before... and I can see myself needing it again in the future... ...
It would be unchangeable.
This is what I don't get, it is only not "enumerable" by |
|
"Enumerable" determines whether it shows up in for..in, Object.assign, Object.keys/values/entries, etc. Object.getOwnPropertyNames, Reflect.ownKeys, and Object.getOwnPropertyDescriptors are the only ones that give you non-enumerable values. Note that I said the spec would be changeable - the assumption is that if this PR were merged, that would constitute evidence that node is willing to make this change. Separately, it is not a breaking change to make a non-enumerable thing enumerable, it's a semver-minor, so it's definitely changeable anyways. |
Can you explain how this change would cause problems when using [ 'DTRACE_NET_SERVER_CONNECTION',
'DTRACE_NET_STREAM_END',
'DTRACE_HTTP_SERVER_REQUEST',
'DTRACE_HTTP_SERVER_RESPONSE',
'DTRACE_HTTP_CLIENT_REQUEST',
'DTRACE_HTTP_CLIENT_RESPONSE',
'global',
'process',
'Buffer',
'clearImmediate',
'clearInterval',
'clearTimeout',
'setImmediate',
'setInterval',
'setTimeout',
'console',
'module',
'require' ]With the proposed change here, it will instead return this: [ 'DTRACE_NET_SERVER_CONNECTION',
'DTRACE_NET_STREAM_END',
'DTRACE_HTTP_SERVER_REQUEST',
'DTRACE_HTTP_SERVER_RESPONSE',
'DTRACE_HTTP_CLIENT_REQUEST',
'DTRACE_HTTP_CLIENT_RESPONSE',
'process',
'Buffer',
'clearImmediate',
'clearInterval',
'clearTimeout',
'setImmediate',
'setInterval',
'setTimeout',
'console',
'module',
'require' ] |
globalglobal non-enumerable
|
Updated to set the property as non-enumerable from C++, rather than having to change it in JS. ( Happy to squash the commits upon review approval. |
src/node.cc
Outdated
global non-enumerableglobal non-enumerable
|
Very minor note: Now that the change is in a C++ file in |
|
@Trott makes sense; when I squash post-approval pre-merge i'll update the commit message to say |
cjihrig
left a comment
There was a problem hiding this comment.
LGTM. This introduces a slight naming inconsistency with the existing READONLY_DONT_ENUM_PROPERTY, although I personally prefer NONENUMERABLE_PROPERTY.
|
@cjihrig happy to rename |
|
commits squashed. |
not-an-aardvark
left a comment
There was a problem hiding this comment.
LGTM aside from a nitpick with the test
There was a problem hiding this comment.
This assertion isn't actually verifying that global is the global object. (If there was a bug where global was set to some other value with a self-referential global property, the assertion would still pass because it's just comparing (the global object).global to (the global object).global.global.)
I think it would be better to compare global to something that is guaranteed to be the global object. For example:
assert.strictEqual(value, (0, eval)('this'), 'global should be global object');edit: reworded for clarity
There was a problem hiding this comment.
Good point, I'll change to Function('return this')() (i assume we're not worried about Function being overwritten in tests, or else i could use function () {}.constructor('return this')())
There was a problem hiding this comment.
I think Function('return this')() is fine. (Technically, function () {}.constructor('return this')() could also cause a problem if Function.prototype.constructor was overridden, but I don't think we need to worry about that here.)
There was a problem hiding this comment.
In that case constructor would be an own property on the function, and thus would shadow anything on Function.prototype, but I agree we don't need to worry about it :-)
|
FWIW I created a CL to implement this in V8: https://codereview.chromium.org/2599903003 |
|
@ljharb The |
|
So does semver-major here mean it won't land in 7.x, but might in 8.x? Or does it mean it won't land until 9.x? |
It means it might land in 8.x. |
|
To clarify, assuming we reach consensus that this is a good idea, this PR will probably be merged and land on master fairly soon. But it won't make it into a release until Node 8 is released in April. |
|
@ljharb Two more things of note:
|
|
@not-an-aardvark what consensus do you envision is required? Node representatives at TC39 in September agreed that unless there was concrete evidence of code breakage, that it would be acceptable - that helped allow the proposal to go to stage 3. node 8.x in April seems fine, thanks for clarifying. |
|
Yep, I don't see any reason why this change cannot land but given the nature of the change, semver-major is appropriate. As @not-an-aardvark and @Trott point out, that means that it can land in |
The absolute rock-bottom minimum would be:
Covering these each in turn:
Again, the above is the absolute minimum. More consensus is always better, of course. |
|
@Fishrock123 wrote:
Re-reading what I wrote (that the above was a response to), I see that I phrased it badly. I made it sound like |
addaleax
left a comment
There was a problem hiding this comment.
LGTM and +1 on considering this semver-major
There was a problem hiding this comment.
tiny nit: This could be const, right?
6f761fd to
4744e3f
Compare
|
Merging this should be withheld, pending the outcome of the issues reported in tc39/proposal-global#20 |
|
I added a |
|
@ljharb ... where are we at on this? |
|
@jasnell It seems like I'll open a new PR in the future when we've settled on the new top-level variable name. |
Per https://github.com/tc39/proposal-global
This is my first PR to node core, so I'm putting it up now without a completed checklist. Early feedback is welcome, and I'll be moving through the items as quickly I can.
Checklist
make -j4 test(UNIX),orpassesvcbuild test(Windows)Affected core subsystem(s)
the JS environment
Description of change
Per the stage 3 proposal,
globalshould be non-enumerable (but writable and configurable). This PR alters the property descriptor to be so.(If there's a better place this should be done, a pointer to it is most welcome)