When specs and implementations clash

One of the points of having open, independently developed standards from the W3C is of course to achieve compatibility.

However, standards are not always clear and consistent, and browsers do not always get things right.

When facing a choice between being compatible with other browsers and websites OR the standard, we may have a third way: fixing the standard to align it with the common implementations and the content. That's the only way one can have the cake and eat it, be standards-compatible and compatible with the Web as it is. Is it feasible? Or even a good idea? Standards are supposed to be set-in-stone after all, to keep implementors happy so that we don't spend hours and money doing it this way only to find a rewritten standard tells us to follow that way instead..

Three real-life examples of cases where we do break or are about to break the standard:

1) getAttribute on non-existing attributes
Standard mandated returning an empty string. Other browsers returned null. Sites running into problems due to Opera's correct standards support included Yahoo mail.

We reached a general consensus that returning null is a better idea, so we have changed Opera and asked the relevant W3C group to consider changing the text in an errata or the next version.

2) Throwing WRONG_DOCUMENT_ERR on cross-document node usage
If a node created in one document is appended to another document, the standard clearly states that a WRONG_DOCUMENT_ERR should be thrown. Firefox doesn't, and sites taking the Firefox behaviour for granted and breaking in Opera included Blogger.com's rich text editor.

Opera will start to call adoptNode implicitly. I'm not sure what way the standard will go – nobody seems to intend to push for a change here. According to their bug report, Mozilla intends to fix it (which is great!) and as soon as they do and websites fix their coding errors, we can revert to spec-compatible mode. Meanwhile, we are not going to live with sites being broken in Opera due to Firefox's bugs.

3) addEventListener and firing capturing events on target
Setting a capturing "click" event listener on, say, an IMG tag has no effect, because the standard clearly says that event listeners should not fire on target. Again, Firefox gets the implementation wrong and sites where this has caused trouble include live.com (according to the Safari team, I have not seen this myself but their analysis is probably right).

Sure, we should fix the standard here and go for it – I don't see any specific benefit to not firing the event listener though I'm all ears if anyone knows why the spec is written like that. We haven't changed this yet but I guess we will follow Safari.

The lesson? To standards bodies: please care about existing implementations, experience and content when developing the standards. Specs that are seriously incompatible with prior implementations or web content cause implementation headaches, incompatibilities and suffering users.


13 thoughts on “When specs and implementations clash

  1. If you're going to repeatedly hammer a competing product (in this post and many others), at least have the courtesy to spell it's name right!It's Firefox, not FireFox.

  2. Sure, we should fix the standard here and go for it – I don't see any specific benefit to not firing the event listener

    Note quite. You'll end up having a event listener fired twice, if you set both a capturing one and non-capturing one.If you feel like implementing Gecko's bugs in Opera, go for it as long as you fix them when the original bug is fixed.

  3. Sorry about the camel case, will fix. But please do not turn this into yet another pointless discussion about the merits of one browser versus the other. Had opera been more popular, Firefox would have to make choices on whether or not to be bug-compatible with us.The interesting discussion is about how to act when spec-compliance *creates* incompatibility with online content. As you see, we're talking big, important sites breaking..

  4. Nelsson – Whilst I am a Firefox user, I'm well aware that Firefox isn't perfect and can handle criticism of it.Hallvord – I'm sure that the camelCase was just a mistake and you meant nothing by it, but when you keep making the same basic mistake, it does tend to make the rest of the post look like a Opera-fan-boy-rant, rather than a well-thought out post about the difficulties of implementing a spec ;-)I have a feeling you're not too happy about SVG 1.2 Tiny…

  5. What about the similar issue preventing correct working ING Bank Online: https://ssl.bsk.com.pl/bskonl/login.ac in Opera 9?In file https://ssl.bsk.com.pl/bskonl/i/script/econl.js?ver=5 there is a definition of a function:

    function isFieldValid(field)
      if (field == null) return true;
      var v,c,f
      if(f==null) return true
      if(f.required!=null && f.required != false && v.replace(/s/gi,'')=='')
        alert(f.emptyMsg!=null?f.emptyMsg:'Prosz´┐Ż wype´┐Żni´┐Ż pole '+c+'.')
        if(f.type!='hidden' && !f.disabled) f.focus()
        return false
      if( f.pattern!=null && f.pattern != '')
        var re;
        if( typeof(f.pattern) == typeof("") )
        var pattern = f.pattern;
        if( pattern.substr(0, 1) == "/" )
           pattern = pattern.substr(1, pattern.length - 2);
        re = new RegExp(pattern);
        re = f.pattern;
        if( v.replace(re,'')!='' ) 
        alert(f.wrongPatternMsg!=null?f.wrongPatternMsg:'Pole '+c+' jest wype´┐Żnione nieprawid´┐Żowo. Prosz´┐Ż poprawi´┐Ż.')
        if(f.type!='hidden' && !f.disabled) f.focus()
        return false
      if(f.boolTest!=null && eval(f.boolTest)!=true)
        alert(f.testFailMsg!=null?f.testFailMsg:'Pole '+c+' nie spe´┐Żnia zadanego warunku. Prosz´┐Ż poprawi´┐Ż.')
        if(f.type!='hidden' && !f.disabled) f.focus()
        return false
      return true

    Since Opera returns an empty string instead of null for 'pattern' attribute the finction throw an alert about not correctly filled form field. Opera 8.54 returns null and works here correctly.

  6. quiris: that's because of the WebForms2 support. Form elements now have both "pattern" and "required" attributes. I'd usually patch, contact the site, and wait for other WF2 implementations – the site will have to change eventually if WF2 implementations become popular. But we also have a big job to do in evangelising WF2, explaining how such a script can be subtly changed to let the UA's built-in validator do the job in WF2-browsers and keep applying the traditional custom validation to the others.It's incredibly hard to introduce a new spec in a way that is compatible with existing content. WF2 tries hard, and yet doesn't always succeed. It runs into issues with custom properties in legacy scripts on many sites.

  7. Hallvors,In your post above you mentioned that "such a script can be subtly changed to let the UA's built-in validator do the job in WF2-browsers and keep applying the traditional custom validation to the others."In the example listed by guiris, would you mind suggesting an approach to this fix? I operate a site with a similar JS validator, and would like to ensure that it is Opera-compatible.Thanks,Gil

  8. Opera will start to call adoptNode implicitly.

    Is this behaviour already present in the latest weekly ?Opera must throw a warning to the error console to alert the developer of the improper coding, stating something like – "appendChild(): adoptNode called implicitly, node doesn't belong to document" or whatever.

  9. GilHildebrandJr: I'll see if I can write a full post on that.xErath: yes, the behaviour is in the weekly and I'll pass on your suggestion and make sure it happens.

  10. Throwing WRONG_DOCUMENT_ERR on cross-document node usage:I'm incorrectly using range = document.createRange(); range.selectNodeContents(src);where src is a node from a document created by XMLHttpRequest.Can you give an example (or a pointer to) what the user issupposed to do?

  11. Hi Staudinger,thought I had replied to this – server monkeys ate it?Rather than range = document.createRange();range.selectNodeContents(src);the correct way would be creating the range in the document you're going to use it in. So range = src.createRange();range.selectNodeContents(src);

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s