 So hi welcome. I'm glad to see you all We're gonna get through a few little boring things first. My name is John That's actually a picture of me So if you see me in the hall look for the scary blue guy and my heterosexual life made here is Aaron. Hello These These slides will be available online So if you need to stalk us via the internet you can find all that information there We work for a company called ad ready and we love them because they pay us to come and do this So thank you very much ad ready. If you need cheesy display ads, we have got you covered come see us We're from Seattle where it is very rainy and we all wear flannel shirts and we drink bad coffee and Sometimes good coffee and we hang out with terrifying angry Ruby people Hello Ryan. Nice to see you So we're here today to talk about two different languages two very very different languages The first of which is JavaScript and I'm gonna do just a little bit of a JavaScript history for you Because some of you may not know it JavaScript was invented by a guy at Netscape and it looks like a C language or Java language But it really has a very very different inheritance it came from scheme and self and just happened to get a little bit of Java ish C ish Syntactic sugar on top to to pay the bills and just a few quick things about JavaScript So we're all on the same page JavaScript objects are really open. They're just like Ruby hashes It's just a bag of crap and you can get to it That's a technical term You can get to it by indexing in just like we do on a Ruby hash You can also get to it through a dot syntax which looks very similar to method invocation JavaScript functions themselves are very free. They're kind of similar to Ruby lambdas You can create them outside of any class you can call them directly by their name But you can also attach them to objects and if you call a JavaScript function that's attached to an object You have a this pointer just like this in there just like self in Ruby JavaScript also doesn't have any classes per se You can create a prototype of something so that anytime you create a new instance of it You have similar methods to what was there before But you don't really have inheritance itself So enough about that. We're over Let me help you care. We care because it is everywhere There are JavaScript interpreters on your freaking phone on every browser you have it's got the greatest penetration of any language ever There's JavaScript here The other language we're gonna talk about The other language we're gonna talk about today is Ruby all of you know all about Ruby So I'm not gonna go through the summaries of where it came from or who wrote it or anything like that Because I'm sure you know that already because you're a big honking group of Ruby nerds so Why do we actually care about these two languages together because we love the internet? Specifically we love the World Wide Web Which is what most of us in this room probably do for a living and the really interesting thing about JavaScript and Ruby is That we use them both constantly we use them every day and they have nothing in common when we do Internet site development. We use Ruby on the server side. We use JavaScript on the client side We use prototype we use rails we use Merb we use jQuery, but we don't really use them together We do stuff on the server we wad it up into a little bundle and we toss it over to the client and forget about it Which is cool. I mean it's obviously worked for us, but we'd really like something a lot better Some of the problems with JavaScript include the fact that the only runtime that we have to mess with Is the one that's built into the browser? We can't do anything else and with that I'm going to high-five in my partner Aaron Patterson Hello Thank you JavaScript is tightly coupled to your browser whenever you want to do any sort of JavaScript testing you have to run it in your browser You it's very difficult to test one thing without dragging along the other so for the purposes of this presentation Pictures of rhinos will represent JavaScript. Yes Carry on it's true and purple arrows mean type coupling Anyway But the awesome thing is that this comes with a sweet standard library of being able to modify Dom trees What else can I do? That's it great it also comes with excellent code packaging systems such as Nothing It's got it's got a great command line interface for testing with test frameworks like I Forgot that one too. I love that one Continuous integration systems we right right like Or just hit refresh right So anyway everything depends on the browser That's totally lame lame We want something different we want to be able to do all this stuff without our runtime having to be part of the browser We want to be able to do our testing outside the browser We want to be able to load a freaking file if we need to we want to be able to extend things easily if we're experimenting with new libraries and stuff like that and Especially we want to be able to mess with the language and the runtime without having to load 30 megs of Firefox firebug and a partridge in a paratree. So we wrote something called Johnson This is not a juvenile penis joke, this is a penis joke made by grown men Thank you So the point of Johnson is to bridge this huge divide between these two very very different languages And we want to do it in both directions We want you to be able to use your JavaScript in your Ruby Whether it's in big segments or in little segments if you want to take a JavaScript function and use it as a Lambda You should be able to and in JavaScript if you want to you should be able to Call Ruby methods. You should be able to use Ruby objects You should be able to toss things back and forth and not have to worry about which language they're implemented it. I Know so really we wanted to take these two languages and make them fall in love. We wanted to make them hug we wanted to let them happily work together and When we originally started this we were doing it for fun to see if we could do something ridiculous But the really nice thing about it is that it's turned out that we found some really good pragmatic excuses for doing this and One of the most important ones is working with the Internet's Now We all use the Internet's right. I know you do Raise your hand if you love the Internet That's right. Yeah web 2.0 Ryan Davis. You're a hater. I've caught you using the Internet. Yes, I have anyway We've all heard of web 2.0, which uses Ajax and You know most websites are dynamic. They use this. We all know what it stands for Sometimes we need to screen scrape these particular sites and it's it's not just for douchebags Truly sometimes you need an automated way of interacting with a website that doesn't have an API and You just can't do that when things are you know Ajax is going on Now the Internet's are full of And it's not just for douchebags It's not just for douchebags. Sometimes you need an automated way of interacting with a website that doesn't have an API on Now the Internet's are full of this JavaScript and What do we do about that? We already have a great screen scraping tool called mechanize But it's got a huge down downfall for example. We have this particular website. That's using some of this Aaron JavaScript Aaron's exchange and Manipulating the DOM so let's say we tried to screen scrape that the we would get the wrong results in mechanize, which is unfortunate But if we were to integrate Johnson We would actually get the right results and With that I'm going to show an example of using the Johnson shell one quick note on on mechanize what we've done there is What mechanize normally does is it makes the request it turns the HTML into a DOM tree and then lets you run XPath or CSS selectors against it what we've done with Johnson is we actually find all the script tags and the links to To JavaScript files and everything we load them in and we run the JavaScript runtime right along with the page So that if there's stuff in there that mucks with the DOM it gets executed on time If you have stuff that messes with CSS classes that gets applied as well Which makes it way easier to deal with that sort of dynamic stuff So using the Johnson shell For example It's very similar to IRB except that you have two different languages You get to deal with JavaScript and deal with Ruby. You can see up here J. S. Stands for JavaScript We're Manipulating JavaScript right now calling alert which unfortunately actually isn't defined in JavaScript at all It's defined in the browser. So you're gonna get an error and I've decided for this slide that we're going to implement it. So we switch over to Ruby With the RB command and we can access the JavaScript runtime via the J. S. Variable and it's treated just like a hash we can toss stuff into it. So We're gonna define the alert function in Ruby, but in the JavaScript runtime. So We'll sign a lambda to it. It gets marshaled over. We switch back over to the JavaScript shell Run hello world. It works Everybody is happy Magic it's magic. We might also want to iterate so in JavaScript We define an iterator which this one multiplies x by itself or x some math thing. I don't know It's a weird So we head back over into our Ruby shell pull out the iterator And then use it just like a proc So really it works just like Ruby and you have no idea So How do we accomplish this awesome stuff? How do we accomplish all this awesome stuff? Well, John I'll tell you via Johnson proxies Now an important thing about Johnson proxies is you know, everything is an object in Ruby. Everything is an object in JavaScript everything can be an object and We take advantage of this unfortunately We have two objects a Ruby object in a JavaScript object and when they send messages, they can't understand each other They speak different languages. So we need some way of Making them look like One another so we need to be able to trick a Ruby object into thinking that a JavaScript object is a Ruby object and we need to trick a JavaScript object into thinking that a Ruby object is a I'm confusing myself Anyway, Johnson takes care of this Johnson sits on the border of the two language of two languages handing out cloaks so Say this Ruby object wants to head over into JavaScript country it needs to consult with Johnson and receive its plus nine cape of invisibility and Vice versa if JavaScript wants to head over into Ruby country needs to do that So, you know, here we have a JavaScript object in the Ruby country and they speak the same language or Vice versa JavaScript Ruby object over in JavaScript country speaking JavaScript Yes, I'm taking you in I'm unprepared for this section Okay, so just a quick example of that if we create a new object in Ruby We can toss it over the the boundary of the language over into JavaScript by binding it to a global variable in the runtime As soon as we get there It's totally available and we can mess with it just like we can mess with any open JavaScript We can add a new variable to it that contains a string We can add a new function to it that's attached and all that stuff will work in JavaScript Just like we would want it to work the interesting thing is is all that stuff will now work in Ruby as well It's it's making changes to the classes or the objects in this case transparently It's defining singleton methods for you on the Ruby side So if you mess with an object no matter which language you're in at the time It'll take care of it for you Now there are a couple places where Things are a little more complicated with regular expressions. We want it to be As as unsurprising as possible We don't want to take Ruby regexes across the border and and proxy to them because they won't work right in any of the The JavaScript methods so with a few things like regular expressions. We actually will We'll convert them by value. We'll take your regex in Ruby We'll parse it and we'll create a JavaScript regex out of it so that it'll work like you expect we also if you move strings across the The language boundary we do those by reference or excuse me by value Because JavaScript strings are immutable and Ruby strings are not which confuses spider monkey to no end so a quick example here just of attaching the functions again pull it across Bring it in attach a function Back over in Ruby and it works fine. That's for a singleton method on a single instance You can also and I'm not sure why you'd use this, but I thought it was awesome You can actually mess with the prototype of a Ruby object In in JavaScript So if you can you want to attach a method that's going to be available available on all strings in Ruby Just like you can do this in JavaScript You can do it to Ruby objects we can attach this method called in big in we'll put it on the prototype of the Ruby object If we head over to Ruby any new instance of the class will have it just like we would expect from JavaScript methods now one of the really scary things about this is that We can have these classes now that are implemented half in one language and half in the other and have no idea Which language they're implemented in which is really scary from one perspective But when we're doing things like making JavaScript libraries run on the server side It's really nice to be able to decorate Ruby objects with some of the stuff that JavaScript expects Boy John this sounds hard. This was hard Aaron. Let me tell you about some of the things that made it hard That's what she said Thank You folks. I'll be here all week This was really really really hard So what we've actually done is taken the spider monkey runtime itself and embedded it as a sea extension in Ruby Which means especially with this transparent as we want to make these things We have to orchestrate between two very very different garbage collection mechanisms So what we end up doing is keeping reference counts on both sides such that if you gc a ruby object And there are still references to its proxy in JavaScript that it doesn't get garbage collected in either place and vice versa This isn't very interesting But it took me so long that I want to punish you by making you listen to me talk about it so that I can feel better The other thing that was really difficult was Threading which is weird because we really don't have an API in the browser for doing multi-threaded work in JavaScript You can do async stuff, but it kind of fakes it, but spider monkey itself is thread safe underneath and Even though there are no threading things there it expects to be dealing with native OS threads Ruby as you may have noticed doesn't have any of those right now So what we've had to do is make sure that when you go across thread boundaries in Ruby that we save the state of the interpreter and make Sure that it's valid no matter what thread you're on once again This is boring, but it hurt me to do so you have to listen to me talk about it So we we ran into this because since we expose everything in Ruby to JavaScript You can also do threaded programming in JavaScript just using Ruby threads Yeah, you can pass thread new a JavaScript function, which is cool until it crashes the world so some of you look a little bit dubious and So to help you with that I'm gonna bring on my friend Aaron Patterson. You may have met him before. Oh, hello Yeah, I know what you may be saying Well, you're wrong Case in point For example here is a Fibonacci sequence, which we at ad ready do all the time We do a lot of Fibonacci a lot of Fibonacci sequence saying it's You wouldn't believe how many Fibonacci numbers you need to do to make online advertising happen So here here's the Fibonacci sequence defined in Ruby and here is the Fibonacci sequence defined in JavaScript in Ruby and Here is the Fibonacci sequence defined in a Ruby class in JavaScript in Ruby Bring it back dude bring it back. Okay. Okay So so we have Def Fib which returns Fibonacci sequence purely Ruby implementation second Fib returns a Fibonacci sequence but implemented in JavaScript and the clients of this class have no idea With how either of these methods are implemented so you can see from this slide here this test case that They actually return the same number and it works. It works just fine now One question you may be asking yourself is Which one is faster? And we will let you figure that out for yourself. It's a very interesting result JavaScript is pretty thin on Standard library stuff as you may have noticed from earlier So we've added a few little helpers to help you out when you're hacking with Johnson The first of which is we've added a JavaScript to where require to Johnson You can use this from inside your JavaScript. It uses the exact same load path as Ruby So you can bundle JavaScript along with your gyms if you're doing a multi language project Especially one where maybe you are testing JavaScript on the server side, but using it on the client side You can also bundle pure JavaScript is gyms if you want I don't know why you would do that But I think that'd be super cool if you did Everything is available through a top-level constant called Ruby We let you get to anything you want through there whether it's a kernel method or one of your nested classes or anything else So you don't have to require anything. You don't have to explicitly import anything. It's just there The one other feature that we had to add because there's no concept of it in JavaScript is a way to do symbols and Originally we did it so that any string that came across the boundary from JavaScript to Ruby that started with a colon Turn into a symbol and that turned out really badly So we have explicit helpers to help you symbolize strings once you've done that they traverse across the barrier They work just fine your symbols work in both places. They are singletons in JavaScript So if you're working with it every time you get it, you'll get the exact same reference The one other thing that we did add was under under file Which is handy on the server side, but pointless on the browser so We've shown you a few excuses that we had for actually doing this and I think I'm gonna have Aaron show you some Of the more ridiculous things that we've been able to do with it, which are way more fun than screen scraping with mechanize Yes, so Johnson the not so practical Since we let you access anything in Ruby. We let you have database access in JavaScript So for example, we may be inside of a Rails project like this I'm just inside some random Rails project with a user model. I fire up my interactive Johnson and switch to the Carry on switch to the Ruby shell and Then I require the environment. So we have our rails environment Require our user model. So we have access to user switch back over into JavaScript and then do a find on users and you can see we're using Johnson symbolize right there So find all users and we have just accomplished database access in JavaScript I Said who needs Ruby who does need Ruby JavaScript does everything you need So we can iterate over each of those Users and output the name so we have Aaron Patterson who is an internet internet expert and John Burnett who is a web and architect So symbolize all We also have a thing called EJS or enterprise job. No What does it stand for that's embedded JavaScript I embedded JavaScript not enterprise hmm, okay So given a say rails controller here that just finds some users we can write our view in JavaScript, so let's say we have index dot html dot EJS You can see that this section here in red is actually implemented in JavaScript and you might have noticed that special variable at dot We define at dot and that contains all of your Instance variables inside of your rails controller. We could have defined them all at the top level But we didn't want to pollute your JavaScript namespace. So they're all stuffed into at dot users And we we did this because we thought it was ridiculous and then realized kind of accidentally that there really is a point to doing this Sometimes one of the nice things is if you've got a page where you're going to render it once And then you're gonna update it a ton via Ajax It's really nice to have this because you use this to render on the server side And then you ship the entire template over to the client side The templatizing code runs just as well in the browser as it runs anywhere else And then you can use the same template to render results from say a JSON result set that you get Via Aaron's JavaScript internet exchange or yes, whatever that's called Ajax All you have to do is implement the at object and you have all the context that you need So that plug-in is available to you in the Johnson gem under lib rails in it And if you have rails 2.0 because it's in this magic directory, you use the what what is it? Gem requirement and plug-in stuff. Yeah, gem plug-in stuff. So it will automatically get loaded What other thing that I've added is break points. So I Allow you to define break points in Johnson. So let's say we have some particular JavaScript We start up our runtime we compile a script before running it and notice the name there my script You actually have to compile the script and then give it a name and then tell the runtime Hey, I want to break in my script on line three And whenever the runtime hits that particular break point it'll execute the block that you've given it and You can do anything you want to inside the block the runtime is frozen such that you can access any variables inside the runtime and inspect Things so this is nice So you can do kind of JavaScript debugging and not have to do it in a browser or you know something More heavier so then evaluate your compiled script and it will actually execute your break points And it looks something like this so You can see I equals zero and X equals zero and that is because back here at the break point The break point gets executed before the line is actually evaluated. So it'll execute your break point then evaluate the line Another thing that we've done this is this is very very important to us. This is very very useful very useful in the Johnson world hot ruby.js has anyone here heard of heard of this? one person, okay three four all right hot ruby.js is a Ruby 1.9 bytecode interpreter written in JavaScript So we have no idea why yeah You can run Ruby 1.9 bytecode in JavaScript. So For example, let's say we have some Ruby code puts. Hello world Another thing that we do in online advertising a lot a Lot puts hello world This is actually more important than Fibonacci sequence believe it or not This is the bytecode for it Yeah, that's lovely. Yeah, so We can actually execute that so we'll do a you know fire up our interactive Johnson Require hot ruby do a new hot ruby Evaluate that bytecode and you can see in red there that hello world was actually executed. We leave it This means that we were able to run Ruby on JavaScript on Ruby on Rails Very important very important one more thing JavaScript parse tree We give you access to the JavaScript parse tree and this is the real parse tree This is the parse tree that spider monkey uses so it's not our own, you know Homecook parse tree. This is actually pulled straight out of spider monkey This is what the API looks like you parse some JavaScript and it gives you back an AST and You can do stuff with the AST For example, you can get directed graphs out of the AST So you can it outputs it as dots file so you can look at it as a dot file It gives you a sex piece. You can read it easily The the AST implements in each method so that you can walk every node in your AST and We also provide a to JS method so you can take your AST and turn it back into JavaScript So given the earlier tree we may want to walk every node and Look for name nodes whose values are foo and change those name nodes to hello and Then we can output that JavaScript. So this is just an example, but you can obviously do much more complicated things Yeah, we think we have enough there that it's pretty easy to write Pre-processors or macros for JavaScript or even some basic AOP stuff We haven't written the libraries for it, but we would love it if somebody else would So and since you can get access to anything inside of Ruby from JavaScript JavaScript gets access to its own parser So you can parse yourself manipulate yourself Turn yourself into JavaScript and then evaluate yourself Yeah, right We know you've all been pining for that in the browser for years, so you're welcome Um Testing there we go So we're good to go on 1.0. We're gonna release it either tonight or tomorrow It does okay. It's it runs on 186 only right now because we're terrified of 1.9 It's on Unix. We're gonna do a Windows build if anybody really wants one. It's it's doing okay It's pretty hard to crash these days, but we're not running it in any really heavy load Multi-threaded environments. We would be delighted if you did Because we really want to make it a lot more solid Just a few people that we want to thank before we go you who the cats who's somewhere back in the back Probably writing angry articles about alias method chain has been really really helpful and wrote a couple of the really neat JavaScript features for it Matthew Draper is our our Australian compatriot who's fixed Every crashing bug that we found so far and we're working with John Resig to get a browser list Dom working For things like mechanized and we think we're gonna be at a place where that's really widely usable very quickly So thank you very much. That's all we've got Except for this really disturbing picture If anybody has any questions, we're happy to answer him now There's some scary bearded guy in the back you who to oh, right He was suggesting that I talked about defined property one of the nice things about having Having the extension language for the JavaScript runtime not be something like see is that we can try out new JavaScript features really easily by prototyping them in Ruby Defined property is something that's going into the next release of JavaScript probably in it's in Firefox 3 1 right you to Okay, it's going in sometime soon, but we were able to very easily implemented in Ruby try it out Experiment with the API and see what worked best for it, which is really nice Yeah, it also let's do things the JavaScript doesn't normally let you do like mark functions as not being enumerable or read-only or anything like that way in the back I'm sitting Harder For those of you who are cursed with the ability to write clear code Ryan and I regularly flog Johnson together on Tuesday nights memory usage Two questions We have, what I would say we've done it really successfully. Trace monkey, we pulled in because it's a TDI, and it runs three times as slow and crashes a lot. But that's probably our usage patterns and not Trace monkey's fault. So we are working on that. We've looked at Squirrelfish and JavaScript Core. They're a little more difficult to implement because the C APIs that we need aren't there. We need to reach a little further into the guts. So we're hoping that there's a better C API there. V8 has a very good C++ API and our compatriot in Australia is working on that right now. The API for Johnson itself is runtime pluggable, so once we get those working there shouldn't really be any outward facing changes. And what, could you potentially use Johnson for unit testing or integrating into the test suite various AJAX facilities so that if you have a system that relies on AJAX very heavily, you can use Johnson to actually run those tests through JavaScript in very small types. Yeah, thank you for mentioning that. We are, like I said, we're working with John Resig on env.js, which among other things has AJAX support in it. We have a couple versions of things like prototypes, unit test, framework where we've pulled out all of the browser specific stuff, although we're looking for a little more clean of the JavaScript unit test framework. And yeah, I don't see any reason why you wouldn't do that. In fact, I'd love to have that. If I could run auto tests on my JavaScript, I would be extremely happy. Anything else? Yeah, you can run as many as you want. All right, well thank you all very much. I hope you enjoyed yourselves. We'll be up here if you want to come up and ask any other questions or hack with us, please feel free. Thank you.