September 07, 2010

Doug Schepers

Pointers on Background of SVG Borders on Mutiny


With SVG being integrated more and more into HTML5, both included via <object> and <img> elements, and inline in the same document, some natural questions about SVG and CSS are receiving more focus. This includes box model questions like background and border, and pointer events.

I’m interested in comments from the community on what direction SVG should take.

It’s pretty clear that the intent of the SVG 1.1 spec was that the box-model CSS properties must not apply to any SVG elements. In addition to what the spec states on the subject, my conversations with people who participated in the SVG WG at the time leave me with no doubt on the matter.

The question is, is that the behavior we want? How hard or easy is it to change that in modern SVG+HTML+CSS implementations? What is most useful and intuitive for content authors?

In my opinion, we could specify that some aspects of the box model apply without screwing with SVG’s coordinate-based positioning system. Here are my initial thoughts on some specific properties:

Borders

A borders is different than a stroke. An SVG element, including any graphical (<rect>, <circle>, <path>, etc.) or container element (<svg>, <g>) can have both a stroke (which conforms to the geometry) and a border (which conforms to the element’s bounding box). A common use case is setting the graphics apart from other content, or doing mouseover highlights of an SVG element; for example, when I mouse over or focus a circle, it would be much nicer, and just as semantic, to simply have a CSS property draw a rectangle around that element as a highlight than for me to generate a rectangle based on the bbox and insert that into the DOM, keep a pointer to it, then remove it when I mouse out.

Paint servers and similar resources (gradients, filters, etc.) should not have any border. Note: <defs> is a non-rendering element, akin to <head>, so no border would be visible for that either, but if the content of a <defs> is <use>d, any border properties would apply in the same manner as for other properties.

The border should not have any effect on the layout or rendering; it would be strictly visual.

Margin

No effect on SVG content, but may affect HTML content around that SVG content. So, an <svg> element with 'margin: 20px;' has a 20-pixel gap around the SVG content, just as if it were <img style="margin: 20px;"/>

Alternately, maybe margin only has an effect for <svg> elements; that might be simpler to specify, implement, and understand for content authors.

Padding

Again, this has no effect on SVG content, but it does affect how the border is drawn. This would be a nice way to compensate for thick stroke widths.

Background

A background is different than a fill. Background is much the same as border; it is a rectangle (modulo the border-radius effects) around the shape, based on its geometric bounding box, taking into account padding.

By default, there should be no background color, including for the <svg> element. Right now, there is a WebKit bug in Chrome and Safari which renders a white, non-transparent background for SVG fragments or documents; this is a major pain for any content creators trying to use SVG, much like the old Internet Explorer bug on transparency in PNGs. I hope it receives some attention from the WebKit developers soon.

SVG Tiny 1.2 defines a 'viewport-fill' and 'viewport-fill-opacity'. I think those should be deprecated in favor of 'background' properties; I have no opinion on which should have precedence… maybe they should be seen as aliases of 'background', if that makes it simpler.

A background on SVG content raises the question of pointer events, which is also relevant to borders.

Pointer Events

Should pointer events on the border or background fire on the element itself? I think that the default should be “no”, just to be safe and consistent with older SVG content, but I could easily be persuaded to reverse that. Either way, there should be a new property or set of properties that can modify this, in a manner consistent with how CSS is defining 'pointer-events'.

This touches on the question, asked in a related thread, on whether the <svg> element, by default, should be a proximal event target for pointer events. My answer on that is a pretty firm “no”; if you want to have it as an event target, give it a background, or change the 'pointer-events' value.

Questions

A few high level questions:

  • Is this a change from SVG 1.1 and SVG Tiny 1.2? Yes.
  • Is this backwards compatible? Kind of. It introduces new behavior that is not consistent with past behavior, but doesn’t explicitly change very much.
  • Does this break existing content? Very doubtful.
  • Is this intuitive for content authors? My intuition says yes.
  • Does this match existing implementations? Some, at least.
  • Does this provide value for content authors? Yes.
  • Does this make it harder to implement? I don’t know; I suspect it makes it easier for at least some implementations.
  • Would defining this improve interoperability? Yes.

Conclusion

I propose we change SVG 2 to explicitly define this behavior. As the editor of the HTML5 spec, Hixie seems to imply that this is not for HTML5 to define, and I tend to agree with that, though maybe some informative mention in the HTML5 or CSS specs for how SVG treats margins and padding might be appropriate. We recently formally closed the Compound Document Formats Working Group, which was formed to look at exactly these sorts of questions, and published its specifications as Working Group Notes for posterity; we wanted to be clear about its status. The CDF WG succumbed to the politics around the reformation of the HTML WG, and probably to good effect overall; but in its absence, we still need to resolve these questions by cooperation between the various groups involved.

I don’t think this should be any different in standalone SVG files than in SVG files referenced or inlined in HTML. That would be very unintuitive, in my opinion.

If this is not controversial, I would be happy to put any or all of this in the SVG Integration spec, which is one of the foundations of SVG 2. If someone disagrees with this, we’ll have to talk about it before I start editing the spec. In either case, it would need to be fleshed out some… I’m probably glossing over some possible stumbling blocks in the box model, which I’d appreciate feedback on.

Please leave a comment if you like my suggestions, if you see a flaw, or have a better suggestion.

Update:

Just to show what I’m talking about, I created a sample. Here is a good example of a bad example; below are 3 instance of the same SVG with the same CSS background and border values, with a border width of 2px. The first 2 are external files referenced as objects, the third is inline in the HTML (you won’t see this one unless you are using preview releases of Firefox 4, WebKit, or IE9); the second image also has a padding and margin of 10px.

I tested this in several browsers, and in the referenced cases, the border width increases the image size, spawning scrollbars; I don’t think that’s a good outcome… it should clip the border, just as it does for any graphical overflow… borders should not contribute to the geometry of SVG images.

In the second case, where I added padding, the argument is less clear, but I still believe that for referenced content, the border and background should not displace the rendered graphics, and should be clipped. For inline content, it would make sense for the padding and margin to be visible in the rendered document, but it should still not change the geometry of the SVG.

Please use a modern browser.

Please use a modern browser.

We’d need to specify this in order for it to behave the same across browsers (and authoring tools). So, do people agree or disagree with my conlcusions?

by Schepers at September 07, 2010 11:46 AM

September 01, 2010

Doug Schepers

Formata Non Grata


Recently, a browser implementer asked me for examples of SVG. He was having trouble finding good examples of SVG in use, particularly as parts of an HTML document. This question has come up again and again, actually, and it always vexes me. I’ve been active in the SVG community for close to a decade, and I’ve seen thousands of amazing SVG files (and many more of mediocre to average quality), but somehow they seem to have disappeared or bitrotted over the years. Some of those files only worked with the slightly-unstandard Adobe SVG Viewer, or didn’t quite work with Firefox’s incomplete support, I know, but surely not all of them. Where is all the great SVG content I remember, the games and GUIs and design and development? Where are all those files to be found?

I hear some browser implementers say that people just don’t use SVG. Intuitively, this feels false to me, based on my own experience. But could it be true?

The statistical insignificance of SVG is often cited by some people in the WHATWG, based on a large dataset of Web content indexed by Google. In the WHATWG, where HTML5 started, great stock is placed on statistics, particularly those conducted by the editor, Ian Hickson, a Google employee.

DrHTML5

There’s no question about it: HTML is the king of the Web. I did some rough calculations, similar to claims I’ve heard before, by counting the number of returns for HTML files versus SVG files. A search for the filetype “.svg” yields around 18,165,500 hits on Google. (Note that this doesn’t count the false hits on the word “SVG” from St. Vincent and the Grenadines, Stan Van Gundy, the Sexy Valley Girls, or any of the numerous other bizarrities that the acronym stands for.) SVG content makes up just 0.106% of all Web content, by my rough estimation. Flash is almost 5 times as common as SVG. That’s pretty grim for SVG.

But wait, let’s put that into perspective. Flash is about 4.8 times more common than SVG. HTML is roughly 838 times more common than SVG. 838 times. Flash content comprises approximately 0.52% of all Web content, and HTML is roughly 189 times more common than Flash. So, Flash is clearly much more popular than SVG (even when you consider that some large percentage of Flash content is actually just encapsulated video content, these days). But that doesn’t mean that nobody’s using SVG. Nearly 20 million documents is pretty impressive, actually, especially given the fact that SVG has been hindered by a lack of native support in browsers for most of its existence (and more recently, even poor support by the Adobe plugin for IE), and a lack of common authoring tools for dynamic content (Inkscape is an excellent vector editor, but it doesn’t yet do animation or interactivity).

Eighteen million documents. That’s a lot of files. So, given that, why is it so hard to find SVG content?

Maybe because the most popular search engine in the world, Google, doesn’t index SVG.

Indexing SVG

A long time ago, back in 2002, I made a page discussing my experiments with text search and translation. The results were not very encouraging, but I reckoned it was just a matter of time. I optimistically wrote to Google to encourage them to enable text search and translation of SVG files.

8 years down the line, things don’t seem to have changed much on that front.

To be fair, many SVG files don’t contain any text at all, not even a <title> element, so indexing them might not yield much. But many other files do have at least a title, and SVG infographics and webapps usually have at least labels that might be meaningful as search terms. Often SVG files are even text-heavy.

It’s not that Google doesn’t take note of the files… obviously, you can search for the filetype, or in the worst case, the specific file URL, and normally get back positive results.  But Google doesn’t seem to search the contents of the SVG files and present them in the relevant result set.  To test this, I tried searching for a few files that I knew to have indexable text content.

As an example, I looked for some SVG files on my little (long out-of-date) SVG promotion site, SVG-Whiz.com. First, I searched for a file I knew to have a cogent block of text, my explanation of the distinctions between ‘display’, ‘visibility’, and ‘opacity’, called HideShow.svg:

Please use a modern browser.

This file has been hosted on my site since 2003, I’ve gotten several positive comments about it, and a direct search for that file URL turns up a few hits linking to it, so it’s seems like a reasonable candidate for indexing. But what are the results of my in-site Google search for the word ‘opacity’? Okay, that just turned up the explanation page linking to the SVG file in question. Fair enough, maybe Google doesn’t treat SVG as a “document” file, only as an image. So, how about an image search for the same term? Nada. So, maybe Google doesn’t consider SVG to be either a “document” nor an “image”… let’s search for the word ‘opacity’ in the site ‘svg-whiz.com’ with the filetype ‘svg’. As specific as that is, at the time of writing, I got not a single resulting hit.

Google can find the files… why doesn’t it do something with them?

Comparison of File Extension Frequency

So, what criteria does Google use to decide which file types it is going to index?

The Google FAQ on search filetypes lists 23 file extensions that it indexes, and says:

There are 13 main file types searched by Google in addition to standard web formatted documents in HTML. The most common formats are PDF, PostScript, Microsoft Office formats [...] Google is also scouring the Web for additional file types that are very rare. You may see them pop up in your results from time to time. [...] PDF formatted files are the most popular after HTML files. PostScript and Microsoft Word files are also fairly common. The other file types are relatively uncommon by comparison.

So, I took the liberty of conducting my own survey of the relative frequency of various filetypes, as collected by Google itself, by using the “filetype:extension” query term. I’m not totally convinced this is at all an accurate means to collect and analyze the data, but it’s what I had at hand.

I put together a table that compares the different file types that Google explicitly mentions. (I thought about representing the data as an SVG barchart, but I was afraid it wouldn’t be indexed… just kidding, the sheer volume of HTML files would make every other bar just a blip.)

I also threw in some other filetypes of interest, including some with functional similarity to SVG, such as Illustrator, PhotoShop, and Silverlight. I expected non-Web filetypes such as Illustrator’s “*.ai” to be disproportionately underrepresentated in the results compared to their actual usage, and that was indeed borne out; it’s hard to know what percentage of SVG files are intended for and presented on the Web (I’ve spoken to many Inkscape users who only use SVG for print or local hard-drive, which surprised me), but I would guess that it is far, far more heavily tilted toward Web usage… but I still thought it would be interesting to compare.

What did surprise me was how “*.svg” compared to such ubiquitous file extensions as “*.txt”, and those for Excel, PowerPoint, and the venerable PostScript. To be frank, the results make me question my methodology, or perhaps the accuracy of Google’s reporting.

File Type File Extension Number of Results Introduction
HyperText Markup Language total 16,574,700,000 1991
html 8,180,000,000
php 7,010,000,000
asp 1,370,000,000
xhtml 14,700,000
Adobe Portable Document Format pdf 281,000,000 1993
Shockwave Flash total 87,923,300 1996
swf 87,900,000
fla 23,300
Microsoft Word doc 58,500,000 1983
Text total 32,757,000 1982
txt 32,600,000
ans 157,000
Scalable Vector Graphics total 18,165,500 1999
svg 18,100,000
svgz 65,500
Microsoft Excel xls 12,500,000 1982
Microsoft PowerPoint ppt 7,790,000 1984
Rich Text Format rtf 5,130,000 1987
Adobe PostScript ps 2,440,000 1982
Adobe Illustrator ai 135,000 1986
OpenOffice.org odt 135,000 1999
MacWrite mw 35,600 1984
Adobe PhotoShop psd 21,800 1988
Silverlight total 8,493 2003
xaml 8,180
xap 313
CorelDRAW cdr 8,310 1989
Microsoft Works total 2,266 1987
wks 1,190
wps 801
wdb 275
Lotus 1-2-3 total 1,981 1983
wks 1,190
wk1 571
wki 89
wk3 47
wk4 41
wku 33
wk5 6
wk2 4
Microsoft Write wri 1,200 1985
Lotus WordPro lwp 148 1995
All Web Content 17,081,255,598 1989

Caveat: I originally compiled this information a few months ago, and when rechecking it for accuracy, I got a surprising result. Normally, the Google search for filetype:svg returned 18,100,000 hits, but late one night, it returned only 2,000,000 hits; now, my most recent check showed around 4,300,000 hits. Jumping around in the results for an explanation, I noticed that there is a lot of duplication of Wikipedia content, and since Wikipedia uses SVG, that might account for some discrepancy. One possibility is that the lower figure represents 2 million unique documents, which are duplicated in a lot of places; the same should be said of any HTML content, and probably to a lesser extent of Flash content. I don’t know if this is the right conclusion, but it would be an interesting data point. Even with the much more modest figure of 2 million documents, I still think that represents an impressive body of work, particularly in light of the fact that SVG documents are normally authored individually, not through forum or blog software, or exporting or reformatting of email and text content as HTML.

Conclusions

I don’t think this is some grand conspiracy by Google to suppress SVG. Simple neglect is much more plausible. They don’t seem to see the value in indexing SVG. But the end result is the same: SVG seems to be statistically underrepresented in terms of access through Google searches, and thus, it is harder to find SVG content.

Relying on the results of a search engine that doesn’t index SVG, to draw conclusions about how many people are using SVG is not statistically sound. This is a bit like conducting a phone survey of English speakers in China, and concluding that nobody speaks with a Southern US accent. I reckon y’all might could see the problem with that methodology if you lived here in North Carolina.

SVG is at least as plentiful on the Web, by Google’s own reckoning, as most other file types that Google does index. Search engines, Google included, should index SVG files. They should read the text inside the file, and if the file is referenced in an HTML page, they should associate those keywords with the SVG file, just as they do with raster images. SVG files should display in image searches, as well. Here’s a list of the kind of useful content that can be gleaned from most SVGs:

  • file name: while pretty primative, many files give some clue as to their contents in their name
  • text elements: there are several elements in SVG that contain text to be rendered to the screen, including <text>, <tspan>, <textPath>, and <textArea>, and the content should be indexed as if it were text in any other format
  • embedded HTML: HTML (and other markup) can be embedded inline in SVG, and search engines should look for that and index it as they would standalone HTML content
  • links: Google, and probably most other modern search engines, give weight to files that are linked from other files, and files referenced from SVG content should benefit in the same way; the @xlink:title and @rel can help define the relationship between the files
  • descriptive elements: like HTML, SVG has a <title> element that doesn’t display, but adds to the information about its parent file or element, and SVG also has a <desc> element for a longer description
  • metadata: SVG can contain RDF, RDFa, microformats, and ARIA markup, which search engines are starting to pick up on these days; these metadata can reveala lot about a file, from its license information to structured content (like calendars or dates or contact info) to intent (such as ARIA roles, which will soon be expanded to include things like different chart types)

And the SVG Working Group would be happy to work with any search engine developers to make improvements to SVG 2 to help make indexing SVG content easier or more fruitful.

I’m not trying to pick on Google here (though I do note that a Bing search for ‘svg opacity svg-whiz.com’ listed the SVG file as the first hit), I’m just noting a discrepancy and an opportunity for improving the experience that people have on the Web with regards to SVG. At the very least, SVG should be recognized by Google as a legitimate file type, rather than a formata non grata.

Update

Rob Russell delivered great news to us in his SVG Open keynote. As of August 31, 2010, Google now indexes SVG and delivers it in some search results. Kudos to Google for stepping up! I’m very pleased… solid results only 6 weeks later. (I guess I should thank Slashdot, too.)

by Schepers at September 01, 2010 02:50 PM

roc

New Google Maps Imagery Of Auckland

At some point relatively recently, Google added much higher-resolution images of Auckland to Google Maps. These images appear to have been taken by aerial photography and they're quite amazing.

by roc (rocallahan@novell.com) at September 01, 2010 11:06 AM

August 30, 2010

roc

A Night Out

I had a very nice dinner at "Wildfire Churrascaria" courtesy of Microsoft. Lots of yummy, fatty, salty meat.

I went to catch my bus and missed it by one minute. At 10:41pm, the next bus was at 11:10pm.

Being impatient, instead of waiting for the next bus I ran home ... well, half-ran, half-walked ... 5.5km In 42 minutes. Not fast, but then I had a backpack full of Microsoft swag plus my laptop, and a belly full of meat. Faster than the bus anyway.

by roc (rocallahan@novell.com) at August 30, 2010 12:35 PM

TechEd

I'm at Microsoft TechEd in Auckland today and tomorrow --- they reached out to invite a few open source people, so I thought I'd go and check out their messages. It's fun too. One of the highlights of today was a talk about geolocation APIs ... the presenter showed the creation of a toy HTML geolocation app, but couldn't get it working in Chrome and had to switch to Firefox :-). And apparently IE9 isn't going to support the geo APIs at all as far as anyone knows. Funny sort of demo for a Microsoft conference!

In fact so far I haven't seen anything about IE9 at all. There's a lot more Silverlight/WIndows Phone 7. I wonder if that's accidental (this is just the first day after all) ... or not.

by roc (rocallahan@novell.com) at August 30, 2010 07:15 AM

August 28, 2010

roc

More Dell Fail (Or Maybe NVidia)

I bought a Dell ST2410 monitor for my new home computer (a Dell XPS 8100 shipped with an NVidia GTX260 graphics card, which has two DVI ports). Dell shipped a VGA cable and a DVI-VGA converter, so I thought I'd go out and buy a digital connector. Dell shipped me a DVI-HDMI converter dongle (made by NVidia apparently), the Dell monitor has HDMI and my TV has HDMI so I thought I'd get an HDMI cable and this would be easy. Wrong. The monitor completely fails to detect any signal from the computer. I tried everything I can think of. Even my old Macbook Pro can drive the monitor through its DVI port, the DVI-HDMI dongle and the HDMI cable. So apart from the cable, which obviously works, we have here three parts all shipped by Dell that don't work together. Sigh. I guess I'll try a DVI cable next...

by roc (rocallahan@novell.com) at August 28, 2010 10:22 AM

Sunshine Rises Again

As previously reported, the wonderful "Sunshine" Chinese restaurant in Market Place near the Viaduct Harbour suffered a tragic demise. And also as previously reported, it has been reincarnated. Today our family visited the new incarnation, "Crystal Harbour". I am very pleased to report that the new version is very similar indeed to the old "Sunshine". The decor is the same, the layout is the same, the lack of queues is the same, and most importantly the food is very much as it was. Where Sunshine excelled --- the unique barbeque pork buns, the seaweed plate, the ice cream dumplings --- so does Crystal Harbour. Crystal Harbour's promotional material claims there's a new chef, but clearly (and fortunately) a lot has been preserved. One change is that there were a lot more people there today than I ever saw at Sunshine. It could be the novelty factor, but I hope Crystal Harbour does well. I certainly plan to contribute as often as I can!

by roc (rocallahan@novell.com) at August 28, 2010 07:32 AM

August 25, 2010

roc

-moz-element Landed

Markus Stange picked up the work I did in 2008 on the "-moz-element()" CSS extension (which was later extended by Ryo Kawaguchi), made some major improvements and got it reviewed and landed. Check out his blog post. -moz-element lets you render the contents of an element as the background image for any other element. This is a very powerful tool that can be used in very interesting ways; check out Markus' amazing demos. This feature is on trunk now and will be in Firefox 4. We will also propose this to the CSS WG.

Note for browser UI and extension authors: eventually -moz-element will be the preferred way to render "live" copies of Web page contents (insteading of using MozAfterPaint/drawWindow). Right now, -moz-element can be used to render the contents of a <browser> element elsewhere, although it's less well-tested and is less tweakable for performance. Post-FF4, we can tie -moz-element into the layers framework so that in many cases --- such as tab thumbnails --- rendering -moz-element just recomposites a layer subtree, fully GPU-accelerated.

by roc (rocallahan@novell.com) at August 25, 2010 03:00 AM

August 23, 2010

roc

Vinge

The first Vernor Vinge books I read were A Fire Upon The Deep and A Deepness In The Sky ... not surprising, since they're the most famous, and also the best. I was a bit disappointed by Rainbows End. Just recently I read two of his earlier novels (written in the 80s), The Peace War and Marooned In Realtime --- the latter being a sequel to the former --- and I think they're excellent, perhaps not as good as Fire and Deepness, but Marooned in particular I found more intriguing and even quite moving.

Warning: if you haven't read these books, go out now and read them before you come back to the rest of this post, because spoilers are ahead...

Marooned and Rainbows End present two rather different visions of human development, and Rainbows End is far closer to my own thinking even though I like the book less. I'm ignoring the bobbles here --- they're a wonderful plot device, but I think the real themes of Marooned are the technological Singularity and a yearning for anarcho-capitalism. At heart I think Marooned is fundamentally an optimistic view of human progress to the Singularity. Rainbows End, on the other hand, seems to me to be a much darker view, a view of humanity lurching from one potential planet-killing catastrophe to the next at decreasing intervals, with no Singularity-salvation in sight. Now, Vinge may make a liar of me yet, since he's said he'd like to do a sequel to Rainbows End, but based on what he's written so far I guess in the twenty years between the books he's become more pessimistic. Although curiously, he may have become a lot more optimistic about governments --- in Marooned he hates governments, in Rainbows End we see a benign totalitarian state.

Personally I think Rainbows End is too optimistic :-). I wrote about this a while ago and I stand by it: the technology that could eventually lead to some kind of Singularity (very eventually; this stuff is way, way harder than most techo-futurists imagine), leads much sooner to either the total elimination of cognitive freedom or the destruction of all intelligent life. It's just not realistic to imagine we can walk the ever-thinning razor's edge for long. Man is fallen, but he still has a long way to fall. God is going to have to save us from ourselves, again.

Time to stop. Excessive futurist navel-gazing is definitely a sin :-).

by roc (rocallahan@novell.com) at August 23, 2010 09:53 PM

August 20, 2010

Doug Schepers

The Map is not Proprietary


Korzybski remarked that “the map is not the territory”, reminding us that we shouldn’t confuse our mental models for reality. But maps, and data visualizations of all kinds, are really powerful, conveying complex ideas easily, and even shaping (or misshaping) perceptions about facts. This is one reason why decentralization of mapping resources and services is good; no one organization should control our common maps.

SVG is a natural fit for mapping. There’s even a detailed proposal by KDDI’s Satoru Takagi-sensei for tiling, layering, and coordinate resolution that fits on top of SVG, which I’d like to see standardized.

I’ve had an idea for a small open-source project for a while, which I’ve discussed with the brilliant Andreas Neumann of Carto.net; he’s been too busy planning SVG Open every year to help out with it thus far, and I don’t have the skills to do it without a great investment in time.

The idea is simple: there are lots of static SVG maps of various countries, states, etc. that are freely available (for example, on Wikipedia). Some effective data visualizations can be made with these (color-coding countries, etc.), but they are by necessity very simple. Content creators can’t use such maps to pinpoint specific locations (long/lat), because they don’t know the projection… the maps are purely visual, not topographical (if that’s the right word).

There are more heavy-weight solutions, like OpenStreetMap, which is awesome, but more than most people need for very simple location-sensitive webapps.

What I would like to do is have a very simple set of basic maps, with low-to-medium level of detail, all with the same projection, and to provide a Javascript utility that converts back and forth between long/lat and the coordinate space of the image. There would be one world map, and a map for each country, and a map for each major region within each country (in the US, this would be states).

For example, using this script and some of these premade maps, I could make a little webapp that allows members of a social network (e.g. a developer community, or people who share a hobby) to type in their location (long/lat), and it would stick a “pin” in the map at that location. They could see the high level overview at the world level (100 people in the US, 20 in Japan, 72 in Europe, etc.), and easily drill to the country level (click on US and open that map, showing 20 in California, 5 in North Carolina), and drill down again to the region level (showing the distribution of pins in North Carolina).

It would not go down to the city level, or show regional features like roads or lakes… that gets too complex, and there are other applications to do that. However, it would include projection metadata and instructions for each region (which the conversion script might use), and the project would make it possible for someone to export their own GIS data into this simplified format by providing instructions (for, say, ArcGIS).

This is something I think could appeal to people on a very high-level, making SVG easier to understand and use for simple projects like this; I want to improve the reusability of SVG in this way.

And I think the stellar Michal Migurski of Stamen Design, and SimpleGeo, have just scooped me. I haven’t looked into the details yet, but they just announced the launch of PolyMaps, a free and simple SVG and Javascript mapping library. Curse and bless you, you maptastic bastards!

Oh, and in case PolyMaps doesn’t completely fit what I described above, let talk.

by Schepers at August 20, 2010 09:34 PM

August 19, 2010

roc

CSS Units Changes Landed

The CSS units changes that I blogged about in January have landed and will be in the next Firefox milestone. With these changes, 1in = 96px always. Likewise 3pt = 4px, 25.4mm = 96px, etc. This matches the behaviour of Internet Explorer, Safari and Chrome.

By default, when printing, 1in is rendered as one physical inch. For other output media, all these units are scaled in a medium-dependent and platform-dependent way by default. One goal of this scaling is to give results consistent with user expectations and other applications on the system. For example, standard form controls such as checkboxes should look the same in Web pages as in other applications, by default. Another goal is to choose default scaling so that a document designed to print well on normal-sized paper will be readable on the output device, e.g., a phone. So, the advice for authors using CSS physical units is to set lengths so the document looks good when printed without scaling; the browser will then scale those lengths to display the document suitably on different kinds of screens.

There are some rare cases where it makes sense to include true physical measurements in a Web document --- for example, "life size" diagrams, or elements in a touch interface. For these cases we have introduced a new experimental unit, "mozmm". For media such as screens that can be touched, 1mozmm is rendered as one physical millimetre (or as close as we can get based on what we know about the medium). For other media, such as contact lens displays, brain-implanted electrodes, or lasers projecting into the sky, we reserve the right to treat 'mozmm' similarly to 'mm'. Authors should only use mozmm for elements which really need the same physical size on, for example, a 4" phone screen and a 24" monitor. This is hardly ever going to be what you want.

Internally, our DPI code has been overhauled. Everything is now controlled by two parameters: for each window, the number of device pixels per inch (returned by nsIWidget::GetDPI), and also for each window, the default scale (returned by nsIWidget::GetDefaultScale). The 'layout.css.dpi' about:config pref overrides the result of nsIWidget::GetDPI, if present. nsIWidget::GetDPI only affects the interpretation of mozmm (unlike before, where on some platforms, some DPI values would trigger automatic scaling). We set CSS 1px to one device pixel times GetDefaultScale times the current zoom factor. Currently GetDefaultScale always returns 1.0 on all platforms, although on Mac we should set it to the system "default UI scale" (and change some other code to compensate), and on Windows we should set it based on the "system font DPI", which is essentially a user preference that controls scaling of all applications on the system. It's important that the default scale be based on a system-wide setting; that will keep Firefox consistent with the rest of the system, and ensure that the user doesn't get a surprise.

by roc (rocallahan@novell.com) at August 19, 2010 11:45 PM

August 16, 2010

roc

mozRequestAnimationFrame

In Firefox 4 we've added support for two major standards for declarative animation --- SVG Animation (aka SMIL) and CSS Transitions. However, I also feel strongly that the Web needs better support for JS-based animations. No matter how rich we make declarative animations, sometimes you'll still need to write JS code to compute ("sample") the state of each animation frame. Furthermore there's a lot of JS animation code already on the Web, and it would be nice to improve its performance and smoothness without requiring authors to rewrite it into a declarative form.

Obviously you can implement animations in JS today using setTimeout/setInterval to trigger animation samples and calling Date.now() to track animation progress. There are two big problems with that approach. The biggest problem is that there is no "right" timeout value to use. Ideally, the animation would be sampled exactly as often as the browser is able to repaint the screen, up to some maximum limit (e.g., the screen refresh rate). But the author has no idea what that frame rate is going to be, and of course it can even vary from moment to moment. Under some conditions (e.g. the animation is not visible), the animation should stop sampling altogether. A secondary problem is that when there are multiple animations running --- some in JS, and some declarative animations --- it's hard to keep them synchronized. For example you'd like a script to be able to start a CSS transition and a JS animation with the same duration and have agreement on the exact moment in time when the animations are deemed to have started. At each paint you'd also like to have them sampled using the same "current time".

These problems have come up from time to time on mailing lists, for example on public-webapps. A while ago I worked out an API proposal and Boris Zbarsky just implemented it; it's in Firefox 4 beta 4. Here's the API, it's really simple:

  • window.mozRequestAnimationFrame(): Signals that an animation is in progress, requests that the browser schedule a repaint of the window for the next animation frame, and requests that a MozBeforePaint event be fired before that repaint.
  • The browser fires a MozBeforePaint event at the window before we repaint it. The timeStamp attribute of the event is the time, in milliseconds since the epoch, deemed to be the "current time" for all animations for this repaint.
  • There is also a window.mozAnimationStartTime attribute, also in milliseconds since the epoch. When a script starts an animation, this attribute indicates when that animation should be deemed to have started. This is different from Date.now() because we ensure that between any two repaints of the window, the value of window.mozAnimationStartTime is constant, so all animations started during the same frame get the same start time. CSS transitions and SMIL animations triggered during that interval also use that start time. (In beta 4 there's a bug that means we don't quite achieve that, but we'll fix it.)

That's it! Here's an example; the relevant sample code:

var start = window.mozAnimationStartTime;
function step(event) {
  var progress = event.timeStamp - start;
  d.style.left = Math.min(progress/10, 200) + "px";
  if (progress < 2000) {
    window.mozRequestAnimationFrame();
  } else {
    window.removeEventListener("MozBeforePaint", step, false);
  }
}
window.addEventListener("MozBeforePaint", step, false);
window.mozRequestAnimationFrame();

It's not very different from the usual setTimeout/Date.now() implementation. We use window.mozAnimationStartTime and event.timeStamp instead of calling Date.now(). We call window.mozRequestAnimationFrame() instead of setTimeout(). Converting existing code should usually be easy. You could even abstract over the differences with a wrapper that calls setTimeout/Date.now if mozAnimationStartTime/mozRequestAnimationFrame are not available. Of course, we want this to become a standard so eventually such wrappers will not be necessary!

Using this API has a few advantages, even in this simple case. The author doesn't have to guess a timeout value. If the browser is overloaded the animation will degrade gracefully instead of uselessly running the step script more times than necessary. If the page is in a hidden tab, we'll be able to throttle the frame rate down to a very low value (e.g. one frame per second), saving CPU load. (This feature has not landed yet though.)

One important feature of this API is that mozRequestAnimationFrame is "one-shot". You have to call it again from your event handler if your animation is still running. An alternative would be to have a "beginAnimation"/"endAnimation" API, but that seems more complex and slightly more likely to leave animations running forever (wasting CPU time) in error situations.

This API is compatible with browser implementations that offload some declarative animations to a dedicated "compositing thread" so they can be animated even while the main thread is blocked. (Safari does this, and we're building something like it too.) If the main thread is blocked on a single event for a long time (e.g. if a MozBeforePaint handler takes a very long time to run) it's obviously impossible for JS animations to stay in sync with animations offloaded to a compositing thread. But if the main thread stays responsive, so MozBeforePaint events can be dispatched and serviced between each compositing step performed by the compositing thread, I think we can keep JS animations in sync with the offloaded animations. We need to carefully choose the animation timestamps returned by mozAnimationStartTime and event.timeStamp and dispatch MozBeforePaint events "early enough".

mozRequestAnimationFrame is an experimental API. We do not guarantee to support it forever, and I wouldn't evangelize sites to depend on it. We've implemented it so that people can experiment with it and we can collect feedback. At the same time we'll propose it as a standard (minus the moz prefix, obviously), and author feedback on our implementation will help us make a better standard.

by roc (rocallahan@novell.com) at August 16, 2010 10:44 PM

The mozRequestAnimationFrame Frame Rate Limit

A few people have been playing with mozRequestAnimationFrame and noticed that they can't get more than 50 frames per second. This is intentional, and it's a good feature.

On modern systems an application usually cannot get more than 50-60 frames per second onto the screen. There are multiple reasons for this. Some of them are hardware limitations: CRTs have a fixed refresh rate, and LCDs are also limited in the rate at which they can update the screen due to bandwidth limitations in the DVI connector and other reasons. Another big reason is that modern operating systems tend to use "compositing window managers" which redraw the entire desktop at a fixed rate. So even if an application updates its window 100 times a second, the user won't be able to see more than about half of those updates. (Some applications on some platforms, typically games, can go full-screen, bypass the window manager and get updates onto the screen as fast as the hardware allows, but obviously desktop browsers aren't usually going to do that.)

So, firing a MozBeforePaint event more than about 50 times a second is going to achieve nothing other than wasting CPU (i.e., power). So we don't. Apart from saving power, reducing animation CPU usage helps overall performance because we can use the free time to perform garbage collection or other house-cleaning tasks, reducing the incidence or length of frame skips.

We need to do some followup work to make sure that on each platform we use the optimal rate; modern platforms have APIs to tell us the window manager's composition rate. But 50Hz is almost always pretty close.

This all means that measuring FPS is a bad way to measure performance, once you're up to 50 or more. At that point you need to increase the difficulty of your workload.

by roc (rocallahan@novell.com) at August 16, 2010 10:06 PM

Something Witty Goes Here

SVG/Canvas Marketshare: July 2010

SVGI’ve updated my marketshare spreadsheet for July 2010 charting the percentage of web users who can view SVG and Canvas: 41.82%

Note that this number is lower than last month’s because I could not include hitslink.com stats (they’ve put their stats behind a pay-wall now). If anyone knows of a better source of stats, let me know.

P.S. This figure does not take into account any user that has a SVG plugin installed or authors who have used the excellent SVG Web or excanvas shims, so this is really a worst-case number.

by Jeff at August 16, 2010 03:18 AM

August 15, 2010

roc

Auckland Food

For cheap tasty food, BBQ King on Wyndham Street West is hard to beat. Today I went there with family and based on past experience, we ordered only two dishes for four people, "BBQ pork and crispy pork stirred noodle" for $13.50 and "seafood fried rice" for $12. After eating the free soup and then dividing the first dish among four of us, we were pretty much satisfied, so boxed the second dish and brought it home. Crazy!

Tragically, my favourite Chinese restaurant in the city --- Sunshine --- closed several months ago. I can understand when a bad restaurant goes under, but not a good one; the imperfections of a market economy! But I have heard rumours that a new Chinese restaurant has taken its place. This needs investigation.

Daikoku Teppanyaki on Quay St is now open for lunch seven days a week. The $13.50 lunch special is still great value.

Around Newmarket: Happy Valley, the Chinese cafe, has closed down. That's sad, since they'd been serving pretty good food since the early 90s.

The Organic Pizza Co.'s $10 lunch specials are pretty good. Their pizzas are about as good as Archie's, but you get a free drink and the place is far less crowded.

Selera, Night Spice, Crazy Noodle and Dee Jai are frequent targets of visits from the Mozilla office, as is the food court under the Rialto carpark. The actual Rialto food court next to the cinema seems to be declining --- two outlets have closed recently --- but they still have the only Subway in the area. We'd go to Hansan more but we're too lazy to walk there except for special occasions.

Pearl Garden still the best yum cha in Newmarket, followed by Sun World and Sunnytown. There's a new place whose name escapes me over near Davis Crescent; not bad, but not great. I need to try it again.

by roc (rocallahan@novell.com) at August 15, 2010 07:59 AM

Firefox Sync

I just tried using Firefox Sync to synchronize data between my main Firefox profile and my newly-installed home computer's Firefox profile. It was easy to set up and worked perfectly --- and it was fast too! I have to confess my expectations were not high for a feature that just got turned on for beta 4 :-). Well done everyone! This is definitely going to make my life a little easier.

by roc (rocallahan@novell.com) at August 15, 2010 05:36 AM

August 13, 2010

roc

Google vs Oracle

I don't know much about the Google/Oracle dispute so I'll limit my remarks, but here they are:

I don't understand why Oracle is doing this. They may wish Google was using Java ME, but I would have thought having more developers using Java was good for Java overall. Probably there are important background discussions we are not privy to.

Dalvik is open source, but it's very much a Google project that Google happens to release under an open source license, rather than a community project. So I think of this as two big companies scrapping rather than Oracle launching an attack on the open source community.

However, this extends a disturbing trend of large mainstream companies using software patents to attack competitors, especially prominent in the mobile space. Observers of software patents, including myself --- and even Bill Gates in his infamous 1991 memo --- have always seen that volumes of easily obtained software patents on straightforward ideas could be a powerful weapon to crush competition; software development is so inventive that most programmers daily write code that someone patented somewhere. Fortunately, for a long time, other than "patent trolls", serious industry players declined to use that power. But now that grace has departed and I fear patent armageddon is upon us. In the end the open source community is likely to be particularly hard-hit, since it's easy to detect infringement, and open source communities have limited funds for defense. People have argued that open source communities are less of a target because they have less money to extract, but the most dangerous suits are about shutting down competition, not about extracting licensing fees --- like this Google/Oracle suit, apparently.

Overall I'm extremely gloomy about the situation. A world where each programmer has to be shepherded by a dozen lawyers through patent minefields is not one I will enjoy working in, and it will be disastrous for the progress of software. I call on employees of Oracle, Apple and other litigating companies to protest to their management in the strongest possible terms, including resignation. Google and Mozilla are hiring :-).

It's little consolation that some enlightened countries --- like New Zealand, apparently --- will hopefully remain free of software patents. A software company --- or an open source project --- that can't do business or get distribution in the USA or many other countries (including most of Europe, given the 'method patent' regime) is somewhat crippled.

by roc (rocallahan@novell.com) at August 13, 2010 10:53 PM

August 11, 2010

roc

Dell Fail

Separate from the laptop discussion, I just bought a new home machine. I just wanted a generic PC, high-ish end for longevity and in case I (or someone else) wants to hack on it. This machine will definitely run Linux, but I'm going to keep the Windows 7 install in a partition in case we ever need it. So I'm going through Dell's Windows 7 first-run experience, and it's not great.

The initial Microsoft setup screens are pretty good, although it all seems to take longer than it should. Then you get to a Dell screen asking you to opt into some Dell stuff, which for some unfathomable reason is rendered in the Windows 95/2000 "Classic" theme, gray box scrollbars and all. It's ugly, jarring and totally mystifying.

Soon you're offered the chance to burn system recovery DVDs. I don't understand why they ask users to obtain blank DVDs and burn them instead of just shipping those DVDs; shipping them with every system would add a few dollars to the system cost, but probably save more in support calls and give a much better user experience.

The application that burns the recovery DVDs has one crazy screen that shows you some information and asks you to click "Next". But there is no "Next" button visible. But there's a vertical scrollbar! Scrolling down, you can get to a "Next" button. Of course, the window is not resizable, and it contains lots of blank vertical space so there is no possible reason why the "Next" button should not be visible.

Microsoft's initial Windows network setup asks you whether you're on a "Home", "Work" or "Public" network, which I bet is often hard for people to answer. I wonder how Windows uses that information. But right after choosing that option, the (preinstalled) McAfee antivirus software pops up an ugly little box in which you have to choose those same options again.

Of course I still have to analyze the system for the paid-to-be-there crapware (including McAfee) and uninstall most of it.

I'm genuinely curious about what motivates system vendors like Dell to sully what could have been a better experience. It's not apathy, since they obviously paid people to develop many of these "extras". Whatever it is, it's no surprise platform vendors want to sell directly to the customer instead of working through partners like Dell.

by roc (rocallahan@novell.com) at August 11, 2010 09:45 AM

August 10, 2010

roc

Choosing Sides

My Macbook Pro is 3.5 years old and still works pretty well, apart from the disk being full, frequently spontaneous wake-ups in my backpack which heat everything up alarmingly, and flaky wireless connection. Plus the turn of Moore's Law means I can now get a quad-core laptop and a lot more RAM and disk. So it's finally time to upgrade. I'm opting for non-Apple hardware; Apple have gone beyond the pale pursuing patent warfare and platform lockdown, and I can no longer live with buying their products. A Lenovo W510 is probably in my future.

Now I'm faced with a somewhat difficult decision: Linux vs Windows. There are good reasons on both sides. The best thing about developing in Windows is that it's good to have developers on the platform that most of our users use. VMWare record and replay is also very attractive. The Mozilla build and tools situation on Windows used to be terrible --- very slow builds, horrible profiling --- but it's gotten a lot better thanks to pymake and xperf. But Microsoft, while not as dangerous as Apple at the moment, still aspires to be, and I won't embrace them gladly.

Linux, of course, has the virtue of freedom, and a chance to regain Miguel's love. On Linux you get valgrind. But not many of our users use Linux, and VMWare's record and replay doesn't really work there. I'd have to use X11, which I loathe with passion.

Tough call. Another thing to consider is that whichever way I go, I'll end up using the other in a VM quite often. Dual-booting is also an option.

by roc (rocallahan@novell.com) at August 10, 2010 12:07 PM

Doug Schepers

Favatars


What’s a favatar? It’s a favicon! It’s an avatar! It’s a portmanteau!

Well, really, a favatar is a profile picture hosted at the URL a commenter provides, with the filename favatar.png. I made it up!

Okay, so I’m not the first person to make it up. Apparently, a gentleman by the name of Paul James scooped me by a few years, with the same name and a rather similar idea for the same problem. I had this idea out of the blue, while in Montreal for Libre Graphics Meeting 2009, and was dismayed to find, again, that there is nothing new under the sun. So, I put it in my box of maybes.

… Until this weekend, when I added a WordPress plugin to display images for commenters, to make it easier to follow a thread and humanize the conversation. Something that has always bothered me about those images is that they usually come from a third-party service, Gravatar.com. This is actually owned by the same parent company that develops WordPress, and I am sure it’s a fine service for what it is, but I dislike such centralization where it isn’t necessary. There are some also-ran services like Wavatar, monsterID, OpenAvatar, and so forth, but Gravatar (or “Globally Recognized Avatar”) is the big one.

What’s the chief difference between a favatar (note the small f ) and a Gravatar (note the big G )? A favatar is a convention, not a service. It’s distributed. It’s cooperative. It’s web-like. It’s owned and controlled by the person, not (necessarily) by a proxy or host.

The problem I see with Paul’s original idea around favatars is that it revolves around reusing the favicon.ico, which is typically too small for the purpose of a comment avatar My favicon (though not always: Paul James' favicon), and ‘*.ico’ files don’t display in the <img> element in all browsers. And stylistically, a favicon and an avatar seem to be distinct. As far as I’ve seen, despite a few plugins made, and some good conversation about it, the idea hasn’t really taken off, and the name is just too good to let lie fallow.

So, I put on my hacking mittens, and borrowed code from one or two existing Gravatar WordPress plugins, Easy Gravatars by Dougal Campbell and WordPress Gravatars by Rune Gulbrandsøy. Stir well, bake for 3 hours, and out comes Favatar Plus, my new WordPress plugin. It first looks to see if the commenter has supplied a website address, and if they have a file there called favatar.png (so far, I assume I’m the only person who does). Failing that, it falls back to a Gravatar, then to an Identicon (courtesy of Gravatar.com, actually), and ultimately, as a last ditch effort, falls back to their favicon, if found.

My original idea also included linking their image to a vCard called contact.vcf, if found at the same base URL, but in testing that, I found it a little unintuitive… you click it, and suddenly you’re opening iCal to import a stranger’s contact info when you just wanted to read their blog. So, I took that bit out, though I suppose I could make it optional. So, instead, it links to the base URL itself.

I do like the idea of a convention for everyone to expose their “about me” info, along with their favatar and contact info and favorite services, at some dereferenceable URL… a portable profile. Maybe I’ll play with that in some later version.

For now, I’ll see if anyone picks up on this and creates their own favatar.png image. I’ll be tickled pink if someone comments on this post and uses their newly minted favatar.

by Schepers at August 10, 2010 12:14 AM

August 09, 2010

Doug Schepers

Short Stuff


I’ve been doing a lot of website stuff this week. Here’s some highlights:

W3C Working Group Sites

A few weeks ago, after long neglect, I finally updated the SVG WG page with a template that better matches the new(ish) W3C site redesign. Each working group has its own eclectic home page, which seems a bit silly to me. So, I took the template I made and converted the group pages of the WebApps WG, SVG Interest Group, and FX Task Force, and I’m talking with other W3C team contacts about converting theirs as well, though we’ll see how many switch over. From my perspective, having a consistent look&feel is important, and would make the W3C site more usable.

The new template I made is done in HTML5, with the <header>, <footer>, <article>, <section>, <aside>, and <nav> elements (and a reference to Remy Sharp’s HTML5 shiv), possibly even used correctly; the SVG WG page has a scripted live microblog feed from the @svgwg Twitter account, and an inline SVG easter egg (look for it in Firefox and WebKit nightlies).

Short Notice

I have been wanting to write or install a URL shortener on my own site for a while, so I didn’t have to rely on the brittle third-party services like TinyURL, which I feel don’t fit the spirit of the Web. They obscure the link, and act as a massive throttling point. I looked around a bit before for a custom URL shortener, but never found one that suited my fancy.

But on Saturday, after converting my URLs to have nicer, more meaningful, more RESTful names on the advice of the ever-helpful Helder Magalhães, I was in a mood to tackle the problem, and I found a great summary of some of the options by a fellow named Eric Severance. He described a better list of criteria than I’d considered, and I went with his top pick, Pretty Link by Blair Williams.

Despite the silly name, Pretty Link has almost all the features I wanted and then some. It’s easy to use, it integrates into my WordPress blog, it lets me pick a meaningful shortname, and I can shorten not only my own blog’s URLs (lots of WP plugins let you do that), but any random URL I want; it even tracks how many people have followed the links, which to me is mildly interesting, but for people more into their brand would be very handy. The only thing I’d like to see is a way to automatically publish a public page that lists all the shortened URLs and the title of each page, along with the expanded original URL; maybe I can hack that in, somehow (and maybe I just haven’t found it yet). Just for posterity, I compiled a list of all the links I had tweeted before, and dereferenced them, which you can find on my expanded URLs page.

Commenter Avatars

I’m playing a bit with my site theme. I’m happy with it overall, but I think the column width could be a bit wider; I’ve already bumped up the font size. I want to enable nested comment threads, because I think they are easier to read, but I’ll need to overhaul my theme quite a lot to do so, since it’s from an older version of WordPress.

In the meantime, I added commenter avatars. The default image is a Gravatar; as with TinyURL, I don’t like artificial centralization in avatars, and in this case, it seems particularly silly. So I cobbled together my own WordPress plugin to take an alternative approach, which I’ll blog about next time.

by Schepers at August 09, 2010 04:39 AM

August 02, 2010

Web Tech Blog

Determining with absolute accuracy whether or not a JavaScript object is an array

Typing problems in JavaScript

JavaScript’s typeof operator is well known to have confusing behavior: typeof null === "object", and typeof null !== "null". This mistake trips up newcomers, and every so often it’ll trip up a seasoned yet forgetful veteran, but we’ve basically grown used to it. Perhaps more important, there’s a failsafe workaround: simply compare directly as v === null to eliminate null from the possibilities under consideration.

Determining whether a value is an array

typeof null === "object" is perhaps the most common typing mistake in JavaScript, but there are others as well. A much less common but no less confusing problem is that of determining whether an object is an array. Surely, say you, this is a simple problem with a simple solution, like so:

if (o instanceof Array)
{
  // Oh frabjous day!
}

Under certain circumstances, the above code is perfectly functional; considering the history of the web, it’s not surprising the issue wasn’t quickly apparent. The problem arises when one considers an aspect of JavaScript in browsers not contemplated by ECMAScript: multiple globals.

The ECMAScript specification describes the environment and mechanisms involved in executing a string of code. The syntax and basic semantics of language constructs are certainly important, but without the built-in methods and objects coding in ECMAScript wouldn’t be much fun. These methods and objects are accessed through the global object, and it is here where things go astray. The ECMAScript 3 environment implicitly assumes the existence of a single global (or, perhaps, of islands each of which is its own environment, with no interaction between them) and does not in any manner address the idea of multiple globals.

Multiple globals, however, are fundamental to the browser; each window object is the global object for the scripts its page contains or references. What about arrays in different windows? The shared-mutation hazard of having arrays in two coordinating windows be instances of the same Array constructor, sharing the same Array.prototype, is enormous when either page augments Array.prototype (not to mention the security problems when one page is malicious!), so Array and Array.prototype in each window must be different. Therefore, by the semantics of instanceof, o instanceof Array works correctly only if o is an array created by that page’s original Array constructor (or, equivalently, by use of an array literal in that page). Pfui.

Are there any other methods of determining whether a value is an array that might work around this? o.constructor === Array is one, with the same problem as an instanceof check. Another option relies on so-called “duck typing”, where if a value quackslooks like a duckan array then it is a duckan array. Along the constructor-checking lines, you could check for other array methods like push or concat, or perhaps for a length property, but these properties could exist in the same fashion on a non-array object. If you’re willing to have false positives and negatives (assuming unconstrained input) that might be acceptable, but of course that won’t always be the case. One test in this style is Object.prototype.toString.call(o) === "[object Array]", but that relies on Object.prototype.toString and Function.prototype.call not being changed (probably a good assumption but still fragile). It’s also a bit more of an obvious hack than any of the other ideas.

Enter Array.isArray

For these reasons, ECMAScript 5 defines a method, Array.isArray, to completely address the problem. If the first argument provided is an array object created in any window at all, it returns true; if no arguments were provided or if the first argument wasn’t an array object, it returns false.

function test(fun, expect) { if (fun() !== expect) alert("FAIL: " + fun); }
test(function() { return Array.isArray([]); }, true);
test(function() { return Array.isArray(new Array); }, true);
test(function() { return Array.isArray(); }, false);
test(function() { return Array.isArray({ constructor: Array }); }, false);
test(function() { return Array.isArray({ push: Array.prototype.push, concat: Array.prototype.concat }); }, false);
test(function() { return Array.isArray(17); }, false);
Object.prototype.toString = function() { return "[object Array]"; };
test(function() { return Array.isArray({}); }, false);
test(function() { return Array.isArray({ __proto__: Array.prototype }); }, false);
test(function() { return Array.isArray({ length: 0 }); }, false);

var w = window.open("about:blank");
w.onload = function()
{
  test(function() { return Array.isArray(arguments); }, false);
  test(function() { return Array.isArray(new w.Array); }, true);
};

Does this method provide any additional functionality beyond the hacks? One important use is for implementing variadic methods. Consider, for example, MochiKit’s MochiKit.Base.flattenArray method, whose documentation states that it:

Return a new Array consisting of every item in lst with Array items expanded in-place recursively. This differs from flattenArguments in that it only takes one argument and it only flattens items that are instanceof Array.

If you happen to be writing JavaScript that crosses window boundaries passing around arrays, you’re out of luck trying to use flattenArray. From the MochiKit interpreter, note the instanceof Array check, with a little reformatting:

>>> MochiKit.Base._flattenArray.toSource()
(function (res, lst) {
  for (var i = 0; i < lst.length; i++) {
    var o = lst[i];
    if (o instanceof Array) {
      arguments.callee(res, o);
    } else {
      res.push(o);
    }
  }
  return res;
})

This is currently cross-window FAIL. :-) MochiKit can’t actually implement exactly what a strict reading of its documentation would claim. Using Array.isArray with a feature-detection guard, however, will make it work correctly on arrays not from the window in which MochiKit.Base is being used.

It’s worth noting that MochiKit’s not the only framework out there that tries to hackily determine whether a value is an array. Dojo, for example, has dojo.isArray with similar limitations, and I suspect this is a common problem across many JS codebases.

When can I use it?

Technically, the answer to this question is: as soon as you want! The usual feature-testing for Array.isArray allows you to use this method if it exists and ignore it if it doesn’t. You will be able to meaningfully use it, however, starting with Firefox 3.6. WebKit nightlies have also added support for it, so it will presumably be in future Safari and Chrome releases. I don’t know about other vendors, but Array.isArray‘s utter triviality to implement (it was a 15-line patch for Mozilla with no complexity whatsoever, and a good bit of that was SpiderMonkey coding idioms) suggests that if you ask, they will provide.

Acknowledgements

I found this article helpful in examining some of the hacks to determine whether or not an object is “most likely” an array.

by Jeff Walden at August 02, 2010 08:10 AM

July 27, 2010

roc

Unexpected Downtime

I seem to have picked up some sort of virus. I'm mostly offline while I wait for this to clear up. Please forgive any delays...

by roc (rocallahan@novell.com) at July 27, 2010 05:40 AM

July 26, 2010

Web Tech Blog

Firefox 3.1 beta 1 – an overview of features for web developers

Firefox 3.1 Beta 1 is out and with it comes a huge pile of new features for developers. While those of you who follow Mozilla’s web-tech blog might know about some of them we thought that with the release of the first beta of 3.1 that it would be good to try to summarize just some of the bigger features for web developers that are part of this beta.

Note: the Firefox 3.1 for Developers page in the wiki is the canonical source for new features in Firefox 3.1.

Geolocation

Mozilla has implemented the draft spec for Geolocation.  Geolocation is a JavaScript API that lets a web page query the browser’s location via JavaScript. It can be used to plot maps, give directions, attach location information to pictures, give a location for a weblog post and a pile of other things.

Geolocation Screenshot

The Geolocation API in Firefox 3.1 exposes a single API to web developers, but can potentially be backed by a number of different location sources.  Examples include the Skyhook service, which guesses your location based on nearby access points, a GPS device in your mobile computer or hand-setting a fixed location where your desktop lives.  Developers who want to write a location provider for Firefox need to implement the nsIGeolocationProvider as part of a component and include it as an extension.

People who want to try out Geolocation in Beta 1 can install Doug Turner’s Geolocation add-on which adds a fixed Geolocation provider. Once you’ve installed it you can visit http://whatismygeolocation.com/ to get your location and update the preference in Tools -> Add-ons -> Geolocation with your latitude and longitude.  There are a number of examples of the API you can try on the Geode Labs Welcome page.

Mozilla Labs recently announced Geode, which is an extension that adds Geolocation support to Firefox 3. Geode added one type of Geolocation support to Firefox 3, based on Skyhook, and was built only as an example.  Aza Raskin recently did a post on the differences.  Geode and the Geolocation support in Firefox 3.1 should be API compatible and the end-user experience should be the same.

Geolocation is pretty hot right now and it will be great to see what people do once this is added directly to the browser.

@font-face

One of our most widely-request features is to add support for the CSS @font-face property. This property allows you to specify a true type font file that includes a specific font you want to use to render a web page. This is important not only for designers to get more consistent formatting and layout, but is also important to web developers for non-english websites who often have users that may or may not have access to high-quality fonts. Beta 1 includes support for @font-face.

Right now the fonts must be located at the same origin as the page that includes it.

@font-face support is implemented for Windows and Mac, but not for Linux. Linux support is underway and will be done by Firefox 3.1 final.

Video and Audio

This is the first beta from Mozilla to include support for the <video> and <audio> elements. This beta includes support for the OGG Theora and OGG Vorbis formats on all platforms. There are quite a few free tools for encoding to OGG Theora and OGG Vorbis. We are also working on backend support for GStreamer for Linux, QuickTime for Mac and Windows Media for Windows. However it’s not clear if those backends will land before 3.1 final is ready.

Our goal with adding support for audio and video has been to make it as easy to post a video as it is to post an image. Along with that ease of use being able to mix audio and video elements with other rich media elements such as <canvas>, SVG and super-fast JavaScript means that we’re able to get video out of the plugin prison and let it interact with the rest of the content on pages. This is a huge step forward for the web.

This beta has quite a few unimplemented features, as noted in the developer pages for audio and video, but fixes for many of those missing features will land before 3.1 final.

Chris Double has created a site with a bunch of sample videos up on it.

XHR Progress Notification

We’ve added a better way to get progress notifications for XML HTTP Requests. We’ve implemented the W3C Draft Spec on progress events. In Firefox 3 the events available on the XHR object were progress, uploadprogress, load, abort and error. For 3.1 we now support the loadstart, progress, load, abort and error events. (uploadprogress is also supported, but is deprecated.)

There’s a great example of the new progress events by Olli Pettay. It’s very simple and does everything in a single script.

XHR Cross-site Access Control

We’ve implemented the draft specification for access-control for cross-site requests.  Web developers have long wanted to be able to get data from one site on another but same-origin restrictions on many types of requests prevent many developers from mashing up content.  This new access control mechanism offers the ability for servers, content and web clients to cooperate to make a lot of new things possible on an opt-in basis.  The spec is complex, and support is new, so if you’re interested reading the spec is probably the best thing to do.  It contains examples and uses cases.

TraceMonkey

Beta 1 does include TraceMonkey, our super-fast JavaScript engine, but it’s not turned on by default.  If you do want to turn it on, go to about:config, set javascript.options.jit.content to True, restart your browser and try it out.

This is an early beta, of course, so there will be issues. Please file bugs if you find sites that don’t work or cause crashes or hangs. The more testing we get, the better it will be when we turn it on.

And more…

There are several other features that are scheduled for Firefox 3.1 Beta 2 and are partially implemented in this beta that we’ll talk about more once Beta 2 is available.  Some of the things you can expect are Worker Threads for JavaScript, new graphics, SVG and CSS capabilities and probably other things as well. The Firefox 3.1 for Developers page is the full source for new stuff that’s coming for 3.1 and it’s size tells the full tale of everything that’s new.

So stay tuned – we’ve got lots of new stuff coming up for Firefox 3.1!

by Christopher Blizzard at July 26, 2010 04:42 PM

Web Workers, Part 2

Firefox Beta 2 is due out very shortly, and with it comes some significant changes to Web Workers.

First, we’ve moved away from the old Gears-esque API that we had in Alpha 2 (see previous post) in favor of the emerging Web Workers standard. We’ve been hard at work with folks from Google, Apple, and others to get this new spec nailed down.

Most of the missing features I identified in Part 1 have been added with the exception of auto-JSON. There will be a very few small changes between Beta 2 and Firefox 3.1 final (most of which have already landed) and I’ll post about those again once we’re close to shipping.

So what’s available in Beta 2? We currently implement this subset of the Web Workers spec. Very briefly, creating a new worker is as simple as adding the following line to your web page’s script:

var worker = new Worker("workerScript.js");

Your workerScript.js file can do almost anything, really, including using XMLHttpRequest, importing additonal scripts, spawning new workers, setting timeouts/intervals, and passing complex messages via JSON. Further information can be found in Using DOM Workers.

And, in case anyone is interested in a more real-world example, I ported Chris Double‘s JavaScript 8080 emulator to use Workers. The nice thing about using workers here is that all the actual emulation is happening on a background thread (or, on my machine, a second CPU). Keystrokes are sent as messages to the emulator thread and then emulator sends screen updates back (all using JSON). It also uses the importScripts function to load Chris’s hosted files rather than having to copy them around. Note that I didn’t bother with very serious error checking so unless you’re using Firefox 3 Beta 2 or newer then it most likely won’t work at all. Check it out here.

by Ben Turner at July 26, 2010 04:41 PM

Firefox 3.1 Beta 2 – what’s new?

Just as we did for Firefox 3.1 Beta 1, we thought it would be good to give an overview of what’s changed in Beta 2 for web developers and add-on authors, as well as cover some stuff we didn’t include in the Beta 1 overview.

Stable for Add-ons Updates

First and foremost, Firefox 3.1 Beta 2 should be stable enough for add-ons developers to start updating their add-ons for 3.1 compatibility.  There will be a 3rd beta, but in between B2 and the RCs we will avoid changes that affect add-ons.

You can see more information about the status of add-ons at our compatibility page, the Updating Extensions for Firefox 3.1 page and the Firefox 3.1 for Developers page.  If you’re an add-ons developer we strongly suggest that you follow the Mozilla add-ons weblog and subscribe to the about:addons newsletter.

We’re hoping that with Beta 3 and the first RC release that we’ll have enough add-ons migrated that users will be able to migrate with little discomfort.

TraceMonkey: It’s On

The super-fast TraceMonkey JavaScript engine is now on by default in Beta 2.  Stability and performance are improved over Beta 1.  Please try it out and report bugs if you find sites that have stopped working with TraceMonkey enabled.

DOM Worker Threads

More and more people are using the web for CPU-intensive applications, including doing a lot of that computation on the client.  However, writing a CPU-intensive JavaScript application would often block the UI of the web app from updating while a specific computation was taking place.  This is because there is only one thread of execution for a particular web page so calls into JavaScript would often block changes or updates to the UI.

In Firefox 3.1 we’re including “DOM Worker Threads” based on a recent draft spec.  This allows you to move JavaScript execution for a discrete chunk of code from the UI thread to another thread of execution.  This means that while a long-running piece of code is executing your web app can do other things and the UI will continue to operate normally.

We have an article up on the Mozilla Developer Center on DOM Worker Threads.  It contains an overview of the new top level Worker object and examples of working code.  Ben Turner also posted an update on what’s included in Beta 2 in a recent post to web-tech.

Audio and Video Improvements

Support for <audio> and <video> have improved in Beta 2.  There is now support for duration-related events as media is downloaded.  Please see the article on using audio and video on the Mozilla Developer Center for more information about events.

In addition to support for OGG Theora and OGG Vorbis there’s a new <audio> backend for .wav files, as required by the spec.

Note that the built-in controls in Beta 2 for <video> don’t include a duration slider.  The underlying mechanisms support it, but the UI does not.  This is something that will be fixed before final release.

DNS Pre-fetching

Firefox 3.1 Beta 2 now does DNS pre-fetching for resources as they are loaded on a page.  Pre-fetching can reduce the time it takes to load a page by pre-loading DNS lookups early in a page load.  When external resources are loaded the browser doesn’t have to wait for the round trip for a DNS lookup to complete before starting the HTTP request, which reduces the overall page load time.  Pat McManus has a blog post about the new feature.

XHR Cross-site Access Control

It was mentioned in the Beta 1 notes, but we’ve implemented more of the new Access Control for Cross-Site Requests specification from the W3C.  This functionality allows Firefox to make XMLHttpRequest (XHR) calls across sites, much like how images and scripts can be loaded from different sites today.  However, unlike calls that load images and scripts, the XHR requests are done such that servers must participate for complex calls that share certain kinds of data in order to protect both users and servers.  This potentially allows for some really interesting data mashups to take place on the web with Firefox.

We have two documents up that describe this functionality in Beta 2.  First, you can look at the HTTP Access Control document in the Mozilla Developer Center.  This is an overview of the client side parts that make up Access Control for XHR.  The second document is a Server-Side Access Control document that gives examples of PHP that you can use to enable some of the more complex access control functionality on your server.

@font-face Changes

The new @font-face functionality that we included in Beta 1 now uses the same access control mechanisms as XMLHttpRequest.  If you want to load a font from a server other than the origin server, the server must choose to participate and explicitly permit the browser to load the font.

Private Browsing

Private Browsing is now included in Beta 2.  This affects add-ons developers more than web developers and is worth a mention.  Add-ons that save data on the user’s machine should also respect the user moving in and out of private browsing mode.  Ehsan Akhgari has made a post in his weblog about what’s required of add-ons developers in order to support private browsing mode.  If you’re an add-on developer it’s worth reading.

by Christopher Blizzard at July 26, 2010 04:41 PM

Web Workers, Part 3

Beta 3 marks the end of the worker changes we expect for Firefox 3.1, so here’s a rundown of what has changed since Beta 2:

  1. The navigator object has been added to the worker scope. It contains the following strings that identify the browser, just as from normal script:
    • appName
    • appVersion
    • platform
    • userAgent
  2. Workers can now be forcefully killed via the terminate function. Calling this function on a worker will immediately stop the worker’s execution.
  3. Workers may only be created from a worker script that is hosted within the same origin as the parent page.
  4. URIs for subworker scripts and imported scripts are now resolved relative to the parent worker script location instead of the owning page.
  5. Error handling has been reworked according to recent spec changes. A worker script can now define an onerror handler that will be called with an error event with details about the exception. If the handler calls preventDefault on the event object then nothing else happens. If preventDefault is not called then the error event propagates to the parent scope’s (either a worker or the parent page) onerror handler.
  6. Numbers, booleans, and even objects may be passed to postMessage in addition to strings. The only restriction is that objects may not contain functions or cyclical references (since we use JSON under the hood). This simplifies previous code that needed to use the JSON object to manually encode/decode the strings passed to postMessage.

To illustrate some of these new features I decided to use workers to decrypt Weave user data (bookmarks, cookies, etc.). Using some code that Anant Narayanan created a while ago for the 0.2 version of the Weave server (which is deprecated, by the way – the 0.3 server has recently emerged!) I created an app that works on real data that I copied from services.mozilla.com. Check it out here, but make sure that you’re using the latest branch nightly (or Beta 3 as soon as it is available). And many thanks to Dan Mills for helping me get this all working.

Continue on to the full post to see how it works.

Weave data decryption requires a username and a private key passphrase. If the data still lived on the services.mozilla.com server it would also require a server password, but I didn’t go that far for this demo. All user data is encrypted with a private key that is itself encrypted, so decrypting the private key must be the first step. After the private key is decrypted then all requested user data is tackled independently and in parallel. For details about the way Weave stores user data please see this excellent post by Atul Varma.

First, the page collects username, password, and server information, as well as the types of user data that should be decrypted. It then spawns the main worker. This worker spawns a subworker to decrypt the private key, then spawns multiple workers to handle each type of user data. Subworkers are used so that the process can be canceled at any time.

Here’s an overview of each file involved in the process:

  1. weaveDecryptor.html
    • Launches the main worker, weaveDecryptorWorker, and communicates the form data (username, passphrase, server location, and the types of data that should be decrypted) to it.
    • Informs the worker that it should cancel subworkers if the Cancel button is pressed.
    • Updates the UI as messages are received from the worker.
  2. weaveDecryptorWorker.js
    • Launches the keyDecryptor subworker to decrypt the user’s private key.
    • Once the private key has successfully been decrypted it launches a dataDecryptor subworker for each type of weave data that was requested.
    • Maintains a list of currently running workers so that they can be canceled.
    • Also maintains some state, like a cached copy of the decrypted private key and whether or not the passphrase was correct.
  3. keyDecryptor.js
    • Username and passphrase info is passed into the worker from the parent.
    • Decrypts the user’s private key and sends the key bits back to the parent.
  4. dataDecryptor.js
    • The parent passes in the private key bits and the type of data that should be decrypted.
    • Decrypted data is passed out to the parent.

by Ben Turner at July 26, 2010 04:09 PM

The Indeterminator – A new checkbox type

If you do any web development, chances are you know checkboxes and radio buttons can have two states: checked and unchecked. But in the case of checkboxes, you may want to indicate to the user that they are half-way between those states, for example when you have a master checkbox above many other checkboxes of singular items. This is now possible on Trunk (Firefox 3.2) thanks to the implementation of the HTML5 “indeterminate” DOM property. All it takes is a bit of script:

document.getElementById(“check1″).indeterminate = true;

And you can use this third state on your checkbox:

indeterminatedemo

So that’s three-quarters of his rant ready for the bin ;) As for the CSS3 :indeterminate pseudoclass, we don’t support that at this stage but it doesn’t look hard so it will probably take me less than a day to do. In the meantime, happy Waitangi Day!

by Michael Ventnor at July 26, 2010 04:09 PM

Native JSON in Firefox 3.1

[ Note: this was original posted to the webdev blog by Ryan Doherty.  Re-posted here with his permission. ]

In case you haven’t heard, one of Firefox 3.1’s awesome new features will be native JSON support. This is totally sweet for two reasons:

  1. eval’ing JSON in the browser is unsafe. Using native JSON parsing protects you against possible code execution.
  2. Safely eval’ing JSON with a 3rd party library can be orders of magnitude slower. Native JSON parsing is much faster.

How does native JSON work compared to plain old eval? Simple:

var jsonString = '{"name":"Ryan", "address":"Mountain View, CA"}';
var person = JSON.parse(jsonString);
// 'person' is now a JavaScript object with 2 properties; name and address

Pretty easy huh? And here’s how to get a JSON string from an object:

var personString = JSON.stringify(person);
// 'personString' now holds the string '{"name":"Ryan", "address":"Mountain View, CA"}'

“But wait!”, you say. “How is it safer? How much faster is it compared to eval?”. Ok, I’ll show you.

Native JSON parsing in Firefox 3.1 is safer because it does not support objects with functions. Attempting to convert an object with functions into a JSON string will only convert its properties and not its functions. And any malformed JSON string will result in a parse error instead of possible code execution.

Now, regarding speed, native JSON parsing is faster, much faster. Instead of pretty charts and graphs, I’ll give you a real-world example.

The new Graph Server uses a JSON API to fetch test information and results, so I figured it would be a good application to benchmark. So I wrapped our code that parses the JSON response with some Firebug profiler calls:

    console.time('parsejson');
    var obj = eval('(' + resp + ')');
    console.timeEnd('parsejson');

Loading a test’s results (array with 3,000 indexes, 24k gzipped) gave me a time of 125ms. (Repeated tests yielded results +/- 5ms). Then I changed eval to JSON.parse:

    console.time('parsejson');
    var obj = JSON.parse(resp);
    console.timeEnd('parsejson');

Which resulted in an average time of 40ms! That’s about 2.7 times faster with 1 line of code changed. Not bad!

Granted, a difference of 80ms isn’t that much, but in an AJAX (or, more accurately, AJAJ?) application, it can add up.

What’s the use of native JSON if it’s only available in Firefox? Luckily, IE8 has implemented it in RC1, which is rumored to be released in March. Hopefully other browsers will follow suit too, but for now it’s best to use a JSON parser such as the one on json.org. It’s small, safe and will not override native JSON implementation if detected.

Points to remember:

  • Plain old eval is unsafe (especially if you don’t trust the source), use a JSON library to protect yourself.
  • Use native JSON when available.
  • Bug other browser vendors to implement native JSON

by Christopher Blizzard at July 26, 2010 04:08 PM

Object and array initializers should not invoke setters when evaluated

Back in the day when everything was more hardcore, a website that needed to request data outside of a page load typically did so using XMLHttpRequest and translation of the requested data from an XML DOM or from a custom format into internal data structures. The translation involved either cumbersome DOM APIs or custom parsing code — much tedium either way. The invention of JSON simplified this process considerably by cutting out the DOM and custom parsing code, reducing data interpretation to simple inspection of JavaScript objects.

The JSON format, however, has the characteristic that its syntax is nearly that of a JavaScript program. As a consequence JSON is more than just data: it’s code that can be unsafely executed by eval or by sourcing it like you would any other JavaScript file.

Of course, then, it’s best practice to sanity-check any JSON string’s syntax before evaluating it to avoid evaluating embedded expressions. As it turns out, tho, even this isn’t quite sufficient in most browsers today due to an extension to JavaScript present in most browsers today — setters. Setters provide a way for JavaScript properties to be more than just making a property with a given value exist on an object. They allow extra actions (such as validation of a value) to be performed at the same time. For example, consider this partial implementation of an object to represent a customer during account registration for a site:

function Customer()
{
  this._phoneNumber = "000-000-0000";
}
Customer.prototype.__defineSetter__("phoneNumber", function(phoneNumber) {
  if (!/^\d\d\d-\d\d\d-\d\d\d\d$/.test(phoneNumber))
    throw new Error("invalid phone number provided for customer: " + phoneNumber);
  return this._phoneNumber = phoneNumber;
});

var c = new Customer();
c.phoneNumber = "555-555-2368";

The phoneNumber property on any Customer object is magical and will verify that the format of the number being specified matches the standard American telephone number format. It’s a convenient (and familiar, since many DOM properties work already work in exactly this manner) syntactic sugar for a method call.

Here’s where it starts to get interesting: what if we don’t just define setters on individual objects but rather define them on all objects? Specifically, let’s see what happens if we put a setter on Object.prototype:

/*
Copy the following URL to test in your browser:
data:text/html,%3Cscript%3Ealert(%22start%22);%20Object.prototype.__defineSetter__(%22foo%22,%20function(v)%20{%20alert(%22setting%20foo%20to%20%22%20+%20v);%20});%20var%20o%20=%20{%20foo%3A%2017%20};%20alert(%22finish%22);%3C/script%3E
*/
alert("start");
Object.prototype.__defineSetter__("foo", function(v) { alert("setting foo to " + v); });
var o = { foo: 17 };
alert("finish");

In the most recent releases of most browsers (Internet Explorer being the notable exception as it doesn’t support __defineSetter__) that link should result in three separate alerts, not two.

Now pretend you’re malicious and combine setters with cross-site JSON. You can’t use XMLHttpRequest to get the data (at least not without cross-site XHR), so what cross-site script “vulnerability” will you exploit to load and evaluate the JSON, then using setters to steal the data therein? This one’s easy: the script element! In fact this has attack has already been done against Twitter, with the result being that any site could find out who your friends are and what they’re doing if you use Twitter — not cool.

Setters are incredibly useful, and they’re being added to the next version of ECMAScript (the skin-disease-sounding industry standard on which JavaScript is based) in a somewhat different form from that demonstrated here, so not supporting setters is off the table. However, it’s a safe bet to say that when most developers write var x = { bar: 42 };, they expect to get back a plain old object with a bar property whose value is 42 and not call any functions while doing it. What if we made the implicit property sets in object and array initializers ignore setters? (Note, however, that evaluating the property’s value might still have side effects.) In fact this is what the next version of ECMAScript will specify — and it’s what Firefox 3.1 beta 3 and 3.5 beta 4 already do and what the eventual release of Firefox 3.5 will do. By making initializers ignore setters, Firefox 3.5 will make browsing sites that serve JSON in this matter just a little bit safer.

by Jeff Walden at July 26, 2010 04:08 PM