Skip to content

Commit

Permalink
Finished first set of symbol tests
Browse files Browse the repository at this point in the history
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

Fixing merge conflicts
  • Loading branch information
JckXia committed Jul 9, 2021
1 parent 37a9b8e commit bdefbb0
Show file tree
Hide file tree
Showing 7 changed files with 198 additions and 2 deletions.
17 changes: 15 additions & 2 deletions doc/symbol.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ If an error occurs, a `Napi::Error` will get thrown. If C++ exceptions are not
being used, callers should check the result of `Napi::Env::IsExceptionPending` before
attempting to use the returned value.
### Utf8Value
### WellKnown
```cpp
static Napi::Symbol Napi::Symbol::WellKnown(napi_env env, const std::string& name);
```
Expand All @@ -45,4 +45,17 @@ static Napi::Symbol Napi::Symbol::WellKnown(napi_env env, const std::string& nam
Returns a `Napi::Symbol` representing a well-known `Symbol` from the
`Symbol` registry.

[`Napi::Name`]: ./name.md
### For
```cpp
static Napi::Symbol Napi::Symbol::For(napi_env env, const std::string& description);
static Napi::Symbol Napi::Symbol::For(napi_env env, const char* description);
static Napi::Symbol Napi::Symbol::For(napi_env env, String description);
static Napi::Symbol Napi::Symbol::For(napi_env env, napi_value description);
```
- `[in] env`: The `napi_env` environment in which to construct the `Napi::Symbol` object.
- `[in] description`: The C++ string representing the `Napi::Symbol` in the global registry to retrieve.
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.
[`Napi::Name`]: ./name.md
21 changes: 21 additions & 0 deletions napi-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -998,6 +998,27 @@ inline Symbol Symbol::WellKnown(napi_env env, const std::string& name) {
return Napi::Env(env).Global().Get("Symbol").As<Object>().Get(name).As<Symbol>();
}

inline Symbol Symbol::For(napi_env env, const std::string& description) {
napi_value descriptionValue = String::New(env, description);
return Symbol::For(env, descriptionValue);
}

inline Symbol Symbol::For(napi_env env, const char* description) {
napi_value descriptionValue = String::New(env, description);
return Symbol::For(env, descriptionValue);
}

inline Symbol Symbol::For(napi_env env, String description) {
return Symbol::For(env, static_cast<napi_value>(description));
}

inline Symbol Symbol::For(napi_env env, napi_value description) {
Object symbObject = Napi::Env(env).Global().Get("Symbol").As<Object>();
auto forSymb =
symbObject.Get("for").As<Function>().Call(symbObject, {description});
return forSymb.As<Symbol>();
}

inline Symbol::Symbol() : Name() {
}

Expand Down
12 changes: 12 additions & 0 deletions napi.h
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,18 @@ namespace Napi {
/// Get a public Symbol (e.g. Symbol.iterator).
static Symbol WellKnown(napi_env, const std::string& name);

// Create a symbol in the global registry, UTF-8 Encoded cpp string
static Symbol For(napi_env env, const std::string& description);

// Create a symbol in the global registry, C style string (null terminated)
static Symbol For(napi_env env, const char* description);

// Create a symbol in the global registry, String value describing the symbol
static Symbol For(napi_env env, String description);

// Create a symbol in the global registry, napi_value describing the symbol
static Symbol For(napi_env env, napi_value description);

Symbol(); ///< Creates a new _empty_ Symbol instance.
Symbol(napi_env env,
napi_value value); ///< Wraps a Node-API value primitive.
Expand Down
2 changes: 2 additions & 0 deletions test/binding.cc
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ Object InitTypedThreadSafeFunctionSum(Env env);
Object InitTypedThreadSafeFunctionUnref(Env env);
Object InitTypedThreadSafeFunction(Env env);
#endif
Object InitSymbol(Env env);
Object InitTypedArray(Env env);
Object InitGlobalObject(Env env);
Object InitObjectWrap(Env env);
Expand Down Expand Up @@ -117,6 +118,7 @@ Object Init(Env env, Object exports) {
#endif // !NODE_ADDON_API_DISABLE_DEPRECATED
exports.Set("promise", InitPromise(env));
exports.Set("run_script", InitRunScript(env));
exports.Set("symbol", InitSymbol(env));
#if (NAPI_VERSION > 3)
exports.Set("threadsafe_function_ctx", InitThreadSafeFunctionCtx(env));
exports.Set("threadsafe_function_existing_tsfn", InitThreadSafeFunctionExistingTsfn(env));
Expand Down
1 change: 1 addition & 0 deletions test/binding.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
'object/subscript_operator.cc',
'promise.cc',
'run_script.cc',
"symbol.cc",
'threadsafe_function/threadsafe_function_ctx.cc',
'threadsafe_function/threadsafe_function_existing_tsfn.cc',
'threadsafe_function/threadsafe_function_ptr.cc',
Expand Down
77 changes: 77 additions & 0 deletions test/symbol.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#include <napi.h>
using namespace Napi;

Symbol CreateNewSymbolWithNoArgs(const Napi::CallbackInfo&) {
return Napi::Symbol();
}

Symbol CreateNewSymbolWithCppStrDesc(const Napi::CallbackInfo& info) {
String cppStrKey = info[0].As<String>();
return Napi::Symbol::New(info.Env(), cppStrKey.Utf8Value());
}

Symbol CreateNewSymbolWithCStrDesc(const Napi::CallbackInfo& info) {
String cStrKey = info[0].As<String>();
return Napi::Symbol::New(info.Env(), cStrKey.Utf8Value().c_str());
}

Symbol CreateNewSymbolWithNapiString(const Napi::CallbackInfo& info) {
String strKey = info[0].As<String>();
return Napi::Symbol::New(info.Env(), strKey);
}

Symbol GetWellknownSymbol(const Napi::CallbackInfo& info) {
String registrySymbol = info[0].As<String>();
return Napi::Symbol::WellKnown(info.Env(),
registrySymbol.Utf8Value().c_str());
}

Symbol FetchSymbolFromGlobalRegistry(const Napi::CallbackInfo& info) {
String registrySymbol = info[0].As<String>();
return Napi::Symbol::For(info.Env(), registrySymbol);
}

Symbol FetchSymbolFromGlobalRegistryWithCppKey(const Napi::CallbackInfo& info) {
String cppStringKey = info[0].As<String>();
return Napi::Symbol::For(info.Env(), cppStringKey.Utf8Value());
}

Symbol FetchSymbolFromGlobalRegistryWithCKey(const Napi::CallbackInfo& info) {
String cppStringKey = info[0].As<String>();
return Napi::Symbol::For(info.Env(), cppStringKey.Utf8Value().c_str());
}

Symbol TestUndefinedSymbolsCanBeCreated(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
return Napi::Symbol::For(env, env.Undefined());
}

Symbol TestNullSymbolsCanBeCreated(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
return Napi::Symbol::For(env, env.Null());
}

Object InitSymbol(Env env) {
Object exports = Object::New(env);

exports["createNewSymbolWithNoArgs"] =
Function::New(env, CreateNewSymbolWithNoArgs);
exports["createNewSymbolWithCppStr"] =
Function::New(env, CreateNewSymbolWithCppStrDesc);
exports["createNewSymbolWithCStr"] =
Function::New(env, CreateNewSymbolWithCStrDesc);
exports["createNewSymbolWithNapi"] =
Function::New(env, CreateNewSymbolWithNapiString);
exports["getWellKnownSymbol"] = Function::New(env, GetWellknownSymbol);
exports["getSymbolFromGlobalRegistry"] =
Function::New(env, FetchSymbolFromGlobalRegistry);
exports["getSymbolFromGlobalRegistryWithCKey"] =
Function::New(env, FetchSymbolFromGlobalRegistryWithCKey);
exports["getSymbolFromGlobalRegistryWithCppKey"] =
Function::New(env, FetchSymbolFromGlobalRegistryWithCppKey);
exports["testUndefinedSymbolCanBeCreated"] =
Function::New(env, TestUndefinedSymbolsCanBeCreated);
exports["testNullSymbolCanBeCreated"] =
Function::New(env, TestNullSymbolsCanBeCreated);
return exports;
}
70 changes: 70 additions & 0 deletions test/symbol.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
'use strict';

const buildType = process.config.target_defaults.default_configuration;
const assert = require('assert');

test(require(`./build/${buildType}/binding.node`));
test(require(`./build/${buildType}/binding_noexcept.node`));


async function test(binding)
{

const wellKnownSymbolFunctions = ['asyncIterator','hasInstance','isConcatSpreadable', 'iterator','match','matchAll','replace','search','split','species','toPrimitive','toStringTag','unscopables'];

function assertCanCreateSymbol(symbol)
{
assert(binding.symbol.createNewSymbolWithCppStr(symbol) !== null);
assert(binding.symbol.createNewSymbolWithCStr(symbol) !== null);
assert(binding.symbol.createNewSymbolWithNapi(symbol) !== null);
}

function assertSymbolAreUnique(symbol)
{
const symbolOne = binding.symbol.createNewSymbolWithCppStr(symbol);
const symbolTwo = binding.symbol.createNewSymbolWithCppStr(symbol);

assert(symbolOne !== symbolTwo);
}

function assertSymbolIsWellknown(symbol)
{
const symbOne = binding.symbol.getWellKnownSymbol(symbol);
const symbTwo = binding.symbol.getWellKnownSymbol(symbol);
assert(symbOne && symbTwo);
assert(symbOne === symbTwo);
}

function assertSymbolIsNotWellknown(symbol)
{
const symbolTest = binding.symbol.getWellKnownSymbol(symbol);
assert(symbolTest === undefined);
}

function assertCanCreateOrFetchGlobalSymbols(symbol, fetchFunction)
{
const symbOne = fetchFunction(symbol);
const symbTwo = fetchFunction(symbol);
assert(symbOne && symbTwo);
assert(symbOne === symbTwo);
}

assertCanCreateSymbol("testing");
assertSymbolAreUnique("symbol");
assertSymbolIsNotWellknown("testing");

for(const wellknownProperty of wellKnownSymbolFunctions)
{
assertSymbolIsWellknown(wellknownProperty);
}

assertCanCreateOrFetchGlobalSymbols("data", binding.symbol.getSymbolFromGlobalRegistry);
assertCanCreateOrFetchGlobalSymbols("CppKey", binding.symbol.getSymbolFromGlobalRegistryWithCppKey);
assertCanCreateOrFetchGlobalSymbols("CKey", binding.symbol.getSymbolFromGlobalRegistryWithCKey);

assert(binding.symbol.createNewSymbolWithNoArgs() === undefined);

assert(binding.symbol.testNullSymbolCanBeCreated() === binding.symbol.testNullSymbolCanBeCreated());
assert(binding.symbol.testUndefinedSymbolCanBeCreated() === binding.symbol.testUndefinedSymbolCanBeCreated());
assert(binding.symbol.testUndefinedSymbolCanBeCreated() !== binding.symbol.testNullSymbolCanBeCreated());
}

0 comments on commit bdefbb0

Please sign in to comment.