Incompetent Browsers: towards a complete, modern solution, part II

Previously: Browser Grading, Historical Browser, Requirements and Loaders

Detection

Our basic logic is:


if (browserIsGood) {
  loadJavascriptAndCSS();
}

Let’s dig in to what sits behind that browserIsGood calculation. We’re currently using module support as our test, so a simple version would be:


if (HTMLScriptElement.supports('module')) {
  loadJavascriptAndCSS();
}

Seems perfectly reasonable. Unfortunately, it’s not true. HTMLScriptElement.supports('module') was added much later than actual module support.

We could test for dynamic import support. That’s a lot closer to our real target.


var test = false;
try {
  var f = import("./mod.js").then(
    () => {
      out.innerHTML = "Module Import Succeeded";
    },
    () => {
      // Edge 16 tries to run import, but doesn't actually do so.
      out.innerHTML = "Module Import Failed";
    }
  );
  test = true;
} catch (e) {
  test = false;
}

But this fails our requirement to be compatible with older browsers! It turns out that import is not a function! It’s a reserved keyword and this code will fail with a syntax error in older browsers. But there is a tool we can use to do a syntax check at runtime: new Function.


var test = false;
try {
  var f = new Function('import("test dynamic imports")');
  test = true;
} catch (e) {
  test = false;
}

var out = document.getElementById("outcome");

if (test) {
  out.innerText = "Test Passed";
} else {
  out.innerText = "Test fAILED";
}

Interestingly, we don’t have to load a real module or deal with the asynchrony. Older browsers will throw an exception with a syntax error, while newer browsers will pass, but the function f is never actually executed!

This code also fails our requirements to be compatible with older browsers, but in a much smaller window. It fails in IE4, because IE4 doesn’t support try. But IE4 will still behave the way we want, because we don’t want to do anything in IE4, and having our JavaScript not run because of a syntax error is a form of not doing anything.

Testing the fallback mode

One of our requirements is that we be able to enter our fallback mode deliberately for the purpose of testing.


if (window.URL && window.URLSearchParams) {
  var url = new URL(document.URL);
  mode = url.searchParams.get("mode");
  if (mode == "fallback") {
    throw new Error("fallback mode requested");
  }
}

This code lets us add ?mode=fallback to our URL and see what it will look like in a browser that doesn’t pass the test. That’s useful for developing your fallback experience


Leave a Reply