1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
class base {
constructor() { }
method() { this.methodCalled++; }
}
class derived extends base {
constructor() { super(); this.methodCalled = 0; }
// Test orderings of various evaluations relative to the superbase
// Unlike in regular element evaluation, the propVal is evaluated before
// checking the starting object ([[HomeObject]].[[Prototype]])
testElem() { super[ruin()]; }
// The starting object for looking up super.method is determined before
// ruin() is called.
testProp() { super.method(ruin()); }
// The entire super.method property lookup has concluded before the args
// are evaluated
testPropCallDeleted() { super.method(()=>delete base.prototype.method); }
// The starting object for looking up super["prop"] is determined before
// ruin() is called.
testElemAssign() { super["prop"] = ruin(); }
// Test the normal assignment gotchas
testAssignElemPropValChange() {
let x = "prop1";
super[x] = (()=>(x = "prop2", 0))();
assertEq(this.prop1, 0);
assertEq(this.prop2, undefined);
}
testAssignProp() {
Object.defineProperty(base.prototype, "piggy",
{
configurable: true,
set() { throw "WEE WEE WEE WEE"; }
});
// The property lookup is noted, but not actually evaluated, until the
// right hand side is. Please don't make the piggy cry.
super.piggy = (() => delete base.prototype.piggy)();
}
testCompoundAssignProp() {
let getterCalled = false;
Object.defineProperty(base.prototype, "horse",
{
configurable: true,
get() { getterCalled = true; return "Of course"; },
set() { throw "NO!"; }
});
super.horse += (()=>(delete base.prototype.horse, ", of course!"))();
assertEq(getterCalled, true);
// So, is a horse a horse?
assertEq(this.horse, "Of course, of course!");
}
}
function ruin() {
Object.setPrototypeOf(derived.prototype, null);
return 5;
}
function reset() {
Object.setPrototypeOf(derived.prototype, base.prototype);
}
let instance = new derived();
assertThrowsInstanceOf(() => instance.testElem(), TypeError);
reset();
instance.testProp();
assertEq(instance.methodCalled, 1);
reset();
instance.testPropCallDeleted();
assertEq(instance.methodCalled, 2);
instance.testElemAssign();
assertEq(instance.prop, 5);
reset();
instance.testAssignElemPropValChange();
instance.testAssignProp();
instance.testCompoundAssignProp();
if (typeof reportCompare === 'function')
reportCompare(0,0,"OK");
|