Node: Hide private symbols

Created on 28 May 2018  路  16Comments  路  Source: nodejs/node

Right now we use a lot of "private" symbols in core. However, those show up when using console.log or util.inspect (the latter as the actual part that makes them visible). The reason for that is that we add them as enumerable symbols instead of non-enumerable ones.

The default for util.inspect is to show all enumerable properties. I would like to hide all of these by changing our symbols to non-enumerable properties. That way they could still be inspected when calling inspect with the showHidden option but I believe that is exactly as it should be.

Are other @nodejs/collaborators fine with changing all those entries? We would only have to change it in the places where we actually add the symbol to the object.

If that is something we all agree to, I would like to add the good-first-issue and help-wanted labels and we should pay attention to always make sure they are added as non-enumerable properties and add tests for that as well to prevent regressions.

console discuss stalled util

Most helpful comment

I'm talking about code in the wild (my team's modules and apps). We use console.log(obj) for debugging, and sometimes console.log(util.inspect(obj, opts)). IMO, the more data we have with the default inspection used by console.log, the better.

All 16 comments

I don鈥檛 think we should make that move unconditionally for every symbol. In particular, showing their values in util.inspect is something I consider helpful in general if it provides extra diagnostic information about the object鈥檚 state.

@addaleax Couldn't you use showHidden still?

@jdalton Yes, you can, but it鈥檚 extra overhead. If we decide to do this, we should have a clear understanding of why we get better debugging output when they are excluded.

@addaleax I agree that it might help for debugging but that is what showHidden is for out of my perspective. It should not be visible to all users unconditionally when they just call console.log on an object. I also believe that the repl should not print these by default but only when explicitly asked for.

@BridgeAR It might be helpful if you could explain why you believe that? From my perspective, it seems like more information about an object鈥檚 state is not a bad thing when coming from a diagnostic utility.

I believe the repl and console.log output are main points where people get the idea to use private internal things directly instead of relying on the public API (for example #19671) . I doubt that people always look into the code to to do these things and instead check what's available on the objects returned from core. That is only speculation and it is no guarantee for anything by hiding them but I just do not think the symbols should be exposed by default.

seeing as v8 extras isn't deprecated anymore, we could also replace them all with private symbols. it would completely kill debugging though.

I think in that case we might just want to wait until V8 supports private properties 脿 la https://github.com/tc39/proposal-class-fields? It鈥檚 stage 3, so I鈥檇 assume it鈥檚 not so terrible long until we have it available.

Otherwise we鈥檙e just shifting the same code twice, right?

@addaleax that might be a solution to most cases but we could tackle this right now. As I said above I think those would be good as good first issues.

IMHO the crux is that util.inspect(coreAPIObj) and console.log(coreAPIObj) should have independent outputs (the first is a debug tool, the second a common runtime tool).

I'm now thinking we should have a different inspect flavor that is more debug-like (maybe even available only behind a CLI flag). So that we can un-link util.inspect and console.log.

IMHO the crux is that util.inspect(coreAPIObj) and console.log(coreAPIObj) should have independent outputs (the first is a debug tool, the second a common runtime tool).

Interesting. My opinion is the other way (console.log for debugging, forbidden with linter).

Interesting. My opinion is the other way (console.log for debugging, forbidden with linter).

I agree with you RE the code in core. But we can't enforce that for code in the wild (where console.log is is affected by changes in util.inspect semantic)

I'm talking about code in the wild (my team's modules and apps). We use console.log(obj) for debugging, and sometimes console.log(util.inspect(obj, opts)). IMO, the more data we have with the default inspection used by console.log, the better.

I'm talking about code in the wild (my team's modules and apps). We use console.log(obj) for debugging

So another possibility is the create "module scope globals" and implement require('util').inspect.defaultOptions so it's stored at that scope.

As for linting console.log from production code in the wild, that IMHO is a hopeless battle ;)

The docs have several util.inspect disclaimers:

image

image

but the console.log API is unqualified so essentially we can't change the semantics of console.log('%o', ...).

I've seen discussions around this pop up every couple on months and I'd say we should make a formal decision either way.

Should this be closed given stalling/inactivity? It can always be re-opened if it becomes A Thing again.

This has been stalled since late May, so I'm going to close it. Feel absolutely free to re-open it or comment. I'm just tidying up and not acting on a super-strong opinion or anything like that.

Was this page helpful?
0 / 5 - 0 ratings