<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-1724694701961948570</id><updated>2011-11-24T00:30:39.507-05:00</updated><category term='faq'/><category term='javascript'/><category term='rhino'/><title type='text'>J5</title><subtitle type='html'>Twitter: &lt;a href="http://twitter.com/j5bot"&gt;@j5bot&lt;/a&gt;</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://j5bot.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1724694701961948570/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://j5bot.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>J5</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://4.bp.blogspot.com/_RMH_gNX4x5g/Sq25DsTa39I/AAAAAAAACLQ/ABSKyWUtKus/s1600-R/Photo_39.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>11</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1724694701961948570.post-3433787203977259564</id><published>2011-11-24T00:30:00.000-05:00</published><updated>2011-11-24T00:30:39.515-05:00</updated><title type='text'>Simultaneoous Background Process Monitoring in Bash using Multitail</title><content type='html'>I'm working on an installer for the development server environment we use at www.salsalabs.com&lt;br /&gt;&lt;br /&gt;There are time-consuming tasks which are part of the installation process which can be done simultaneously:  installation of program dependencies (with brew) and download of code repositories (using git).&lt;br /&gt;&lt;br /&gt;I backgrounded the first task in my installation script using the usual &amp; and let the script continue on and complete the second task "normally".  After the second task completed, a &lt;code&gt;wait&lt;/code&gt; command makes sure that the script does not proceed until the first task is also complete.&lt;br /&gt;&lt;br /&gt;That's all well and good.  It works just dandy... except that the output of these two processes is intermixed and due to each process providing feedback about the process of individual steps ... that output is very very very very very messy.&lt;br /&gt;&lt;br /&gt;So I looked for a solution and I found &lt;a href="http://www.vanheusden.com/multitail/index.html"&gt;MultiTail&lt;/a&gt;.  Awesome!  And available via &lt;code&gt;brew&lt;/code&gt;!  Awesome!&lt;br /&gt;&lt;br /&gt;Except ... I don't have log files, and I don't want to generate log files.  I want to have two different output streams and use multitail to view them simultaneously in one terminal window.&lt;br /&gt;&lt;br /&gt;Two different output streams is easy enough, we've got file descriptors for that, right?  (check out the exercise &lt;a href="http://linuxtopia.org/online_books/advanced_bash_scripting_guide/ioredirintro.html"&gt;here&lt;/a&gt;, it makes my brain hurt).  No, we need two different files that are going to act like streams.  Oh!  We want buffers!&lt;br /&gt;&lt;br /&gt;(Cue the superhero music)&lt;br /&gt;&lt;br /&gt;Here come FIFOs to the rescue!  Use the handy-dandy &lt;code&gt;mkfifo&lt;/code&gt; command and you can turn any output stream like stdout, stderr into a buffer that looks like a file to the operating system.  Yay!!!!&lt;br /&gt;&lt;br /&gt;So, our code, something like this:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;install_dependencies.sh &amp;&lt;br /&gt;install_packages.sh&lt;br /&gt;wait&lt;br /&gt;&lt;br /&gt;install_something_else.sh&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;becomes:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;mkdir /tmp/fifos&lt;br /&gt;mkfifo "/tmp/fifos/Dependencies"&lt;br /&gt;mkfifo "/tmp/fifos/Code Installation"&lt;br /&gt;&lt;br /&gt;install_dependencies.sh &gt; "/tmp/fifos/Dependencies" &amp;&lt;br /&gt;install_packages.sh &gt; "/tmp/fifos/Code Installation"&lt;br /&gt;wait&lt;br /&gt;&lt;br /&gt;install_something_else.sh&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;And we add on multitail:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;mkdir /tmp/fifos&lt;br /&gt;mkfifo "/tmp/fifos/Dependencies"&lt;br /&gt;mkfifo "/tmp/fifos/Code Installation"&lt;br /&gt;&lt;br /&gt;install_dependencies.sh &gt; "/tmp/fifos/Dependencies" &amp;&lt;br /&gt;install_packages.sh &gt; "/tmp/fifos/Code Installation" &amp;&lt;br /&gt;multitail -ts --basename "/tmp/fifos/Dependencies" "/tmp/fifos/Code Installation"&lt;br /&gt;wait&lt;br /&gt;&lt;br /&gt;install_something_else.sh&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;The problem, now?  &lt;code&gt;multitail&lt;/code&gt; is never going to exit on it's own, we'll have to press "q" to end the process when the other stuff is done ... assuming we can tell for sure.  So we never get to the wait command and we never get on to the next steps of our installation.  Let's send an email to the developer and ask him for that feature ... but we'll make our own solution in the meantime.&lt;br /&gt;&lt;br /&gt;So, here presented for you is my solution for monitoring a group of parallel background processes using multitail and ending the monitoring when all processes are complete.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;PROCESS_COMPLETED_COUNT_TMP_FILE=$(mktemp -t "proc-count")&lt;br /&gt;echo 0 &gt; $PROCESS_COMPLETED_COUNT_TMP_FILE&lt;br /&gt;&lt;br /&gt;function killtail {&lt;br /&gt;    MUST_COMPLETE=$1&lt;br /&gt;    PROCESS_COMPLETED=$(cat $PROCESS_COMPLETED_COUNT_TMPO_FILE)&lt;br /&gt;    ((PROCESS_COMPLETED++))&lt;br /&gt;&lt;br /&gt;    if [ PROCESS_COMPLETED -ge $MUST_COMPLETE ]; then&lt;br /&gt;        # dangerous if there are multiple multitails running at the same time&lt;br /&gt;        TAIL_PID=$(pidof multitail)&lt;br /&gt;        kill $TAIL_PID&lt;br /&gt;        rm -rf $PROCESS_COMPLETED_COUNT_TMP_FILE&lt;br /&gt;    fi&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;mkdir /tmp/fifos&lt;br /&gt;mkfifo "/tmp/fifos/Dependencies"&lt;br /&gt;mkfifo "/tmp/fifos/Code Installation"&lt;br /&gt;&lt;br /&gt;# subshell for everything involved with installing dependencies&lt;br /&gt;(&lt;br /&gt;    install_dependencies.sh &gt; "/tmp/fifos/Dependencies"&lt;br /&gt;    killtail 2&lt;br /&gt;)&gt; "/tmp/fifos/Dependencies" &amp;&lt;br /&gt;&lt;br /&gt;# subshell for everything involved with installing code&lt;br /&gt;(&lt;br /&gt;    install_packages.sh &gt; "/tmp/fifos/Code Installation" &amp;&lt;br /&gt;    killtail 2&lt;br /&gt;)&gt; "/tmp/fifos/Code Installation" &amp;&lt;br /&gt;&lt;br /&gt;multitail -ts --basename "/tmp/fifos/Dependencies" "/tmp/fifos/Code Installation" 2&gt; /dev/null&lt;br /&gt;wait&lt;br /&gt;&lt;br /&gt;rm "/tmp/fifos/Dependencies"&lt;br /&gt;rm "/tmp/fifos/Code Installation"&lt;br /&gt;&lt;br /&gt;install_something_else.sh&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Now the subshells are backgrounded instead of the scripts themselves.  Both "steps" are backgrounded, not just the first one.  The command to increment the kill counter and check for the appropriate number of processes to have completed is added to the block of code.  As well as backgrounding the subshells, we're directing stdout output from the subshells into our FIFOs, instead of directing the output of individual commands.&lt;br /&gt;&lt;br /&gt;We pass the --basename option to &lt;code&gt;multitail&lt;/code&gt; so that we see only the name of our FIFO in the multitail windows... and we've used nice human readable names for these temporary buffer files, so isn't that special?&lt;br /&gt;&lt;br /&gt;When the kill counter hits the magic number, a SIGTERM will be sent to the multitail that we get back from &lt;code&gt;pidof multitail&lt;/code&gt;.  This makes multitail error, so we're throwing away the error output from multitail.&lt;br /&gt;&lt;br /&gt;Finally, we still have a "wait" statement, just in case our multitail monitoring of the processes doesn't work for some reason.  We still want to make sure they complete before moving forward with more steps.  We remove the FIFOs and move on to the next steps in our installation.&lt;br /&gt;&lt;br /&gt;Happy process monitoring!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1724694701961948570-3433787203977259564?l=j5bot.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://j5bot.blogspot.com/feeds/3433787203977259564/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://j5bot.blogspot.com/2011/11/simultaneoous-background-process.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1724694701961948570/posts/default/3433787203977259564'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1724694701961948570/posts/default/3433787203977259564'/><link rel='alternate' type='text/html' href='http://j5bot.blogspot.com/2011/11/simultaneoous-background-process.html' title='Simultaneoous Background Process Monitoring in Bash using Multitail'/><author><name>J5</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://4.bp.blogspot.com/_RMH_gNX4x5g/Sq25DsTa39I/AAAAAAAACLQ/ABSKyWUtKus/s1600-R/Photo_39.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1724694701961948570.post-5357172175410048362</id><published>2009-12-21T15:46:00.001-05:00</published><updated>2009-12-21T15:47:09.948-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='faq'/><category scheme='http://www.blogger.com/atom/ns#' term='rhino'/><title type='text'>Question: How do you convert a Java String object to a Javascript String in Rhino?</title><content type='html'>Convert any Java object with a toString() method into a JS string by calling String(object) in JS&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;var javaString = new java.lang.String("Java String");&lt;br /&gt;var javascriptString = String(javaString);&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1724694701961948570-5357172175410048362?l=j5bot.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://j5bot.blogspot.com/feeds/5357172175410048362/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://j5bot.blogspot.com/2009/12/question-how-do-you-convert-java-string.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1724694701961948570/posts/default/5357172175410048362'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1724694701961948570/posts/default/5357172175410048362'/><link rel='alternate' type='text/html' href='http://j5bot.blogspot.com/2009/12/question-how-do-you-convert-java-string.html' title='Question: How do you convert a Java String object to a Javascript String in Rhino?'/><author><name>J5</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://4.bp.blogspot.com/_RMH_gNX4x5g/Sq25DsTa39I/AAAAAAAACLQ/ABSKyWUtKus/s1600-R/Photo_39.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1724694701961948570.post-1389005108418242842</id><published>2009-12-16T12:25:00.001-05:00</published><updated>2009-12-16T12:26:25.634-05:00</updated><title type='text'>Javascript for the Mad Scientist: advanced javascript for jQuery</title><content type='html'>I had a great time last night presenting a talk on advanced js for jQuery to the &lt;a href="http://www.meetup.com/WebTechFrederick"&gt;Frederick Web Tech. Meetup&lt;/a&gt;.  &lt;br /&gt;&lt;br /&gt;Christopher Thatcher of env.js and &lt;a href="http://www.claypooljs.com/"&gt;jQuery-Claypool&lt;/a&gt; fame and I hung out after the meeting and had drinks and lots of great conversation.  Because of family and holidays and such-like many of the regulars couldn't come or couldn't stay for after-meeting socializing.&lt;br /&gt;&lt;br /&gt;You can &lt;a href="http://www.geke.net/MadScientistJS/intro.html"&gt;view&lt;/a&gt; or &lt;a href="http://github.com/j5bot/MadScientistJS"&gt;download/fork&lt;/a&gt; the presentation "slides" if you are interested in looking at the material.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1724694701961948570-1389005108418242842?l=j5bot.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://j5bot.blogspot.com/feeds/1389005108418242842/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://j5bot.blogspot.com/2009/12/javascript-for-mad-scientist-advanced.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1724694701961948570/posts/default/1389005108418242842'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1724694701961948570/posts/default/1389005108418242842'/><link rel='alternate' type='text/html' href='http://j5bot.blogspot.com/2009/12/javascript-for-mad-scientist-advanced.html' title='Javascript for the Mad Scientist: advanced javascript for jQuery'/><author><name>J5</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://4.bp.blogspot.com/_RMH_gNX4x5g/Sq25DsTa39I/AAAAAAAACLQ/ABSKyWUtKus/s1600-R/Photo_39.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1724694701961948570.post-1304224065283026811</id><published>2009-12-12T10:28:00.000-05:00</published><updated>2009-12-12T10:28:12.354-05:00</updated><title type='text'>jQuery Namespacing / Child Plugins Update</title><content type='html'>I've updated the &lt;a href="http://github.com/j5bot/MadScientistJS/blob/master/js/jquery.madscience.js"&gt;example namespacing plugin&lt;/a&gt; to use new arguments.callee() instead of extending the method and prototype individually.&amp;nbsp; This should allow for proper inheritance.&lt;br /&gt;&lt;br /&gt;It does require that the method also wrap the plugin behavior in&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;if (this.jquery) { ... }&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1724694701961948570-1304224065283026811?l=j5bot.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://j5bot.blogspot.com/feeds/1304224065283026811/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://j5bot.blogspot.com/2009/12/jquery-namespacing-child-plugins-update.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1724694701961948570/posts/default/1304224065283026811'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1724694701961948570/posts/default/1304224065283026811'/><link rel='alternate' type='text/html' href='http://j5bot.blogspot.com/2009/12/jquery-namespacing-child-plugins-update.html' title='jQuery Namespacing / Child Plugins Update'/><author><name>J5</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://4.bp.blogspot.com/_RMH_gNX4x5g/Sq25DsTa39I/AAAAAAAACLQ/ABSKyWUtKus/s1600-R/Photo_39.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1724694701961948570.post-5029471048170628827</id><published>2009-12-08T02:27:00.002-05:00</published><updated>2009-12-08T14:05:08.570-05:00</updated><title type='text'>jQuery Namespacing / Child Plugins / Modularization</title><content type='html'>When writing jQuery plugins, you'll find that you want to group related functionality into a single "namespace" or "module", that acts as a parent for multiple child plugins.&lt;br /&gt;&lt;br /&gt;There is not a lot of information readily accessible about the subject, from what I can tell.&amp;nbsp; So little in fact that only after I came up with a quick and dirty method for myself did I dive deep enough to find anything.&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://malnotna.wordpress.com/category/jquery/"&gt;Malnota's Wordpress Blog shows examples of three&lt;/a&gt; plugins that aim to do the job.&amp;nbsp; They aren't reviews so much as they are demonstrations.&lt;br /&gt;&lt;br /&gt;First up is &lt;a href="http://projects.pro.br/gsaraiva/wp-content/uploads/2009/06/jquery.namespace.js"&gt;jQuery.NameSpace&lt;/a&gt; by &lt;a href="http://projects.pro.br/gsaraiva"&gt;Gilberto Saraiva&lt;/a&gt;.&amp;nbsp; Gilberto posts an &lt;a href="http://projects.pro.br/gsaraiva/jquerynamespace/"&gt;example&lt;/a&gt; along with his download link, but to be honest with you, I don't follow any of it.&amp;nbsp; Could be the moving stuff in the background of the blog.&amp;nbsp; Could be the hour that I'm writing this at (I really should be in bed, kids!).&lt;br /&gt;&lt;br /&gt;Malnota writes up the features a little more clearly in his &lt;a href="http://malnotna.wordpress.com/2009/01/13/jquerynamespace/"&gt;review/article&lt;/a&gt; but again, I don't get a sense of what it's doing under the hood or how well it performs.&amp;nbsp; Except that Malnota says that the "child" plugin did not receive arguments that were passed to it.&lt;br /&gt;&lt;br /&gt;UH-OH!&lt;br /&gt;&lt;br /&gt;A relatively casual review of the code shows that Saraiva is going through a lot of complicated eval gymnastics, and hasn't commented a single thing that he's doing.&amp;nbsp; Double UH-OH.&amp;nbsp; Seriously, though this looks like it took a lot of effort to complete and using my spidey sense, it might be close to a neat solution to the problem.&amp;nbsp; I'll tell you that I like the fact that you don't need to call the parent/namespace as a function in order to use it.&amp;nbsp; If nothing else, the approach taken here is interesting because of that aspect.&lt;br /&gt;&lt;br /&gt;Next we have a solution created by the master himself, &lt;a href="http://ejohn.org/"&gt;John Resig&lt;/a&gt;.&amp;nbsp; Is this a good time to mention that my friends used to call ME ejohn?&amp;nbsp; I wonder if I could have snapped up the domain name before he got to it and somehow switched places with him like he was my Dad and it was Vice Versa.&amp;nbsp; That's right, I too wish that I could be John Resig.&lt;br /&gt;&lt;br /&gt;John's solution is &lt;a href="http://dev.jquery.com/%7Ejohn/plugins/space/"&gt;jQuery.space&lt;/a&gt; and the thing to say about it is that he has his own ideas about how to approach the situation.&amp;nbsp; From the way that I read the code.. he's doing the same thing that Gilberto does in jQuery.NameSpace, but in a much more elegant fashion.&amp;nbsp; It looks to me like he's creating a new copy of jQuery.fn for each namespace.&amp;nbsp; Then when you want to stop working that space, you do the magical endSpace call and this code runs:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;newjQuery.endSpace = function(){&lt;br /&gt;  newjQuery.fn = oldFn;&lt;br /&gt; };&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Just like magic you climb out of the rabbit hole.  Hey, that's pretty neat.&amp;nbsp; That's why they call him "The King".&lt;br /&gt;&lt;br /&gt;Last out of the gate is &lt;a href="http://flesler.blogspot.com/2008/04/jquerymodularize.html"&gt;jQuery.Modularize&lt;/a&gt; by &lt;a href="http://flesler.blogspot.com/"&gt;Arial Flesler&lt;/a&gt;.&amp;nbsp; I analyzed this one more than the other two to figure out what it was doing.&amp;nbsp; Essentially, it creates an inner copy of the namespace, and stores the "this" (jQuery object) that is normally expected there and currying each function so that it will be called with the stored "this".&lt;br /&gt;&lt;br /&gt;If you have a namespace "foo" (called via jQuery.foo() natch!) and methods "bar" and "baz", jQuery.Modularize creates "foo._" and "foo._.bar" and "foo._.baz" and "foo._._s_" (this).&amp;nbsp; It only does the magic currying part of the algorithm once, or when you specify "lazy: true".&lt;br /&gt;&lt;br /&gt;I find the cryptic ._. and _s_ and _o_ stuff to be offputting when studying the source code, but overall this is quite the nifty piece of craftsmanship.&amp;nbsp; I was going to complain about the storing of _s_ (data) with the namespace (code) but then I remembered that javascript doesn't have threads so there's no way that it can collide with a simultaneous call for the same namespace with different data.&lt;br /&gt;&lt;br /&gt;What a world.&lt;br /&gt;&lt;br /&gt;If you've made it this far and want to see what I did, have a peek at the &lt;a href="http://github.com/j5bot/MadScientistJS/raw/master/js/jquery.madscience.js"&gt;madscience namespace plugin&lt;/a&gt; in &lt;a href="http://github.com/j5bot"&gt;my github&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;My approach is really freaking simple.&amp;nbsp; I was happy I came up with anything.&amp;nbsp; Since anything I write isn't likely to have 10,000 child plugins, I think that simplicity and terseness might make up for the lack of wowee zowee shown.&amp;nbsp; Certainly I'll be leaving it as is for the purposes it was written ...&lt;br /&gt;&lt;br /&gt;And I'll probably add links to this blog post and/or the two top namespacing plugins reviewed into the comments.&amp;nbsp; So that the people who see my code can go see that there are other, more subtle ways to solve this problem.&lt;br /&gt;&lt;br /&gt;P.S. John's plugin isn't up at &lt;a href="http://plugins.jquery.com/"&gt;plugins.jquery.com&lt;/a&gt; ... and unfortunately that site is a little bit app-store-licious ... I rarely find anything good searching it.&lt;br /&gt;&lt;br /&gt;UPDATE: I think that there could be a collision in the stored jQuery object _s_ in the jQuery.Modularize plugin if you were using the same namespace in multiple asynchronous callbacks/timers.&amp;nbsp; Something like this:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;jQuery("#content").foo().bar(function () { jQuery("#heading").foo().bar(); this.baz(); });&lt;/pre&gt;&lt;br /&gt;If I am reading the control flow correctly, this.baz() will act on "#heading" and not "#content".&amp;nbsp; I'll ping Flesler and see whether this has been considered or is a real life (edge) case or not.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1724694701961948570-5029471048170628827?l=j5bot.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://j5bot.blogspot.com/feeds/5029471048170628827/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://j5bot.blogspot.com/2009/12/jquery-namespacing-child-plugins.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1724694701961948570/posts/default/5029471048170628827'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1724694701961948570/posts/default/5029471048170628827'/><link rel='alternate' type='text/html' href='http://j5bot.blogspot.com/2009/12/jquery-namespacing-child-plugins.html' title='jQuery Namespacing / Child Plugins / Modularization'/><author><name>J5</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://4.bp.blogspot.com/_RMH_gNX4x5g/Sq25DsTa39I/AAAAAAAACLQ/ABSKyWUtKus/s1600-R/Photo_39.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1724694701961948570.post-344849839813375828</id><published>2009-12-04T13:07:00.003-05:00</published><updated>2009-12-05T00:21:09.319-05:00</updated><title type='text'>Splitting Directives - Modular "Molecule" Configurations of Apache httpd</title><content type='html'>At my 9 to 5, I am currently wearing a sys admin hat (this is something between a welder's mask and sherlock holmes' tweed cap, I think).  I love process automation (the foundation of programming, I'd say) so everything is done with a bash script for maximum reuse.&lt;br /&gt;&lt;br /&gt;My vision is to be able to rebuild a new version of my httpd configurations and deploy them to the target servers in one command (the testing process happens BEFORE the final build and deploy, silly!)&lt;br /&gt;&lt;br /&gt;Why?  One of the problems that I've seen in past projects is lack of configuration management and revision control for infrastructure applications like httpd or websphere.  Worse, different tiers in the enterprise (boldly going, anyone?) and different servers might have different configurations because of lack of strictness in implementing changes methodically.&lt;br /&gt;&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Awesome sauce local geek-about-town &lt;a href="http://twitter.com/jleveille"&gt;Jason Leveille&lt;/a&gt; turned me on to a tool called &lt;a href="http://reductivelabs.com/trac/puppet"&gt;Puppet&lt;/a&gt; by &lt;a href="http://reductivelabs.com/"&gt;Reductive Labs&lt;/a&gt;.  I am impressed with the featureset that I have seen, but alas, the method of delivery can't be used for my purposes (client daemons running on all the boxes).&lt;br /&gt;&lt;br /&gt;If you have complete control of your deploy environment and want to solve lots of other problems besides automating and modularizing updates/builds of Apache httpd, I think that you should definitely look at Puppet.  I will likely be diving deeper even without having a clear need right now that it can fill.&lt;br /&gt;&lt;br /&gt;Enough about Puppet, though.  This post is called Splitting Directives and there hasn't been one mention of httpd.conf yet! What gives?  Well if you've ever met me I'm either listening and agreeing with what you say or I'm telling it the long way.  Life is a journey, right?  Forgive me my exposition and proceed if you want to know the method I cooked up for splitting common and specific Apache httpd.conf directives and for building and deploying them.&lt;br /&gt;&lt;br /&gt;First, you have to reorganize your httpd.conf file and bring related directives close together.  Good examples of this are that you would move &lt;directory&gt; entries that refer to virtual host docroots into the VirtualHost directives.  You would put the Listen and NamedVirtualHost directives right before the VirtualHost block that they apply to.  Move IfModule blocks to occur right after the module is loaded (be careful if the stuff in the IfModule has multiple dependencies).  That kind of thing.&lt;br /&gt;&lt;br /&gt;Next, mark up with comments how you can split the httpd.conf up into multiple files.  Put a start and end for each section you think is "modular molecule".&lt;br /&gt;&lt;br /&gt;Split the httpd.conf using the start and end markers into separate files, put the new files in a subdirectory called "common" or similar underneath /apacheroot/conf.  Replace (or comment out and replace) the original directives in the httpd.conf file with Include directives that match your "modular molecule" filenames.&lt;br /&gt;&lt;br /&gt;For example, here is a very basic version of the httpd.conf I am currently working with:&lt;br /&gt;&lt;br /&gt;&lt;/directory&gt;&lt;br /&gt;&lt;pre&gt;# ServerRoot, ServerName, DocumentRoot, ServerAdmin directives&lt;br /&gt;Include conf/common/main.conf&lt;br /&gt;# All the LoadModule directives&lt;br /&gt;Include conf/common/modules.conf&lt;br /&gt;# LoadModule and WebspherePluginConfig directives &lt;br /&gt;Include conf/common/websphere.conf&lt;br /&gt;# User and Group directives, with IfModule blocks around them&lt;br /&gt;Include conf/common/runas.conf&lt;br /&gt;# VirtualHost blocks and associated Listen and NamedVirtualHost records, one per file.&lt;br /&gt;# Remember you can repeat directives like Listen and NamedVirtualHost with the same value without harm,&lt;br /&gt;# So make it one VirtualHost block per file even if they share an IP and port.&lt;br /&gt;# For extra "security" you can explicitly include these, or include one file at conf/common/vhosts.conf that specifies all the others.&lt;br /&gt;Include conf/common/vhosts/*.conf&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;OK, so at this point we just have a bunch of files and a bunch of includes and there's not much to it.  Certainly it can't be used across the enterprise in this form, no matter how fancy the deployment script is.  The configuration is just not suitable for more than one computer (unless they all use the same hostnames and all IPs are bound the same, etc. etc.).  I am assuming that like me, your configurations should all be substantially the same and that there are only a few things that you need to modify per-host.  Things like IPs and hostnames.&lt;br /&gt;&lt;br /&gt;That is what the next step addresses.  We create another folder underneath /apacheroot/conf called "config" or similar.  We now go into each of the files we created earlier, and reorganize them according to whether the directive is a specific one or a common one.  The difference between the previous method of organization and this one?  This time, &lt;b&gt;wrap&lt;/b&gt; the specific directives around the common ones.  Where common and specific directives occur in the same file, create a heirarchy with common directives at the core.&lt;br /&gt;&lt;br /&gt;We're running a decorator pattern on the configurations ... the common directives are wrapped and decorated by the specific directives.  Specific directives go into the conf/config folder and common directives stay in the common folder, albeit in an "unwrapped" (and probably unusable) state.&lt;br /&gt;&lt;br /&gt;Edit your httpd.conf to reflect where you have included "modules" that are only specific directives, or wrap specific directives.  Omitting the comments for brevity, you now have something like this:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;Include conf/config/main.conf&lt;br /&gt;Include conf/common/modules.conf&lt;br /&gt;Include conf/config/websphere.conf&lt;br /&gt;Include conf/config/runas.conf&lt;br /&gt;Include conf/config/vhosts/*.conf&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;A sample vhost.conf might look like this:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;Listen 127.0.0.1&lt;br /&gt;NamedVirtualHost 127.0.0.1:80&lt;br /&gt;&amp;lt;VirtualHost 127.0.0.1:80&amp;gt;&lt;br /&gt;   ServerName localhost&lt;br /&gt;   ServerAlias local.dev mysite.dev mysite.local foo.bar&lt;br /&gt;   Include conf/common/vhosts/sample.vhost.conf   &lt;br /&gt;&amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Run apachectl -t from bin to check your configuration.  Working?  Awesome.  Tweak as necessary if not.&lt;br /&gt;&lt;br /&gt;This is a configuration good for one single host, but all of the specific directives have been isolated on the filesystem to the "conf/config" directory.  We can now use whatever means we want to organize multiple configurations on the filesystem -- based on the same common directives with similar specific directives.&lt;br /&gt;&lt;br /&gt;At the simplest, we just copy the config directory and make a different configuration there.  We started with a "dev" configuration we use on our localhost, but what about when we want to deploy this out onto the QA server(s)?&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;cp conf/config conf/qa1&lt;br /&gt;cp conf/config conf/qa2&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;We need to store these in version control for later use.  And that is going to factor in to the deployment method.  This project is using svn so I'd run these commands, too:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;svn add conf/qa1&lt;br /&gt;svn add conf/qa2&lt;br /&gt;svn commit conf -m "Adding configurations for qa1 and qa2"&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now you have to go in and edit them to have the right IPs and hostnames and what-not and then commit changes after.&lt;br /&gt;&lt;br /&gt;On your buildserver, you should have all these configurations checked out somewhere local.  Let's say in /build/apache/httpd/modular/ and that the source code repository is at svn://localhost/apache .  You should also have a working area outside of SVN where you can build a configuration locally before you deploy it across the wire to a target.  Something like /build/apache/httpd/configs&lt;br /&gt;&lt;br /&gt;The build script is pretty simple.  Designed to be run from /build/apache/httpd and for there to be directories "modular" and "configs" for the configurations and build directories:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;#! /bin/bash&lt;br /&gt;# $1 config to build&lt;br /&gt;SVNREPO="svn://localhost/apache"&lt;br /&gt;CONFIG="$1"&lt;br /&gt;&lt;br /&gt;# make directory for configuration&lt;br /&gt;mkdir -p configs/$CONFIG&lt;br /&gt;&lt;br /&gt;# export the common directive files to the build dir for this config&lt;br /&gt;svn export $SVNREPO/common configs/$CONFIG/common&lt;br /&gt;# export the configuration specific files to the build dir for this config as "conf/config"&lt;br /&gt;svn export $SVNREPO/$CONFIG configs/$CONFIG/config&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Run this script with the parameter "qa1" and there is now a functional configuration for your qa1 server at /build/apache/httpd/configs/qa1.  There are a lot of ways to deploy this configuration to a target.  I am currently using scp directly but you could just as easily compress the config with tar or another program and move it across as one file.&lt;br /&gt;&lt;br /&gt;Example:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;#! /bin/bash&lt;br /&gt;# $1 config $2 user $3 host $4 apache root path on host&lt;br /&gt;CONFIG="$1"&lt;br /&gt;USER="$2"&lt;br /&gt;HOST="$3"&lt;br /&gt;PATH="$4"&lt;br /&gt;&lt;br /&gt;scp -r configs/$CONFIG/* $USER@$HOST:$PATH/conf&lt;br /&gt;&lt;br /&gt;# test and then restart apache here too?&lt;br /&gt;# ssh $USER@$HOST "$PATH/bin/apachectl -l"&lt;br /&gt;## should check the response above before proceeding ... you can roll that yourself :)&lt;br /&gt;# ssh $USER@$HOST "$PATH/bin/apachectl graceful-restart"&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;There are a lot of configuration directives that are tied to a particular site or a particular layer of the enterprise (dev, qa, stage, production, etc.) and not just the specific server.  The method given above can be extended to allow for more complex heirarchies of configuration to be built.  Simply repeat the steps but consider commonalities between "stage1" and "stage2" that have analogs in "prod" layer as well.  Separate them from the "config" level as you did with the "common" directives.  Make a template set as "layer" or "mode" or whatever you think of the steps in the deployment cycle as.  Copy that template set on the filesystem as you did with the "config" folder.&lt;br /&gt;&lt;br /&gt;Consider the best way to nest your files for your use when modifying configurations.  All of the intermediary levels between the most specific and the most general directives need to stay as closely in sync as they can for this system to be useful in avoiding misconfigurations and configuration entropy.&lt;br /&gt;&lt;br /&gt;I think a good general rule would be that each server has a "site" role (when there are multiple httpd installs for instance), a "layer" role, and a "server" role.  That would correspond to a structure like this:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;conf/common&lt;br /&gt;conf/site (template for conf/sites)&lt;br /&gt;conf/sites/site1&lt;br /&gt;conf/sites/site2&lt;br /&gt;conf/layer (template for conf/layers)&lt;br /&gt;conf/layers/layer1&lt;br /&gt;conf/layers/layer2&lt;br /&gt;conf/server (template for conf/servers)&lt;br /&gt;conf/servers/server1&lt;br /&gt;conf/servers/server2&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The build script then must be adapted to take each of these into account when reducing the set of configurations down into the configuration needed for this particular host.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;#! /bin/bash&lt;br /&gt;# $1 server to build&lt;br /&gt;# $2 layer to build&lt;br /&gt;# $3 site to build&lt;br /&gt;SVNREPO="svn://localhost/apache"&lt;br /&gt;SERVER="$1"&lt;br /&gt;LAYER="$2"&lt;br /&gt;SITE="$3"&lt;br /&gt;&lt;br /&gt;BUILDDIR="$SITE/$LAYER/$SERVER"&lt;br /&gt;&lt;br /&gt;# make directory for configuration&lt;br /&gt;mkdir -p configs/$BUILDDIR&lt;br /&gt;&lt;br /&gt;# export the common directive files to the build dir for this config&lt;br /&gt;svn export $SVNREPO/common configs/$BUILDDIR/common&lt;br /&gt;# export the server specific files to the build dir for this config as "conf/server"&lt;br /&gt;svn export $SVNREPO/servers/$SERVER configs/$BUILDDIR/server&lt;br /&gt;svn export $SVNREPO/layers/$LAYER configs/$BUILDDIR/layer&lt;br /&gt;svn export $SVNREPO/sites/$SITE configs/$BUILDDIR/site&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Each site may have different configurations for each layer.  If the way that the Include statements in your configuration files works there are lots of levels of heirarchy, you may wish to use a heirarchical folder structer.  That is the fundamental model that I used, but it is more complex to illustrate conceptually and so I will leave illustrating it to a later post (if there is demand).&lt;br /&gt;&lt;br /&gt;I hope this post helps someone else who is looking for information on build scripts, modular configurations, modular directives, magic modular molecules or general httpd common configuration tomfoolery.  Good luck and take care!  Considered actions are the only defensible ones.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1724694701961948570-344849839813375828?l=j5bot.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://j5bot.blogspot.com/feeds/344849839813375828/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://j5bot.blogspot.com/2009/12/splitting-directives-modular-molecule.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1724694701961948570/posts/default/344849839813375828'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1724694701961948570/posts/default/344849839813375828'/><link rel='alternate' type='text/html' href='http://j5bot.blogspot.com/2009/12/splitting-directives-modular-molecule.html' title='Splitting Directives - Modular &quot;Molecule&quot; Configurations of Apache httpd'/><author><name>J5</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://4.bp.blogspot.com/_RMH_gNX4x5g/Sq25DsTa39I/AAAAAAAACLQ/ABSKyWUtKus/s1600-R/Photo_39.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1724694701961948570.post-5234050485016976565</id><published>2009-11-29T13:58:00.000-05:00</published><updated>2009-11-29T13:58:56.172-05:00</updated><title type='text'>Google Chrome Frame</title><content type='html'>Since my Web Worker shim relies on Google Gears plugin and the Google Chrome Frame plugin may make Gears obsolete (at least for this use case), I have temporarily suspended work on my html5 shims while I wait for that issue to shake out.&lt;br /&gt;&lt;br /&gt;I may push harder for a non-Gears, native solution based on Statified JS.  There is also a possibility to offer server-side worker implementations, which dovetails nicely with my recent research about the state of server-side JS.&lt;br /&gt;&lt;br /&gt;People seem to be very excited about &lt;a href="http://nodejs.com"&gt;Node&lt;/a&gt;, but I prefer env.js and the &lt;a href="http://www.claypooljs.com"&gt;Claypool JS&lt;/a&gt; framework from what I can see.&lt;br /&gt;&lt;br /&gt;I think that server-side DOM emulation is the "BIG DEAL™" and that server-side JS should build on an existing server stack (which was one of the nicest points in Jaxer's favor when it was in active development).&lt;br /&gt;&lt;br /&gt;Is anyone working on making any of the other server-side JS servers apache httpd modules?  I haven't seen any indication that they are interested in this kind of integrated approach.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1724694701961948570-5234050485016976565?l=j5bot.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://j5bot.blogspot.com/feeds/5234050485016976565/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://j5bot.blogspot.com/2009/11/google-chrome-frame.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1724694701961948570/posts/default/5234050485016976565'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1724694701961948570/posts/default/5234050485016976565'/><link rel='alternate' type='text/html' href='http://j5bot.blogspot.com/2009/11/google-chrome-frame.html' title='Google Chrome Frame'/><author><name>J5</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://4.bp.blogspot.com/_RMH_gNX4x5g/Sq25DsTa39I/AAAAAAAACLQ/ABSKyWUtKus/s1600-R/Photo_39.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1724694701961948570.post-4762944349257079396</id><published>2009-09-18T15:45:00.000-04:00</published><updated>2009-09-18T15:56:36.999-04:00</updated><title type='text'>First Test Suite Complete</title><content type='html'>The first version of the &lt;a href="http://html5-shims.googlecode.com/svn/trunk/test/workers.html"&gt;test suite&lt;/a&gt; is completed now and everything is passing, testing 6 levels of child worker nesting, and some core functionalities such as importScripts, self alias for the worker global scope, the lack of "window" and hiding the worker global scope constructors.&lt;br /&gt;&lt;br /&gt;The results of the test suite are this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;worker received: worker&lt;br /&gt;worker: JSUNITY: Running unnamed test suite&lt;br /&gt;worker: JSUNITY: 4 tests found&lt;br /&gt;worker: JSUNITY: [PASSED] testImport&lt;br /&gt;worker: JSUNITY: [PASSED] testWindow&lt;br /&gt;worker: JSUNITY: [PASSED] testSelf&lt;br /&gt;worker: JSUNITY: [PASSED] testWGSVisibility&lt;br /&gt;worker: JSUNITY: 4 tests passed&lt;br /&gt;worker: JSUNITY: 0 tests failed&lt;br /&gt;worker: JSUNITY: 2 milliseconds elapsed&lt;br /&gt;[object Object]&lt;br /&gt;worker: JSUNITY: Running unnamed test suite&lt;br /&gt;worker: JSUNITY: 1 test found&lt;br /&gt;worker: JSUNITY: [PASSED] testInnerWorkerExists&lt;br /&gt;worker: JSUNITY: 1 test passed&lt;br /&gt;worker: JSUNITY: 0 tests failed&lt;br /&gt;worker: JSUNITY: 0 milliseconds elapsed&lt;br /&gt;[object Object]&lt;br /&gt;worker-child queue: worker-child&lt;br /&gt;worker received: another message from parent&lt;br /&gt;worker received: worker-child received: worker-child&lt;br /&gt;worker received: worker-child: JSUNITY: Running unnamed test suite&lt;br /&gt;worker received: worker-child: JSUNITY: 4 tests found&lt;br /&gt;worker received: worker-child: JSUNITY: [PASSED] testImport&lt;br /&gt;worker received: worker-child: JSUNITY: [PASSED] testWindow&lt;br /&gt;worker received: worker-child: JSUNITY: [PASSED] testSelf&lt;br /&gt;worker received: worker-child: JSUNITY: [PASSED] testWGSVisibility&lt;br /&gt;worker received: worker-child: JSUNITY: 4 tests passed&lt;br /&gt;worker received: worker-child: JSUNITY: 0 tests failed&lt;br /&gt;worker received: worker-child: JSUNITY: 3 milliseconds elapsed&lt;br /&gt;worker received: [object Object]&lt;br /&gt;worker received: worker-child: JSUNITY: Running unnamed test suite&lt;br /&gt;worker received: worker-child: JSUNITY: 1 test found&lt;br /&gt;worker received: worker-child: JSUNITY: [PASSED] testInnerWorkerExists&lt;br /&gt;worker received: worker-child: JSUNITY: 1 test passed&lt;br /&gt;worker received: worker-child: JSUNITY: 0 tests failed&lt;br /&gt;worker received: worker-child: JSUNITY: 0 milliseconds elapsed&lt;br /&gt;...&lt;/pre&gt;&lt;br /&gt;I need to add tests for the other portions of the API that are completed as well as the portions which are not.  Once I do that, I will start working on using a MessagePort implementation for the communication between the worker and worker global scope.  This should allow me to plug in communication based on local storage or web database, which is necessary for implementing SharedWorker.&lt;br /&gt;&lt;br /&gt;The work I have been doing on the postMessage and onmessage events and how they queue when the objects are not ready should make it simpler to implement the MessagePort / MessageChannel structure.&lt;br /&gt;&lt;br /&gt;Right now the most glaring problem is that there is significant duplication of the onmessage code between DedicatedWorker and WorkerGlobalScope.  I was allowing this because the code in WorkerGlobalScope uses a closure to remember the scope inside the workerPool onmessage method and the DedicatedWorker didn't need it, but there shouldn't be any reason not to just store the scope reference for DedicatedWorker, too.&lt;br /&gt;&lt;br /&gt;I need to experiment with where I can store that function for both objects to use, however.  I am finding that the structure of the current objects and how they are passed around is proving quite limiting in terms of allowing for shared functions.  Solving this will be even more important as I design a larger framework that includes other parts of the HTML5 and related APIs, available inside and outside of the worker scope.&lt;br /&gt;&lt;br /&gt;I will try to create an object called html5shims and attach all of the shim API implementations to the global scope from within the closure surrounding html5shims.  The current implementation of Worker uses a style of function assignment which is not compatible, so I will have to check again which browser was requiring that and see if I can find a different way.&lt;br /&gt;&lt;br /&gt;Here's that style if you're curious:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;Worker = (function InitWorker(window,navigator,wgsSource) {&lt;br /&gt;                  function DedicatedWorker (url) {&lt;br /&gt;...&lt;br /&gt;                  }&lt;br /&gt;              return DedicatedWorker;&lt;br /&gt;          })(this,...);&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1724694701961948570-4762944349257079396?l=j5bot.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://j5bot.blogspot.com/feeds/4762944349257079396/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://j5bot.blogspot.com/2009/09/first-test-suite-complete.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1724694701961948570/posts/default/4762944349257079396'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1724694701961948570/posts/default/4762944349257079396'/><link rel='alternate' type='text/html' href='http://j5bot.blogspot.com/2009/09/first-test-suite-complete.html' title='First Test Suite Complete'/><author><name>J5</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://4.bp.blogspot.com/_RMH_gNX4x5g/Sq25DsTa39I/AAAAAAAACLQ/ABSKyWUtKus/s1600-R/Photo_39.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1724694701961948570.post-1046474622500025383</id><published>2009-09-17T21:38:00.000-04:00</published><updated>2009-09-17T21:38:24.946-04:00</updated><title type='text'>with (foo) { function bar() {} } fubared</title><content type='html'>The last two days I've been working on a test suite for my webworker shim and found a couple of wrinkles.&lt;br /&gt;&lt;br /&gt;The first was that messages were being lost when they were sent immediately after the worker creation.&lt;br /&gt;&lt;br /&gt;For example:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;var w = new Worker("foo.js");&lt;br /&gt;w.onmessage = function (event) {&lt;br /&gt;    alert(event.data);&lt;br /&gt;};&lt;br /&gt;w.postMessage("foo");&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The message "foo" would never reach the worker.  This was solved simply enough by queueing messages when the communication channel is not ready.  Which brought me back to looking at the spec for MessagePort and MessageChannel, but that's not important right now.&lt;br /&gt;&lt;br /&gt;The really wrinkly thing that I'm seeing now is based on this test:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;function testImportScripts () {&lt;br /&gt;   importScripts("../scripts/import.js"); // declares function importedFunction&lt;br /&gt;   assertNotUndefined(importedFunction,"imported function is defined");&lt;br /&gt;   ...&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;First I was getting reference errors telling me that importScripts was undefined.  I was able to get around that by surrounding the call to importScripts in a with (this) {} block.  That worried me.  And importedFunction was still undefined.&lt;br /&gt;&lt;br /&gt;So I write a simple worker script:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;onmessage = function (event) {&lt;br /&gt; postMessage("received: " + event.data);&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;importScripts("../scripts/import.js");&lt;br /&gt;importedFunction();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;No importedFunction.  However, with importedFunction assigned instead of declared -- viola!  function declarations inside of with blocks are not supported according to &lt;a href="http://www.ecma-international.org/publications/standards/Ecma-262.htm"&gt;ECMA-262 3rd edition&lt;/a&gt;.  It makes sense, but it puts a bit of a crimp in my plans.  (I found &lt;a href="http://www.ecma-international.org/publications/standards/Ecma-262.htm"&gt;this post&lt;/a&gt; which confirmed my suspicion, I didn't actually dig through the spec to find out!&lt;br /&gt;&lt;br /&gt;The current version of the WorkerGlobalScope uses this code inside of it's _executed method for all internal executions:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;Function("with (this) { " + source + " }").call(this);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I strongly prefer to maintain the use of with so for now I am modifying the code passed to the worker to make function declarations function assigments.  The latest version of the code and the tests so far are checked in to SVN.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1724694701961948570-1046474622500025383?l=j5bot.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://j5bot.blogspot.com/feeds/1046474622500025383/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://j5bot.blogspot.com/2009/09/with-foo-function-bar-fubared.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1724694701961948570/posts/default/1046474622500025383'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1724694701961948570/posts/default/1046474622500025383'/><link rel='alternate' type='text/html' href='http://j5bot.blogspot.com/2009/09/with-foo-function-bar-fubared.html' title='with (foo) { function bar() {} } fubared'/><author><name>J5</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://4.bp.blogspot.com/_RMH_gNX4x5g/Sq25DsTa39I/AAAAAAAACLQ/ABSKyWUtKus/s1600-R/Photo_39.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1724694701961948570.post-979775019909209404</id><published>2009-09-13T22:08:00.001-04:00</published><updated>2009-09-13T23:28:22.638-04:00</updated><title type='text'>Web Worker API Shim Demo Posted</title><content type='html'>I finally got the Web Worker API shim demo posted on Google Code tonight.&lt;br /&gt;&lt;br /&gt;There is an interesting trick to posting the demo HTML page where you need to set the svn:mime-type property to "text/html" or it won't be served as HTML.  Makes sense but confused me for a while and made me sidetrack looking at cleaning up my old portfolio site.&lt;br /&gt;&lt;br /&gt;Not that that wouldn't be a great idea, too.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://html5-shims.googlecode.com/svn/trunk/demo/workers.html"&gt;Web Worker Demo&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;To see the shim, visit that URL with a non-supporting browser that has &lt;a href="http://gears.google.com"&gt;Google Gears&lt;/a&gt; installed.  You may also be interested in comparing it against browser implementing web workers natively such as FF 3.5.&lt;br /&gt;&lt;br /&gt;The shim is implemented via two classes.  Probably the simplest way to understand how they work is from the inside out.  Implementing the Worker object and the worker-to-worker-thread messaging mechanism on top of Gears is pretty simple.  But the API doesn't just cover instantiating a worker, giving it some work to do and talking to it.  The API defines a window-like environment that the worker thread operates in, where other APIs are available:&lt;br /&gt;&lt;br /&gt;WorkerGlobalScope&lt;br /&gt;&lt;br /&gt;Once the WorkerGlobalScope is created, the Worker itself is a dispatcher, sending and receiving messages.  So what does the WorkerGlobalScope look like and how do we make one?&lt;br /&gt;&lt;br /&gt;The HTML5 Web Workers API spec covers the WorkerGlobalScope in detail.  &lt;a href="http://code.google.com/p/html5-shims/source/browse/trunk/src/WorkerGlobalScope.js"&gt;WorkerGlobalScope.js&lt;/a&gt; is my implementation.  In it, we have constructor functions for each of the WorkerGlobalScopes (Dedicated, Shared and the "base") which handle setting instance variables both private and public.  We also have DedicatedWorkerGlobalScope onmessage prototype and a prototype object which handles all of the methods available in any WGS, including empty Worker and SharedWorker constructor methods.&lt;br /&gt;&lt;br /&gt;But the WorkerGlobalScope established by the constructor and prototype is incomplete -- not only because I haven't finished everything!  It is missing the very crucial piece of providing a working Worker implementation.&lt;br /&gt;&lt;br /&gt;Of course, we can't have a WorkerGlobalScope without having already created a Worker.  The implementation of Worker is provided not directly by WorkerGlobalScope but by the calling Worker.  The &lt;a href="http://code.google.com/p/html5-shims/source/browse/trunk/src/DedicatedWorker.js"&gt;DedicatedWorker.js&lt;/a&gt; file bootstraps the Worker into the originating window environment with the InitWorker method that returns the DedicatedWorker constructor.&lt;br /&gt;&lt;br /&gt;Simplified:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; Worker = (function InitWorker(window) {&lt;br /&gt;  function DedicatedWorker(url) {&lt;br /&gt;  ...&lt;br /&gt;  }&lt;br /&gt;  return DedicatedWorker;&lt;br /&gt; })(this,navigator,WorkerGlobalScopeSource);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The InitiWorker method provides closure around the bootstrap parameters.  "this", the global scope for workers.  "navigator", the navigator object passed through from the global scope. The source which can be used to create the WGS.  Because it is named, it can be easily passed as a string via function decompilation into the Gears worker pool thread.  It is my understanding that because it is defined as part of an assignment operation, it does not pollute the namespace (I think there are some finer points there, but I don't know them as well as I would like).&lt;br /&gt;&lt;br /&gt;When we create the code to execute our worker's payload in the workerPool, which must instantiate the worker global scope and make all of the APIs available to the worker, we basically repeat the exact same construction.  There it is text and not source code, but it is still the same thing.  In this way, we share the source code for Workers and WorkerGlobalScope with all child instances even though we cannot directly pass the objects.&lt;br /&gt;&lt;br /&gt;The code which is executed by the Gears workerPool thread:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;this._source = [&lt;br /&gt; wgsSource,&lt;br /&gt; "var wgs = new DedicatedWorkerGlobalScope(\""+url+"\");",&lt;br /&gt; "wgs.navigator = " + toSource.call(navigator)+";",&lt;br /&gt; "wgs.navigator.online=true;",&lt;br /&gt; "Worker=wgs.Worker=("+InitWorker+")(wgs,"+ toSource.call(navigator) +",'"+ escapeQuotes(wgsSource)+"');",&lt;br /&gt; "wgs._loadSource({url: ['" + url + "'], "+&lt;br /&gt; "callback: function(scripts){ wgs._scripts = scripts; wgs._execute('importScripts(\""+url+"\")'); } });"&lt;br /&gt;].join("\n");&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Matters are complicated by the fact that the HttpRequest object (analog to XHR) available in Gears does not allow for synchronous operations but that is a story for another day.&lt;br /&gt;&lt;br /&gt;As the credits on the demo say, thanks to &lt;a href="http://webreflection.blogspot.com"&gt;Andrea Giammarchi&lt;/a&gt; for pointing me at the need for this shim.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1724694701961948570-979775019909209404?l=j5bot.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://j5bot.blogspot.com/feeds/979775019909209404/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://j5bot.blogspot.com/2009/09/web-worker-api-shim-demo-posted.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1724694701961948570/posts/default/979775019909209404'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1724694701961948570/posts/default/979775019909209404'/><link rel='alternate' type='text/html' href='http://j5bot.blogspot.com/2009/09/web-worker-api-shim-demo-posted.html' title='Web Worker API Shim Demo Posted'/><author><name>J5</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://4.bp.blogspot.com/_RMH_gNX4x5g/Sq25DsTa39I/AAAAAAAACLQ/ABSKyWUtKus/s1600-R/Photo_39.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1724694701961948570.post-4715936246651801186</id><published>2009-09-10T10:47:00.000-04:00</published><updated>2009-09-13T22:07:55.793-04:00</updated><title type='text'>HTML5 Shims, Shivs, Fallbacks and Compatibility Layers</title><content type='html'>I am working on my implementation of HTML5 WebWorker shim via Google Gears plugin (currently).  Part of what is interesting is that the WebWorker has a lot of the other HTML5 APIs available internally, so I am also looking to bring in other shims / write my own if I want the project to be complete and provide an actual fully-functioning Worker-alike and SharedWorker-alike.&lt;br /&gt;&lt;br /&gt;As a result, I've decided to start a project to collect the available shims.  Rather than just the Web Worker, I will try to bring together as much of the HTML5 js apis as possible.  The project is called "html5-shims" and is hosted on Google Code.&lt;br /&gt;&lt;br /&gt;I have added a page to the wiki for my worker shim/html5 shims project which lists other shims available, the relevant specs, etc.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://code.google.com/p/html5-shims/wiki/LinksandResources"&gt;HTML5 Shims : Links &amp;amp; Resources&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1724694701961948570-4715936246651801186?l=j5bot.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://j5bot.blogspot.com/feeds/4715936246651801186/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://j5bot.blogspot.com/2009/09/html5-shims-shivs-fallbacks-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1724694701961948570/posts/default/4715936246651801186'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1724694701961948570/posts/default/4715936246651801186'/><link rel='alternate' type='text/html' href='http://j5bot.blogspot.com/2009/09/html5-shims-shivs-fallbacks-and.html' title='HTML5 Shims, Shivs, Fallbacks and Compatibility Layers'/><author><name>J5</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://4.bp.blogspot.com/_RMH_gNX4x5g/Sq25DsTa39I/AAAAAAAACLQ/ABSKyWUtKus/s1600-R/Photo_39.jpg'/></author><thr:total>0</thr:total></entry></feed>
