Support for eager evaluation in JSTerm

NEW
Unassigned

Status

enhancement
P3
normal
Last year
2 months ago

People

(Reporter: Honza, Unassigned)

Tracking

(Blocks 1 bug)

Firefox Tracking Flags

(Not tracked)

Details

(Whiteboard: [boogaloo-reserve])

JSTerm can support eager evaluation. This feature allows instant evaluation of side effect free expressions without you needing to press enter key.

This allows easily craft expression while seeing the result (can be an error message) live. It's very useful for inspecting object (results) properties as well as learning JS.

Short post:
https://medium.com/better-things-digital/chrome-devtools-instant-evaluation-of-javascript-expressions-cf13af597a2e

Live demo:
https://youtu.be/mfuE53x4b3k?t=1564

Honza
Awesome! But the video at 31:10 says
> eager evaluation is done in a way that we can guarantee there are no side effects. And we did this by introducing a new mode in V8, where we attempt to evaluate the code. But if we know it's about to cause a side effect that changes the outside state —your application, the page, other parts of the DOM—, we just bail and stop doing that work.

Does SpiderMonkey have something like this?
This is a very awesome feature, but like Oriol, I'm curious about the side-effect free aspect of it.
I remember years ago having that same discussion with :past. He was telling me how our autocomplete popup couldn't work after function calls because that would require actually running the function and therefore causing side effects.
Pinging him here in case he remembers the context.
Flags: needinfo?(past)
Yes, "side effect free" mode is the hard part of this. Note that we might need such mode for bug 1460530 as well.

Honza
I think at the time we were talking about a recurring request to autocomplete things like |document.getElementsByTagName("div").|, which could cause side effects (well, perhaps not this specific case, but function calls generally can). I think we have some helpers to identify safe getters and safe objects from a side-effect point of view that could be used to determine when to do eager evaluation. I don't know which cases Chrome can evaluate eagerly, but it seems like the kind of thing where we could take care of the easy cases first and keep expanding from there if there is enough demand.
Flags: needinfo?(past)
@Jim: how feasible (amount of work estimate) would be to provide "side effect free" evaluation mode in SpiderMonkey? Such mode would help us to implement this eager evaluation feature as well as better auto-completion. Or is there anyone else we could ask?

Honza
Flags: needinfo?(jimb)
(In reply to Panos Astithas [:past] (please ni?) from comment #4)
> I don't know which cases Chrome can evaluate eagerly, but it seems like
> the kind of thing where we could take care of the easy cases first and
> keep expanding from there if there is enough demand.

Chrome can evaluate eagerly most user-defined functions, e.g.

  > var obj = {get a(){if(Math.random() < 0) {} return true}}
  < undefined
  > obj.a
    true

It seems their heuristic has some false negatives (which I guess are preferable to false positives):

  > var obj = {get a(){if(Math.random() < 0) sideEffect = true; return true}}
  < undefined
  > obj.a
    // no eager evaluation

> I think we have some helpers to identify safe getters
> and safe objects from a side-effect point of view that could be used to
> determine when to do eager evaluation.

I guess you refer to DevToolsUtils.hasSafeGetter, which is already used e.g. in autocomplete. It doesn't really check side-effects, but it has very few false positives. The inconvenient is that there are too many false negatives, e.g. all user-defined getters are considered unsafe.
Priority: P3 → P2
Whiteboard: [boogaloo-mvp]
Product: Firefox → DevTools
(In reply to Jan Honza Odvarko [:Honza] PTO from 7/22 to 8/5 from comment #5)
> @Jim: how feasible (amount of work estimate) would be to provide "side
> effect free" evaluation mode in SpiderMonkey? Such mode would help us to
> implement this eager evaluation feature as well as better auto-completion.
> Or is there anyone else we could ask?

Let me talk with Ted Campbell about this. I think we could do something.
Flags: needinfo?(jimb)
I had a chat with Jason Orendorff and Ted Campbell about possible approaches here.

Any approach requires whitelisting native JSFunctions.

One possibility would be to create a temporary compartment that refers to the original evaluation environment via special cross-compartment wrappers, and then do the evaluation in that compartment. These wrappers would handle any attempt to use the object whatsoever by cloning their referent into the temporary compartment, wrapping any objects it refers to in turn with the same sort of wrapper. Scripts would also be cloned into the temporary compartment.

Then, as the expression evaluates, every object and script it uses would be cloned into the new compartment, where it could be freely modified. When evaluation ends, we would simply drop the compartment.

We already have the cross-compartment and brain transplant machinery. I don't know about the object cloning code.
Why do we need the wrapper and brain transplant? Isn't it simpler to either:

(1) Have the wrapper handler only forward safe operations (getting a data property, etc).

(2) Use no wrappers at all, but have some sort of environment object/proxy that clones objects into the target compartment as soon as you access them.

I'd really like to avoid more uses of brain transplants. Using them on arbitrary objects might reveal more issues and in general it's a big hack I want to remove (or severely limit) at some point.
About object cloning: what if you clone some DOM object we know nothing about, do we just create a new PlainObject, copy all the data properties and lose the special DOM object slots/clasp etc? A filtering wrapper feels nicer here in that we don't have to worry about this problem.
The problem with the filtering wrapper is that it has no way to tell when to permit a 'get'. That can run arbitrary code.
(In reply to Jim Blandy :jimb from comment #12)
> The problem with the filtering wrapper is that it has no way to tell when to
> permit a 'get'. That can run arbitrary code.

Can't you do a GetPropertyPure or something?
Hmm, GetPropertyPure might work.
Priority: P2 → P3
Whiteboard: [boogaloo-mvp] → [boogaloo-reserve]
Whiteboard: [boogaloo-reserve] → [boogaloo-mvp]
Priority: P3 → P2
Priority: P2 → P3
Whiteboard: [boogaloo-mvp] → [boogaloo-reserve]
Duplicate of this bug: 1549169
You need to log in before you can comment on or make changes to this bug.