Tales from the Trenches Battling Browser Bugs for Fun and - - PowerPoint PPT Presentation

tales from the trenches battling browser bugs for fun and
SMART_READER_LITE
LIVE PREVIEW

Tales from the Trenches Battling Browser Bugs for Fun and - - PowerPoint PPT Presentation

Tales from the Trenches Battling Browser Bugs for Fun and (Non-)Profit Roan Kattouw http://tinyurl.com/browserbugsLCA15 Web development used to be HARD var remove = document . getElementsByClassName( 'removeMe' ); for ( var i = 0; i


slide-1
SLIDE 1

Tales from the Trenches Battling Browser Bugs for “Fun” and (Non-)Profit Roan Kattouw http://tinyurl.com/browserbugsLCA15

slide-2
SLIDE 2

Web development used to be

HARD

slide-3
SLIDE 3

var remove = document. getElementsByClassName( 'removeMe' ); for ( var i = 0; i < remove.length; i++ ) { remove[i].parentNode.removeChild( remove[i] ); } $( '.removeMe' ).remove();

slide-4
SLIDE 4
slide-5
SLIDE 5
slide-6
SLIDE 6
slide-7
SLIDE 7
slide-8
SLIDE 8

<title>W</title> <title>We</title> <title>Wel</title> <title>Welc</title> <title>Welco</title> <title>Welcom</title> <title>Welcome</title>

slide-9
SLIDE 9

$( 'body' ).animate( { 'scrollTop': 1000 } );

slide-10
SLIDE 10

.button { border: 1px #c9c9c9 solid; border-radius: 0.3em; transition: border-color 100ms ease-in-out; } .button:hover { border-color: #aaaaaa; }

slide-11
SLIDE 11

The modern web is EASY

slide-12
SLIDE 12

Browsers used to be GARBAGE

slide-13
SLIDE 13
slide-14
SLIDE 14
slide-15
SLIDE 15

Modern browsers JUST WORK

slide-16
SLIDE 16

Well... not REALLY

slide-17
SLIDE 17

Browsers used to be GARBAGE are

slide-18
SLIDE 18

Modern browsers JUST WORK kind of in common cases

slide-19
SLIDE 19

Modern browsers are incredibly complex

slide-20
SLIDE 20

Modern browsers have LOTS of bugs

slide-21
SLIDE 21

Let's talk about Chrome

slide-22
SLIDE 22

Interactive box-shadow

https://code.google.com/p/chromium/issues/detail?id=314291

FIXED now

slide-23
SLIDE 23

Image rendering is hard

https://code.google.com/p/chromium/issues/detail?id=308046

slide-24
SLIDE 24

Font rendering is harder

https://code.google.com/p/chromium/issues/detail?id=236298

FIXED in Chrome 33

(Feb 2014)

slide-25
SLIDE 25
slide-26
SLIDE 26

Why respect CSS3 selection colors?

https://code.google.com/p/chromium/issues/detail?id=304826

slide-27
SLIDE 27

Because selection is also hard

https://code.google.com/p/chromium/issues/detail?id=269556

slide-28
SLIDE 28

...very hard actually

https://code.google.com/p/chromium/issues/detail?id=298175

slide-29
SLIDE 29

Dead scrollbars deserve memorials

https://code.google.com/p/chromium/issues/detail?id=387290

Workaround: change CSS properties in “right” order

  • Remove height: Npx;
  • Force reflow
  • Remove overflow-y: hidden;
slide-30
SLIDE 30
  • nbeforeunload dialog

Pretty standard But what if you reload instead?

slide-31
SLIDE 31

There's a dialog for that! Now click Reload this page Then close the tab

slide-32
SLIDE 32

Same dialog But I tried to close the tab... Reload this Page: closes tab (?) Don't Reload: continues reload (!!)

https://code.google.com/p/chromium/issues/detail?id=254202

slide-33
SLIDE 33

Saga #1 splice()

slide-34
SLIDE 34

Inserting items

slide-35
SLIDE 35

What if you have an array of items?

slide-36
SLIDE 36

But what if you have a LOT?

slide-37
SLIDE 37

How far can you go?

  • What happens if you pass too

many arguments?

  • How many is “too many”?
slide-38
SLIDE 38

ECMAScript spec Says nothing

slide-39
SLIDE 39

Chrome

131072 (=217)

RangeError: Maximum call stack size exceeded

slide-40
SLIDE 40

Firefox

524288 (=219)

RangeError: arguments array passed to Function.prototype.apply is too large

slide-41
SLIDE 41

Opera 12 and below

2097152 (=221)

Error: Function.prototype.apply: argArray is too large

slide-42
SLIDE 42

Safari

65536 (=216)

RangeError: Maximum call stack size exceeded

slide-43
SLIDE 43

IE10+

262144 (=218)

Error: Out of stack space

slide-44
SLIDE 44

IE9 and below

No apparent limit

Error: Out of memory (!!)

Got up to 33554432 (=225) No apparent limit

slide-45
SLIDE 45

Solution: splice.apply() in batches

  • f 1024
slide-46
SLIDE 46

Note assumption: no crash === correctness

slide-47
SLIDE 47

Basic operations would never be implemented incorrectly, right?

slide-48
SLIDE 48
slide-49
SLIDE 49
slide-50
SLIDE 50

function isMyBrowserAPieceOfGarbage() { var n = 256, a = []; a[n] = 'a'; a.splice( n + 1, 0, 'b' ); return a[n] !== 'a'; }

slide-51
SLIDE 51

Let's talk about Firefox

slide-52
SLIDE 52

Underline? Overline!

https://bugzilla.mozilla.org/show_bug.cgi?id=727125

FIXED in Firefox 33

slide-53
SLIDE 53

Unfollowable but active

https://bugzilla.mozilla.org/show_bug.cgi?id=924087

slide-54
SLIDE 54

Cursoring over “invisible” things

https://bugzilla.mozilla.org/show_bug.cgi?id=989012

slide-55
SLIDE 55

Who needs bottom padding?

https://bugzilla.mozilla.org/show_bug.cgi?id=748518

RESOLVED INVALID

slide-56
SLIDE 56

Textareas, is who!

https://bugzilla.mozilla.org/show_bug.cgi?id=157846

FIXED in FF 30 (2014-06-10)

Filed 2002-07-16 (!)

slide-57
SLIDE 57

Saga #2 HTML parsing

slide-58
SLIDE 58

Input: HTML string Desired output: DOM

slide-59
SLIDE 59

This is easy for fragments

slide-60
SLIDE 60
slide-61
SLIDE 61

But I have a document

slide-62
SLIDE 62
slide-63
SLIDE 63

iframe hack

function createDocument( html ) { var newDocument, iframe; iframe = document.createElement( 'iframe' ); document.body.appendChild( iframe ); newDocument = iframe.contentDocument; newDocument.open(); // Party like it's 1995! newDocument.write( html ); newDocument.close(); iframe.parentNode.removeChild( iframe ); return newDocument; }

breaks in IE8 after yield

.contentWindow.document for IE8

slide-64
SLIDE 64

createHTMLDocument()

function createDocument( html ) { var newDocument = document.implementation. createHTMLDocument( '' ); // Regex the doctype and html tags out *barf* html = html.replace( /^\s*(?:<!doctype[^>]*>)?\s*<html[^>]*>/i, '' ); html = html.replace( /<\/html>\s*$/i, '' ); newDocument.documentElement.innerHTML = html; return newDocument; } Why not pass html here?

slide-65
SLIDE 65
slide-66
SLIDE 66

“We're not doing anything weird, we're doing exactly what the W3C says!”

slide-67
SLIDE 67

DOMParser

function createDocument( html ) { var parser = new DOMParser(); return parser.parseFromString( html, 'text/html' ); }

slide-68
SLIDE 68

DOMParser HTML support

  • Firefox 12 (April 2012)
  • IE 10 (October 2012)
  • Chrome 30 (October 2013)
  • Opera 17 (October 2013)
  • Safari 7.1 (September 2014)
slide-69
SLIDE 69
slide-70
SLIDE 70
  • Firefox: behaves to spec
  • Chrome: URL is null
  • IE: URL is undefined, location errors
slide-71
SLIDE 71

Let's talk about IE

slide-72
SLIDE 72

Text background in RTL

http://jsfiddle.net/v939T/3/

slide-73
SLIDE 73

Measuring superscript position

http://jsfiddle.net/k3QV2/8/

sup, sub { display: inline-block; }

slide-74
SLIDE 74

Style attribute normalization

http://jsfiddle.net/zwcrn6dv/1/

Workaround:

  • Parse as XML
  • Copy style to data-unmangled-style
  • Serialize XML DOM back to string
  • Parse string as HTML
  • Read/write data-unmangled-style instead of style
slide-75
SLIDE 75

DOM serialization

slide-76
SLIDE 76

doc.documentElement .outerHTML

slide-77
SLIDE 77

<pre> parsing is weird

slide-78
SLIDE 78

<pre> serialization is broken

slide-79
SLIDE 79

Very broken

slide-80
SLIDE 80

Broken in all browsers except...

function isMyBrowserAPieceOfGarbage() { var div = document.createElement( 'div' ); div.innerHTML = '<pre>\n\n</pre>'; return div.innerHTML === '<pre>\n</pre>'; }

Opera 12 and below

slide-81
SLIDE 81

Workaround: add newlines to DOM in the right places

slide-82
SLIDE 82

function fixupNewlines( $element ) { $element.find( 'pre, textarea, listing' ) .each( function () { var child = this.firstChild; if ( child.nodeType === Node.TEXT_NODE && child.data.charAt( 0 ) === '\n' ) { child.insertData( 0, '\n' ); } } ); }

slide-83
SLIDE 83

function fixupNewlines( $element ) { $element.find( 'pre, textarea, listing' ) .each( function () { var matches, child = this.firstChild; if ( child.nodeType === Node.TEXT_NODE ) { matches = child.data.match( /^(\r\n|\r|\n)/ ); if ( matches && matches[1] ) { child.insertData( 0, matches[1] ); } } } ); }

slide-84
SLIDE 84

So browsers suck?

slide-85
SLIDE 85

Browsers are still pretty awesome

http://krinkle.github.io/dom-ce/

slide-86
SLIDE 86

Thank you!

http://tinyurl.com/browserbugsLCA15