-
Notifications
You must be signed in to change notification settings - Fork 29.8k
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
doc: added symbols guidelines #22684
Conversation
doc/guides/using-symbols.md
Outdated
} | ||
``` | ||
|
||
Local symbols makes it harder for developers to monkey patch/access |
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.
nit: s/makes/make
801d47f
to
40ec16b
Compare
Tagging it tsc-agenda to raise awareness. cc @nodejs/tsc. |
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.
Some of the content could probably be replaced with a link to MDN, but LGTM. A link to MDN probably wouldn't hurt either way though 😄
doc/guides/using-symbols.md
Outdated
it is often used for metaprogramming purposes, as they can be used as | ||
property keys like string. There are two types of | ||
symbols, local and globals. Symbols are not included in | ||
JSON.stringify() but thay are by `util.inspect()`. |
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.
s/thay/they/
doc/guides/using-symbols.md
Outdated
In the Node.js runtime we prefix all our global symbols with `nodejs.`, | ||
e.g. `Symbol.for('nodejs.hello')`. | ||
|
||
Globals symbols should be preferred to allow customizations of certain |
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.
s/Globals/Global/
I suggest to rephrase this sentence to something like: Global symbols are used in Node.js to allow customization of certain behaviors, i.e., metaprogramming.
doc/guides/using-symbols.md
Outdated
# Using global symbols | ||
|
||
ES6 introduced a new type: `Symbol`. This new type is _immutable_, and | ||
it is often used for metaprogramming purposes, as they can be used as |
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 they
is a bit confusing since there are no plurals before (except purposes
).
doc/guides/using-symbols.md
Outdated
ES6 introduced a new type: `Symbol`. This new type is _immutable_, and | ||
it is often used for metaprogramming purposes, as they can be used as | ||
property keys like string. There are two types of | ||
symbols, local and globals. Symbols are not included in |
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.
globals
-> global
?
doc/guides/using-symbols.md
Outdated
private fields, as they require more work than a property prefixed | ||
with an `_`. | ||
|
||
## Global symbols - `Symbol.for` |
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.
Symbol.for
-> Symbol.for()
?
doc/guides/using-symbols.md
Outdated
ES6 introduced a new type: `Symbol`. This new type is _immutable_, and | ||
it is often used for metaprogramming purposes, as they can be used as | ||
property keys like string. There are two types of | ||
symbols, local and globals. Symbols are not included in |
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.
Symbols in the GlobalSymbolRegistry have no intrinsic differences from symbols created through Symbol()
-- other than that it is in a global map. There are no two "types" of symbols.
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.
From a user point of view, those are two different things. It might well be the same type, but a) I cannot add a symbol that I created to the global map and b) I cannot remove a symbol from the global map. Specifically Symbol('hello') !== Symbol('hello')
and Symbol.for('hello') === Symbol.for('hello')
: this alone makes me think that they are two different things. Would you mind to suggest some different wording?
doc/guides/using-symbols.md
Outdated
symbols, local and globals. Symbols are not included in | ||
JSON.stringify() but thay are by `util.inspect()`. | ||
|
||
## Local `Symbol` |
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.
There is no such thing as a "local" Symbol. Just say symbols created using the Symbol()
function.
doc/guides/using-symbols.md
Outdated
|
||
Local symbols make it harder for developers to monkey patch/access | ||
private fields, as they require more work than a property prefixed | ||
with an `_`. |
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.
Say why this is good. If I were an unsuspecting developer I might consider
make it harder for developers to monkey patch/access private fields
a bad thing and question why Node.js is doing this.
doc/guides/using-symbols.md
Outdated
In the Node.js runtime we prefix all our global symbols with `nodejs.`, | ||
e.g. `Symbol.for('nodejs.hello')`. | ||
|
||
Globals symbols should be preferred to allow customizations of certain |
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.
Drive home the fact that the symbol is intended developer-facing.
Global symbols should be preferred when a developer-facing interface is needed to allow behavior customization, i.e., metaprogramming.
doc/guides/using-symbols.md
Outdated
## Global symbols - `Symbol.for` | ||
|
||
Global symbols are created with `Symbol.for(string)`. These symbols are | ||
stored in a global registry and they can be easily retrieved. However, |
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'd also clarify what "global" mean here: they are global to all contexts (including VM contexts) in the same process/JavaScript agent/V8 Isolate.
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 would just say v8 isolate
doc/guides/using-symbols.md
Outdated
For this reason, we often use them to simulate private fields, like so: | ||
|
||
```js | ||
const kField = Symbol('field'); |
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.
Please make this Symbol('kField')
. Having consistent naming is so helpful for grep
-ping, and I’ve been changing it to this pattern whenever I touched these lines.
40ec16b
to
a9d210a
Compare
PTAL @TimothyGu @addaleax. |
doc/guides/using-symbols.md
Outdated
monkey-patchable make maintaining and evolving Node.js harder, as private | ||
properties are not documented and can change within a patch release. | ||
Some extremely popular modules in the ecosystem monkey patch some | ||
internals, making it impossible for us to update and imoprove those |
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.
s/imoprove/improve/
doc/guides/using-symbols.md
Outdated
properties are not documented and can change within a patch release. | ||
Some extremely popular modules in the ecosystem monkey patch some | ||
internals, making it impossible for us to update and imoprove those | ||
areas without breaking a significant amount of users. |
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.
-breaking
+causing issues for
a9d210a
to
0d9162a
Compare
Landed in 4f5aa36. |
PR-URL: #22684 Reviewed-By: Tobias Nießen <tniessen@tnie.de> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Vse Mozhet Byt <vsemozhetbyt@gmail.com> Reviewed-By: Daniel Bevenius <daniel.bevenius@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Anatoli Papirovski <apapirovski@mac.com>
PR-URL: #22684 Reviewed-By: Tobias Nießen <tniessen@tnie.de> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Vse Mozhet Byt <vsemozhetbyt@gmail.com> Reviewed-By: Daniel Bevenius <daniel.bevenius@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Anatoli Papirovski <apapirovski@mac.com>
@BridgeAR suggested to make symbols non-enumerable for private fields in #22747 (comment). If we decide to do that, we should probably add to these guidelines, so I would love to hear opinions. |
I’m not super fond of that, because we would have to use defineProperty instead of a basic assignment in class definitions and in a lot of property assignment. It’d make the code less maintainable over time and it might cause some performance loss. |
I'm not particularly fond of it either. While I was not really happy with the change that caused symbols to be included in the inspect output, if we really want to hide those details we can do so by providing a custom inspect implementation. |
I don't think that the code becomes less maintainable by using A custom inspect function is not ideal since we would have to reimplement a couple of features every time and that's significantly more work and code than just switching to non-enumerable properties. |
The refactoring needed to https://github.com/nodejs/node/blob/master/lib/internal/http2/core.js would be massive, and definitely hinder its readability. As an example node/lib/internal/http2/core.js Lines 1566 to 1595 in 922a1b0
|
PR-URL: nodejs#22770 Refs: nodejs#22684 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
PR-URL: #22770 Refs: #22684 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
Define `util.inspect.custom` as `Symbol.for("nodejs.util.inspect.custom")` rather than `Symbol("util.inspect.custom")`. This allows `inspect` hooks to easily/safely be defined in non-Node.js environments. Fixes: #20821 Refs: #22684 PR-URL: #20857 Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com> Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: John-David Dalton <john.david.dalton@gmail.com>
PR-URL: #22770 Refs: #22684 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
PR-URL: #22770 Refs: #22684 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
Define `util.inspect.custom` as `Symbol.for("nodejs.util.inspect.custom")` rather than `Symbol("util.inspect.custom")`. This allows `inspect` hooks to easily/safely be defined in non-Node.js environments. Fixes: nodejs#20821 Refs: nodejs#22684 PR-URL: nodejs#20857 Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com> Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: John-David Dalton <john.david.dalton@gmail.com>
Define `util.inspect.custom` as `Symbol.for("nodejs.util.inspect.custom")` rather than `Symbol("util.inspect.custom")`. This allows `inspect` hooks to easily/safely be defined in non-Node.js environments. Fixes: #20821 Refs: #22684 Backport-PR-URL: #23039 PR-URL: #20857 Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com> Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: John-David Dalton <john.david.dalton@gmail.com>
I've added the
Symbol
guideline that spun out from the discussion in #20857.Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passes