Context-sensitive examples are not extensible
還沒有人認領這個 Issue。
評估
- 難度
- 4/5
- 預估耗時
- 3-5 天
- 新手友好度
- 35/100
- Issue 類型
- 缺陷
- 描述清晰度
- 基本清楚
- 活躍度
- 停滯
- 技術堆疊
- cpp, nodejs
研究方向
Start with the test.cc and test.js reproducer, then read the N-API SetInstanceData documentation cited in the issue. Verify how creating Foo and Bar causes the second instance-data value to replace the first. Done means both createFoo() and createBar() produce objects passing their respective instanceof checks without leaking the earlier constructor reference.
由索引模型根據 Issue 內容生成。
描述
This pull request https://github.com/nodejs/node-addon-examples/pull/139 removes global static references from the examples. However, proposed solution works only for single object wrap.
Consider the following example where two object wraps are created using the same code snippet:
Napi::FunctionReference* constructor = new Napi::FunctionReference();
*constructor = Napi::Persistent(func);
env.SetInstanceData(constructor);
test.cc
#include <napi.h>
#include <cassert>
class Foo : public Napi::ObjectWrap<Foo> {
public:
static void Init(Napi::Env env, Napi::Object exports) {
Napi::Function func = DefineClass(env, "Foo", {});
Napi::FunctionReference* constructor = new Napi::FunctionReference();
*constructor = Napi::Persistent(func);
env.SetInstanceData(constructor);
exports.Set("Foo", func);
}
static Napi::Object NewInstance(Napi::Env env) {
const auto constructor = env.GetInstanceData<Napi::FunctionReference>();
assert(constructor != nullptr);
return constructor->New({});
}
explicit Foo(const Napi::CallbackInfo& info) : Napi::ObjectWrap<Foo>{info} {}
};
class Bar : public Napi::ObjectWrap<Foo> {
public:
static void Init(Napi::Env env, Napi::Object exports) {
Napi::Function func = DefineClass(env, "Bar", {});
Napi::FunctionReference* constructor = new Napi::FunctionReference();
*constructor = Napi::Persistent(func);
env.SetInstanceData(constructor);
exports.Set("Bar", func);
}
static Napi::Object NewInstance(Napi::Env env) {
const auto constructor = env.GetInstanceData<Napi::FunctionReference>();
assert(constructor != nullptr);
return constructor->New({});
}
explicit Bar(const Napi::CallbackInfo& info) : Napi::ObjectWrap<Foo>{info} {}
};
Napi::Value CreateFoo(const Napi::CallbackInfo& info) {
return Foo::NewInstance(info.Env());
}
Napi::Value CreateBar(const Napi::CallbackInfo& info) {
return Bar::NewInstance(info.Env());
}
Napi::Object InitAll(Napi::Env env, Napi::Object exports) {
Foo::Init(env, exports);
Bar::Init(env, exports);
exports.Set("createFoo", Napi::Function::New(env, CreateFoo));
exports.Set("createBar", Napi::Function::New(env, CreateBar));
return exports;
}
NODE_API_MODULE(NODE_GYP_MODULE_NAME, InitAll)
test.js
'use strict';
const assert = require('assert');
const {createFoo, createBar, Foo, Bar} = require('./build/Debug/test');
const foo = createFoo();
assert(foo instanceof Foo); // fails
const bar = createBar();
assert(bar instanceof Bar);
$ node test.js
assert.js:383
throw err;
^
AssertionError [ERR_ASSERTION]: The expression evaluated to a falsy value:
assert(foo instanceof Foo)
at Object.<anonymous> (/home/kostya/tmp/napi-test/test.js:7:1)
at Module._compile (internal/modules/cjs/loader.js:1063:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
at Module.load (internal/modules/cjs/loader.js:928:32)
at Function.Module._load (internal/modules/cjs/loader.js:769:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:72:12)
at internal/main/run_main_module.js:17:47 {
generatedMessage: true,
code: 'ERR_ASSERTION',
actual: false,
expected: true,
operator: '=='
}
As we can see second call of Env::SetInstanceData() in Bar::Init() overrides reference to Foo constructor. Moreover, this causes memory leak, because destructor of the first reference will not be called
From https://nodejs.org/dist/latest-v14.x/docs/api/n-api.html#n_api_napi_set_instance_data
Any existing data associated with the currently running Agent which was set by means of a previous call to napi_set_instance_data() will be overwritten. If a finalize_cb was provided by the previous call, it will not be called.
- 主要語言
- C++
- 星號
- 2.6k
- 分支
- 598
- PR 合併指標
- 30 天內沒有已合併 PR
環境準備
- 沒有 Dockerfile 或 Docker Compose 檔案
- 有 Pull Request 範本
- 閱讀貢獻指南
從這裡開始
- 先讀完整個 Issue,再讀專案的貢獻指南。
- 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
- Fork 儲存庫,在一個分支上完成修改。
- 送出 Pull Request,並在描述裡引用這個 Issue 編號。
nodejs/node-addon-examples 的其他 Issue
-
enhancement
難度 4/5 3-5 天 新手友好度 38/100
nodejs/node-addon-examples#585 · 1 個 reaction ·
-
難度 3/5 1-2 天 新手友好度 38/100
nodejs/node-addon-examples#530 · 1 則留言 ·
-
難度 4/5 3-5 天 新手友好度 35/100
nodejs/node-addon-examples#445 ·
-
難度 3/5 1-2 天 新手友好度 32/100
nodejs/node-addon-examples#444 · 1 則留言 ·
-
難度 3/5 1-2 天 新手友好度 35/100
nodejs/node-addon-examples#381 ·
查看 nodejs/node-addon-examples 的全部 Issue
相似的 Issue
-
難度 2/5 1-3 小時 新手友好度 70/100
meshcore-dev/MeshCore#3760 · 1 則留言 ·
維護者通常 1 天內回覆
-
難度 1/5 1 小時以內 新手友好度 88/100
deepseek-ai/DeepGEMM-Ascend#29 ·
維護者通常 1 天內回覆
-
documentation
難度 2/5 1-3 小時 新手友好度 70/100
EchoTools/nevr-runtime#2042 ·
維護者通常 1 天內回覆
-
難度 2/5 1-3 小時 新手友好度 85/100
emscripten-core/emscripten#28160 · 1 則留言 ·
維護者通常 1 天內回覆
-
Download size and speed show scientific notation between 1000 and 1023 units可能已有人在做 @RaphaelFakhri 今天認領。 未關閉
難度 2/5 1 小時以內 新手友好度 88/100
kiwix/kiwix-desktop#1570 ·
維護者通常 1 天內回覆