tc39/how-we-work

define "observable behavior"

Opened this issue · 6 comments

This term is used here, and also here, and a number of other places. It seems like it'd be good to define it here in a detailed way.

mpcsh commented

I've always understood it to refer to edge cases in the spec or non-spec-compliant engine behavior that, e.g., is possible to replicate in a node REPL or browser console. Does that intuition sound correct to you?

The repl should not be able to observe non observable behavior. Dev tools may show implementation details that reveal what would be unobservable to the program. My understanding is that the engine can deviate from the exact step described in the spec if that deviation doesn't have any impact on any program. An example that came up recently was how engines may implement registered symbols (as creating and collecting unique symbols, and mapping them in a collection, or as simply creating a new internal type wrapping the description value)

syg commented

I've always understood it to refer to edge cases in the spec or non-spec-compliant engine behavior that, e.g., is possible to replicate in a node REPL or browser console. Does that intuition sound correct to you?

No, observable behavior is all behavior that can be observed... somehow, and is far from dealing with just edge cases. The spec exists to specify observable behavior.

My non-detailed intuition is basically any behavior that can change program output, whether that be pixels on the screen or console output. The hard thing to nail down here is the what's observable is environment and per-program, so when we talk about it in context of the spec it's usually a fairly conservative notion of observability.

The repl or browser dev tools should not be able to observe non observable behavior.

It most definitely can! E.g. it's reasonable for devtools to observe the values of dead variables, even though dead variables are otherwise unobservable.

It most definitely can! E.g. it's reasonable for devtools to observe the values of dead variables, even though dead variables are otherwise unobservable.

Sorry I was originally only thinking of the console. Dev tools can definitely show internal details that are otherwise unobservable. Edited

syg commented

Rigorously defining observable behaviors requires us to have rigorous notions of 1) what's observable (e.g. all memory? pixels on screen?) and 2) notions of "confluence" of evaluation (e.g. something like Church-Rosser or bi-similarity). Then a "behavior", e.g. a step in the evaluation, is unobservable iff all possible evaluations with and without that behavior are confluent up to what's observable.

We can probably say something useful by providing non-normative guidance around 1).

Edit: I should qualify this as the classical notion of observability. There's a very real sense in which timing is observable, since, you know, machines can count nanoseconds, but timing is usually not considered as observable when reasoning about programs. Of course things like Spectre made a mockery out of that...

My thinking around this for JS is that observable behavior is anything a compliant JS program can observe, which does not include a repl, nor using things that expose internals, like node's inspection methods. This includes the presence of internal slots, often their values, function names/lengths, when/if exceptions are thrown and what kind of exception, etc.

Basically, everything JS can see that's covered by the spec, minus the things that are implementation-dependent/defined.