 I'm here to present the Ronan Katao and he's making a presentation on browser bugs. Good morning. I'm Ronan Katao. I work at the Wikimedia Foundation where my team works on trying to push the limits of the kinds of applications that you can build on the web and run inside of a browser, not just pages. I have put the slides for this talk online already. They are on the URL on the screen. That's because there are a bunch of links from my slide. There's a bunch of code samples, so people might want to read those at the leisure or follow them. I'm sure that the conference organizers will also publish slides at some point in time, but I decided to come prepared. So, web development. It used to be very difficult. The 90s were a really dark time where you had to write horrible code that looked like this. And, you know, you can ask this five seconds and you will not be able to tell what this does very quickly. The answer is it does the same as this line. We have things like jQuery now, which make web development easy and nice. And, by the way, there is also a bug in this code above because if you write things the obvious way in DOM APIs, they don't work because the APIs aren't helpful. You used to have to debug things like this where you use alert boxes, and then if you weren't careful and you didn't dump a string into it, you got useless garbage. Nowadays, we have consoles where you can dump entire objects and DOM nodes, which you can then highlight with your mouse, and the browser will show you where they are. And you have the buggers where you can put in breakpoints, where you can deminify the code and have call stacks and do all the kind of lovely things. You have a DOM inspector where you can find nodes in the page, and it will highlight where they are for you and tell you what the padding boxes and border boxes are and all that kind of stuff. And where if you wanted to do a cool thing before in, say, the 90s and you wanted to exploit a bug and I think it was Netscape 1 or something or Netscape 2, then you would have to do something like this. This does exactly what you think. It animates the title to be welcome, one character at a time because Netscape is stupid, and immediately you put the title on the title bar as soon as it's part of the tag. And so you could trick it into doing your things, and nowadays you just have animation things that you can just call and it's obvious what they do. And you can build buttons with like rounded corners and you can transition the roundedness of the corners and the color of the corners all with CSS. So the modern web is easy. We have jQuery, HTML5, we have CSS3 and it all works nicely and browsers used to be pieces of garbage because if you go to, this is a very American centric example, but if you go to healthcare.gov and IE6, it looked like this. We just clearly not what they intended because in Chrome it looks like this. So, you know, modern browsers, the web just works, right? Well, that's not really true. If you're trying to build your standard garden variety, like web page, then yes, now is better than ever. You don't have to build with three times or three browsers anymore. You don't have to worry about comparability issues and interoperability issues as much anymore because for sort of the, if you're staying on the sort of the beaten path, then things just work and it's all fine. But the reality is browsers are still just as bad and they only kind of work and only in the cases where you're staying on the beaten path because there is so many areas off the beaten path that people don't use as often and when you're building an application instead of just a static page and a web browser, you run into these kinds of things. If you try to do interesting things, then you're going to run into this fact that browsers are incredibly complex because there's so many standards now and you can do so many useful things. I mean, think about the rounded colors transition example. Brows have to support all that crap. They have to be able to transition the color of your like rounded border. That's a lot of code. And consequently, there's a lot of bugs. So I'm going to talk about some things that I was really wanting to do and browsers that are difficult to do, but to keep it light, I'm also going to make fun of browsers a little bit. So first of all, let's make fun of Chrome a little bit. Chrome used to have these lovely non-featured interactive box shadows. So if you built a scrollable container with a box shadow around it, then it would consider the box shadow part of the area of the container, but also not. The correct answer, by the way, is not. And so if you put your mouse like in the screenshot, if you put your mouse outside of the container, you can still interact with things that are below your mouse pointer. And you can click them. You can use a scrollable to scroll the container when you're not even in it. And you can hover things. You can click on them and the interaction will work. And this is very amusing. Unfortunately, for entertainment value, they fixed it. So I'm not going to be able to demo these to you. This kind of thing also happens in Chrome. Chrome is so high-performance that it doesn't even work properly, because half of its time it tries to cash things for rendering, but then it cashed the wrong thing or doesn't evaluate it at the right time. And so very common problems with Chrome revolve around. This is what the page looked like a second ago. It doesn't look like that anymore, but not all parts of Chrome know, only some parts, which is exemplified in this bug where the font rendering engine doesn't always know whether to use a serif font or a sans serif font. The layout engine knows which font it's supposed to be using, and you can tell by the lengths of the underlines that it has a different font in mind. But sometimes the font just disappears in memory, and it uses another font. This is especially common on macOS, because the fallback font rendering in macOS is not very good, or was weak, as they claim to have fixed it in Chrome 33, which is a little bit difficult to confirm, because it was kind of an intermittent bug. But before it was fixed, someone submitted this lovely video to the bug report, where you can just see the font changing all the time, because sometimes the normal font renderer fails, and it falls back to the fallback font renderer, which is fine, except the macOS people were like, well, it's just a fallback font renderer, so it doesn't have to actually work. It's never going to get used. And that turned out to be very slightly wrong. And of course, you can see sort of relatively Chrome in a schizophrenia, where the layout engine still knows how wide the text will speak, because the column widths and the text didn't reflow. The column was in change, and with the links, the underline lengths didn't change. And if you ask the browser how wide is this line, it will give you the correct answer. It's just that the font rendering engine kind of goes out and does its own thing. Another thing that's very difficult is the CSS3 selection colors. So there is a CSS feature that you can use to overwrite what the selection color is. I can guarantee you it is not natively red on my machine. But if you do this, then you can see what the native selection color actually is. It's blue. So just in case you were thinking that you were actually going to use this feature, it's not that useful, because it doesn't actually work correctly, and you end up with ugly stuff like this. Selection in general is just difficult, because if you have some text that you inject using column before, then it shouldn't really be selectable. But if you do this, then that happens. This is, I don't think this is a classic symptom of Chrome, but it's fun anyway. What's really fun, and this is a case where it's not really obvious what should be happening. But on these lines, all the a's are normal a's, and all the b's are absolutely positioned to be next to the a's. And so if you try to select things, it just does very weird things, where some of the b's are still visible and some of them are not. And you can see that it's actually, you may not be able to see them as projected very well, but some lines are actually double blue. They're made blue twice or thrice by the, it looked even prettier when the selection color in my operating system was still orange. It looked something like this. And you can see a whole patchwork of there a's that are where the text color is orange instead of the background color. And some of the b's are white, and some of them are black, and some of them are invisible. Yeah, there must be some kind of compositing going on. Another really fun one that we encountered is if you have a thing with some things in it, then you can give this a lower height than it really wants to be, and you can give it overflow y auto, and then it will become scrollable. And you can do this and scroll a thing. And I have a scroll bar. But if you then try to make it full height, it again, using the obvious way, then you end up with this, where now these things aren't full width anymore, because the scroll bar, even though it's not there anymore, it's still there. The workaround, of course, is to first change the height back, and then make it not scrollable, instead of the other way around, and also forcing a reflow in between. Because then it knows what you, sort of, all the stars align, and every part of Chrome realize what the other part is doing. But if you don't do that, then the little boxes apparently don't get the message that they're supposed to relay out themselves, because there's now more horizontal space available. Needless to say, this doesn't happen in other browsers. And this led to some very confusing interaction between me and my QA people, because they always think it's my fault. There is also a lovely feature in browsers called an un-before-unload dialogue. This is another sort of thing. This is in our case why browsers are so complex, because you've all these ridiculous features that you have to support. Number four, unload dialogue is what you get when a web page indicates you can't just leave me, because the user has unsaved data, and they need to confirm that they want to leave. And so if you close the page, and you set the thing like that, it goes like, are you sure you want to leave this page? This happens if you close the tab. This is pretty standard garden variety thing. But what if I'm trying to reload the page? That's also going to obliterate my data, but that's not technically leaving. So they have a different dialogue for that, which has reload this page and don't reload as opposed to stay in this page and leave this page, which is fine. I think that's a good decision in Chrome to make the distinction. But now you can do, you can reload the page, and then while it's still reloading, you can close the tab. Now what is it going to do? Clearly nobody ever thought of this, because I get the same dialogue. It asks me whether I want to reload the page, even though that's not what I was doing. I was closing a tab. Now what's really fun is what happens when you click these buttons. If you click Reload This Page, it's going to close the tab. Who wants to guess what's going to happen when I click Don't Reload? Yes, it reloads the page, or rather it continues reloading the page, which it was already doing. OK, so these are just fun little things and minor bugs, and I'm sure they can all be fixed. But sometimes there is a more fundamental thing where you just want to do something in a browser and it fights you. So in our case, what we wanted to do is we wanted to maintain a large data model in a browser, in an array, in a JavaScript array. So we messed around with some techniques, and we found that the most efficient way to insert items into the middle of an already very large array was to use Splice, where you have an array. You tell it, after the second item, I want to remove zero items and I want to insert x and y. And then it goes off and does that. Which is fine. That's an API for inserting items. That's great. What if my items are in an array? Well, then there's another API that I can use to call a function, because the things that I'm inserting over here are not actually, I don't actually pass an array of things to insert. I pass it like variadic arguments to insert. So if I have an array of things to insert, I can use apply, which is like a variadic calling helper function, and I can construct the array of arguments, rather, and then pass it Splice. Yes? Could you put it in slow? Sure. So this works. I mean it's a bit awkward, but it works fine. And you can even do this with a lot of items, like, say 500. That also works fine. So how far can you take this? Like what's going to happen if I pass, because I'm not passing an array, I'm passing this set of arguments. So what's going to happen if I pass too many? And how many is too many? So we look for these kinds of questions. We look to the atmospheric spec, because they are the people that are supposed to answer profound questions. And as you can see, they have. So the way that you actually find out is for experimentation. It turns out in Chrome, you can go up to 2 to the 17. And it gives you a somewhat confusing array, which I'm sure is true technically, but doesn't help me understand what's going on very much. In Firefox, it's 2 to the 19. And that actually gives me a reasonable error message. Opera 12 and below is 2 to the 21. Gives me a reasonable error message. Safari is like Chrome except with a lower limit, 2 to the 16. IE will give me an even more technical error message and it's 2 to the 18. And IE 9 and below, excuse me, there doesn't appear to be a limit, it's just unless you actually run out of memory. Like that is actually what happens if the process runs out of memory. As you can see, except in the case of IE 9 and below, these limits are actually powers of 2. And the error message that you get are reasonable most of the time. So it does seem to kind of work. It's just that everybody chose a different power of 2. So we decided to keep this, you know, stay in the safe side and use 2 to the 10, which is way lower than any limit that we encountered and batch it up, which is fine. But in our testing, we noticed something, which is that we had assumed that if the splice called in crash, then it would perform correctly. Because you would think that an elementary operation like inserting data into an array would not be performed incorrectly by any browser engine. And you would be wrong. So we had this particular case where you can create a sparse array, which is where you create an empty array and then just decide to declare that a sub 6 is now x. And it goes like, oh, I guess you want this array to be longer. And it creates a bunch of holes in your array, which it represents is undefined, and then an x. And in a sparse array, you can also splice, even between the holes and after things. And in this case, I say after the seven thing, which is all the way at the end, remove nothing and insert y. So you can also do this in opera, opera 12 and below. And it represents things slightly differently in the console, but it gives you the same results. Now I'm going to do the exact same thing, but I'm going to add 250. So now I'm going to declare the 256th item and then insert something after it. And that performs correctly in Chrome. And in opera, the 256th item just disappears into nowhere. And we have anecdotally observed situations where like the entire first 255 elements of the array just get scrambled and reordered randomly. Especially if you have way more than 256 items in this array, if there's like thousands, then things just get screwed up completely as soon as you try to insert things past 256. And so we ended up writing a function like this, where we set the 256 thing, try to insert after it, and then check if the thing that we set was still there. And if that returns false, then we need to use your own homebrew implementation of splice because the browsers are reliable. The function isn't actually called this in my code base because function names need to be unique, which in this presentation they are not. All right, so lighter matters. Let's make some fun of Firefox. This is a lovely bug that I also can't demonstrate because they listened to me and fixed it. If you have superscripted text inside of a link and you hover over it and your link has some special properties, then sometimes the underlying will be displayed above rather than below the link, at least for superscripted parts. This, again, makes QA departments upset and they look at you and you can't do anything about it. This is fixed in Firefox 33, which came out in June or something. There's also another fun thing. We work with the technological content editable, which allows you to have HTML elements that you can just type in and modify. But you also have links. And when you click on links, they aren't followed because they need to be able to drop my cursor here and type. But if I try and select across a link and I mouse down on it, it changes color because it becomes colon active, which is the CSS styling gets applied for links that are being clicked and about to be navigated to, even though they're not because I can't click them. But that doesn't stop the coloring from happening and there's no way you can write CSS to prevent this from happening because the browser doesn't distinguish. So that looks like this. Firefox also has a bit of trouble determining when things are visible or not. So if you have an image like here and you're cursoring over it in the content editable, then you expect this kind of behavior where if I'm here and then I press the left arrow, then it jumps over the image and lets me continue. If your image has no source attributes but it has alt text, then Firefox renders the alt text, which is correct. But it also believes the image is invisible because it is having the source attributes. And so it shouldn't be skipped over. And so you get lovely behavior where if I'm here and I press right arrow, I end up there. And if I'm here and I press left arrow, I end up there. If you were trying to write something where users expect arrow keys to work, which is most of the time, then this is kind of a nightmare. The solution turns out to be, don't do this. It's kind of like, doctor it first if I do this, then stop doing it. But at the same time, this was a kind of legitimate use case that we didn't really, I guess you can set the source to something before or before or something. It will have the same result and it will work. But that's just stupid. You have to do that. Apparently something that we don't need in the world according to Firefox is bottom padding. Because if you, was it sorry? Bottom padding. So this red box here, this red box here has a gratuitous amount of padding where there is white space within the red box around the contents on all four sides. I've just declared it to be the same all four sides. But if the box is scrollable, then Firefox's side at the bottom, there's not going to be any. And you can see that in this case it's particularly ugly because the red border starts the next pixel over from the input box, which at least paragraphs have margins in browsers by default. But this just rides up right against there. And again, my QA people were upset because in, whoops, now I screw this up. And that's going so well. Here we go. My QA people were upset because in Firefox, it does introduce white space at both the top and the bottom. Or second chroma does. And in Firefox, it doesn't. So I reported this to the Firefox people. And their response was, yeah, this is not a bug. Because if you read the spec and interpret it the way that they do, then bottom padding isn't part of something that necessitates something to be scrollable. And so it also shouldn't be accessible through scrolling. And they argue that that's what the spec says. Most people almost agree that that is what the spec says because the spec isn't very clear on it. But no other browser does it that way. And Firefox says, well, first of all, this is what the spec says. And second of all, we can't change it because it will break the internet. It's like, no, it won't break the internet because everyone else is already doing this. And you're violating a principle, but at least surprised. But they seem to not be. This is something that I have to actually gather the energy to take up with the W3C to what WG people because that's where specs are made. Something to do acknowledges a bug is that if you use text areas of padding, they definitely padding because on the right is what it's supposed to look like. Note that Internet Explorer is doing it correctly this time. And on the left is what Firefox used to do. This is just if you make a text area have some padding and a border and stuff. They fixed this in Firefox 30, which came out in June. The reason I mention it is because of when it was filed, which was in July of 2002. So that's like Firefox, I don't know, I was 11 in July 2002. That was like in Firefox 1 or something, or one point? I don't know. But apparently it turns out that if you know somebody who knows somebody who knows the bug ranger from Mozilla, then you can pull some strings and eventually get this fixed, which was nice that it worked. So another thing that I like being able to do in browsers or that I would like to be able to do in browsers is parsing HTML, which is not something that you're going to run into in your standard garden variety application or a standard garden variety web page. But if you're building an application that's manipulating HTML, which as from the things with content editable earlier, you might have guessed that I am, you want to be able to parse HTML. And this should not be hard because browsers implement an HTML parser. That is almost implied by the definition of a browser. They have to parse the HTML page to show it to you. So if I input an HTML string and I want a DOM tree, this should be easy. This should be what browsers do all the time. And it turns out for fragments it is easy, which is to say if you just have a little bit of HTML, then their APIs, I mean there's even a jQuery wrapper for them, where you can give it a string of little bits of HTML, it will parse them for you and it will come out with DOM elements and DOM trees and all those nice things. But if you have a full document, that is to say you have a doc type, and an HTML tag, and a head tag, and everything, as opposed to just like, oh, here's a paragraph in Spendings, then it's harder. The most reliable way to do this across browser, across old browsers, is something called the iframe hack, which gives you an idea of its reliability and quality. The idea is that if you create within the document, then the iframe will have its own document because there's a whole other document in there. And then you can somehow write your HTML string into the document, and then you can return a document, and then you have sort of fulfill your contract of what you would expect when you create a document function that takes an HTML string. So it turns out you have to put the iframe actually in the document, otherwise it doesn't get its own document because browsers, it also can't display none or hidden in any way, because then Firefox doesn't load the iframe. This is the source of it. It can't be 0, but 0 pixels. Either it has to be 1 by 1, and it has to be kind of visible, but you can still try and make it not visible. It also turns out that the API that you have to use to put the HTML in is very 90s-tastic, and you have to use DocumentWrite, which we've been telling will not use for a very long time. But in this case, it's OK. We promise. And then maybe you would like to clean up the iframe afterwards, like you don't need it anymore. You can throw it away. Turns out this isn't quite work, because in an X4-8, you have to use content. We know the document instead of content document, because of reasons. And if you remove the iframe, the whole thing explodes in I8, but only after some time. So you have to keep the iframe around. So with the caveats on the screen, this is actually a nice way to do it. But it's not nice for programmers. So the W3C came up with something better, and they introduced a very promising looking thing called create HTML document, which lo and behold, just gives you an HTML document. Now, apart from the thing where an opera sometimes gives you a document and sometimes gives you an object that looks like a document that doesn't behave like one. It also isn't always very helpful, because the way that you do this is you create an HTML document, and then it has an HTML tag in it already, and then you write to the contents of that, which means that you can't provide your own doc type or your own HTML tag, and so you have to regex them out of the way, which is not what you want to do, but this kind of works. And to be fair, in most browsers, if you don't do this, then the browser will do it for you anyway, because it understands that nesting an HTML tag instead of an HTML tag is not going to go very well. But there's a string parameter here to create HTML document. Why am I not just passing the HTML? Why am I not using this? Why am I passing it to string? Well, the W3C in its infinite wisdom made the API such that the string parameter is the title of the HTML document, because clearly people are too lazy to create a title tag and populate it with a string. They have to be provided like a super fast affordance for sending a title, whereas if they want to provide a whole HTML string, then who cares? Who wants to do that anyway? So of course, browser vendors say this is a quote heard around our office, which we're not doing anything. We're doing exactly what W3C says. The problem is that that is not always a very wise thing to do. Eventually, the W3C realized that it extended an existing API called DomParser, which has been around since the Firefox one days. And it used to be you could give it a string and it would parse XML. And then they added SOG at some point. And then recently, they were like, well, this is an nice API for parsing things. Let's add HTML to it. And so now the world is good now. You can actually do this. You can write this function. It's like what, four lines? And you can give it an HTML string, and the document will come out with your doc type, and with your HTML tag, and with your head, and everything. This is great. So who supports it? Well, Firefox was early. They started supporting this in April 2012. I imagine this might have been a case of Firefox implemented and then it became a standard. At some point, Internet Explorer 10 implemented this. Keep in mind, this is a chronological order. And Internet Explorer was the second browser to implement this, which should worry you a little bit. Chrome implemented it a full year after IE did. Opera never implemented it. Instead, they switched to being a skin version of Chrome, and so they have an Opera 17, but that's cheating because Opera 17 is just Chrome 30. And Safari has it now. The last time I gave this talk, Safari didn't even have it yet. They have it like four months ago or something. So I guess it might be in iOS 8 now. But if you're writing something for mobile and your audience basically are not people in San Francisco who make more than $150,000 a year, they don't have an iOS 8 device and you're screwed. Also, the spec for this thing is lovely. This is what the spec looked like at the time that I last looked into this. It's currently unclear what the URL of the document should be, and it ends with, it's like, this is what some browsers do, and it ends with, name of random news is just using this. Thanks, W3C, for specifying your thing so clearly. Nowadays, they actually have a spec that actually says what you need to do. And this is a couple months old now. Of course, nobody implements it. Firefox behaves according to spec, but that's just because they decided the spec was going to be if Firefox already did. And Chrome doesn't behave correctly, Internet Explorer doesn't behave correctly. So let's talk about Internet Explorer. Because if there's any browser that we can make fun of, it's Internet Explorer, right? So people like, there are lots of traditional problems with Internet Explorer that people like to make fun of. I have discovered some that have been really interesting and I've been in touch with people at Microsoft that have actually been working on fixing these things, which is exciting because Microsoft is now listening to open source people because they care about their browser working with Wikipedia. And they're like, well, maybe we should listen to you and fix your bugs. So it turns out, for instance, if you try to give text a background and it happens to your right to left text, your text isn't rendered, it just isn't there. So how do you work around this? Don't use color backgrounds in combination with RTL text. Don't do this, Doctor. This is not a very good solution. I think this is fixed in the IE 12 developer preview. But for real, a browser is still a problem. If you have superscripted and subscripted text and you try to measure the position, like the location on the page of those things so that you can render maybe blue highlights on top of them, it doesn't work that well because it lies to you. And the dimensions are all correct, but it pretends that the boxes are at the baseline instead of being raised or lowered for super and subscripting. You can work around this because you make them inline block instead of inline, then it does work because there is an internal implementation detail in IE where things that are not inlined or in charge of their own positioning instead of being slaves to their parents. And apparently, it doesn't deal with the super uncommon case of superscripted text. So the hell ever uses that, especially in encyclopedia, right? I don't think this is fixed yet, although they keep promising me that it will be fixed. This one is really annoying. If you're using a DOM as your data model, then what you expect is that you put things in and the same stuff comes back out, like at round trips, right? You have a string, you put it in the DOM, and then when you serialize the DOM back to the string, you get something that's almost the same, or at least has the same meaning, whatever. The values of style actually just get completely clobbered by Internet Explorer. If you have a color with accessible limitation, it gets converted to RGB. If you have something without semicolons, the semicolons are inserted. If you don't have spaces, they are inserted. If you do something invalid, it just gets removed. You end up with an empty string. And if you put in an empty string for style attributes, it tells you there was a style tree to begin with. So this is not actually a normalization, because it isn't ad impotent. Because if you start it with invalid CSS, then after the first time, it will be an empty string. And then after a second time, it will be null. This is ridiculous, because when I take an HTML string that I get from somebody and I parse it in Internet Explorer, I can't tell what the original attribute value was, because Internet Explorer has already normalized it for me. And it's already decided that clearly they didn't intend to write FFDDFF, the person that's talking to me actually meant RGB 255, 251, 255, which is not helpful, because then when I serialize it back, I give them different data and they're like, oh my god, you changed this. These are the kinds of things that happen where I have an application and you want your browser interface to be reliable and Internet Explorer's aren't. The workaround is hideous. It involves parsing the HTML as XML, copying the attribute to different attributes, then serializing the XML back to a string, then parsing that as HTML, and then reading the other attribute instead of the style attributes, because then Internet Explorer doesn't know that it has a meaning and won't clobber it. This is also something that I've been trying to convince the Internet Explorer people is even a bug, or is even important at least, but hopefully I'm succeeding in that. So, OK. Having made fun of Internet Explorer, there is a final thing that I would like to be able to do. I've talked previously about parsing HTML and getting a DOM, and now I have my DOM. I've done things to my DOM, and I want to serialize it, which is to take the DOM and make it back into an HTML string and send that over the network to somebody. So there is actually a very well-specified way to do this, which is you take the root node of the DOM and you ask for its outer HTML property and it gives you a string, which that's fine, but of course there is a caveat. There is a weird thing in the HTML spec about parsing of pre-tags. Wipespace matters in pre-tags. And so if you would take the spec strictly, then if you wanted a pre with a poem in it or whatever, then you would have to put the first line of your poem on the same line as the opening tag, because you put a line break there, then it would be a real line break. The line break is ignored. So the people that wrote the HTML spec were like, well, that's really unhelpful towards people. So in pre-tags, the first new line is free. The first new line in a pre-tag, if it starts with a new line, it is ignored. And then if you wanted a new line there, you can use two. And so if you do, if you write something like pre, new line, new line, foo, close pre, and you ask the DOM what is the contents of the text node in there, it will say there was one new line. This is a bit confusing, but it is actually helpful to people, and it's fine as long as you understand how it works. The problem is, when you then take this DOM and serialize it, you only get one of the new lines back. The serializer is not aware of this behavior, and so it just goes like, oh, here's a pre-tag, here's a text node, and so it just emits a pre with one and a foo, because that's where it's using the DOM. Of course, if you parse this again, there is not going to be a new line. And then if you serialize it again, there's not going to be a new line. So you can actually do console sessions like this, where you just run div.interhtml equals div.interhtml over and over again, which should do nothing, but instead what it does is it eats the new lines of your pre one by one. And so we have a feature detection test in our code that goes like, if I create a pre with two new lines, then does it come back with two new lines? This is very unhelpful when you're trying to interact with another service over in the network, and they give you an HTML string, and you modify it, and you're supposed to give it to them back, because in both stages you're going to end up eating new lines. So this is actually not broken to Opera 12, which is hugely surprising, because they don't even know how arrays work, but they know this. They are the only browser to do this correctly. But then, of course, they switch to being a skin version of Chrome, and now they're broken, too. I've complained to browsers about this, and there is a chicken and egg problem where they all are afraid of being the first people to change it, because it's already worked its way, and they're afraid that that will cause problems. The workaround for this is to add new lines to them in the right places. I'm going to skip over this, because it's not very interesting, but basically it's like you walk through all the affected tags, and if the first child was a text node, and it starts a new line, then you insert another new line, and if you're very paranoid like me, you also account for both backslash R and backslash N. This is a fun code to write. You can look it up in PDF slides later. So do browsers suck? Well, not that much. Browsers are actually still pretty great, because a coworker of mine built this, where this is an HTML page. There is some CSS involved, but there is no JavaScript at all, and I can edit the title, and I can edit the CSS, and it all updates live, and you can do really cool things. And I think, and depending on the browser, you can even do this. This is Control-B here, and this is Control-I. And when he showed this to me, I thought this was pretty amazing, and he's not even using JavaScript to accomplish this. So thank you for your time. As I said, the slides, and all the code samples, and everything, because if you're trying to parse dons or something, some of this stuff might actually be useful to you as opposed to entertainment. They're often at the URL, and I think I might have five minister questions. Is that right? Sweet. So, yes. There is a mic somewhere. You can mic to the microphone. Yeah. All the way back. If it's flashing, it's working, I think. Where things disappear and so on. Have you managed to cause internal state corruption? That's an excellent question. Just in case it's not going to record it, because I don't hear his voice amplified. His question was the array example where elements disappear. Is that exploitable? I have worried about this, because if the element disappeared, then where did it go? It probably went somewhere, and it probably went somewhere not very good. I've never managed to crash a browser or get it to run code of my own or whatever. I have wondered highly about this, but I've never tried exploiting this. Also, because it's not a very easy bug to reproduce, and I wasn't really feeling like digging into C code to figure out what was going on. The answer is maybe, but it is upper, tall, and below. Those browsers are pretty ancient and pretty bad. And hopefully, nobody's using them anymore. So if you figure out an exploit, then you can own 0.01% of the internet and more power to you. Anyone else? There isn't like, I won't repeat questions, if it's like, but sure. Speaking of older browsers and stuff, do you have data on what percentage of the users of the visual editor are using older browsers, and how much do you support those older browsers and their bugs? We have some data like that. We mostly have data for the website as a whole. I do not have memorized. We do know that the browser we support are IE10 and up mostly with some degradation where necessary to work around the ridiculous problems that I showed you earlier, and modern versions of Firefox and Chrome. We have noticed that when there is a, it seems like Internet Explorer usage is not very high, but noticeable to the point where when there is a bug, where we have a bug interacting with Internet Explorer, we get complaints from people quite quickly that pages are being corrupted, but I don't have percentage for you. I get the impression that it's mostly Chrome and Firefox. Maybe Chrome a little bit more than Firefox would pretty evenly split, and a smaller but still substantial use of Internet Explorer. And this is why building Internet Explorer support has been a priority for us. And this is why the Internet Explorer-related slides have been added to this presentation after I last gave it, because I dug into this and found all these ridiculous things. How responsive are the different browser software writers, I guess, to the bug reports that you sent? Oh, that is actually, thank you for asking a question, because that is something that I meant to mention and forgot to put a slide in for. It varies by browser. So Internet Explorer has historically kind of been a black hole until someone from Microsoft, like someone on my team, like, knew a person in the Microsoft, and they knew another person in Microsoft, and they sort of they were having coffee and complaining about this, and then she decided to get the right person in contact with me. And that's how we now have a contact with the IE team, and they actually care about their next release of IE, not breaking Wikipedia. And so I have some leverage with pushing these bugs on them and going, please deal with this. The Firefox people are usually reasonably responsive. Their problem is mostly that they sometimes are kind of obtuse, and I've seen cases where the entire Internet is trying to convince the GECO people that what they're doing violates a pretentiously surprise, or there was a bug related to SVG measurement, where it took three months for a group of two or three people to convince the maintainer of the SVG subsystem of a basic fact about interaction between HTML and SVG. So that's the kind of problems that we see in Firefox. The kind of problems that we see with Chrome is, unless you know people, maybe, because I guess I don't, my bugs have never, ever been responded to with Chrome. Like my only response that I've ever gotten to a bug that I've ever filed with Chrome has been a single comment from a person with an ad-goo.com address confirming that it happens for them too in a different version of Chrome. And like there's been some triaging changes and like tagging things. And sometimes they've fixed bugs that I have filed without ever responding to the bugs, so I guess someone else must have filed it or it could fix that similarly. But like I have like Chrome's thing or is it me? Time for one more. Yeah. Is there one more question? Or is it really happy and happy to go to morning to you or no, next talk, right? Thank you for your presentation. As a token of our gratitude, here you are. Thank you.