mirror of
https://github.com/micropython/micropython.git
synced 2026-01-08 13:10:21 +01:00
webassembly/objjsproxy: Lookup attributes without testing they exist.
In JavaScript when accessing an attribute such as `obj.attr` a value of `undefined` is returned if the attribute does not exist. This is unlike Python semantics where an `AttributeError` is raised. Furthermore, in some cases in JavaScript (eg a Proxy instance) `attr in obj` can return false yet `obj.attr` is still valid and returns something other than `undefined`. So the source of truth for whether a JavaScript attribute exists is to just right away attempt `obj.attr`. To more closely match these JavaScript semantics when proxying a JavaScript object through to Python, change the attribute lookup logic on a `JsProxy` so that it immediately attempts `obj.attr` instead of first testing if the attribute exists via `attr in obj`. This allows JavaScript objects which dynamically create attributes to work correctly on the Python side, with both `obj.attr` and `obj["attr"]`. Note that `obj["attr"]` already works in all cases because it immediately does the subscript access without first testing if the attribute exists. As a benefit, this new behaviour matches the Pyodide behaviour. Signed-off-by: Damien George <damien@micropython.org>
This commit is contained in:
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user