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

test: Add tests for escape and handlescope #1263

Closed

Conversation

JckXia
Copy link
Member

@JckXia JckXia commented Jan 4, 2023

Adding test coverage for Escape and HandleScope, closes #990

@JckXia JckXia changed the title Add tests for escape and handlescope test: Add tests for escape and handlescope Jan 4, 2023
Value createScopeFromExisting(const CallbackInfo& info) {
{
napi_handle_scope scope;
napi_open_handle_scope(info.Env(), &scope);
Copy link
Member

@mhdawson mhdawson Jan 9, 2023

Choose a reason for hiding this comment

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

Could you have used a second HandleScope declaration here instead of making the node-api call directly? I think it would then look like

HandleScope scope_one(info.Env())
HandleScope scope_two(info.Env(), scope_one.napi_handle_scope())

Same would go for the other test added as well.

Copy link
Member Author

@JckXia JckXia Jan 9, 2023

Choose a reason for hiding this comment

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

I think I've tried that approach before, but ran into some issues with napi_close_handle_scope in ~HandleScope being called on the same underly napi_handle_scope twice when they go out of scope.

Copy link
Member

Choose a reason for hiding this comment

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

@JckXia if that's the case then I think we might have a real problem?

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, I believe the HandleScopeconstructor where we provide an existing napi_handle_scope simply saves a reference of the napi_handle_scope passed in, as opposed to something like a move constructor where we set the other to null.

I think this means when scope_two goes out of scope, its dtor gets ran, we successfully close the referenced handle scope. But when scope_one goes out of scope, its dtor will attempt to call napi_close_handle_scope on what I assume is an already closed handle scope, resulting in a napi_handle_scope_mismatch error.

The reason I created the napi_handle_scope via a direct call to node-api is such that only scope_two's dtor will be ran, closing it successfully.

Copy link
Member Author

@JckXia JckXia Jan 13, 2023

Choose a reason for hiding this comment

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

Sorry @mhdawson , I think I should've been more specific.

The HandleScope::HandleScope(napi_env env, napi_handle_scope scope) overload that we are testing here simply takes an existing napi_handle_scope ref and constructs a C++ stack object. I believe that ctor overload does not open any new scopes in V8.

This napi_handle_scope ref was created by HandleScope scope_one(napi_env), via the HandleScope::HandleScope(napi_env env) ctor from the example. In other words, now we have two HandleScope objects on the C++ stack that is referencing the same napi_handle_scope pointer.

When we reach the end of the function, scope_two goes out of the C++ stack, and its dtor gets ran. In HandleScope::~HandleScope we make a call to napi_close_handle_scope to reflect this change on V8's side. Its successfully ran, and now from V8's POV we have 0 open_handle_scopes. Then, scope_one goes out of the C++ stack, and we run its dtor. We make another call to napi_close_handle_scope, but by now there isn't any open handle scopes in env, (https://github1s.com/nodejs/node/blob/HEAD/src/js_native_api_v8.cc#L2535), which is why we see the napi_handle_scope_mismatch_error

@mhdawson
Copy link
Member

I looked a little more carefully and I understand now. It's not that we have two scopes where one is beeing used in the second. Instead the API is to create an node-addon-api object from an existing node-api C handle. In that case creating the handle through a node-addon-api object would result in a double free since there would be two node-addon-api objects pointing to the same node-api C handle.

Based on that I think this looks good :)

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 pushed a commit that referenced this pull request Jan 13, 2023
@mhdawson
Copy link
Member

Landed as 35d9d66

@mhdawson mhdawson closed this Jan 13, 2023
@JckXia
Copy link
Member Author

JckXia commented Jan 13, 2023

Thanks! @mhdawson :)

@JckXia JckXia deleted the add-tests-for-escape-and-handlescope branch January 14, 2023 00:01
johnfrench3 pushed a commit to johnfrench3/node-addon-api-git that referenced this pull request Aug 11, 2023
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.

[Tests] add documentation for handleScope class and EscapableHandleScope class
2 participants