| async function loadIframeAndReturnContentWindow() { |
| // Create and attach an iframe. |
| const iframe = document.createElement('iframe'); |
| const iframeLoadPromise = new Promise((resolve, reject) => { |
| iframe.onload = resolve; |
| iframe.onerror = reject; |
| }); |
| document.body.append(iframe); |
| await iframeLoadPromise; |
| return iframe.contentWindow; |
| } |
| |
| promise_test(async t => { |
| const contentWin = await loadIframeAndReturnContentWindow(); |
| |
| window.results = []; |
| |
| contentWin.eval(` |
| const parentResults = parent.results; |
| |
| const source = new Observable(subscriber => { |
| // Detach the document before calling next(). |
| window.frameElement.remove(); |
| |
| // This invokes the map() operator's internal observer's next steps, |
| // which at least in Chromium, must have a special "context is detached" |
| // check to early-return, so as to not crash before invoking the "mapper" |
| // callback supplied to the map() operator. |
| subscriber.next(1); |
| }); |
| |
| source.map(value => { |
| parentResults.push(value); |
| }).subscribe(v => parentResults.push(v)); |
| `); |
| |
| // If we got here, we didn't crash! Let's also check that `results` is empty. |
| assert_array_equals(results, []); |
| }, "map()'s internal observer's next steps do not crash in a detached document"); |
| |