Bug 1264780 - Handle destructuring cases when forcing binding initialization; r=bgrins

--HG--
extra : rebase_source : 98cd72020897bb606ce1b7ce98ac9f7a368f293b
This commit is contained in:
Morgan Phillips 2016-04-15 19:01:09 -07:00
parent 2b86c7361b
commit 286ca684cf
2 changed files with 103 additions and 19 deletions

View File

@ -1302,11 +1302,50 @@ WebConsoleActor.prototype =
ast = {"body": []};
}
for (let line of ast.body) {
if (line.type == "VariableDeclaration" &&
(line.kind == "let" || line.kind == "const")) {
for (let decl of line.declarations)
dbgWindow.forceLexicalInitializationByName(decl.id.name);
// Only let and const declarations put bindings into an
// "initializing" state.
if (!(line.kind == "let" || line.kind == "const"))
continue;
let identifiers = [];
for (let decl of line.declarations) {
switch (decl.id.type) {
case "Identifier":
// let foo = bar;
identifiers.push(decl.id.name);
break;
case "ArrayPattern":
// let [foo, bar] = [1, 2];
// let [foo=99, bar] = [1, 2];
for (let e of decl.id.elements) {
if (e.type == "Identifier") {
identifiers.push(e.name);
} else if (e.type == "AssignmentExpression") {
identifiers.push(e.left.name);
}
}
break;
case "ObjectPattern":
// let {bilbo, my} = {bilbo: "baggins", my: "precious"};
// let {blah: foo} = {blah: yabba()}
// let {blah: foo=99} = {blah: yabba()}
for (let prop of decl.id.properties) {
// key
if (prop.key.type == "Identifier")
identifiers.push(prop.key.name);
// value
if (prop.value.type == "Identifier") {
identifiers.push(prop.value.name);
} else if (prop.value.type == "AssignmentExpression") {
identifiers.push(prop.value.left.name);
}
}
break;
}
}
for (let name of identifiers)
dbgWindow.forceLexicalInitializationByName(name);
}
}
}

View File

@ -225,21 +225,66 @@ function* doEvalWithBindingFrame() {
}
function* forceLexicalInit() {
info("test `let x = SomeError` results in x being initialized to undefined");
let response = yield evaluateJS("let foopie = wubbalubadubdub;");
checkObject(response, {
from: gState.actor,
input: "let foopie = wubbalubadubdub;",
result: undefined,
});
ok(response.exception, "expected exception");
let response2 = yield evaluateJS("foopie;");
checkObject(response2, {
from: gState.actor,
input: "foopie;",
result: undefined,
});
ok(!response2.exception, "unexpected exception");
info("test that failed let/const bindings are initialized to undefined");
const testData = [
{
stmt: "let foopie = wubbalubadubdub",
vars: ["foopie"]
},
{
stmt: "let {z, w={n}=null} = {}",
vars: ["z", "w"]
},
{
stmt: "let [a, b, c] = null",
vars: ["a", "b", "c"]
},
{
stmt: "const nein1 = rofl, nein2 = copter",
vars: ["nein1", "nein2"]
},
{
stmt: "const {ha} = null",
vars: ["ha"]
},
{
stmt: "const [haw=[lame]=null] = []",
vars: ["haw"]
},
{
stmt: "const [rawr, wat=[lame]=null] = []",
vars: ["rawr", "haw"]
},
{
stmt: "let {zzz: xyz=99, zwz: wb} = nexistepas()",
vars: ["xyz", "wb"]
},
{
stmt: "let {c3pdoh=101} = null",
vars: ["c3pdoh"]
}
];
for (let data of testData) {
let response = yield evaluateJS(data.stmt);
checkObject(response, {
from: gState.actor,
input: data.stmt,
result: undefined,
});
ok(response.exception, "expected exception");
for (let varName of data.vars) {
let response2 = yield evaluateJS(varName);
checkObject(response2, {
from: gState.actor,
input: varName,
result: undefined,
});
ok(!response2.exception, "unexpected exception");
}
}
nextTest();
}