The problem with window.URL

I was working on a library where I needed to resolve a relative URL using a base URL with JavaScript in the browser. After googling I found the relatively new window.URL API documented on MDN. It allows you to create a URL object that returns a resolved URL, which was great, just what I needed!


var url = new URL('/test.htm', 'http://example.com');
console.log( url.toString() );  
// output is:  http://example.com/test.htm

As with all new API’s I don’t expect all the browsers to support them straight away, but that’s OK I can test for the existence of APIs such as window.URL and use a fallback or polyfill. The code should look something like this.


if(window.URL){
	var url = new URL('/test.htm', 'http://example.com');
	console.log( url.toString() );
else{
	// do something else – fallback or polyfill
}

In this case it does not work because the URL API is actually two overlapping specifications and designed in such a way to allow for one to break the other if they are not implemented together. This is because they both lay claim to the window.URL object. The two specifications are:

The problem

The IE team have implemented just the File API specification, which is not wrong in itself, but if you try use the URL object in IE10 as specified in the URL API specification it throws an error and stops the code execution. Testing for window.URL will not help you as it does exist in IE10 and IE11.

I don’t think IE throwing the error is the issue. Its more of a case of how did the wider web community design APIs that end up clashing?

The workaround

You need to write something like this:


// test URL object for parse support
function hasURLParseSupport (){
	try{
		var url = new URL('/test.htm', 'http://example.com');
		return true;
	}catch(e){
		return false;
	}
}

if(hasParseURLSupport()){
	var url = new URL('/test.htm', 'http://example.com');
	console.log( url.toString() );
}else{
	// do something else
}  

Not meeting expectation’s

Having done a bit of UX design in my time I would class this issue of one of not meeting developers expectations. At least to me using a try/catch block is not how I expect to have to deal with the implementation of new APIs. This should have been resolved at the API design stage before they became public in the browsers.

Wasting time

It took me quite a bit of research to work out what the issue was (2-3 hours) and come up with a small workaround I could trust. Mainly because I had to start reading the specifications and running browser tests.

Going forward

  • As IE10 will be with us for many years the only practical way to use the URL object will be to use more complex tests like the hasURLParseSupport above.
  • This issue should be recognized in the two specifications that lay claim over the URL object.
  • The places that provide documentation of the APIs like MDN should discuss the issue and provide code examples of workarounds.
  • The W3Ctag should review overlapping specifications in fine detail to provide advice on implementation at this level.

I may have got the above wrong

I would just like to point out I am just a web developer and not part of the specifications community that created URL APIs. It’s possible that I may have missed some element of the specifications that deals with this issue. I do not know about the whole history of the URL object and all the discussions of its design. Please let me know if any of the above is incorrect of or can be added too and I will change the post.

Links

  • url javascript api