From 2089d4238ba662ae051f7db7bcdc10ca2834077c Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Wed, 28 Jun 2023 20:18:28 -0700 Subject: [PATCH] Only check if key in obj if obj[key] returns undefined (#3963) This is a minor optimization in `JsObject_GetString`. We only need to check if `key in obj` when `obj[key]` returns `undefined` to distinguish between missing and present but set to `undefined`. --- src/core/hiwire.c | 13 ++++++++----- src/tests/test_jsproxy.py | 29 +++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/core/hiwire.c b/src/core/hiwire.c index 16f8a8d45..4fced3392 100644 --- a/src/core/hiwire.c +++ b/src/core/hiwire.c @@ -966,12 +966,15 @@ EM_JS(int, normalizeReservedWords, (int word), { }); EM_JS_REF(JsRef, JsObject_GetString, (JsRef idobj, const char* ptrkey), { - let jsobj = Hiwire.get_value(idobj); - let jskey = normalizeReservedWords(UTF8ToString(ptrkey)); - if (jskey in jsobj) { - return Hiwire.new_value(jsobj[jskey]); + const jsobj = Hiwire.get_value(idobj); + const jskey = normalizeReservedWords(UTF8ToString(ptrkey)); + const result = jsobj[jskey]; + // clang-format off + if (result === undefined && !(jskey in jsobj)) { + // clang-format on + return ERROR_REF; } - return ERROR_REF; + return Hiwire.new_value(result); }); // clang-format off diff --git a/src/tests/test_jsproxy.py b/src/tests/test_jsproxy.py index 2532012f8..c92a118f4 100644 --- a/src/tests/test_jsproxy.py +++ b/src/tests/test_jsproxy.py @@ -2431,3 +2431,32 @@ def test_revoked_proxy(selenium): x = run_js("(p = Proxy.revocable({}, {})); p.revoke(); p.proxy") run_js("((x) => x)")(x) + + +@run_in_pyodide +def test_js_proxy_attribute(selenium): + # Check that `in` is only consulted as a fallback if indexing returns None + import pytest + + from pyodide.code import run_js + + x = run_js( + """ + new Proxy( + {}, + { + get(target, val) { + return { a: 3, b: 7, c: undefined, d: undefined }[val]; + }, + has(target, val) { + return { a: true, b: false, c: true, d: false }[val]; + }, + } + ); + """ + ) + assert x.a == 3 + assert x.b == 7 # Previously this raised AttributeError + assert x.c is None + with pytest.raises(AttributeError): + x.d