GoogleChromeLabs / comlink

Comlink makes WebWorkers enjoyable.
Apache License 2.0
11k stars 382 forks source link

Feature request: Automatic proxy of arguments #662

Open kubijo opened 1 month ago

kubijo commented 1 month ago

Out of curiosity, why doesn't comlink automatically proxy callbacks out of the box or at least give an opt-in for that?

I have been able to achieve it in the following way…

function $<T>(w: Worker): Remote<T> {
    const remote = comlinkWrap<T>(w);
    return new Proxy<Remote<T>>(remote, {
        get(target, prop, receiver) {
            if (typeof target[prop] === 'function') {
                return new Proxy(target[prop], {
                    apply(target, thisArg, argArray) {
                        // Proxy functions in the argument list as well
                        const proxiedArgs = argArray.map(arg => (typeof arg === 'function' ? comlinkProxy(arg) : arg));
                        return Reflect.apply(target, thisArg, proxiedArgs);
                    },
                });
            }

            return Reflect.get(target, prop, receiver);
        },
    });
}

Am I missing something important here?

surma commented 1 month ago

It does not do it automatically because every callback requires creating a new proxy that holds on to the proxied value, which is basically a memory leak.

If you want to automatically proxy callbacks, you can use transfer handlers. The example for in the README shows how to automatically proxy events and you can use the exact same technique for functions.

yelouafi commented 1 month ago

I was curious about this as well. Mainly because callbacks can’t be sent natively so we’ll always need to proxy them, which seems redundant IMO.

kubijo commented 1 month ago

Yeah, then again... there is a strong chance for memory leaks with callbacks in general. I think I'm gonna in the end rather use some observed triggers in indexeddb (which is part of my whole setup for the project)