Repository navigation
[Node-API] Symbol.toStringTag support #41358
Description
Activity
- addedfeature requestIssues requesting new Node.js features.Issues requesting new Node.js features.
on Dec 30, 2021 - changed the title
[-][Node-API] Symbol.toStringTag support in created objects[/-][+][Node-API] Symbol.toStringTag support[/+]on Dec 30, 2021 - addednode-apiIssues and PRs related to Node-API.Issues and PRs related to Node-API.
on Dec 30, 2021 - added a commit that references this issue
on Jan 1, 2022 PR: #41370
Reacted by Romain Lamothe and Gang ChenYou can use
napi_get_globalto access the global variable of the current context; and then usenapi_get_propertyto accessSymbol.toStringTag.Using the C++ wrapper API, this is a one-liner:
env.Global().Get("Symbol").As<Napi::Object>().Get("toStringTag").I would strongly recommend doing that instead of adding a new functionality to get a small, specific, not very well-defined JS built-in values like #41370 would suggest. Using the existing mechanisms also has the advantage that it already works just fine, and you don’t need to wait for a new Node-API version in order to use this feature.
Reacted by Gang ChenReacted by Romain LamotheWell that works perfectly. Thanks @addaleax.
Indeed, no need for change on the Node-API with your solution.Actually I printed
globalin Node but global.Symbol was not enumerated so I thought it was not available there.Maybe we can write an example in the docs or somewhere? Because I never came across any solution to do this.
Here is another example that works in C (no C++ wrapper API):
static napi_value init_module(napi_env env, napi_value exports) { napi_value global, symbol, symbol_to_string_tag, tag_name; // Get JavaScript global Symbol.toStringTag if(napi_get_global(env, &global) != napi_ok) return NULL; if(napi_get_named_property(env, global, "Symbol", &symbol) != napi_ok) return NULL; if(napi_get_named_property(env, symbol, "toStringTag", &symbol_to_string_tag) != napi_ok) return NULL; // Declare JavaScript tag name if(napi_create_string_utf8(env, "My Module", NAPI_AUTO_LENGTH, &tag_name) != napi_ok) return NULL; // Declare properties for JavaScript `exports` object napi_property_descriptor props[] = { { NULL, symbol_to_string_tag, NULL, NULL, NULL, tag_name, napi_enumerable, NULL }, // ... }; // Write properties to JavaScript `exports` object size_t nb_props = sizeof(props) / sizeof(napi_property_descriptor); if(napi_define_properties(env, exports, nb_props, props) != napi_ok) return NULL; return exports; } NAPI_MODULE(my_module, init_module)
Using the C++ wrapper API, this is a one-liner: env.Global().Get("Symbol").AsNapi::Object().Get("toStringTag").
This already takes care of getting the Symbol object from the global object:
Napi::Symbol::WellKnown(env, "toStringTag");
Reacted by Romain Lamothe and Anna Henningsen
What is the problem this feature will solve?
Using Node-API, I would like my C/C++ addon to generate a JavaScript object decorated with a tag name, like this:
So I can get:

I believe this is not possible to set the
Symbol.toStringTagproperty to an object created with the current Node-API.What is the feature you are proposing to solve the problem?
I guess we need access to the global
Symbol.toStringTagand other well-known Symbols defined in JavaScript.Below is the Node.js example to create a new Symbol and set it as a property for an object (along other properties):
node/test/js-native-api/test_properties/test_properties.c
Lines 72 to 96 in e46c680
Instead of creating a new Symbol we would have to use the existing
Symbol.toStringTag.Maybe you could consider to have a method like
napi_get_symbol_tostringtag(env, &name_symbol)to replacenapi_create_symbol(..used on line 78.What alternatives have you considered?
Explored the Node-API but I have no clue for a workaround in the C/C++ code.
For a root object returned by the add-on, one may use the add-on
main.jsfile to add the property dynamically in JavaScript before the export, but it's not pretty.