Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Iterating keys of proxy object #2557

Open
alandefreitas opened this issue Nov 27, 2023 · 1 comment
Open

Iterating keys of proxy object #2557

alandefreitas opened this issue Nov 27, 2023 · 1 comment

Comments

@alandefreitas
Copy link

alandefreitas commented Nov 27, 2023

I'm virtualizing an object as a duktape Proxy object but can't iterate or get all the keys in this object. When I try to get the object keys, I always get an empty array. Is there a solution or even a workaround to this?

I created a minimal example just in case:

duk_context* ctx = duk_create_heap_default();
duk_push_object(ctx); // [target]
duk_push_object(ctx); // [target] [handler]
duk_push_c_function(ctx, ownKeysFn, 1); // [target] [handler] [function]
duk_put_prop_string(ctx, -2, "ownKeys"); // [target] [handler]
duk_push_c_function(ctx, getKeyFn, 1); // [target] [handler] [function]
duk_put_prop_string(ctx, -2, "get"); // [target] [handler]
duk_push_proxy(ctx, 0); // [proxy]

where

duk_ret_t
ownKeysFn(duk_context* ctx)
{
    // return ["k1", "k2", "k3"]
    duk_idx_t arr_idx = duk_push_array(ctx); // [target] [array]
    duk_push_string(ctx, "k1"); // [target] [array] [string]
    duk_put_prop_index(ctx, arr_idx, 0); // [target] [array]
    duk_push_string(ctx, "k2"); // [target] [array] [string]
    duk_put_prop_index(ctx, arr_idx, 1); // [target] [array]
    duk_push_string(ctx, "k3"); // [target] [array] [string]
    duk_put_prop_index(ctx, arr_idx, 2); // [target] [array]
    return 1;
}

and

duk_ret_t
getKeyFn(duk_context* ctx)
{
    // Any key returns 1 just for the sake of the test.
    duk_idx_t arr_idx = duk_push_array(ctx); // [target] [key] [recv]
    duk_push_int(ctx, 1); // [target] [key] [recv] [int]
    return 1;
}

When I try to get or iterate the keys, I get an empty array. I tried many ways of iterating these values (scripts, from C, etc), including the following:

duk_enum(ctx, -1, DUK_ENUM_OWN_PROPERTIES_ONLY); // this triggers ownKeysFn
while (duk_next(ctx, -1, 1))
{
    // This never executes:
    const char * key = duk_get_string(ctx, -2); // [proxy] [key] [value]
    do_something_with_key(key);
    duk_pop_2(ctx); // [proxy]
}
duk_pop(ctx);

I guess this issue could be related to #2153 but I'm not sure if the use cases are the same because I honestly don't completely understand that discussion since I'm not as fluent in JavaScript. If I understand that discussion correctly, do I need either to define getOwnPropertyDescriptor (which duktape doesn't support) or somehow define the keys explicitly (which breaks virtualization)? Is there a workaround to achieve virtualization somehow with duktape? #2153 issue is from 2019 so maybe some things have changed?

@alandefreitas
Copy link
Author

Update: I tried another version where the target stores a "keys" property containing an array with the keys and ownKeysFn returns that array instead of creating it. Unfortunately, this doesn't work either.

It's an unreasonable solution anyway, but I thought ownKeysFn could update the keys in target whenever it's called. It would be a last-resort workaround.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant