Source code

Revision control

Copy as Markdown

Other Tools

var BUGNUMBER = 1204028;
var summary = "Destructuring should evaluate lhs reference before rhs in super property";
if (typeof assertEq === "undefined") {
assertEq = function(a, b) {
if (a !== b)
throw new Error(`expected ${b}, got ${a}\n${new Error().stack}`);
};
}
print(BUGNUMBER + ": " + summary);
let logs = [];
function log(x) {
logs.push(x);
}
let unwrapMap = new Map();
function unwrap(maybeWrapped) {
if (unwrapMap.has(maybeWrapped))
return unwrapMap.get(maybeWrapped);
return maybeWrapped;
}
function ToString(name) {
if (name == Symbol.iterator)
return "@@iterator";
return String(name);
}
function logger(obj, prefix=[]) {
let wrapped = new Proxy(obj, {
get(that, name) {
if (name == "return") {
// FIXME: Bug 1147371.
// We ignore IteratorClose for now.
return obj[name];
}
let names = prefix.concat(ToString(name));
log("rhs get " + names.join("::"));
let v = obj[name];
if (typeof v === "object" || typeof v === "function")
return logger(v, names);
return v;
},
apply(that, thisArg, args) {
let names = prefix.slice();
log("rhs call " + names.join("::"));
let v = obj.apply(unwrap(thisArg), args);
if (typeof v === "object" || typeof v === "function") {
names[names.length - 1] += "()";
return logger(v, names);
}
return v;
}
});
unwrapMap.set(wrapped, obj);
return wrapped;
}
class C1 {
constructor() {
this.clear();
}
clear() {
this.values = {};
}
}
for (let name of [
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
"n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
"0", "1", "length"
]) {
Object.defineProperty(C1.prototype, name, {
set: function(value) {
log("lhs set " + name);
this.values[name] = value;
}
});
}
class C2 extends C1 {
constructor() {
super();
let clear = () => {
logs = [];
this.clear();
};
// Array.
clear();
[
super.a
] = logger(["A"]);
assertEq(logs.join(","),
[
"rhs get @@iterator",
"rhs call @@iterator",
"rhs get @@iterator()::next",
"rhs call @@iterator()::next",
"rhs get @@iterator()::next()::done",
"rhs get @@iterator()::next()::value",
"lhs set a",
].join(","));
assertEq(this.values.a, "A");
clear();
[
super[ (log("lhs before name a"), "a") ]
] = logger(["A"]);
assertEq(logs.join(","),
[
"rhs get @@iterator",
"rhs call @@iterator",
"rhs get @@iterator()::next",
"lhs before name a",
"rhs call @@iterator()::next",
"rhs get @@iterator()::next()::done",
"rhs get @@iterator()::next()::value",
"lhs set a",
].join(","));
assertEq(this.values.a, "A");
// Array rest.
clear();
[
...super.a
] = logger(["A", "B", "C"]);
assertEq(logs.join(","),
[
"rhs get @@iterator",
"rhs call @@iterator",
"rhs get @@iterator()::next",
"rhs call @@iterator()::next",
"rhs get @@iterator()::next()::done",
"rhs get @@iterator()::next()::value",
"rhs call @@iterator()::next",
"rhs get @@iterator()::next()::done",
"rhs get @@iterator()::next()::value",
"rhs call @@iterator()::next",
"rhs get @@iterator()::next()::done",
"rhs get @@iterator()::next()::value",
"rhs call @@iterator()::next",
"rhs get @@iterator()::next()::done",
"lhs set a",
].join(","));
assertEq(this.values.a.join(","), "A,B,C");
clear();
[
...super[ (log("lhs before name a"), "a") ]
] = logger(["A", "B", "C"]);;
assertEq(logs.join(","),
[
"rhs get @@iterator",
"rhs call @@iterator",
"rhs get @@iterator()::next",
"lhs before name a",
"rhs call @@iterator()::next",
"rhs get @@iterator()::next()::done",
"rhs get @@iterator()::next()::value",
"rhs call @@iterator()::next",
"rhs get @@iterator()::next()::done",
"rhs get @@iterator()::next()::value",
"rhs call @@iterator()::next",
"rhs get @@iterator()::next()::done",
"rhs get @@iterator()::next()::value",
"rhs call @@iterator()::next",
"rhs get @@iterator()::next()::done",
"lhs set a",
].join(","));
assertEq(this.values.a.join(","), "A,B,C");
// Array combined.
clear();
[
super.a,
super[ (log("lhs before name b"), "b") ],
...super[ (log("lhs before name c"), "c") ]
] = logger(["A", "B", "C"]);
assertEq(logs.join(","),
[
"rhs get @@iterator",
"rhs call @@iterator",
"rhs get @@iterator()::next",
"rhs call @@iterator()::next",
"rhs get @@iterator()::next()::done",
"rhs get @@iterator()::next()::value",
"lhs set a",
"lhs before name b",
"rhs call @@iterator()::next",
"rhs get @@iterator()::next()::done",
"rhs get @@iterator()::next()::value",
"lhs set b",
"lhs before name c",
"rhs call @@iterator()::next",
"rhs get @@iterator()::next()::done",
"rhs get @@iterator()::next()::value",
"rhs call @@iterator()::next",
"rhs get @@iterator()::next()::done",
"lhs set c",
].join(","));
assertEq(this.values.a, "A");
assertEq(this.values.b, "B");
assertEq(this.values.c.join(","), "C");
// Object.
clear();
({
a: super.a
} = logger({a: "A"}));
assertEq(logs.join(","),
[
"rhs get a",
"lhs set a",
].join(","));
assertEq(this.values.a, "A");
clear();
({
a: super[ (log("lhs before name a"), "a") ]
} = logger({a: "A"}));
assertEq(logs.join(","),
[
"lhs before name a",
"rhs get a",
"lhs set a",
].join(","));
assertEq(this.values.a, "A");
// Object combined.
clear();
({
a: super.a,
b: super[ (log("lhs before name b"), "b") ]
} = logger({a: "A", b: "B"}));
assertEq(logs.join(","),
[
"rhs get a",
"lhs set a",
"lhs before name b",
"rhs get b",
"lhs set b",
].join(","));
assertEq(this.values.a, "A");
assertEq(this.values.b, "B");
// == Nested ==
// Array -> Array
clear();
[
[
super[ (log("lhs before name a"), "a") ],
...super[ (log("lhs before name b"), "b") ]
]
] = logger([["A", "B"]]);
assertEq(logs.join(","),
[
"rhs get @@iterator",
"rhs call @@iterator",
"rhs get @@iterator()::next",
"rhs call @@iterator()::next",
"rhs get @@iterator()::next()::done",
"rhs get @@iterator()::next()::value",
"rhs get @@iterator()::next()::value::@@iterator",
"rhs call @@iterator()::next()::value::@@iterator",
"rhs get @@iterator()::next()::value::@@iterator()::next",
"lhs before name a",
"rhs call @@iterator()::next()::value::@@iterator()::next",
"rhs get @@iterator()::next()::value::@@iterator()::next()::done",
"rhs get @@iterator()::next()::value::@@iterator()::next()::value",
"lhs set a",
"lhs before name b",
"rhs call @@iterator()::next()::value::@@iterator()::next",
"rhs get @@iterator()::next()::value::@@iterator()::next()::done",
"rhs get @@iterator()::next()::value::@@iterator()::next()::value",
"rhs call @@iterator()::next()::value::@@iterator()::next",
"rhs get @@iterator()::next()::value::@@iterator()::next()::done",
"lhs set b",
].join(","));
assertEq(this.values.a, "A");
assertEq(this.values.b.length, 1);
assertEq(this.values.b[0], "B");
// Array rest -> Array
clear();
[
...[
super[ (log("lhs before name a"), "a") ],
...super[ (log("lhs before name b"), "b") ]
]
] = logger(["A", "B"]);
assertEq(logs.join(","),
[
"rhs get @@iterator",
"rhs call @@iterator",
"rhs get @@iterator()::next",
"rhs call @@iterator()::next",
"rhs get @@iterator()::next()::done",
"rhs get @@iterator()::next()::value",
"rhs call @@iterator()::next",
"rhs get @@iterator()::next()::done",
"rhs get @@iterator()::next()::value",
"rhs call @@iterator()::next",
"rhs get @@iterator()::next()::done",
"lhs before name a",
"lhs set a",
"lhs before name b",
"lhs set b",
].join(","));
assertEq(this.values.a, "A");
assertEq(this.values.b.join(","), "B");
// Array -> Object
clear();
[
{
a: super[ (log("lhs before name a"), "a") ]
}
] = logger([{a: "A"}]);
assertEq(logs.join(","),
[
"rhs get @@iterator",
"rhs call @@iterator",
"rhs get @@iterator()::next",
"rhs call @@iterator()::next",
"rhs get @@iterator()::next()::done",
"rhs get @@iterator()::next()::value",
"lhs before name a",
"rhs get @@iterator()::next()::value::a",
"lhs set a",
].join(","));
assertEq(this.values.a, "A");
// Array rest -> Object
clear();
[
...{
0: super[ (log("lhs before name 0"), "0") ],
1: super[ (log("lhs before name 1"), "1") ],
length: super[ (log("lhs before name length"), "length") ],
}
] = logger(["A", "B"]);
assertEq(logs.join(","),
[
"rhs get @@iterator",
"rhs call @@iterator",
"rhs get @@iterator()::next",
"rhs call @@iterator()::next",
"rhs get @@iterator()::next()::done",
"rhs get @@iterator()::next()::value",
"rhs call @@iterator()::next",
"rhs get @@iterator()::next()::done",
"rhs get @@iterator()::next()::value",
"rhs call @@iterator()::next",
"rhs get @@iterator()::next()::done",
"lhs before name 0",
"lhs set 0",
"lhs before name 1",
"lhs set 1",
"lhs before name length",
"lhs set length",
].join(","));
assertEq(this.values["0"], "A");
assertEq(this.values["1"], "B");
assertEq(this.values.length, 2);
// Object -> Array
clear();
({
a: [
super[ (log("lhs before name b"), "b") ]
]
} = logger({a: ["B"]}));
assertEq(logs.join(","),
[
"rhs get a",
"rhs get a::@@iterator",
"rhs call a::@@iterator",
"rhs get a::@@iterator()::next",
"lhs before name b",
"rhs call a::@@iterator()::next",
"rhs get a::@@iterator()::next()::done",
"rhs get a::@@iterator()::next()::value",
"lhs set b",
].join(","));
assertEq(this.values.b, "B");
// Object -> Object
clear();
({
a: {
b: super[ (log("lhs before name b"), "b") ]
}
} = logger({a: {b: "B"}}));
assertEq(logs.join(","),
[
"rhs get a",
"lhs before name b",
"rhs get a::b",
"lhs set b",
].join(","));
assertEq(this.values.b, "B");
// All combined
clear();
[
super[ (log("lhs before name a"), "a") ],
[
super[ (log("lhs before name b"), "b") ],
{
c: super[ (log("lhs before name c"), "c") ],
d: {
e: super[ (log("lhs before name e"), "e") ],
f: [
super[ (log("lhs before name g"), "g") ]
]
}
}
],
{
h: super[ (log("lhs before name h"), "h") ],
i: [
super[ (log("lhs before name j"), "j") ],
{
k: [
super[ (log("lhs before name l"), "l") ]
]
}
]
},
...[
super[ (log("lhs before name m"), "m") ],
[
super[ (log("lhs before name n"), "n") ],
{
o: super[ (log("lhs before name o"), "o") ],
p: {
q: super[ (log("lhs before name q"), "q") ],
r: [
super[ (log("lhs before name s"), "s") ]
]
}
}
],
...{
0: super[ (log("lhs before name t"), "t") ],
1: [
super[ (log("lhs before name u"), "u") ],
{
v: super[ (log("lhs before name v"), "v") ],
w: {
x: super[ (log("lhs before name x"), "x") ],
y: [
super[ (log("lhs before name z"), "z") ]
]
}
}
],
length: super[ (log("lhs before name length"), "length") ],
}
]
] = logger(["A",
["B", {c: "C", d: {e: "E", f: ["G"]}}],
{h: "H", i: ["J", {k: ["L"]}]},
"M",
["N", {o: "O", p: {q: "Q", r: ["S"]}}],
"T", ["U", {v: "V", w: {x: "X", y: ["Z"]}}]]);
assertEq(logs.join(","),
[
"rhs get @@iterator",
"rhs call @@iterator",
"rhs get @@iterator()::next",
"lhs before name a",
"rhs call @@iterator()::next",
"rhs get @@iterator()::next()::done",
"rhs get @@iterator()::next()::value",
"lhs set a",
"rhs call @@iterator()::next",
"rhs get @@iterator()::next()::done",
"rhs get @@iterator()::next()::value",
"rhs get @@iterator()::next()::value::@@iterator",
"rhs call @@iterator()::next()::value::@@iterator",
"rhs get @@iterator()::next()::value::@@iterator()::next",
"lhs before name b",
"rhs call @@iterator()::next()::value::@@iterator()::next",
"rhs get @@iterator()::next()::value::@@iterator()::next()::done",
"rhs get @@iterator()::next()::value::@@iterator()::next()::value",
"lhs set b",
"rhs call @@iterator()::next()::value::@@iterator()::next",
"rhs get @@iterator()::next()::value::@@iterator()::next()::done",
"rhs get @@iterator()::next()::value::@@iterator()::next()::value",
"lhs before name c",
"rhs get @@iterator()::next()::value::@@iterator()::next()::value::c",
"lhs set c",
"rhs get @@iterator()::next()::value::@@iterator()::next()::value::d",
"lhs before name e",
"rhs get @@iterator()::next()::value::@@iterator()::next()::value::d::e",
"lhs set e",
"rhs get @@iterator()::next()::value::@@iterator()::next()::value::d::f",
"rhs get @@iterator()::next()::value::@@iterator()::next()::value::d::f::@@iterator",
"rhs call @@iterator()::next()::value::@@iterator()::next()::value::d::f::@@iterator",
"rhs get @@iterator()::next()::value::@@iterator()::next()::value::d::f::@@iterator()::next",
"lhs before name g",
"rhs call @@iterator()::next()::value::@@iterator()::next()::value::d::f::@@iterator()::next",
"rhs get @@iterator()::next()::value::@@iterator()::next()::value::d::f::@@iterator()::next()::done",
"rhs get @@iterator()::next()::value::@@iterator()::next()::value::d::f::@@iterator()::next()::value",
"lhs set g",
"rhs call @@iterator()::next",
"rhs get @@iterator()::next()::done",
"rhs get @@iterator()::next()::value",
"lhs before name h",
"rhs get @@iterator()::next()::value::h",
"lhs set h",
"rhs get @@iterator()::next()::value::i",
"rhs get @@iterator()::next()::value::i::@@iterator",
"rhs call @@iterator()::next()::value::i::@@iterator",
"rhs get @@iterator()::next()::value::i::@@iterator()::next",
"lhs before name j",
"rhs call @@iterator()::next()::value::i::@@iterator()::next",
"rhs get @@iterator()::next()::value::i::@@iterator()::next()::done",
"rhs get @@iterator()::next()::value::i::@@iterator()::next()::value",
"lhs set j",
"rhs call @@iterator()::next()::value::i::@@iterator()::next",
"rhs get @@iterator()::next()::value::i::@@iterator()::next()::done",
"rhs get @@iterator()::next()::value::i::@@iterator()::next()::value",
"rhs get @@iterator()::next()::value::i::@@iterator()::next()::value::k",
"rhs get @@iterator()::next()::value::i::@@iterator()::next()::value::k::@@iterator",
"rhs call @@iterator()::next()::value::i::@@iterator()::next()::value::k::@@iterator",
"rhs get @@iterator()::next()::value::i::@@iterator()::next()::value::k::@@iterator()::next",
"lhs before name l",
"rhs call @@iterator()::next()::value::i::@@iterator()::next()::value::k::@@iterator()::next",
"rhs get @@iterator()::next()::value::i::@@iterator()::next()::value::k::@@iterator()::next()::done",
"rhs get @@iterator()::next()::value::i::@@iterator()::next()::value::k::@@iterator()::next()::value",
"lhs set l",
"rhs call @@iterator()::next",
"rhs get @@iterator()::next()::done",
"rhs get @@iterator()::next()::value",
"rhs call @@iterator()::next",
"rhs get @@iterator()::next()::done",
"rhs get @@iterator()::next()::value",
"rhs call @@iterator()::next",
"rhs get @@iterator()::next()::done",
"rhs get @@iterator()::next()::value",
"rhs call @@iterator()::next",
"rhs get @@iterator()::next()::done",
"rhs get @@iterator()::next()::value",
"rhs call @@iterator()::next",
"rhs get @@iterator()::next()::done",
"lhs before name m",
"lhs set m",
"rhs get @@iterator()::next()::value::@@iterator",
"rhs call @@iterator()::next()::value::@@iterator",
"rhs get @@iterator()::next()::value::@@iterator()::next",
"lhs before name n",
"rhs call @@iterator()::next()::value::@@iterator()::next",
"rhs get @@iterator()::next()::value::@@iterator()::next()::done",
"rhs get @@iterator()::next()::value::@@iterator()::next()::value",
"lhs set n",
"rhs call @@iterator()::next()::value::@@iterator()::next",
"rhs get @@iterator()::next()::value::@@iterator()::next()::done",
"rhs get @@iterator()::next()::value::@@iterator()::next()::value",
"lhs before name o",
"rhs get @@iterator()::next()::value::@@iterator()::next()::value::o",
"lhs set o",
"rhs get @@iterator()::next()::value::@@iterator()::next()::value::p",
"lhs before name q",
"rhs get @@iterator()::next()::value::@@iterator()::next()::value::p::q",
"lhs set q",
"rhs get @@iterator()::next()::value::@@iterator()::next()::value::p::r",
"rhs get @@iterator()::next()::value::@@iterator()::next()::value::p::r::@@iterator",
"rhs call @@iterator()::next()::value::@@iterator()::next()::value::p::r::@@iterator",
"rhs get @@iterator()::next()::value::@@iterator()::next()::value::p::r::@@iterator()::next",
"lhs before name s",
"rhs call @@iterator()::next()::value::@@iterator()::next()::value::p::r::@@iterator()::next",
"rhs get @@iterator()::next()::value::@@iterator()::next()::value::p::r::@@iterator()::next()::done",
"rhs get @@iterator()::next()::value::@@iterator()::next()::value::p::r::@@iterator()::next()::value",
"lhs set s",
"lhs before name t",
"lhs set t",
"rhs get @@iterator()::next()::value::@@iterator",
"rhs call @@iterator()::next()::value::@@iterator",
"rhs get @@iterator()::next()::value::@@iterator()::next",
"lhs before name u",
"rhs call @@iterator()::next()::value::@@iterator()::next",
"rhs get @@iterator()::next()::value::@@iterator()::next()::done",
"rhs get @@iterator()::next()::value::@@iterator()::next()::value",
"lhs set u",
"rhs call @@iterator()::next()::value::@@iterator()::next",
"rhs get @@iterator()::next()::value::@@iterator()::next()::done",
"rhs get @@iterator()::next()::value::@@iterator()::next()::value",
"lhs before name v",
"rhs get @@iterator()::next()::value::@@iterator()::next()::value::v",
"lhs set v",
"rhs get @@iterator()::next()::value::@@iterator()::next()::value::w",
"lhs before name x",
"rhs get @@iterator()::next()::value::@@iterator()::next()::value::w::x",
"lhs set x",
"rhs get @@iterator()::next()::value::@@iterator()::next()::value::w::y",
"rhs get @@iterator()::next()::value::@@iterator()::next()::value::w::y::@@iterator",
"rhs call @@iterator()::next()::value::@@iterator()::next()::value::w::y::@@iterator",
"rhs get @@iterator()::next()::value::@@iterator()::next()::value::w::y::@@iterator()::next",
"lhs before name z",
"rhs call @@iterator()::next()::value::@@iterator()::next()::value::w::y::@@iterator()::next",
"rhs get @@iterator()::next()::value::@@iterator()::next()::value::w::y::@@iterator()::next()::done",
"rhs get @@iterator()::next()::value::@@iterator()::next()::value::w::y::@@iterator()::next()::value",
"lhs set z",
"lhs before name length",
"lhs set length",
].join(","));
assertEq(this.values.a, "A");
assertEq(this.values.b, "B");
assertEq(this.values.c, "C");
assertEq(this.values.e, "E");
assertEq(this.values.g, "G");
assertEq(this.values.h, "H");
assertEq(this.values.j, "J");
assertEq(this.values.l, "L");
assertEq(this.values.m, "M");
assertEq(this.values.n, "N");
assertEq(this.values.o, "O");
assertEq(this.values.q, "Q");
assertEq(this.values.s, "S");
assertEq(this.values.t, "T");
assertEq(this.values.u, "U");
assertEq(this.values.v, "V");
assertEq(this.values.x, "X");
assertEq(this.values.z, "Z");
assertEq(this.values.length, 2);
}
}
new C2();
if (typeof reportCompare === "function")
reportCompare(true, true);