Assembling the Future: crafting the missing pieces of the Ruby on Wasm puzzle


Summarized using AI

Assembling the Future: crafting the missing pieces of the Ruby on Wasm puzzle

Svyatoslav Kryukov • September 12, 2024 • Sarajevo, Bosnia and Herzegovina • Talk

The talk titled "Assembling the Future: crafting the missing pieces of the Ruby on Wasm puzzle" by Svyatoslav Kryukov at EuRuKo 2024 explores the potential of running the Ruby programming language and its ecosystem directly in the browser using WebAssembly (Wasm). The session highlights innovative approaches to overcome existing limitations in the Ruby ecosystem within Wasm, aiming to enable tools such as Bundler, Rack, and Rake to function seamlessly in a web environment. Key points include:

  • Introduction to WebAssembly: The speaker begins by discussing the complexities of Wasm, emphasizing its role as a binary instruction format designed for sandboxed execution.

  • Ruby WASM Overview: The talk details the integration of Ruby with Wasm, noting that Ruby WASM operates under strict limitations, such as lack of threading and networking capabilities, which are critical for many Ruby libraries.

  • Building Interactive Environments: Kryukov presents the creation of a Ruby playground called Run ruby.dev, which serves as an emulated development environment, allowing users to write and modify Ruby code directly in the browser. Key functionalities include virtual file systems and limited networking.

  • Challenges and Solutions: The speaker discusses significant hurdles faced in implementing Ruby and provides creative workarounds, such as monkey patching parts of the Ruby core library to support necessary functions that are missing in the WASI (WebAssembly System Interface) environment.

  • Integrating Ruby Tools: Plans for integrating essential Ruby tools like Bundler and Rack are outlined, with concrete examples illustrating the process of installing gems and interfacing a Ruby web server with JavaScript.

  • Future Prospects: Finally, Kryukov expresses optimism about the future of Ruby in the web ecosystem, suggesting that ongoing development in the Ruby WASM space could one day allow full-featured Ruby applications, including frameworks like Rails, to run entirely in the browser.

In conclusion, the presentation not only emphasizes the technical aspects of adapting Ruby for browser execution but also opens up discussions on how these advancements could reshape the web development landscape.

Assembling the Future: crafting the missing pieces of the Ruby on Wasm puzzle
Svyatoslav Kryukov • Sarajevo, Bosnia and Herzegovina • Talk

Date: September 12, 2024
Published: January 13, 2025
Announced: unknown

Buckle up for a journey beyond ruby.wasm limits—making the entire Ruby ecosystem run in-browser a reality! No threads, networking, or beloved nokogiri? We tackle it all—from Kernel patches to CORS, crafting WASI functions, and Wasm within Wasm—we're bending reality to shape the web's next frontier!

Dive into the frontier of web innovation with a mission to bring Bundler, Rack, Rake, and more Ruby ecosystem tools into the browser! This session unveils the potential of Ruby.wasm, pushing past the limits of WASI to reshape how we think about web development. Explore the possibilities of running essential Ruby development tools directly in your browser, turning the dream of a fully interactive Ruby development environment on the web into reality.

Discover strategies for integrating Bundler for gem management, enabling Rack for web server interfacing, and leveraging Rake for automated tasks—all within the browser. We'll navigate the challenges of virtual file systems, dynamic gem loading, and network interactions through Ruby.wasm, offering insights into overcoming these hurdles.

We'll shine a light on the critical gaps in the ecosystem and the essential components still needed to make running comprehensive Ruby tools in the browser—from a theoretical dream to a practical, everyday reality. Get ready for a journey that promises to expand your understanding of what's possible with Ruby.wasm, setting the stage for a future where the web is powered by Ruby's elegance and versatility. Buckle up!

EuRuKo 2024

00:00:10.160 so that's the second um talk about wasm
00:00:13.360 for today and I hope it will add some
00:00:16.279 value uh to the like whole thing uh but
00:00:20.680 I will start like with some uh story I
00:00:24.519 don't know I've seen things you people
00:00:26.920 wouldn't believe not just running in
00:00:29.519 browser powered by web assembly I
00:00:32.480 watched bug reproductions quick
00:00:34.960 experiments live documentation
00:00:37.440 examples all those moments available for
00:00:40.160 JavaScript but missing for
00:00:42.879 Ruby like tears and
00:00:45.559 rain but it's not time to die it's time
00:00:48.120 to
00:00:49.120 change so welcome to assembling the
00:00:52.359 future I'm sosav krov a developer at
00:00:55.239 evil mushions and we are going to piece
00:00:57.840 together a future where Ruby shines
00:01:00.280 bright in neon
00:01:02.640 lights but our story start starts with
00:01:06.159 tag blits it's a fully working in
00:01:08.920 browser ID and the most fascinating part
00:01:12.280 about it um it runs not just right in
00:01:16.159 the browser using web assembly I'm big
00:01:19.759 fan of stets but it doesn't support
00:01:23.079 truby so um when I saw that utyo was
00:01:28.680 working on Ruby wasm
00:01:30.640 I thought why should JavaScript
00:01:32.880 developers have all the fun right um
00:01:35.920 that's when I decided to create this Min
00:01:38.600 stag blades for
00:01:40.040 Ruby um and I created Run ruby. def it's
00:01:45.920 a ruby playground um like many others uh
00:01:49.920 but with a Twist it's also an emulated
00:01:53.399 development environment this means we
00:01:56.200 have virtual file system um ability to
00:01:59.399 install gems from your gem file and
00:02:02.840 limited network support as well and all
00:02:05.719 of that runs in your
00:02:08.640 browser today today I want to show you
00:02:11.840 uh what it takes to build such such
00:02:16.239 thing uh we'll start with some mandatory
00:02:20.120 um info about Wason um and yeah honestly
00:02:24.920 I'm still learning
00:02:26.440 it and the technology is so young and
00:02:30.040 actively developed it might change while
00:02:33.080 we're speaking um yeah and next we'll
00:02:36.360 take a look at Ruby wasm and discuss how
00:02:39.480 it overcome uh its current limitations
00:02:42.640 and by the way UTA I see you um working
00:02:45.920 on something please don't push anything
00:02:48.239 he's so fast like I'm afraid this talk
00:02:51.680 will be
00:02:53.360 stale while we're
00:02:55.319 talking um yeah and we will show how to
00:02:59.319 overcome some of limitations of current
00:03:01.239 limitations of Ruby
00:03:03.640 W um and let's start with web
00:03:11.879 assembly to be honest web assembly is
00:03:14.840 complex based um and for today's talk we
00:03:19.480 only need two things to know it's a
00:03:22.519 binary instruction format and it is
00:03:25.480 designed to be a
00:03:27.360 Sandbox um let's break it down
00:03:32.920 so the binary instruction format means
00:03:36.360 portability um wasm acts as just another
00:03:39.840 Target for your
00:03:41.560 llvm uh toolkit so uh we can compile
00:03:44.959 your code or say CB interpreter for
00:03:48.280 example um into wasm module alongside
00:03:51.400 other
00:03:54.840 platforms that will make it executable
00:03:57.560 on different VM run times like the
00:03:59.959 official wasm time feature each wasmer
00:04:02.840 and many more including all browsers
00:04:06.159 because they all can execute wasm
00:04:10.239 modules this is an example of a simple
00:04:14.159 wasm module uh and you can see on the
00:04:17.199 right I hope you you can see it uh that
00:04:21.040 it imports and exports some functions
00:04:25.400 and this is the sandbox part I'm talking
00:04:27.720 about you can do anything out outside of
00:04:30.160 the module unless you explicitly uh
00:04:33.680 exported and imported stuff so for
00:04:36.919 instance even to print hello world we
00:04:39.800 must to import a function because it's
00:04:43.639 IO and for the browser it means we need
00:04:46.600 to write some quite quite some
00:04:48.759 JavaScript
00:04:50.440 right um in the basic setup um we only
00:04:54.759 need to initialize a module and call the
00:04:57.680 exported function uh but due to this
00:05:01.160 lowlevel nature of web assembly um we
00:05:04.560 also need to like work with some
00:05:07.840 pointers and this is pretty ugly if you
00:05:11.479 ask me and there is obviously must be a
00:05:14.520 better way to work with web web
00:05:17.880 assembly and of course there is one it's
00:05:22.199 YY uh web assembly system interface it
00:05:26.240 defines a list of standard CIS calls
00:05:28.800 like posx
00:05:30.720 um and it enables web assembly modules
00:05:34.080 to run on different
00:05:37.800 platforms wasi releases new apis in
00:05:41.560 numbered previews in and this is how it
00:05:46.199 looks like basically this is the wasi
00:05:49.319 interface
00:05:51.199 description um and the list of defined
00:05:54.280 functions is quite limited so for
00:05:56.479 example with wasi preview one we can't
00:05:59.360 use use threats networking and much more
00:06:03.080 and all that obviously affects Ruby wasm
00:06:05.880 as
00:06:08.720 well to make wasm work with wasi one
00:06:12.479 modules uh on the on the module side we
00:06:15.880 need to um inject YY functions instead
00:06:20.000 of Cals and this is done by uh y
00:06:24.280 SDK on the host side uh there are two
00:06:27.680 options we either uh um have an
00:06:30.960 implementation wasi functions uh wasi
00:06:33.880 interface or we need to use shins and in
00:06:37.800 case of
00:06:39.120 browser um there are shims um to use
00:06:43.840 here's an example of a shims function
00:06:46.240 that we saw earlier that's you know you
00:06:49.280 don't want to write that every day
00:06:53.120 right shims provide a list of ready to
00:06:56.000 use y functions to import um into the
00:07:00.160 was module and posix like entities like
00:07:04.280 virtual file system and so on to use on
00:07:08.240 the JavaScript side so we have this
00:07:14.319 connection actually Ruby wasm can be
00:07:17.840 initialized with a new more powerful
00:07:20.240 wasi preview to already thanks to UD um
00:07:24.560 which can unlock networking for example
00:07:27.400 uh but full support is not yet ready um
00:07:31.639 on either y SDK side and also on Shin's
00:07:36.680 side hope uto will fix that for us but
00:07:40.080 for now we need to use YC preview
00:07:44.919 one now let's talk about Ruby wasm what
00:07:48.319 what it is exactly right um it's CR Ruby
00:07:51.879 interpreter uh with a set of patches to
00:07:55.080 remove or reimplement some
00:07:57.680 parts um of like core and library and
00:08:04.319 with injected YY
00:08:06.720 functions since it uses wasi it shares
00:08:09.879 the same problems no threats no
00:08:12.960 networking no Dynamic
00:08:15.400 linking and here is okay you can't do
00:08:19.759 that I guess but there is a link to the
00:08:22.599 talk from
00:08:25.560 UT um Al Dynamic linking is kind of
00:08:29.680 reduces the number of gems we can
00:08:31.839 use uh we still can use a lot of
00:08:35.519 gems um in was and there are two ways we
00:08:39.839 can install gems so at build time uh by
00:08:43.959 a special packaging system we can also
00:08:46.279 unlock some of the C extensions and I
00:08:49.640 think you saw the talk by UTA he like
00:08:53.640 explained that uh and the second option
00:08:56.760 is to do that in runtime and that's what
00:08:59.560 we going to do it today and to do that
00:09:02.360 we need to uh use
00:09:05.600 networking but how to do that without
00:09:08.839 networking um here we can use a special
00:09:12.360 feature of
00:09:13.600 ruas uh JavaScript
00:09:16.880 interrup that's one of the most exciting
00:09:19.680 things uh with Ruby
00:09:21.600 LM and it's easier to show than uh
00:09:26.200 explain with JavaScript interop we can
00:09:29.040 execute Ruby code uh from JavaScript and
00:09:32.680 pass values back so both Ruby and
00:09:35.880 JavaScript are
00:09:41.720 Interlink with that knowledge uh we can
00:09:44.959 finally proceed to Ruby playground
00:09:50.560 implementation first of all we will need
00:09:52.720 to um run Rubin browser then we want to
00:09:57.640 share file system to use uh it in Ruby
00:10:01.880 and also to show that in the browser and
00:10:04.600 edit files and so on big chunk of work
00:10:08.120 will be also related to enabling bundler
00:10:11.519 and
00:10:12.800 finally we will also as a bonus spin up
00:10:15.920 a server with Ruby on
00:10:20.600 board so first uh let's see how to run
00:10:25.480 ruin browser this is a simple script
00:10:28.079 from the uh read me we only need to
00:10:31.200 import uh this browser script that does
00:10:34.120 the whole Magic and we can execute rubby
00:10:37.079 code in a special script tag this allows
00:10:40.160 us to run Ruby script once which is you
00:10:43.399 know we couldn't make our thing work uh
00:10:47.000 with that so let's enhance this
00:10:49.560 example by exposing the this uh default
00:10:52.680 Ruby VM function uh we can now uh access
00:10:56.600 the Ruby virtual machine uh and also
00:10:59.800 replace versions of uh Ruby wasm file
00:11:02.639 itself so you can pre-build something
00:11:04.360 and use it uh it's great but let's zoom
00:11:08.600 into this default Ruby VM function as
00:11:14.160 well um yeah finally we can see familiar
00:11:19.800 Yi uh gluc code the file system the
00:11:23.040 imputs everything is here and here is
00:11:26.120 also like some uh rubas initialization
00:11:29.360 as well we don't need to care about
00:11:33.800 that now when we know where to find wasi
00:11:37.839 code uh like in the whole file system
00:11:40.680 initialization let's focus on sharing
00:11:42.839 the file system
00:11:46.600 part here's a basic basic
00:11:49.839 example here we create a ruby file and
00:11:53.560 put it into the directory
00:11:59.680 once the file system is set up we can
00:12:02.240 run files from
00:12:05.279 Ruby to make example more Dynamic and
00:12:08.519 interactive we will use code mirror to
00:12:10.360 modify files um and also uh add a button
00:12:15.560 to execute theme and display the
00:12:19.560 result so demo time yeah cess is hard so
00:12:24.600 it looks not not really nice but yeah it
00:12:28.160 works and also I think it's
00:12:36.480 Dynamic okay I missed but you see errors
00:12:39.800 s also
00:12:44.160 life so um thanks to wasi uh the file
00:12:48.639 system is just an inmemory JavaScript so
00:12:52.440 uh we can use U it on JavaScript side to
00:12:56.120 manipulate it and also to read that as a
00:12:58.800 real file system on the Ruby
00:13:02.399 side with that out of the way let's
00:13:04.880 focus on installing gems via
00:13:11.160 bundler this is simple script behind the
00:13:14.279 bundle install command and let's try to
00:13:17.880 run it in our editor why
00:13:23.120 not okay error that's why you don't do
00:13:26.600 live coding right um so um in this case
00:13:32.480 error comes from a missing core class uh
00:13:36.440 socket to handle this kind of problem we
00:13:39.639 can just reimplement missing class just
00:13:43.240 enough to avoid the error and sometimes
00:13:48.199 it means that we can just create a empty
00:13:50.519 file sometimes we need to implement some
00:13:53.600 um methods for our case this is enough
00:13:59.440 then we can create this virtual um
00:14:02.399 directory and put those files
00:14:05.959 there and we call uh we also need to
00:14:09.199 prepend um the lad pass Global variable
00:14:14.320 uh because Ruby uses that to find
00:14:16.800 required
00:14:20.360 files let's try
00:14:22.440 it okay another error um so this time
00:14:28.000 it's directly related to the missing C
00:14:38.160 function sorry oh oh
00:14:42.920 no
00:14:45.040 Jesus okay I will I will click it on
00:14:47.839 here
00:14:50.480 sorry not you you oh okay I will do that
00:14:54.519 like that thank
00:14:56.880 you so yeah
00:15:00.079 we have an
00:15:03.480 error where is my mouse sorry that that
00:15:07.279 will be
00:15:08.240 ugly um so um this is related to the
00:15:12.480 missing C Orby functions um and when
00:15:17.560 this happens it means that uh we use CIS
00:15:20.399 call that is not available in wasi so um
00:15:24.480 keep away uh keep Heats away from the
00:15:27.120 slides because we are going to monkey
00:15:30.000 pouching um this is just an example
00:15:33.759 there are a lot of monkey patches in my
00:15:36.240 version of code and yes it's ugly but
00:15:39.759 this is how it works right now
00:15:44.440 right hello mouse let's go here and
00:15:48.800 click on
00:15:53.240 it okay another
00:15:55.440 error um so sometimes uh you must stop
00:15:59.680 blindly patching everything and find the
00:16:02.680 right spot to uh apply your patch
00:16:04.720 because in this case we already trying
00:16:07.199 to access network and there is no reason
00:16:10.639 to reimplement openness cell that
00:16:12.600 wouldn't work
00:16:15.959 so in this case it's time to finally
00:16:19.360 play our JavaScript interrupt
00:16:23.120 card in this method uh we are going to
00:16:27.519 use uh JavaScript
00:16:29.720 Fetch and uh pass it and return to Ruby
00:16:34.759 uh as a ruby
00:16:40.199 object and after that yes again monkey
00:16:43.040 patching that that's that's how it works
00:16:44.720 right now
00:16:48.040 sorry
00:16:55.319 hello and it works um
00:16:59.639 this is not a flying Ruby that you saw
00:17:02.240 um but yeah it's it's fine I guess uh
00:17:05.559 the jam just been downloaded and
00:17:08.760 installed and the code is running
00:17:14.640 cool um finally it's important to be
00:17:18.280 creative when you are working with the
00:17:19.760 current state of rasm uh because uh here
00:17:22.559 is a list of minor issues I also uh was
00:17:25.439 forced to kind of fix uh issues for
00:17:29.640 example or be gems don't allow you to
00:17:32.360 download gems um so I need to implement
00:17:36.720 proxy uh also when you uh call bundler
00:17:40.679 install first time first time it tries
00:17:43.600 to uh cash all the metadata like all the
00:17:46.760 versions all that and uh yeah it's slow
00:17:51.440 and you saw this is fine even on this
00:17:53.600 wi-fi so uh I just reimplemented uh the
00:17:57.000 whole thing uh on in the cloud and just
00:18:00.000 download one file instead of like
00:18:03.840 many and yeah there is something else
00:18:07.679 always you know um now something special
00:18:12.720 um the feature that doesn't exist in R
00:18:15.320 ruby. Dev and um if you want you can
00:18:18.320 come to me after the talk and I will
00:18:20.080 tell you why um so let's enable um web
00:18:24.600 server with Ruby
00:18:26.799 was this is our scat nothing special
00:18:29.960 just couple you know uh
00:18:34.880 roads and the thing is that we have this
00:18:39.320 rack um thing in Ruby World which makes
00:18:43.000 it really easy to replace a PMA with a
00:18:46.240 JavaScript
00:18:50.159 code same thing with fetches almost like
00:18:53.480 we trying to um serialize data from
00:18:56.679 JavaScript back to Ruby
00:19:00.520 and then in Ruby we use U mock request
00:19:03.919 on on the Ruby yeah and just call uh Rec
00:19:08.000 App application like
00:19:11.360 that the question like like this is
00:19:14.520 already I don't know kind of obvious so
00:19:18.520 the question is where to put this
00:19:23.120 code and there are several options there
00:19:26.039 we can use service worker um another
00:19:29.120 option is web RTC it's a bit hocky and I
00:19:32.679 don't know I never tried that but it
00:19:34.320 looks promising and the final um version
00:19:38.919 like we can use some custom networking
00:19:41.559 layer um like one uh like one done in St
00:19:47.320 blits web
00:19:49.360 containers um but today service worker
00:19:53.919 will be fine for
00:19:56.360 us I think we need to
00:19:59.400 can explain what this what service
00:20:01.280 worker is and it's a script that is
00:20:04.080 running uh in parallel with your web
00:20:07.080 page uh totally separated so this
00:20:11.919 snippet interrupts all the
00:20:14.760 requests um and provides a custom
00:20:18.120 response from Ruby instead of like uh
00:20:22.679 version request that could uh go
00:20:29.600 okay we
00:20:32.320 have this
00:20:34.799 demo let's see if it
00:20:38.679 works yeah it works cool so again this
00:20:44.200 is not the rails application that you
00:20:46.480 showed but it's fine and yeah obviously
00:20:52.400 um there is a small difference between
00:20:55.200 this uh demo and the demo that UT showed
00:20:58.640 because all with uh all uh the things
00:21:03.200 that I showed are working um without
00:21:07.120 pre-built version of Ruby this is the
00:21:09.600 thing and um to run rails we need to
00:21:14.559 overcome a lot of problems like uh there
00:21:17.960 is no way right now to use wasum gems uh
00:21:23.480 with C
00:21:24.799 extensions um there is problem with
00:21:27.360 database adapter because uses sockets so
00:21:29.960 we need again to rewrite some things and
00:21:33.320 there are much more like problems uh but
00:21:37.679 the whole toolkit of patching everything
00:21:41.000 and everywhere uh keeps the same so yeah
00:21:44.799 we can run rails
00:21:49.159 actually and you know today in this talk
00:21:53.279 uh we did a lot of horrible things uh we
00:21:56.360 implemented and like P some core classes
00:22:00.640 really poorly uh we wrote some
00:22:03.320 JavaScript which is a scene for someone
00:22:06.080 like I don't know uh but despite all
00:22:09.240 those problems and hacks and
00:22:12.320 limitations I'm really thankful that
00:22:15.240 trby already allows us to you know
00:22:18.440 glimpse into the future and try web
00:22:22.760 assembly that will I think will replace
00:22:26.360 everything um and there will be a world
00:22:29.880 with a perfect uniform un like platform
00:22:33.240 unification you
00:22:35.279 know but for now that's it thank you
Explore all talks recorded at EuRuKo 2024
+39