Skip to content
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

Added test coverage for Symbol class #972

Closed
wants to merge 1 commit into from

Conversation

JckXia
Copy link
Member

@JckXia JckXia commented Apr 20, 2021

Added new tests for the Symbol class. Also added a static method to the Symbol class to perform "Symbol.For()" from the C++ side, since the exisiting method (Symbol::Wellknown) , which has a different functionality caused some confusion.

@JckXia
Copy link
Member Author

JckXia commented Apr 20, 2021

I can't seem to recreate this test failure. It seems intermittent as the CI running against this commit is successful in my forked repo. https://github.com/JckXia/node-addon-api/actions/runs/765661855.

Copy link
Member

@NickNaso NickNaso left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JckXia well done. Just some comments.

napi.h Outdated
@@ -538,6 +538,9 @@ 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;
static Symbol For(napi_env env, const std::string& name);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need some other overloads for this methods?

static Symbol For(napi_env env,  const char* description = nullptr);
static Symbol For(napi_env env,  String description);
static Symbol For(napi_env env, napi_value description);

What do you think about?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm yeah I think that will be a good idea. Will add them in soon.

napi.h Outdated
@@ -538,6 +538,9 @@ 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;
static Symbol For(napi_env env, const std::string& name);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remember to add documentation for this new method.

test/symbol.cc Outdated
using namespace Napi;

Symbol CreateNewSymbolWithNoArgs(const Napi::CallbackInfo& info) {
(void)info;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does it necessary do this?

(void)info;

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this was to suppress compiler warnings for unused parameter, since the default Symbol constructor doesn't take in any values. But i can remove this function since it's not being called from js.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To avoid compiler complains maybe you can try the following solution (comment the formal parameter of the function):

Symbol CreateNewSymbolWithNoArgs(const Napi::CallbackInfo& /*info*/) {

Let me know if it worked.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep it works. Thanks!

test/symbol.js Outdated

}


Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove one empty new line.

exports["getSymbolFromGlobalRegistry"] =
Function::New(env, FetchSymbolFromGlobalRegistry);
return exports;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PLease add one empty new line.

@NickNaso
Copy link
Member

I can't seem to recreate this test failure. It seems intermittent as the CI running against this commit is successful in my forked repo. https://github.com/JckXia/node-addon-api/actions/runs/765661855.

Don't worry I restarted the jobs and now it's all green.

Copy link
Member

@NickNaso NickNaso left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @JckXia,
I added som e comments about you last work.

doc/symbol.md Outdated
@@ -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
### Wellkown
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please fix the typo it should be WellKnown

```cpp
static Napi::Symbol Napi::Symbol::WellKnown(napi_env env, const std::string& name);
```

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add the documentation for all the overloads of Napi::Symbol Napi::Symbol::WellKnown() methos.

doc/symbol.md Outdated
- `[in] env`: The `napi_env` environment in which to construct the `Napi::Symbol` object.
- `[in] name`: The C++ string representing the `Napi::Symbol` to retrieve.

Register `Napi::Symbol` in the global registry. If symbol already exist retrieve said symbol. Equivalent to `Symbol.for("symb")` called from JS.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe the following description is better:
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-inl.h Outdated
}

inline Symbol Symbol::For(napi_env env, String description) {
napi_value descriptionValue = description;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can directory pass description to Symbol::For() because Napi::String is a Napi::Value that has the cast operator napi_value.

doc/symbol.md Outdated
@@ -45,4 +45,14 @@ 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.

### For
```cpp
static Napi::Symbol Napi::Symbol::WellKnown(napi_env env, const std::string& name);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are adding the For method... should this be For...?

Copy link
Member

@NickNaso NickNaso left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @JckXia,
just something to fix.

doc/symbol.md Outdated
@@ -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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It shlould be WellKnown insteand of Wellknown. The k should be in uppercase.

doc/symbol.md Outdated
Comment on lines 51 to 53
static Napi::Symbol For(napi_env env, const char* description = nullptr);
static Napi::Symbol For(napi_env env, String description);
static Napi::Symbol For(napi_env env, napi_value description);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use the complete namespace there:

static Napi::Symbol Napi::Symbol::For(napi_env env, const char* description = nullptr);
static Napi::Symbol Napi::Symbol::For(napi_env env, String description);
static Napi::Symbol Napi::Symbol::For(napi_env env,napi_value description);

Copy link
Member

@NickNaso NickNaso left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @JckXia,
could you propose the last change on the package.json on a different PR? I'm asking for this because the change it's not correlated with the test and in case we will need to revert the change it will be more simpler to do. For the rest it's all ok.

@JckXia
Copy link
Member Author

JckXia commented Apr 28, 2021

Hey @NickNaso
Thanks for the review! I think I accidentally made some changes to package.json and checked it into git for some reason and was trying to revert it. There was no changes needed to be made to package.json and I will try to revert the changes made to it. Sorry about that.

Copy link
Member

@NickNaso NickNaso left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Contributor

@gabrielschulhof gabrielschulhof left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking until we figure out what happens when you pass nullptr to napi_create_string_utf8() as its const char* parameter.

napi.h Outdated
Comment on lines 542 to 552
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 = nullptr);

// 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);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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 = nullptr);
// 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);
static Symbol For(Env env, const std::string& description);
// Create a symbol in the global registry, C style string (null terminated)
static Symbol For(Env env, const char* description = nullptr);
// Create a symbol in the global registry, String value describing the symbol
static Symbol For(Env env, String description);
// Create a symbol in the global registry, napi_value describing the symbol
static Symbol For(Env env, napi_value description);

@@ -998,6 +998,29 @@ 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) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
inline Symbol Symbol::For(napi_env env, const std::string& description) {
inline Symbol Symbol::For(Napi::Env env, const std::string& description) {

... and a similar change for all APIs below.

@gabrielschulhof
Copy link
Contributor

@JckXia thanks for catching this!

@gabrielschulhof
Copy link
Contributor

We must never pass nullptr into napi_create_string_*() because that will cause a crash. Thus, we should actually change all the APIs (even existing ones) that end up calling napi_create_string_*() to return napi_invalid_arg when passed in what evaluates to (const char *)nullptr.

I'll make a PR upstream to fix this in core.

@JckXia
Copy link
Member Author

JckXia commented Jun 2, 2021

Thanks for the review @gabrielschulhof . Just making sure, are we converting the env parameter in these overloads from type napi_env to type Napi::Env ? Or are we keeping overloads for both napi_env and Napi::Env ?

@gabrielschulhof
Copy link
Contributor

I checked napi.h by looking for [(]napi_env and it turns out most of our APIs take napi_env as the first argument so it's OK to keep the napi_env and we need neither replace nor provide overloads. So, LGTM except for the passing-null-to-napi_create_string_* part.

@gabrielschulhof
Copy link
Contributor

Refs: nodejs/node#38923

@mhdawson
Copy link
Member

@JckXia just wondering what the next steps are to get this landed?

@JckXia
Copy link
Member Author

JckXia commented Jun 14, 2021

@mhdawson I believe that it is ready to be merged.

doc/symbol.md Outdated
### 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 = nullptr);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @JckXia ,

Do we have a test for this nullptr value...? I am not sure what happens when using a nullptr napi_value for the description here:

  auto forSymb =
      symbObject.Get("for").As<Function>().Call(symbObject, {description});

and I think a test would be beneficial

@JckXia
Copy link
Member Author

JckXia commented Jun 16, 2021

@KevinEady Thanks for catching that! Apparently if we simply pass the C++ nullptr into that function it will cause a SegFault. I updated the Symbol::For method impl to use the napi_value we get from calling the napi_get_null function instead and it seems to work.

@KevinEady
Copy link
Contributor

@KevinEady Thanks for catching that! Apparently if we simply pass the C++ nullptr into that function it will cause a SegFault. I updated the Symbol::For method impl to use the napi_value we get from calling the napi_get_null function instead and it seems to work.

@JckXia Aahahh... I am inclined then to remove the std::nullptr default and the "check if nullptr, assume napi_get_null" ... Because that is not something we have in other locations. For example,

{
  [null]: "3"
}

is a valid JSON object, but we do not check in Object::Get for using const char* utf8name with std::nullptr:

node-addon-api/napi-inl.h

Lines 1227 to 1232 in ad76ad0

inline Value Object::Get(const char* utf8name) const {
napi_value result;
napi_status status = napi_get_named_property(_env, _value, utf8name, &result);
NAPI_THROW_IF_FAILED(_env, status, Value());
return Value(_env, result);
}

The application would just crash (I assume). I would think, for consistency purposes, we should remove the nullptr default as well as the runtime check (which is additional overhead anyway).

If the user wanted to explicitly use null, they could use Symbol::For(env, env.Null()).

Thoughts?

@JckXia
Copy link
Member Author

JckXia commented Jun 16, 2021

@KevinEady Oh okay I see. So I think we can simply pass the description argument into String::New(), and pass the newly constructed Napi string the Symbol::For function? Also, I think this Symbol::For(env, env.Null()) is a good approach, as I believe they could do something similar for undefined. Will update the PR and later today. :)

@KevinEady
Copy link
Contributor

This depends on landing #1015 first.

@gabrielschulhof
Copy link
Contributor

Please feel free to dismiss my change request after #1015 has landed and the nullptr default for the char * argument was removed!

@KevinEady
Copy link
Contributor

As discussed in today's meeting, please remove the std::nullptr default value in Symbol::For.

@mhdawson
Copy link
Member

mhdawson commented Jul 9, 2021

1015 landed, dismissing @gabrielschulhof review as suggested above.

@mhdawson mhdawson dismissed gabrielschulhof’s stale review July 9, 2021 15:52

He said it could be dismissed after 1015 landed which has landed.

Copy link
Member

@mhdawson mhdawson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@mhdawson
Copy link
Member

mhdawson commented Jul 9, 2021

@JckXia could you squash down to 1 commit? I'm having trouble landing because it crashes in an git am and I'm thinking it being in 1 commit would resolve that.

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
@JckXia
Copy link
Member Author

JckXia commented Jul 9, 2021

@mhdawson Thanks, it's been fixed.

mhdawson pushed a commit that referenced this pull request Jul 9, 2021
PR-URL: #972
Reviewed-By: Michael Dawson <midawson@redhat.com>
Reviewed-By: Nicola Del Gobbo <nicoladelgobbo@gmail.com>
@mhdawson
Copy link
Member

mhdawson commented Jul 9, 2021

Landed in e02e8a4

@mhdawson mhdawson closed this Jul 9, 2021
deepakrkris pushed a commit to deepakrkris/node-addon-api that referenced this pull request Sep 23, 2021
PR-URL: nodejs#972
Reviewed-By: Michael Dawson <midawson@redhat.com>
Reviewed-By: Nicola Del Gobbo <nicoladelgobbo@gmail.com>
deepakrkris pushed a commit to deepakrkris/node-addon-api that referenced this pull request Oct 15, 2021
PR-URL: nodejs#972
Reviewed-By: Michael Dawson <midawson@redhat.com>
Reviewed-By: Nicola Del Gobbo <nicoladelgobbo@gmail.com>
kevindavies8 added a commit to kevindavies8/node-addon-api-Develop that referenced this pull request Aug 24, 2022
PR-URL: nodejs/node-addon-api#972
Reviewed-By: Michael Dawson <midawson@redhat.com>
Reviewed-By: Nicola Del Gobbo <nicoladelgobbo@gmail.com>
Marlyfleitas added a commit to Marlyfleitas/node-api-addon-Development that referenced this pull request Aug 26, 2022
PR-URL: nodejs/node-addon-api#972
Reviewed-By: Michael Dawson <midawson@redhat.com>
Reviewed-By: Nicola Del Gobbo <nicoladelgobbo@gmail.com>
wroy7860 added a commit to wroy7860/addon-api-benchmark-node that referenced this pull request Sep 19, 2022
PR-URL: nodejs/node-addon-api#972
Reviewed-By: Michael Dawson <midawson@redhat.com>
Reviewed-By: Nicola Del Gobbo <nicoladelgobbo@gmail.com>
@JckXia JckXia deleted the symbol-class-tests branch December 14, 2022 00:46
austinli64 added a commit to austinli64/node-addon-api that referenced this pull request May 9, 2023
PR-URL: nodejs/node-addon-api#972
Reviewed-By: Michael Dawson <midawson@redhat.com>
Reviewed-By: Nicola Del Gobbo <nicoladelgobbo@gmail.com>
johnfrench3 pushed a commit to johnfrench3/node-addon-api-git that referenced this pull request Aug 11, 2023
PR-URL: nodejs/node-addon-api#972
Reviewed-By: Michael Dawson <midawson@redhat.com>
Reviewed-By: Nicola Del Gobbo <nicoladelgobbo@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants