Skip to content

Commit 26e2930

Browse files
committed
Finished first set of symbol tests
Add new static method to symbol and updated tests Updated Symbol.md 's docs, added function overload for Symbol class and new tests Remove extra space and comments Remove un-necssary string initialization Update PR based on comments received Add test checking if it's possible to pass nullptr to Symbol::For method Update Symbol::For implementations and added new tests Remove default parameter Update documentation for Symbol
1 parent 37a9b8e commit 26e2930

File tree

7 files changed

+217
-2
lines changed

7 files changed

+217
-2
lines changed

doc/symbol.md

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ If an error occurs, a `Napi::Error` will get thrown. If C++ exceptions are not
3434
being used, callers should check the result of `Napi::Env::IsExceptionPending` before
3535
attempting to use the returned value.
3636
37-
### Utf8Value
37+
### WellKnown
3838
```cpp
3939
static Napi::Symbol Napi::Symbol::WellKnown(napi_env env, const std::string& name);
4040
```
@@ -45,4 +45,17 @@ static Napi::Symbol Napi::Symbol::WellKnown(napi_env env, const std::string& nam
4545
Returns a `Napi::Symbol` representing a well-known `Symbol` from the
4646
`Symbol` registry.
4747

48-
[`Napi::Name`]: ./name.md
48+
### For
49+
```cpp
50+
static Napi::Symbol Napi::Symbol::For(napi_env env, const std::string& description);
51+
static Napi::Symbol Napi::Symbol::For(napi_env env, const char* description);
52+
static Napi::Symbol Napi::Symbol::For(napi_env env, String description);
53+
static Napi::Symbol Napi::Symbol::For(napi_env env, napi_value description);
54+
```
55+
56+
- `[in] env`: The `napi_env` environment in which to construct the `Napi::Symbol` object.
57+
- `[in] description`: The C++ string representing the `Napi::Symbol` in the global registry to retrieve.
58+
59+
Searches in the global registry for existing symbol with the given name. If the symbol already exist it will be returned, otherwise a new symbol will be created in the registry. It's equivalent to Symbol.for() called from JavaScript.
60+
61+
[`Napi::Name`]: ./name.md

napi-inl.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -998,6 +998,27 @@ inline Symbol Symbol::WellKnown(napi_env env, const std::string& name) {
998998
return Napi::Env(env).Global().Get("Symbol").As<Object>().Get(name).As<Symbol>();
999999
}
10001000

1001+
inline Symbol Symbol::For(napi_env env, const std::string& description) {
1002+
napi_value descriptionValue = String::New(env, description);
1003+
return Symbol::For(env, descriptionValue);
1004+
}
1005+
1006+
inline Symbol Symbol::For(napi_env env, const char* description) {
1007+
napi_value descriptionValue = String::New(env, description);
1008+
return Symbol::For(env, descriptionValue);
1009+
}
1010+
1011+
inline Symbol Symbol::For(napi_env env, String description) {
1012+
return Symbol::For(env, static_cast<napi_value>(description));
1013+
}
1014+
1015+
inline Symbol Symbol::For(napi_env env, napi_value description) {
1016+
Object symbObject = Napi::Env(env).Global().Get("Symbol").As<Object>();
1017+
auto forSymb =
1018+
symbObject.Get("for").As<Function>().Call(symbObject, {description});
1019+
return forSymb.As<Symbol>();
1020+
}
1021+
10011022
inline Symbol::Symbol() : Name() {
10021023
}
10031024

@@ -2397,6 +2418,7 @@ inline const std::string& Error::Message() const NAPI_NOEXCEPT {
23972418
inline void Error::ThrowAsJavaScriptException() const {
23982419
HandleScope scope(_env);
23992420
if (!IsEmpty()) {
2421+
<<<<<<< HEAD
24002422
#ifdef NODE_API_SWALLOW_UNTHROWABLE_EXCEPTIONS
24012423
bool pendingException = false;
24022424

@@ -2423,6 +2445,8 @@ inline void Error::ThrowAsJavaScriptException() const {
24232445
status = napi_pending_exception;
24242446
}
24252447
#else
2448+
=======
2449+
>>>>>>> 7bfbd3e... Update Symbol::For implementations and added new tests
24262450
// We intentionally don't use `NAPI_THROW_*` macros here to ensure
24272451
// that there is no possible recursion as `ThrowAsJavaScriptException`
24282452
// is part of `NAPI_THROW_*` macro definition for noexcept.
@@ -2740,19 +2764,31 @@ inline bool ObjectReference::Set(const char* utf8name, double numberValue) {
27402764
return Value().Set(utf8name, numberValue);
27412765
}
27422766

2767+
<<<<<<< HEAD
27432768
inline bool ObjectReference::Set(const std::string& utf8name,
2769+
=======
2770+
inline void ObjectReference::Set(const std::string& utf8name,
2771+
>>>>>>> 7bfbd3e... Update Symbol::For implementations and added new tests
27442772
napi_value value) {
27452773
HandleScope scope(_env);
27462774
return Value().Set(utf8name, value);
27472775
}
27482776

2777+
<<<<<<< HEAD
27492778
inline bool ObjectReference::Set(const std::string& utf8name,
2779+
=======
2780+
inline void ObjectReference::Set(const std::string& utf8name,
2781+
>>>>>>> 7bfbd3e... Update Symbol::For implementations and added new tests
27502782
Napi::Value value) {
27512783
HandleScope scope(_env);
27522784
return Value().Set(utf8name, value);
27532785
}
27542786

2787+
<<<<<<< HEAD
27552788
inline bool ObjectReference::Set(const std::string& utf8name,
2789+
=======
2790+
inline void ObjectReference::Set(const std::string& utf8name,
2791+
>>>>>>> 7bfbd3e... Update Symbol::For implementations and added new tests
27562792
std::string& utf8value) {
27572793
HandleScope scope(_env);
27582794
return Value().Set(utf8name, utf8value);
@@ -2763,7 +2799,11 @@ inline bool ObjectReference::Set(const std::string& utf8name, bool boolValue) {
27632799
return Value().Set(utf8name, boolValue);
27642800
}
27652801

2802+
<<<<<<< HEAD
27662803
inline bool ObjectReference::Set(const std::string& utf8name,
2804+
=======
2805+
inline void ObjectReference::Set(const std::string& utf8name,
2806+
>>>>>>> 7bfbd3e... Update Symbol::For implementations and added new tests
27672807
double numberValue) {
27682808
HandleScope scope(_env);
27692809
return Value().Set(utf8name, numberValue);

napi.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,18 @@ namespace Napi {
538538
/// Get a public Symbol (e.g. Symbol.iterator).
539539
static Symbol WellKnown(napi_env, const std::string& name);
540540

541+
// Create a symbol in the global registry, UTF-8 Encoded cpp string
542+
static Symbol For(napi_env env, const std::string& description);
543+
544+
// Create a symbol in the global registry, C style string (null terminated)
545+
static Symbol For(napi_env env, const char* description);
546+
547+
// Create a symbol in the global registry, String value describing the symbol
548+
static Symbol For(napi_env env, String description);
549+
550+
// Create a symbol in the global registry, napi_value describing the symbol
551+
static Symbol For(napi_env env, napi_value description);
552+
541553
Symbol(); ///< Creates a new _empty_ Symbol instance.
542554
Symbol(napi_env env,
543555
napi_value value); ///< Wraps a Node-API value primitive.

test/binding.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ Object InitTypedThreadSafeFunctionSum(Env env);
5858
Object InitTypedThreadSafeFunctionUnref(Env env);
5959
Object InitTypedThreadSafeFunction(Env env);
6060
#endif
61+
Object InitSymbol(Env env);
6162
Object InitTypedArray(Env env);
6263
Object InitGlobalObject(Env env);
6364
Object InitObjectWrap(Env env);
@@ -117,6 +118,7 @@ Object Init(Env env, Object exports) {
117118
#endif // !NODE_ADDON_API_DISABLE_DEPRECATED
118119
exports.Set("promise", InitPromise(env));
119120
exports.Set("run_script", InitRunScript(env));
121+
exports.Set("symbol", InitSymbol(env));
120122
#if (NAPI_VERSION > 3)
121123
exports.Set("threadsafe_function_ctx", InitThreadSafeFunctionCtx(env));
122124
exports.Set("threadsafe_function_existing_tsfn", InitThreadSafeFunctionExistingTsfn(env));

test/binding.gyp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
'object/subscript_operator.cc',
4747
'promise.cc',
4848
'run_script.cc',
49+
"symbol.cc",
4950
'threadsafe_function/threadsafe_function_ctx.cc',
5051
'threadsafe_function/threadsafe_function_existing_tsfn.cc',
5152
'threadsafe_function/threadsafe_function_ptr.cc',

test/symbol.cc

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
#include <napi.h>
2+
using namespace Napi;
3+
4+
Symbol CreateNewSymbolWithNoArgs(const Napi::CallbackInfo&) {
5+
return Napi::Symbol();
6+
}
7+
8+
Symbol CreateNewSymbolWithCppStrDesc(const Napi::CallbackInfo& info) {
9+
String cppStrKey = info[0].As<String>();
10+
return Napi::Symbol::New(info.Env(), cppStrKey.Utf8Value());
11+
}
12+
13+
Symbol CreateNewSymbolWithCStrDesc(const Napi::CallbackInfo& info) {
14+
String cStrKey = info[0].As<String>();
15+
return Napi::Symbol::New(info.Env(), cStrKey.Utf8Value().c_str());
16+
}
17+
18+
Symbol CreateNewSymbolWithNapiString(const Napi::CallbackInfo& info) {
19+
String strKey = info[0].As<String>();
20+
return Napi::Symbol::New(info.Env(), strKey);
21+
}
22+
23+
Symbol GetWellknownSymbol(const Napi::CallbackInfo& info) {
24+
String registrySymbol = info[0].As<String>();
25+
return Napi::Symbol::WellKnown(info.Env(),
26+
registrySymbol.Utf8Value().c_str());
27+
}
28+
29+
Symbol FetchSymbolFromGlobalRegistry(const Napi::CallbackInfo& info) {
30+
String registrySymbol = info[0].As<String>();
31+
return Napi::Symbol::For(info.Env(), registrySymbol);
32+
}
33+
34+
Symbol FetchSymbolFromGlobalRegistryWithCppKey(const Napi::CallbackInfo& info) {
35+
String cppStringKey = info[0].As<String>();
36+
return Napi::Symbol::For(info.Env(), cppStringKey.Utf8Value());
37+
}
38+
39+
Symbol FetchSymbolFromGlobalRegistryWithCKey(const Napi::CallbackInfo& info) {
40+
String cppStringKey = info[0].As<String>();
41+
return Napi::Symbol::For(info.Env(), cppStringKey.Utf8Value().c_str());
42+
}
43+
44+
Symbol TestUndefinedSymbolsCanBeCreated(const Napi::CallbackInfo& info) {
45+
Napi::Env env = info.Env();
46+
return Napi::Symbol::For(env, env.Undefined());
47+
}
48+
49+
Symbol TestNullSymbolsCanBeCreated(const Napi::CallbackInfo& info) {
50+
Napi::Env env = info.Env();
51+
return Napi::Symbol::For(env, env.Null());
52+
}
53+
54+
Object InitSymbol(Env env) {
55+
Object exports = Object::New(env);
56+
57+
exports["createNewSymbolWithNoArgs"] =
58+
Function::New(env, CreateNewSymbolWithNoArgs);
59+
exports["createNewSymbolWithCppStr"] =
60+
Function::New(env, CreateNewSymbolWithCppStrDesc);
61+
exports["createNewSymbolWithCStr"] =
62+
Function::New(env, CreateNewSymbolWithCStrDesc);
63+
exports["createNewSymbolWithNapi"] =
64+
Function::New(env, CreateNewSymbolWithNapiString);
65+
exports["getWellKnownSymbol"] = Function::New(env, GetWellknownSymbol);
66+
exports["getSymbolFromGlobalRegistry"] =
67+
Function::New(env, FetchSymbolFromGlobalRegistry);
68+
exports["getSymbolFromGlobalRegistryWithCKey"] =
69+
Function::New(env, FetchSymbolFromGlobalRegistryWithCKey);
70+
exports["getSymbolFromGlobalRegistryWithCppKey"] =
71+
Function::New(env, FetchSymbolFromGlobalRegistryWithCppKey);
72+
exports["testUndefinedSymbolCanBeCreated"] =
73+
Function::New(env, TestUndefinedSymbolsCanBeCreated);
74+
exports["testNullSymbolCanBeCreated"] =
75+
Function::New(env, TestNullSymbolsCanBeCreated);
76+
return exports;
77+
}

test/symbol.js

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
'use strict';
2+
3+
const buildType = process.config.target_defaults.default_configuration;
4+
const assert = require('assert');
5+
6+
test(require(`./build/${buildType}/binding.node`));
7+
test(require(`./build/${buildType}/binding_noexcept.node`));
8+
9+
10+
async function test(binding)
11+
{
12+
13+
const wellKnownSymbolFunctions = ['asyncIterator','hasInstance','isConcatSpreadable', 'iterator','match','matchAll','replace','search','split','species','toPrimitive','toStringTag','unscopables'];
14+
15+
function assertCanCreateSymbol(symbol)
16+
{
17+
assert(binding.symbol.createNewSymbolWithCppStr(symbol) !== null);
18+
assert(binding.symbol.createNewSymbolWithCStr(symbol) !== null);
19+
assert(binding.symbol.createNewSymbolWithNapi(symbol) !== null);
20+
}
21+
22+
function assertSymbolAreUnique(symbol)
23+
{
24+
const symbolOne = binding.symbol.createNewSymbolWithCppStr(symbol);
25+
const symbolTwo = binding.symbol.createNewSymbolWithCppStr(symbol);
26+
27+
assert(symbolOne !== symbolTwo);
28+
}
29+
30+
function assertSymbolIsWellknown(symbol)
31+
{
32+
const symbOne = binding.symbol.getWellKnownSymbol(symbol);
33+
const symbTwo = binding.symbol.getWellKnownSymbol(symbol);
34+
assert(symbOne && symbTwo);
35+
assert(symbOne === symbTwo);
36+
}
37+
38+
function assertSymbolIsNotWellknown(symbol)
39+
{
40+
const symbolTest = binding.symbol.getWellKnownSymbol(symbol);
41+
assert(symbolTest === undefined);
42+
}
43+
44+
function assertCanCreateOrFetchGlobalSymbols(symbol, fetchFunction)
45+
{
46+
const symbOne = fetchFunction(symbol);
47+
const symbTwo = fetchFunction(symbol);
48+
assert(symbOne && symbTwo);
49+
assert(symbOne === symbTwo);
50+
}
51+
52+
assertCanCreateSymbol("testing");
53+
assertSymbolAreUnique("symbol");
54+
assertSymbolIsNotWellknown("testing");
55+
56+
for(const wellknownProperty of wellKnownSymbolFunctions)
57+
{
58+
assertSymbolIsWellknown(wellknownProperty);
59+
}
60+
61+
assertCanCreateOrFetchGlobalSymbols("data", binding.symbol.getSymbolFromGlobalRegistry);
62+
assertCanCreateOrFetchGlobalSymbols("CppKey", binding.symbol.getSymbolFromGlobalRegistryWithCppKey);
63+
assertCanCreateOrFetchGlobalSymbols("CKey", binding.symbol.getSymbolFromGlobalRegistryWithCKey);
64+
65+
assert(binding.symbol.createNewSymbolWithNoArgs() === undefined);
66+
67+
assert(binding.symbol.testNullSymbolCanBeCreated() === binding.symbol.testNullSymbolCanBeCreated());
68+
assert(binding.symbol.testUndefinedSymbolCanBeCreated() === binding.symbol.testUndefinedSymbolCanBeCreated());
69+
assert(binding.symbol.testUndefinedSymbolCanBeCreated() !== binding.symbol.testNullSymbolCanBeCreated());
70+
}

0 commit comments

Comments
 (0)