chromium/third_party/blink/web_tests/fast/dom/navigator-detached-no-crash.html

<!DOCTYPE html>
<html>
<head>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<script src="../../resources/gc.js"></script>
</head>
<body>
  <iframe id="subframe" src="about:blank"></iframe>
<script>

var testNavigatorOnLoad = async_test("Accessing a navigator object that just got removed does not crash.")
var testNavigatorLater = async_test("Accessing a navigator object that got removed some time before does not crash.")

// Reference to the removed navigator object.
var oldNav = null;

function test() {
  // Keep a reference of the navigator and remove the frame.
  oldNav = window.frames[0].navigator;
  var frame = document.getElementById("subframe");
  frame.parentNode.removeChild(frame);

  if (window.GCController)
    window.GCController.collect();

  // Check once immediately.
  testNavigatorOnLoad.step(function() {
    check_navigator();
  });
  testNavigatorOnLoad.done();

  gc();

  // Check one more time later, when the frame is likely to be destroyed.
  setTimeout(function() {
    testNavigatorLater.step(function() {
      check_navigator();
    });
    testNavigatorLater.done();
  }, 200);
}

function check_navigator() {
  for (p in oldNav) {
    if (typeof oldNav[p] == 'function') {
      try {
        var v = oldNav[p]();
        assert_true(true, "navigator."+p+"() is OK");
      } catch(err) {
        // Some function call will asserts, the assert shouldn't make the test fail.
        assert_true(true, "navigator."+p+"() threw err "+err);
      }
    } else {
      var v = oldNav[p];
      assert_true(true, "navigator."+p+" is OK");
    }
  }
}

window.addEventListener('load', test);

</script>

</body>
</html>