<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Ash Searle's Blog &#187; Browsers</title>
	<atom:link href="http://hexmen.com/blog/category/browsers/feed/" rel="self" type="application/rss+xml" />
	<link>http://hexmen.com/blog</link>
	<description>On programming, and other things...</description>
	<lastBuildDate>Mon, 03 Jan 2011 16:21:36 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Fixing Firebug&#8217;s Style&#160;Tab</title>
		<link>http://hexmen.com/blog/2006/12/fixing-firebugs-style-tab/</link>
		<comments>http://hexmen.com/blog/2006/12/fixing-firebugs-style-tab/#comments</comments>
		<pubDate>Mon, 11 Dec 2006 10:13:40 +0000</pubDate>
		<dc:creator>Ash</dc:creator>
				<category><![CDATA[Browsers]]></category>
		<category><![CDATA[CSS]]></category>

		<guid isPermaLink="false">http://hexmen.com/blog/2006/12/fixing-firebugs-style-tab/</guid>
		<description><![CDATA[Some users upgrading to the new Firebug Beta are having problems using the <strong>Style</strong> tab.  There is a short three-step procedure for fixing the problem, described here.]]></description>
			<content:encoded><![CDATA[<p>Lots of people are unable to use the <strong>Style</strong> tab in the new <a href="http://www.getfirebug.com/downloads.html" title="Download Firebug at www.getfirebug.com">Firebug</a> beta.  The <a href="http://getfirebug.com/faq.html">Firebug FAQ</a> leads to a thread suggesting this fix:</p>
<ol>
<li>Uninstall Firefox</li>
<li>Delete the (left-over) install folder (e.g. <code>C:\Program Files\Mozilla Firefox</code>)</li>
<li>Reinstall Firefox using a <em>custom install</em> (to ensure the DOM Inspector is installed</li>
</ol>
<p>Knowing that I already had the DOM Inspector installed, I thought I&#8217;d try removing just a few files, instead of the whole install folder.  Whatever I did worked, and the <strong>Style</strong> tab works for me now.  This more conservative procedure is:</p>
<ol>
<li>Uninstall Firefox</li>
<li>Delete only the named <code>inspector</code>* in <code>C:\Program Files\Mozilla Firefox\components</code>
</li>
<li>Reinstall Firefox using a <em>custom install</em> (to ensure the DOM Inspector is installed</li>
</ol>
<p>I&#8217;m not sure whether the uninstall and reinstall procedure is strictly necessary, so I&#8217;m hoping someone out there can try this:</p>
<ol>
<li>Stop Firefox</li>
<li>Delete all files named <code>inspector</code>* in <code>C:\Program Files\Mozilla Firefox\components</code>
</li>
<li>Restart Firefox</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://hexmen.com/blog/2006/12/fixing-firebugs-style-tab/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Array push and pop: a complete embarrassment for&#160;JavaScript</title>
		<link>http://hexmen.com/blog/2006/12/push-and-pop/</link>
		<comments>http://hexmen.com/blog/2006/12/push-and-pop/#comments</comments>
		<pubDate>Wed, 06 Dec 2006 12:00:49 +0000</pubDate>
		<dc:creator>Ash</dc:creator>
				<category><![CDATA[Browsers]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://hexmen.com/blog/2006/12/push-and-pop/</guid>
		<description><![CDATA[Most JavaScript libraries include trivial implementations of Array's <code>push</code> and <code>pop</code> methods to provide support for older browsers.  With no exaggeration, <em>every implementation is flawed</em>.  While this is quite damming, I've discovered something worse: <em>not one browser implements push and pop correctly</em>.  Each browser has its own bugs: Internet Explorer's methods can't be reused; Safari has type-conversion issues; Firefox &#38; Opera don't truncate Arrays properly.

Seven years after the publication of the <a href="http://www.ecma-international.org/publications/standards/Ecma-262.htm">ECMAScript Language Specification</a>, shouldn't we expect a little more?  In this article, I'll document the current problems, and show how to write implementations that conform precisely to the language spec'.]]></description>
			<content:encoded><![CDATA[<p>Most JavaScript libraries include trivial implementations of Array&#8217;s <code>push</code> and <code>pop</code> methods to provide support for older browsers.  However, literally <em>every</em> library&#8217;s implementation is flawed.  While this is bad enough, I&#8217;ve also found that <em>every browser&#8217;s implementation of push and pop contains bugs</em>.  These vary from browser to browser: Internet Explorer&#8217;s methods can&#8217;t be reused; Safari has type-conversion issues; and Firefox &amp; Opera don&#8217;t truncate Arrays properly.</p>
<p>It&#8217;s been seven years since the publication of the <a href="http://www.ecma-international.org/publications/standards/Ecma-262.htm">official ECMAScript Language Specification</a>, and I think we should expect a little more from our browsers.  In this article, I&#8217;ve documented the current problems, and I show how to write library implementations conforming precisely to the language spec&#8217;.<span id="more-13"></span></p>
<h3>JavaScript Implementation</h3>
<p>Here are my functions (the <code>&gt;&gt;&gt;</code> operator is explained later in the article):</p>
<pre><code class="javascript">Array.prototype.push = function() {
    var n = this.length &gt;&gt;&gt; 0;
    for (var i = 0; i &lt; arguments.length; i++) {
	this[n] = arguments[i];
	n = n + 1 &gt;&gt;&gt; 0;
    }
    this.length = n;
    return n;
};

Array.prototype.pop = function() {
    var n = this.length &gt;&gt;&gt; 0, value;
    if (n) {
	value = this[--n];
	delete this[n];
    }
    this.length = n;
    return value;
};
</code></pre>
<p class="download">Download: <a href="/code/push-pop.js">push-pop.js</a></p>
<h3>Testing</h3>
<p>Always up for a challenge, I&#8217;ve tried to produce a bug-free implementation that conforms to the specification.  You can see how it fares on my <a href="http://hexmen.com/tests/pushpop.html">push and pop test page</a> <ins datetime="2007-01-03T17:47:12+00:00">(fixed link)</ins>.  The test page allows you to compare several library implementations to the browser&#8217;s built-in implementation, and mine.  There are about thirty tests in all, and you should find that even the browser&#8217;s implementations fail a couple of tests (some fail substantially more.)</p>
<p>So, why the high failure rate?  Simple: most browsers haven&#8217;t implemented arrays correctly; their understanding of an <em>array index</em> and <code>length</code> is wrong.  From the specification (section 15.4):</p>
<blockquote><p>A property name <em>P</em> (in the form of a string value) is an <em>array index</em> if and only if ToString(ToUint32(P)) is equal to P and ToUint32(<em>P</em>) is not equal to 2<sup>32</sup>−1.  Every Array object has a <code>length</code> property whose value is always a non-negative integer less than 2<sup>32</sup>. The value of the <code>length</code> property is numerically greater than the name of every property whose name is an array index; whenever a property of an Array object is created or changed, other properties are adjusted as necessary to maintain this invariant. Specifically, whenever a property is added whose name is an array index, the <code>length</code> property is changed, if necessary, to be one more than the numeric value of that array index; and whenever the <code>length</code> property is changed, every property whose name is an array index whose value is not smaller than the new length is automatically deleted. This constraint applies only to properties of the Array object itself and is unaffected by <code>length</code> or array index properties that may be inherited from its prototype.</p></blockquote>
<p>In simplified terms: array indexes are integers in the range [0, 2<sup>32</sup>-2], and the array <code>length</code> can take any integer value in the range [0, 2<sup>32</sup>-1] (both ranges start at 0, but end at different values.)  The <code>length</code> of an array is greater than any set <em>array index</em>; if the <code>length</code> is set explicitly, all array indexes &ge; <code>length</code> are deleted.</p>
<h3>Bugs</h3>
<ul>
<li>setting an array <code>length</code> to a non-integer value, a negative value, or an integer &ge; 2<sup>32</sup> should cause an error to be thrown.  Firefox is the only browser to get this right &#8211; Safari, Opera and Internet Explorer all fail this test (I called this test, unimaginatively, <code>testArrayLength</code>)</li>
<li>truncating an array doesn&#8217;t always cause the right array values to be deleted in Firefox (<code>testArrayTruncation</code>)</li>
<li><code>length</code> is updated incorrectly in certain circumstances in Firefox, Safari and Opera (<code>testArrayLengthMagic</code>)</li>
</ul>
<p>Now we&#8217;ve established that every browser has at least one problem with arrays, let&#8217;s look at the specification of push:</p>
<blockquote><p>
<b>15.4.4.7 Array.prototype.push ( [ item1 [ , item2 [ , … ] ] ] )</b><br />
The arguments are appended to the end of the array, in the order in which they appear. The new length of the array is returned as the result of the call.</p>
<p>When the <b>push</b> method is called with zero or more arguments <em>item1, item2</em>, etc., the following steps<br />
are taken:</p>
<ol>
<li>Call the [[Get]] method of this object with argument <code>"length"</code>.</li>
<li>Let <em>n</em> be the result of calling ToUint32(Result(1)).</li>
<li>Get the next argument in the argument list; if there are no more arguments, go to step 7.</li>
<li>Call the [[Put]] method of this object with arguments ToString(<em>n</em>) and Result(3).</li>
<li>Increase <em>n</em> by 1.</li>
<li>Go to step 3.</li>
<li>Call the [[Put]] method of this object with arguments <strong>&#8220;length&#8221;</strong> and <em>n</em>.</li>
<li>Return <em>n</em>.</li>
</ol>
<p>The length property of the push method is 1.</p>
<p><em>NOTE</em><br />
<em>The <code>push</code> function is intentionally generic; it does not require that its <strong>this</strong> value be an Array object.  Therefore it can be transferred to other kinds of objects for use as a method. Whether the <code>push</code> function can be applied successfully to a host object is implementation-dependent.</em>
</p></blockquote>
<p>And the specification for <code>pop</code>:</p>
<blockquote><p>
<b>15.4.4.6 Array.prototype.pop ( )</b><br />
The last element of the array is removed from the array and returned.</p>
<ol>
<li>Call the [[Get]] method of this object with argument <code>"length"</code>.</li>
<li>Call ToUint32(Result(1)).</li>
<li>If Result(2) is not zero, go to step 6.</li>
<li>Call the [[Put]] method of this object with arguments <code>"length"</code> and Result(2).</li>
<li>Return <code><b>undefined</b></code>.</li>
<li>Call ToString(Result(2)-1).</li>
<li>Call the [[Get]] method of this object with argument Result(6).</li>
<li>Call the [[Delete]] method of this object with argument Result(6).</li>
<li>Call the [[Put]] method of this object with arguments <code>"length"</code> and (Result(2)-1).</li>
<li>Return Result(7).</li>
</ol>
<p><em>NOTE</em><br />
<em>The <code>pop</code> function is intentionally generic; it does not require that its <b>this</b> value be an Array object. Therefore it can be transferred to other kinds of objects for use as a method. Whether the <code>pop</code> function can be applied successfully to a host object is implementation-dependent.</em>
</p></blockquote>
<p>The notes in both specifications are very important &#8211; they mean that each method must be portable, able to work in isolation &#8211; no dependence on other Array methods or properties.  Implementation should not rely on side-effects of manipulating a <code>length</code> property, nor should they use other array methods like <code>splice</code> (as seen in an unusual implementation of push and pop in <a href="http://javascript.crockford.com/remedial.html">Douglas Crockford&#8217;s Remedial JavaScript</a>).</p>
<p>It&#8217;s this requirement for independence that causes Internet Explorer to fail a whole slew of tests, and puts it at the back of the pack in terms of standards compliance. </p>
<h3>The <code>&gt;&gt;&gt;</code> operator</h3>
<p>Working through the <code>push</code> and <code>pop</code> specifications, both methods need to use type-conversion to convert arbitrary (possibly undefined) objects to unsigned 32-bit integers.  This can be done using the unsigned right-shift operator (<code>&gt;&gt;&gt;</code>), and this reveals another &#8211; trivial &#8211; bug:  IE5 and Safari fail to ignore particular white-space characters when converting strings to unsigned 32-bit integers.  It&#8217;s a minor bug, and I hope Safari can be easily fixed by the <a href="http://webkit.org/">WebKit</a> guys &#8211; Microsoft fixed this particular Internet Explorer bug when they released IE5.5. (<code>testToUint32</code>)</p>
<p>Steps 3 &#8211; 6 of <code>push</code> are a little ambiguous, and the specification probably should have stated that repeated increments to <code>n</code> must be done using 32-bit unsigned integer arithmetic &#8211; it&#8217;s kind-of implicit as <code>n</code> is assigned the result of the internal ToUint32 operator.  Using 32-bit arithmetic leads to some strange edge-cases: when <code>n</code> overflows from 2<sup>32</sup>-1 to 0, <code>push</code> will have set a property called <code>4294967295</code>.  This is strange, as <code>429496795</code> is <em>not</em> an <em>array index</em> (as discussed above), but at least it means the property-value will still be available after the inevitable array-truncation (when <code>length</code> is set to some small value in step 8.)</p>
<p>Although the specification leaves room for the occasional bit of ambiguity, and prescribes some strange behaviour as a consequence, I think it&#8217;s well put together.  On-screen, it&#8217;s not so easy to work with, but Mozilla have produced an <a href="http://www.mozilla.org/js/language/E262-3.pdf" title="Mozilla's improved ECMAScript Language Specification PDF">improved PDF</a> which includes lots of bookmarks to help navigate through the document.</p>
]]></content:encoded>
			<wfw:commentRss>http://hexmen.com/blog/2006/12/push-and-pop/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

