napi_get_property_names: throws on JavaScriptCore; inconsistent enumerability/prototype semantics on Chakra and QuickJS
メンテナーはふだん 1 日以内に返信
@bkaradzic-microsoft がすでに取り組んでいます。
2026年7月30日 から。
評価
この issue はまだ評価されていません。
説明
napi_get_property_names behaves differently on all three non-V8 backends, and throws unconditionally on JavaScriptCore. Since Napi::Object::GetPropertyNames() is a direct wrapper, that method is unusable on JSC for every N-API caller — and JSC is the default engine on macOS and iOS.
Reference behaviour (V8)
js_native_api_v8.cc matches the Node-API specification: enumerable, string-keyed properties, including the prototype chain.
obj->GetPropertyNames(
context,
v8::KeyCollectionMode::kIncludePrototypes,
static_cast<v8::PropertyFilter>(
v8::PropertyFilter::ONLY_ENUMERABLE |
v8::PropertyFilter::SKIP_SYMBOLS),
v8::IndexFilter::kIncludeIndices,
v8::KeyConversionMode::kConvertToString);
JavaScriptCore — throws
Core/Node-API/Source/js_native_api_javascriptcore.cc:
CHECK_NAPI(napi_get_named_property(env, object_ctor, "getOwnPropertyNames", &function));
CHECK_NAPI(napi_call_function(env, object_ctor, function, 0, nullptr, result));
The object parameter is never used. The call passes argc 0 / argv nullptr, so it evaluates Object.getOwnPropertyNames(undefined), which throws TypeError. Note there is also no CHECK_ARG(env, object).
Passing the object is necessary but not sufficient. Object.getOwnPropertyNames is own-only and includes non-enumerable properties, so it disagrees with V8 on both axes. A conforming JSC implementation needs enumerable properties across the prototype chain — the semantics of for...in filtered to string keys.
Chakra — own-only, includes non-enumerables
js_native_api_chakra.cc uses JsGetOwnPropertyNames, which is own-only and does not filter to enumerable properties. Wrong on both axes, though it does not throw.
QuickJS — own-only
js_native_api_quickjs.cc uses JS_GetOwnPropertyNames with JS_GPN_STRING_MASK | JS_GPN_ENUM_ONLY. Enumerability is correct; the prototype chain is missing.
Summary
| backend | enumerable-only | includes prototype chain | throws |
|---|---|---|---|
| V8 | yes | yes | no |
| JavaScriptCore | n/a | n/a | yes |
| Chakra | no | no | no |
| QuickJS | yes | no | no |
Repro
const proto = { inherited: 1 };
const obj = Object.create(proto);
obj.own = 2;
Object.defineProperty(obj, "hidden", { value: 3, enumerable: false });
// napi_get_property_names(obj) should yield exactly ["own", "inherited"].
On JSC this throws instead of returning. On Chakra it yields ["own", "hidden"]. On QuickJS it yields ["own"].
Impact / workaround
Encountered in Babylon Native while enumerating a plain JS data object (BabylonJS/BabylonNative#1797). The workaround is to fetch Object.keys from the global and call it via napi_call_function, which behaves consistently across engines for plain data objects:
const auto objectCtor = env.Global().Get("Object").As<Napi::Object>();
const auto keys = objectCtor.Get("keys").As<Napi::Function>();
That is only equivalent for own-enumerable cases, so it is a local workaround rather than a fix.
- 主要言語
- C++
- スター
- 22
- フォーク
- 23
- 平均マージ
- 2時間 29分
- マージ済み PR(30日)
- 3
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートなし
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
BabylonJS/JsRuntimeHost のほかの issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 84/100
BabylonJS/JsRuntimeHost#234 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
BabylonJS/JsRuntimeHost#173 ·
メンテナーはふだん 1 日以内に返信
-
難易度 4/5 3〜5日 初心者へのやさしさ 42/100
BabylonJS/JsRuntimeHost#241 · コメント 3 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 5/5 1週間以上 初心者へのやさしさ 35/100
BabylonJS/JsRuntimeHost#228 ·
メンテナーはふだん 1 日以内に返信
-
napi_unwrap does not reject objects that were never wrapped (V8 port faults, QuickJS port confuses types)対応中かも @bghgary が 51 日前に担当しました。 オープン
難易度 4/5 3〜5日 初心者へのやさしさ 68/100
BabylonJS/JsRuntimeHost#226 ·
メンテナーはふだん 1 日以内に返信
BabylonJS/JsRuntimeHost の issue をすべて見る
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
bitcoin-core/gui-qml#1003 ·
メンテナーはふだん 3 日以内に返信
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 63/100
metasequoiaime/msime#7328 ·
メンテナーはふだん 1 日以内に返信
-
[Linux] --calibrate combined with --model silently falls through to plain re-setup (setup.py:4958)オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
メンテナーはふだん 1 日以内に返信
-
bug
難易度 1/5 1〜3時間 初心者へのやさしさ 65/100
メンテナーはふだん 1 日以内に返信
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 66/100
メンテナーはふだん 1 日以内に返信