proposal-signals
proposal-signals copied to clipboard
Should we include a Signal.subtle.currentComputed API?
@shaylew has raised that this API may be "too powerful"--it is a bit like arguments.caller in a way. In particular, it allows you to reach across frameworks and look at a computed context that might be none of your business. Let's be careful about whether we want to add this API, and explore how useful/important it is during prototyping signals within frameworks.
I think the "next weakest" useful alternative here is something like this:
namespace Signal {
namespace subtle {
const context = Symbol("context");
function currentContext(): unknown;
}
interface Options<T> {
[Signal.subtle.context]?: (this: AnySignal<T>) => unknown;
}
}
So this lets you expose the whole shebang (with { [Signal.subtle.context]() { return this } }), expose nothing, or have frameworks come up with some other context object that exposes certain things about the signal and hides others. It does still result in every framework sharing a context, which can be useful and also a footgun (hard to tell at this stage).
I think this is good enough for ownership, and for various contextual warnings, but yeah IMO let's leave the maximally powerful one in place, let people come up with ways to use it, and then figure out if there's something better that covers the uses we think are worth it (there might turn out to be, there might not).
I like this idea! It preserves encapsulation and the capability simultaneously. But do we need it to be actually calling a function, or should we make it just a constant value? (You could always call a method on that value if it feels right for your usage.)
If you pass a constant value you have to construct a new one for each Computed -- even if you wanted to expose the entire Computed, since you can't pass it to its own constructor and need to use mutation and a wrapper object to tie the knot.
I thought frameworks might not be so hot on that idea, which is why that API lets you pass the same function every time but have it return something different based on the receiver. But yeah... we might want to go to the plain value option, or else maybe specify that the function gets invoked at most once (the first time something within its body asks for currentContext) and then the value is cached on the computed thereafter.