Revisit the behavior of lexical declarations in Debugger.Object.prototype.executeInGlobalWithBindings
Categories
(Core :: JavaScript Engine, task, P2)
Tracking
()
People
(Reporter: arai, Unassigned)
References
(Blocks 2 open bugs)
Details
As described in bug 1385198 comment #16, top-level let
and const
behaves in unexpected way in Debugger.Object.prototype.executeInGlobalWithBindings
if the passed bindings object has the same binding.
This comes from the corner case around with
environment + lexical declaration without a block, which is disallowed in ECMAScript itself.
Possible options is to add implicit block scope, or enforce the consumer to add explicit block scope.
Reporter | ||
Comment 1•2 years ago
|
||
(In reply to Tooru Fujisawa [:arai] from comment #0)
Possible options is to add implicit block scope, or enforce the consumer to add explicit block scope.
Actually, adding a block won't work as expected if the consumer really wants to declare a global lexical variable by calling executeInGlobalWithBindings
.
So, this is very specific to the case where the binding conflicts between the top-level lexical declaration and the passed bindings object.
Reporter | ||
Comment 2•2 years ago
|
||
If there's no conflict, the behavior would be intuitive for both var
and let
:
var g = newGlobal({newCompartment: true});
var dbg = new Debugger;
var gw = dbg.addDebuggee(g);
var bindings = {};
// This declares a global variable x with 1,
// and gets the global variable and prints 1.
console.log(gw.executeInGlobalWithBindings(`var x = 1; x;`, bindings).return);
// This still prints 1 given there's global variable x = 1.
g.evaluate(`console.log(x);`);
var g = newGlobal({newCompartment: true});
var dbg = new Debugger;
var gw = dbg.addDebuggee(g);
var bindings = {};
// This declares a global lexical variable x with 1,
// and gets the global lexical variable and prints 1.
console.log(gw.executeInGlobalWithBindings(`let x = 1; x;`, bindings).return);
// This still prints 1 given there's global lexical variable x = 1.
g.evaluate(`console.log(x);`);
If there's a conflict, the behavior is somewhat strange even with var
.
var g = newGlobal({newCompartment: true});
var dbg = new Debugger;
var gw = dbg.addDebuggee(g);
var bindings = { x: 10 };
// This modifies x in the with env,
// and gets x from the with env and prints 1
console.log(gw.executeInGlobalWithBindings(`var x = 1; x;`, bindings).return);
// This prints undefined, given there's no global variable x.
// This doesn't match with the no-conflict case.
g.evaluate(`console.log(x);`);
And it behaves more strangely with let
.
var g = newGlobal({newCompartment: true});
var dbg = new Debugger;
var gw = dbg.addDebuggee(g);
var bindings = { x: 10 };
// This declares a global lexical variable x with 1,
// and gets x from the with env and prints 10.
// This doesn't match with the no-conflict case.
console.log(gw.executeInGlobalWithBindings(`let x = 1; x;`, bindings).return);
// This prints 1 given there's global lexical variable x = 1.
// This matches to the no-conflict case, but doesn't match with the
// var with conflicting binding case.
g.evaluate(`console.log(x);`);
So, the behavior completely disagree between var
and let
if there's confllicting binding.
Reporter | ||
Comment 3•2 years ago
|
||
possible intuitive behavior would be to use the passed bindings object as the enclosing environment of the global, so that the passed binding is used as read-only, and always shadowed by any global/local variables:
WithEnvironmentObject(bindings)
<- GlobalObject
<- global LexicalEnvironmentObject
but it has some problems:
- it simply require many change to how environment and lookup work
- other non-syntactic case may expect the
var
being put intowith
env, and in that case we'll need to maintain both behavior
Reporter | ||
Comment 4•2 years ago
|
||
there's difference between an assignment within a declaration and bare assignment.
// bindings = { x: 10, y: 20 };
let x = 11; // written to GlobalLexicalEnvironmentObject
console.log(x); // 10
y = 21; // written to WithEnvironmentObject
console.log(y); // 21
so, other possible solution would be to tweak the assignment handling inside declaration.
Comment 5•2 years ago
|
||
The performance cliff with the web console (bug 793345) is also related to executeInGlobalWithBindings
, so while you're looking at this it might make sense to see if there are other ways to implement these bindings that would fix that issue too.
Reporter | ||
Updated•2 years ago
|
Description
•