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`.
This commit is contained in:
Hood Chatham 2023-06-28 20:18:28 -07:00 committed by GitHub
parent b67660ff9d
commit 2089d4238b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 37 additions and 5 deletions

View File

@ -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

View File

@ -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