diff --git a/ports/webassembly/objjsproxy.c b/ports/webassembly/objjsproxy.c index cbfe8be49baf..167d4382bc63 100644 --- a/ports/webassembly/objjsproxy.c +++ b/ports/webassembly/objjsproxy.c @@ -46,8 +46,14 @@ EM_JS(bool, has_attr, (int jsref, const char *str), { EM_JS(bool, lookup_attr, (int jsref, const char *str, uint32_t * out), { const base = proxy_js_ref[jsref]; const attr = UTF8ToString(str); - if (attr in base) { - let value = base[attr]; + + // Attempt to lookup the requested attribute from the base object: + // - If the value is not `undefined` then the attribute exists with that value. + // - Otherwise if the value is `undefined` and the `in` operator returns true, then + // that attribute does exist and is intended to have a value of `undefined`. + // - Otherwise, the attribute does not exist. + let value = base[attr]; + if (value !== undefined || attr in base) { if (typeof value === "function") { if (base !== globalThis) { if ("_ref" in value) { diff --git a/tests/ports/webassembly/js_proxy_attribute.mjs b/tests/ports/webassembly/js_proxy_attribute.mjs new file mode 100644 index 000000000000..5d950122778b --- /dev/null +++ b/tests/ports/webassembly/js_proxy_attribute.mjs @@ -0,0 +1,34 @@ +// Test lookup of attributes on JsProxy objects. + +const mp = await (await import(process.argv[2])).loadMicroPython(); + +// Simple attribute names and values. +globalThis.obj1 = { a: 1, b: 2 }; + +// Unconventional attribute names and values. +globalThis.obj2 = { undefined: "undefined", undef: undefined }; + +// Dynamically created attribute names and values. +globalThis.obj3 = new Proxy(new Map(), { + get(map, name) { + if (!map.has(name)) { + console.log("creating attribute", name); + map.set(name, name); + } + return map.get(name); + }, +}); + +mp.runPython(` +import js + +print(js.obj1.a, js.obj1.b) +print(js.obj1["a"], js.obj1["b"]) + +print(js.obj2.undefined, js.obj2.undef) + +print(js.obj3.c) +print(js.obj3["c"]) +print(hasattr(js.obj3, "d")) +print(js.obj3.d) +`); diff --git a/tests/ports/webassembly/js_proxy_attribute.mjs.exp b/tests/ports/webassembly/js_proxy_attribute.mjs.exp new file mode 100644 index 000000000000..7de85a56648a --- /dev/null +++ b/tests/ports/webassembly/js_proxy_attribute.mjs.exp @@ -0,0 +1,9 @@ +1 2 +1 2 +undefined +creating attribute c +c +c +creating attribute d +True +d