private-methods-eval-in-frame.js (4586B)
1 load(libdir + 'evalInFrame.js'); 2 3 class B { 4 #priv() { 5 return 12; 6 } 7 8 #privF = () => { return 12; } 9 10 callPriv() { 11 return this.#priv(); 12 } 13 14 callPrivF() { 15 return this.#privF(); 16 } 17 18 #val = 'constructed'; 19 set #x(x) { 20 this.#val = x + ' haha'; 21 } 22 get #x() { 23 return this.#val; 24 } 25 26 ef(str) { 27 return evalInFrame(0, str); 28 } 29 30 layerEf(str) { 31 // Nested functions here result in computeEffectiveScope traversing 32 // more than one environment, necessitating more hops. 33 function tester(o) { 34 let a = 10; 35 function interior(o) { 36 let b = a; 37 return evalInFrame(0, str.replace("this", "o")); 38 }; 39 return interior(o); 40 } 41 return tester(this); 42 } 43 44 moreLayerEf(str) { 45 // Nested functions here result in computeEffectiveScope traversing 46 // more than one environment, necessitating more hops. 47 function tester(o) { 48 let a = 0; 49 function interior(o) { 50 let b = a; 51 return (() => { 52 let k = o; 53 let replace = str.replace("this", "k"); 54 print(replace); 55 return evalInFrame(b, replace); 56 })(); 57 }; 58 return interior(o); 59 } 60 return tester(this); 61 } 62 63 callFunc(f) { 64 return f(); 65 } 66 67 static #smethod() { 68 return 14; 69 } 70 71 static #unusedmethod() { 72 return 19; 73 } 74 75 static get #unusedgetter() { 76 return 10; 77 } 78 79 static setter = undefined; 80 static set #unusedsetter(x) { this.setter = x } 81 82 83 static f() { 84 return this.#smethod(); 85 } 86 87 static seval(str) { 88 return eval(str); 89 } 90 91 static sef(str) { 92 return evalInFrame(0, str); 93 } 94 95 96 static sLayerEf(str) { 97 // Nested functions here result in computeEffectiveScope traversing 98 // more than one environment, necessitating more hops. 99 function tester(o) { 100 let a = 10; 101 function interior(o) { 102 if (a == 10) { 103 let b = 10 - a; 104 return evalInFrame(b, str.replace("this", "o")); 105 } 106 }; 107 return interior(o); 108 } 109 return tester(this); 110 } 111 112 113 } 114 115 var b = new B(); 116 117 assertEq(b.ef("this.callPriv()"), 12); 118 assertEq(b.ef("this.callPrivF()"), 12); 119 120 // Private fields don't need brand checking and should succeed. 121 assertEq(b.ef("this.#val"), 'constructed') 122 123 // PrivF is a field, not a method, and so isn't brand checked like a method. 124 assertEq(b.ef(`this.callFunc(() => { return this.#privF() })`), 12); 125 assertEq(b.ef(`this.#privF()`), 12); 126 127 // Accesors are stored like fields, and so successfully execute, as they don't 128 // need brand checking. 129 assertEq(b.ef(`this.#x = 'Bye'; this.#x`), 'Bye haha'); 130 assertEq(b.ef(`var x = () => { this.#x = 'Hi'; return this.#x}; x()`), 'Hi haha'); 131 132 133 // // Private methods require very special brand checking. 134 assertEq(b.ef(`this.#priv()`), 12); 135 assertEq(b.ef(`let hello; 136 let f = () => { 137 hello = this.#priv(); 138 assertEq(hello, 12); 139 }; 140 f(); 141 hello`), 12); 142 assertEq(b.layerEf(`this.#priv()`), 12); 143 assertEq(b.moreLayerEf(`this.#priv()`), 12); 144 145 if ('dis' in this) { 146 // Ensure disassembly of GetAliasedDebugVar wroks. 147 assertEq(b.ef(`dis(); this.#priv()`), 12); 148 } 149 150 assertEq(b.ef(`var x = () => { return this.#priv(); }; x()`), 12); 151 assertEq(b.ef(`function x(o) { function y(o) { return o.#priv(); }; return y(o); } x(this)`), 12); 152 153 assertEq(B.f(), 14); 154 assertEq(B.sef(`this.#smethod()`), 14); 155 assertEq(B.sLayerEf(`this.#smethod()`), 14); 156 assertEq(B.sef("this.#unusedmethod()"), 19); 157 assertEq(B.sef("this.#unusedgetter"), 10); 158 159 160 B.sef("this.#unusedsetter = 13"); 161 assertEq(B.setter, 13); 162 163 // Test case variant from Arai. 164 class C { 165 #priv() { 166 return 12; 167 } 168 169 efInFunction(str) { 170 return (() => { 171 let self = this; 172 return evalInFrame(0, str); 173 })(); 174 } 175 } 176 c = new C; 177 assertEq(c.efInFunction(`self.#priv()`), 12); 178 179 // JIT testing 180 assertEq(b.ef(` 181 let result; 182 let f = () => { 183 result = this.#priv(); 184 assertEq(result, 12); 185 }; 186 for (let i = 0; i < 1000; i++) { 187 f(); 188 } 189 result 190 `), 12); 191 192 assertEq(b.ef("function f(o) { return o.callPriv() }; for (let i = 0; i < 1000; i++) { f(this); } f(this)"), 12); 193 assertEq(b.ef("function f(o) { return o.callPrivF() }; for (let i = 0; i < 1000; i++) { f(this); } f(this)"), 12); 194 assertEq(b.ef(`function x(o) { function y(o) { return o.#priv(); }; return y(o); } x(this)`), 12); 195 196 assertEq(B.sef(`function f(o) { return o.#smethod() }; for (let i = 0; i < 1000; i ++) { f(this); }; f(this)`), 14); 197 198 assertEq(b.ef(` 199 var x = () => { 200 return (() => { 201 return (() => { 202 let a; 203 return (() => { 204 let b = a; 205 return this.#priv(); 206 })(); 207 })(); 208 })(); 209 }; 210 x() 211 `), 12);