Debugger.Frame.prototype.eval can miss inner bindings

NEW
Unassigned

Status

()

Core
JavaScript Engine
6 years ago
3 years ago

People

(Reporter: jimb, Unassigned)

Tracking

Firefox Tracking Flags

(Not tracked)

Details

Attachments

(1 attachment)

(Reporter)

Description

6 years ago
Created attachment 585447 [details] [diff] [review]
test to show that Debugger.Frame.prototype.eval can miss inner bindings

In code like this:

var x = 'outer';
function f() { var x = 'inner'; return function g() { h(); } }
function h() { debugger; }

Evaluating f()(), stopping at the debugger statement, and evaluating 'x' in h's caller's frame can return 'outer': f's local binding for x is not visible to Debugger.Frame.prototype.eval.

This is probably due to SpiderMonkey using the null closure representation for g's closure, and Debugger.Environment not catching that.
(Reporter)

Comment 1

6 years ago
I don't think SpiderMonkey should try to keep the inner 'x' around in this case; almost all the time, the user won't need to see it, and will appreciate the space-saving optimization. Instead, I think the call to Debugger.Frame.prototype.eval should throw an error indicating that the variable's value isn't available due to optimizations.

Comment 2

6 years ago
Agreed.

From IRC, and for the record: bug 690135 is going to fix JS_GetFrameScopeChain to return a scope chain composed of wrappers (which wrap pre-existing or lazily-reified ScopeObjects).  This bug could be fixed by extending that approach with a new Proxy which represents an environment that could not be lazily reified.  This Proxy could then use the script's Bindings to throw errors on lookups that hit.

A challenge is that inner scripts do not root outer scripts and probably shouldn't so we can't work our way from fp->fun()->script() outward.  A direct solution that hopefully wouldn't waste too much memory would be to instead have JSScript.bindings root the bindings of enclosing scripts.

An alternative is to use the js::types::TypeScriptNesting that TI attaches to JSScripts.  The problem is that, IIRC, the tree of TypeScriptNestings is incomplete and gets thrown away at various times.  I'm not totally sure what the invariants are, though.  If we went with the first strategy, perhaps it could be generalized so that TI could reuse it instead of doing the same thing?  What do you think Brian?
Bug 692984 comment 3 mentions this bug. In short: when this gets fixed, please also add a test that looks for the bug using frame.environment.
(Assignee)

Updated

3 years ago
Assignee: general → nobody
You need to log in before you can comment on or make changes to this bug.