job-realm.js (9070B)
1 // `debugGetQueuedJobs` is available only in debug build. 2 if (!getBuildConfiguration("debug")) { 3 quit(); 4 } 5 6 function testOne(func) { 7 assertEq(debugGetQueuedJobs().length, 0); 8 9 func(); 10 11 drainJobQueue(); 12 13 assertEq(debugGetQueuedJobs().length, 0); 14 15 if (func.length == 1) { 16 func({sameCompartmentAs: globalThis}); 17 18 drainJobQueue(); 19 20 assertEq(debugGetQueuedJobs().length, 0); 21 } 22 } 23 24 function assertGlobal(obj, expectedGlobal) { 25 const global = objectGlobal(obj); 26 if (global) { 27 assertEq(global === expectedGlobal, true); 28 } else { 29 // obj is a wrapper. 30 // expectedGlobal should be other global than this. 31 assertEq(expectedGlobal !== globalThis, true); 32 } 33 } 34 35 testOne(() => { 36 // Just creating a promise shouldn't enqueue any jobs. 37 Promise.resolve(10); 38 assertEq(debugGetQueuedJobs().length, 0); 39 }); 40 41 testOne(() => { 42 // Calling then should create a job for each. 43 Promise.resolve(10).then(() => {}); 44 Promise.resolve(10).then(() => {}); 45 Promise.resolve(10).then(() => {}); 46 47 assertEq(debugGetQueuedJobs().length, 3); 48 }); 49 50 testOne(() => { 51 // The reaction job should use the function's realm. 52 Promise.resolve(10).then(() => {}); 53 54 var jobs = debugGetQueuedJobs(); 55 assertEq(jobs.length, 1); 56 assertGlobal(jobs[0], globalThis); 57 }); 58 59 testOne(newGlobalOptions => { 60 // The reaction job should use the function's realm. 61 var g = newGlobal(newGlobalOptions); 62 g.eval(` 63 Promise.resolve(10).then(() => {}); 64 `); 65 66 var jobs = debugGetQueuedJobs(); 67 assertEq(jobs.length, 1); 68 assertGlobal(jobs[0], g); 69 }); 70 71 testOne(newGlobalOptions => { 72 // The reaction job should use the function's realm. 73 var g = newGlobal(newGlobalOptions); 74 g.Promise.resolve(10).then(g.eval(`() => {}`)); 75 76 var jobs = debugGetQueuedJobs(); 77 assertEq(jobs.length, 1); 78 assertGlobal(jobs[0], g); 79 }); 80 81 testOne(newGlobalOptions => { 82 // The reaction job should use the function's realm. 83 var g = newGlobal(newGlobalOptions); 84 g.Promise.resolve(10).then(() => {}); 85 86 var jobs = debugGetQueuedJobs(); 87 assertEq(jobs.length, 1); 88 assertGlobal(jobs[0], globalThis); 89 }); 90 91 testOne(newGlobalOptions => { 92 // The reaction job should use the bound function's target function's realm. 93 var g = newGlobal(newGlobalOptions); 94 g.Promise.resolve(10) 95 .then(Function.prototype.bind.call(g.eval(`() => {}`), this)); 96 97 var jobs = debugGetQueuedJobs(); 98 assertEq(jobs.length, 1); 99 assertGlobal(jobs[0], g); 100 }); 101 102 testOne(newGlobalOptions => { 103 // The reaction job should use the bound function's target function's realm. 104 var g = newGlobal(newGlobalOptions); 105 g.Promise.resolve(10) 106 .then(g.Function.prototype.bind.call(() => {}, g)); 107 108 var jobs = debugGetQueuedJobs(); 109 assertEq(jobs.length, 1); 110 assertGlobal(jobs[0], globalThis); 111 }); 112 113 testOne(newGlobalOptions => { 114 // The reaction job should use the bound function's target function's realm, 115 // recursively 116 var g = newGlobal(newGlobalOptions); 117 g.Promise.resolve(10) 118 .then( 119 g.Function.prototype.bind.call( 120 Function.prototype.bind.call( 121 g.Function.prototype.bind.call( 122 () => {}, 123 g), 124 this), 125 g) 126 ); 127 128 var jobs = debugGetQueuedJobs(); 129 assertEq(jobs.length, 1); 130 assertGlobal(jobs[0], globalThis); 131 }); 132 133 testOne(newGlobalOptions => { 134 // The reaction job should use the bound function's target function's realm, 135 // recursively 136 var g = newGlobal(newGlobalOptions); 137 Promise.resolve(10) 138 .then( 139 g.Function.prototype.bind.call( 140 Function.prototype.bind.call( 141 g.Function.prototype.bind.call( 142 Function.prototype.bind.call( 143 g.eval(`() => {}`), 144 this), 145 g), 146 this), 147 g) 148 ); 149 150 var jobs = debugGetQueuedJobs(); 151 assertEq(jobs.length, 1); 152 assertGlobal(jobs[0], g); 153 }); 154 155 testOne(newGlobalOptions => { 156 // The reaction job should use the proxy's target function's realm. 157 var g = newGlobal(newGlobalOptions); 158 g.handler = () => {}; 159 g.eval(` 160 Promise.resolve(10).then(new Proxy(handler, {})); 161 `); 162 163 var jobs = debugGetQueuedJobs(); 164 assertEq(jobs.length, 1); 165 assertGlobal(jobs[0], globalThis); 166 }); 167 168 testOne(newGlobalOptions => { 169 // The reaction job should use the proxy's target function's realm. 170 var g = newGlobal(newGlobalOptions); 171 g.eval(` 172 var handler = () => {}; 173 `); 174 Promise.resolve(10).then(new Proxy(g.handler, {})); 175 176 var jobs = debugGetQueuedJobs(); 177 assertEq(jobs.length, 1); 178 assertGlobal(jobs[0], g); 179 }); 180 181 182 testOne(newGlobalOptions => { 183 // The reaction job should use the proxy's target function's realm, 184 // recursively. 185 var g = newGlobal(newGlobalOptions); 186 g.handler = () => {}; 187 g.outerProxy = Proxy; 188 g.eval(` 189 Promise.resolve(10).then( 190 new outerProxy(new Proxy(new outerProxy(new Proxy(handler, {}), {}), {}), {}) 191 ); 192 `); 193 194 var jobs = debugGetQueuedJobs(); 195 assertEq(jobs.length, 1); 196 assertGlobal(jobs[0], globalThis); 197 }); 198 199 testOne(newGlobalOptions => { 200 // The reaction job should use the proxy's target function's realm, 201 // recursively. 202 var g = newGlobal(newGlobalOptions); 203 g.eval(` 204 var handler = () => {}; 205 `); 206 Promise.resolve(10) 207 .then(new Proxy(new g.Proxy(new Proxy(g.handler, {}), {}), {})); 208 209 var jobs = debugGetQueuedJobs(); 210 assertEq(jobs.length, 1); 211 assertGlobal(jobs[0], g); 212 }); 213 214 testOne(() => { 215 // The thenable job should use the `then` function's realm. 216 Promise.resolve({ 217 then: () => {} 218 }); 219 220 var jobs = debugGetQueuedJobs(); 221 assertEq(jobs.length, 1); 222 assertGlobal(jobs[0], globalThis); 223 }); 224 225 testOne(newGlobalOptions => { 226 // The thenable job should use the `then` function's realm. 227 var g = newGlobal(newGlobalOptions); 228 Promise.resolve(g.eval(` 229 ({ 230 then: () => {} 231 }); 232 `)); 233 234 var jobs = debugGetQueuedJobs(); 235 assertEq(jobs.length, 1); 236 assertGlobal(jobs[0], g); 237 }); 238 239 testOne(newGlobalOptions => { 240 // The thenable job should use the `then` function's realm. 241 var g = newGlobal(newGlobalOptions); 242 Promise.resolve({ 243 then: g.eval(`() => {}`), 244 }); 245 246 var jobs = debugGetQueuedJobs(); 247 assertEq(jobs.length, 1); 248 assertGlobal(jobs[0], g); 249 }); 250 251 testOne(newGlobalOptions => { 252 // The thenable job should use the bound function's target function's realm. 253 var g = newGlobal(newGlobalOptions); 254 Promise.resolve({ 255 then: Function.prototype.bind.call(g.eval(`() => {}`), this), 256 }); 257 258 var jobs = debugGetQueuedJobs(); 259 assertEq(jobs.length, 1); 260 assertGlobal(jobs[0], g); 261 }); 262 263 testOne(newGlobalOptions => { 264 // The thenable job should use the bound function's target function's realm. 265 var g = newGlobal(newGlobalOptions); 266 Promise.resolve({ 267 then: g.Function.prototype.bind.call(() => {}, g), 268 }); 269 270 var jobs = debugGetQueuedJobs(); 271 assertEq(jobs.length, 1); 272 assertGlobal(jobs[0], globalThis); 273 }); 274 275 testOne(newGlobalOptions => { 276 // The thenable job should use the bound function's target function's realm, 277 // recursively. 278 var g = newGlobal(newGlobalOptions); 279 Promise.resolve({ 280 then: Function.prototype.bind.call( 281 g.Function.prototype.bind.call( 282 Function.prototype.bind.call( 283 g.eval(`() => {}`), 284 this), 285 g), 286 this) 287 }); 288 289 var jobs = debugGetQueuedJobs(); 290 assertEq(jobs.length, 1); 291 assertGlobal(jobs[0], g); 292 }); 293 294 testOne(newGlobalOptions => { 295 // The thenable job should use the bound function's target function's realm, 296 // recursively. 297 var g = newGlobal(newGlobalOptions); 298 Promise.resolve({ 299 then: g.Function.prototype.bind.call( 300 Function.prototype.bind.call( 301 g.Function.prototype.bind.call( 302 () => {}, 303 g), 304 this), 305 g), 306 }); 307 308 var jobs = debugGetQueuedJobs(); 309 assertEq(jobs.length, 1); 310 assertGlobal(jobs[0], globalThis); 311 }); 312 313 testOne(newGlobalOptions => { 314 // The thenable job should use the proxy's target function's realm. 315 var g = newGlobal(newGlobalOptions); 316 Promise.resolve({ 317 then: new Proxy(g.eval(`() => {}`), {}), 318 }); 319 320 var jobs = debugGetQueuedJobs(); 321 assertEq(jobs.length, 1); 322 assertGlobal(jobs[0], g); 323 }); 324 325 testOne(newGlobalOptions => { 326 // The thenable job should use the proxy's target function's realm. 327 var g = newGlobal(newGlobalOptions); 328 Promise.resolve({ 329 then: new g.Proxy(() => {}, {}), 330 }); 331 332 var jobs = debugGetQueuedJobs(); 333 assertEq(jobs.length, 1); 334 assertGlobal(jobs[0], globalThis); 335 }); 336 337 testOne(newGlobalOptions => { 338 // The thenable job should use the proxy's target function's realm, 339 // recursively. 340 var g = newGlobal(newGlobalOptions); 341 Promise.resolve({ 342 then: new Proxy(new g.Proxy(new Proxy(g.eval(`() => {}`), {}), {}), {}), 343 }); 344 345 var jobs = debugGetQueuedJobs(); 346 assertEq(jobs.length, 1); 347 assertGlobal(jobs[0], g); 348 }); 349 350 testOne(newGlobalOptions => { 351 // The thenable job should use the proxy's target function's realm, 352 // recursively. 353 var g = newGlobal(newGlobalOptions); 354 Promise.resolve({ 355 then: new g.Proxy(new Proxy(new g.Proxy(() => {}, {}), {}), {}), 356 }); 357 358 var jobs = debugGetQueuedJobs(); 359 assertEq(jobs.length, 1); 360 assertGlobal(jobs[0], globalThis); 361 }); 362 363 print("ok");