00:00:05.720
morning all
00:00:08.200
right let's get
00:00:10.360
start
00:00:12.120
so I so yeah thanks for joining my
00:00:16.440
session i hope everyone had a yeah great
00:00:19.840
day one yesterday and also the official
00:00:23.640
party for me the yeah it's first time to
00:00:27.039
attend Ruby Kai after six years so I'm
00:00:30.480
so excited for being here thanks for
00:00:33.680
having me Lubiki but yeah last night
00:00:37.440
yeah I enjoy too so this picture was
00:00:40.719
taken at about 3:00 actually
00:00:44.680
today fortunately the Yeah I'm not so
00:00:47.440
hung over thanks to my nervousness
00:00:50.840
now this is so funny so now I'm gonna
00:00:54.800
talk about the running JavaScript within
00:00:57.440
Ruby which is implemented by C rank in
00:01:00.879
pearl room so yeah for my favorite
00:01:05.600
langages are gathered in the yeah same
00:01:08.760
place so hi again uh I'm Ko or at HMSK
00:01:15.119
i'm working as a product engineer for
00:01:18.439
persona which is an identity
00:01:21.040
verification startup so I used to be in
00:01:24.400
Ruby Kai organizers for about 10 years
00:01:27.360
but this is my first time to attend Ruby
00:01:30.159
Kai as a speaker and uh I'm a home
00:01:33.600
brewer so yeah but not about the package
00:01:36.640
manager so yeah this is real
00:01:40.040
brewing so yeah these years I brewed
00:01:42.960
over 100 gallon so about 380 liters so
00:01:47.840
yeah I guess I'm kind of yeah beer noob
00:01:50.960
and uh yeah please give me
00:01:52.720
recommendations for breweries around
00:01:55.040
Matsyama i hope I can visit there to
00:01:57.920
celebrate with nice beer if my this
00:02:00.880
presentation goes
00:02:03.399
well although my hometown is actually
00:02:06.560
Foka but my dad came from Eime
00:02:09.599
Prefecture where Masyama is so I'm
00:02:13.360
feeling something special for this
00:02:15.120
year's Ruby Kai that is one of my yeah
00:02:18.160
some reasons I submitted my proposal for
00:02:21.840
yeah this this
00:02:23.800
kai but my dad does hometown is Kobuchi
00:02:28.400
that where is a bit far away that yeah
00:02:31.120
even from Matsyama it takes 10 hours
00:02:33.840
from Tokyo so yeah that is longer than
00:02:36.879
my flight for San Francisco where I live
00:02:39.360
in now so I never had a chance to visit
00:02:42.640
yeah over 10 years so thanks to Ruby Kai
00:02:46.080
I'm going to visit yeah this
00:02:49.800
weekend anyways so let's talk about
00:02:53.200
technical stuff so this session is just
00:02:56.239
about my project quickJS RB so it's
00:02:59.840
published as a Ruby gem already and the
00:03:02.159
source code is on
00:03:04.200
GitHub so let me show a quick demo about
00:03:07.280
the yeah this gem at first
00:03:13.159
so you can require the this gen and you
00:03:18.800
can have the quick js cross
00:03:23.239
oh oh
00:03:31.799
so yeah I I just require require for the
00:03:35.840
first and
00:03:38.360
uh this
00:03:42.519
uh this method can evaluate the JS code
00:03:47.920
but it looks like not JS
00:03:51.480
actually so let's try the yeah some
00:03:54.760
JSish code so you can define the
00:03:58.920
const a and uh if you evaluate a you can
00:04:04.000
get yeah one or the yeah let's see some
00:04:07.959
other yeah javascript specific for
00:04:11.840
example mass prototype
00:04:14.480
uh maybe p
00:04:17.160
to this should be 256 maybe yes it's
00:04:22.320
running and also the
00:04:25.000
quickjs is having the yeah VM class
00:04:29.280
which is kind of the runtime instance so
00:04:32.080
you can instantiate
00:04:34.919
it and this keeps the yeah maintains the
00:04:39.040
yeah consistent runtime so if you do e
00:04:42.880
code for
00:04:44.440
example so let's define some
00:04:49.320
function a b a + v
00:04:57.800
And if you do another
00:05:03.639
code so let's call
00:05:07.080
funk one and
00:05:10.120
two
00:05:12.199
oh so yeah it's returning three such
00:05:15.280
like this
00:05:20.919
and so this gem could run JavaScript
00:05:24.240
code on Ruby but uh yeah this is just
00:05:26.639
wrapping an existing open-source project
00:05:29.919
uh which is named quickjs that is made
00:05:32.960
by a legendary programmer the fvis bar
00:05:37.039
who made very famous projects like
00:05:39.360
ffmpeg or qmu yeah there are so more and
00:05:43.520
quickjs supports the modern javascripts
00:05:45.919
specification ECM script 2023 mostly and
00:05:50.880
it's written by C rank and the work
00:05:53.440
standard one and the binary size is
00:05:55.840
relative to very
00:05:58.280
small so what I made actually you may
00:06:01.840
think that I just wrapped such a great
00:06:04.080
project so yeah that's totally right so
00:06:07.039
my focus were mostly about the
00:06:09.280
productizing and interfacing by binding
00:06:12.479
a Ruby uh building a Ruby binding of
00:06:16.280
quickjs so this session is more about my
00:06:19.440
practice like why and how I built it for
00:06:23.120
the real world use case this my
00:06:26.319
presentation may be bored for some
00:06:28.560
people who are familiar with Ruby's
00:06:30.720
native extension so I just recommend
00:06:33.120
them leaving for other sessions and my
00:06:36.160
personal recommendation is I'll show you
00:06:38.400
some the session about about performance
00:06:41.360
as subh hall and uh yeah honestly I want
00:06:44.479
to watch that instead of presenting here
00:06:47.039
right
00:06:48.520
now all right then yeah let me dump why
00:06:52.560
I built quick
00:06:54.919
JSR so my employer uh persona is running
00:06:59.680
a s platform for identity
00:07:02.840
verification if I explain our business I
00:07:07.120
usually say the stripe.com for
00:07:09.880
identity it's learning by a monoic waves
00:07:13.280
project and also yeah we are hiring nice
00:07:15.919
rubies like people in Ruby Kai so talk
00:07:19.280
to me if you're interested
00:07:21.160
in and persona is learning multiple
00:07:24.400
products within a single platform for
00:07:27.280
example the inquiry product is to build
00:07:30.560
a customer's journey to get verified and
00:07:33.919
the verification product is for checking
00:07:36.720
specific document documentation or
00:07:39.440
biometrics like driving license or
00:07:42.639
social security number or my number for
00:07:45.520
Japan and selfie or yeah whatever and
00:07:49.680
case product is for manual check uh yeah
00:07:53.599
providing a way to correct and summarize
00:07:56.000
for making a decision about an identity
00:07:59.520
and the graph product is to build and uh
00:08:03.440
build and visualize uh networks of the
00:08:07.360
end users to find the fraud stores or
00:08:10.240
scams or something undiscovered
00:08:14.160
and my team's primary product is
00:08:16.400
workflows uh which is a no code tool to
00:08:19.440
automate all operations of platform
00:08:22.479
internally and
00:08:25.080
externally and this is a yeah sample of
00:08:27.680
workflows configuration so this workflow
00:08:30.319
is listening to the event the inquiry is
00:08:33.279
created then making a decision per end
00:08:36.640
user's input on the conditional step and
00:08:40.479
uh learning additional process per that
00:08:42.919
decision among these steps uh we are
00:08:46.399
providing an interesting feature which
00:08:48.880
is called custom
00:08:51.240
code so custom code is the tool to run
00:08:55.600
JavaScript code on no port tool so yes
00:08:59.279
code maybe and this feature generates uh
00:09:02.800
much revenue since it fills the gaps uh
00:09:06.080
which we or our competitors can't cover
00:09:08.800
customers needs by yeah native product
00:09:12.480
uh product natively so customers can
00:09:15.839
write code to make something happens
00:09:18.399
within personaliz platform so arbitrary
00:09:21.600
JavaScript code is executed and for
00:09:24.480
security purposes the we needed to care
00:09:27.360
about sandboxing it and typical
00:09:30.560
implementation of the product like
00:09:32.880
custom code for companies that who don't
00:09:35.920
use JavaScript in backend servers like
00:09:38.560
yeah we are using rails and should be
00:09:41.760
using the function as a service usually
00:09:44.240
so like Amazon lambda or Google cloud
00:09:47.080
functions as a yeah natural choice that
00:09:50.240
we also adopted function as a service as
00:09:54.040
well but then we continuously annoyed by
00:09:58.560
some issues with using function as a
00:10:00.720
service over three years in general uh
00:10:04.640
this adds another yeah points of failure
00:10:08.160
and need to manage environment of
00:10:10.560
function as a service and as network
00:10:13.120
latency and requires some additional
00:10:15.920
maintenance cost for the yeah keeping in
00:10:20.440
infrastructure so while maintaining this
00:10:23.120
system for about three years I was
00:10:25.360
wondering if we could run JavaScript
00:10:28.000
within various servers itself so there
00:10:32.079
are some prior arts like the mini racer
00:10:35.839
which calls the yeah which runs V8 and
00:10:38.760
NodeJS which is also running by V8 and
00:10:42.240
the duct tape is kind of the similar
00:10:45.360
product as quick JS but not supporting
00:10:47.440
the modern JS so actually I ended up
00:10:51.680
with using quickjs since it seems to fit
00:10:55.120
to our use
00:10:58.360
cases but I couldn't find a binding of
00:11:01.920
the quickjs for ruby in public so I
00:11:06.320
thought I should build by myself it will
00:11:10.399
be writing crank to handle quickjs that
00:11:14.560
most of co-workers didn't get this idea
00:11:17.360
because of Cang however that I knew
00:11:20.800
building native extension is not so uh
00:11:23.680
exceptional choice thanks to Ruby Kagi
00:11:26.480
and because yeah and also I had a
00:11:29.519
somewhat experience in Cang when I was
00:11:32.320
in tech courage cosen and uh also in my
00:11:35.920
new grad job I had published a simple
00:11:38.640
native binding of the compression
00:11:41.040
library which is called LZ FX so yeah I
00:11:45.279
published it as a result of team's
00:11:47.839
workshop in
00:11:49.240
cookbat so I experimentally started to
00:11:52.480
build quickjs binding as a personal
00:11:57.000
project so how could I build the quick
00:12:00.480
quick js
00:12:03.000
rv i'd like to say that building a yeah
00:12:06.720
new native function yeah even for now
00:12:09.120
that is very fun so this is a yeah a
00:12:11.760
quick summary from my journey so there
00:12:15.279
are the great modern resources and C
00:12:17.920
ruby is so powerful to use Ruby in C but
00:12:21.519
because of C Ruby so I could build C
00:12:24.800
parts incrementally and starting from
00:12:27.279
writing just Ruby through the
00:12:29.800
implementation I found so much efforts
00:12:32.880
by C Ruby authors for yeah interfacing
00:12:36.160
to handle Ruby by C also that yeah
00:12:40.000
sometimes the AI is like chat GPT helped
00:12:45.839
specifically about the resources so this
00:12:48.800
one the uh lubist walk around the
00:12:51.440
seaside is an amazing series of articles
00:12:54.720
about using Ruby in C i' I'd like to
00:12:58.720
shout out here to the author the Peter
00:13:01.360
Jour who is a Ruby comeer and the
00:13:04.000
speaker at day three
00:13:05.800
tomorrow and I found existing native
00:13:09.200
bindings for other langages as well so
00:13:12.560
they were the great references to learn
00:13:15.279
how I handle quickjs
00:13:19.399
externally for incremental seeing so
00:13:23.200
yeah I could write what I needed by just
00:13:26.079
Ruby so and yes for the first I lo the C
00:13:30.839
to call Ruby's implementation like this
00:13:34.399
code so this code is getting a class
00:13:37.040
object and calling uh yeah cross method
00:13:40.399
on it then I wrote tests by Ruby to
00:13:44.399
ensure it works and once I completed
00:13:47.720
testing started to migrate Ruby's
00:13:50.480
implementations to C and by repeating
00:13:54.240
this that most of implementations are
00:13:56.800
built by C
00:13:59.800
eventually so yeah I enjoyed building a
00:14:02.720
native extensions uh thanks to the
00:14:05.519
Ruby's friendliness
00:14:07.600
now let me show that yeah what I built
00:14:11.360
uh until today for quickjs
00:14:14.519
RV while the core quickjs does
00:14:17.760
JavaScript processing so I could focus
00:14:20.639
on the productizing and the
00:14:22.839
interfacing these three pillars were my
00:14:25.680
main focus sandboxing and the
00:14:28.000
peripherals and the interfacing for
00:14:33.079
Ruby for soundboxing so quickjs
00:14:37.519
has yeah powerful feature which may
00:14:40.560
touch OS resources directly so that kind
00:14:44.399
of Marcus code can do something
00:14:47.720
unpreent so I restricted all those all
00:14:51.440
those features as default and gave
00:14:54.240
options to enable it
00:14:56.199
instead and some essential features for
00:14:59.839
JavaScript we needed so then I provided
00:15:03.760
a replacement which is implemented
00:15:06.240
implemented by C
00:15:10.600
Ruby so for prefields the yeah the
00:15:14.399
biggest missing piece of quick JS is
00:15:17.240
internationalization API this was really
00:15:20.240
important for our custom codes use case
00:15:23.839
so for example that if you call the two
00:15:26.320
ro string of uh date prototype so quickj
00:15:31.279
just ignore us about those
00:15:33.480
formatting so I work worked on providing
00:15:36.720
the peripherals from existing open
00:15:38.800
source
00:15:40.839
projects but uh yeah even if it's
00:15:43.680
bundled and the minified the peripheral
00:15:46.240
implementation is not so small so
00:15:49.839
evaluating such the huge bundle
00:15:52.320
peripheral js is a bit cumbersome to
00:15:55.440
even for the quickjs so I needed some
00:15:59.519
creativity on it and I figured it out so
00:16:03.440
quickjs is amazingly supporting
00:16:05.759
compilation of JS code into binary or C
00:16:10.000
C so the bite code is
00:16:12.440
generated so I built a workflow to
00:16:15.600
bundle JS then compile it into C and uh
00:16:20.000
improving it into the quick JS main
00:16:23.240
build that was
00:16:26.440
insane and the main enjoyment was uh was
00:16:30.240
yeah considering about how we want to
00:16:33.040
learn JavaScript from Ruby i' I'd like
00:16:36.560
to introduce these three features which
00:16:39.199
are my favorites
00:16:42.560
so the first one is yeah importing
00:16:45.279
feature the you can import ES module by
00:16:48.160
calling the import method on the runtime
00:16:51.480
instance i try to design to show how I
00:16:55.440
write importings in JavaScript syntax so
00:16:59.120
for the first line uh you can pass a
00:17:01.839
hash to map imported members to local
00:17:06.160
areas yeah it looks like JS and the
00:17:10.160
second one is taking a n for the first
00:17:13.360
argument to list yeah imported members
00:17:17.199
with keeping the the original names and
00:17:20.400
the third one is uh taking a string
00:17:24.480
which is deemed as a default
00:17:26.760
import and the last one you can give
00:17:30.080
arbitrary string which expects the
00:17:32.480
JavaScript syntax directory
00:17:35.600
these are totally powered by Ruby's
00:17:37.840
powerful pattern matching which is
00:17:39.919
relatively new feature and this fe this
00:17:43.520
features implementation is not fully
00:17:45.840
migrated to C lang yet because of the
00:17:49.360
its intuitiveness i decided to keep as
00:17:54.200
Ruby so you can call uh another another
00:17:58.160
feature so you can call the yeah console
00:18:00.640
rogue within JavaScript yeah as same as
00:18:03.679
uh you do in NodeJS or
00:18:06.280
browsers and the recorded logs will be
00:18:09.679
persisted on the consistent runtime as
00:18:12.799
instance variable let me show
00:18:18.200
the now you're
00:18:20.600
seeing
00:18:23.240
okay so against
00:18:26.440
to instance that you can call evil code
00:18:30.960
and let's try console log here
00:18:38.280
hello and uh if you hit the logs method
00:18:44.720
uh yeah it's something yeah decoded so
00:18:48.559
and the logs
00:18:51.320
last is log and then you can take the
00:18:55.360
yeah low data instead of the uh instead
00:18:58.559
of the actual uh representation and also
00:19:02.400
you can see the ser oh it's
00:19:07.160
not so it's info and uh so the you can
00:19:12.799
see you can use another severity as well
00:19:16.480
like the one console one if you do this
00:19:20.400
yeah you can see the
00:19:26.760
warning and uh yeah this is this is my
00:19:30.400
most favorite feature the define
00:19:32.640
function feature the for runtime
00:19:34.880
instance we can define a JavaScript uh
00:19:38.720
JavaScript function which is implemented
00:19:41.039
by Ruby this is so powerful or for
00:19:44.919
example yeah we built our specific HTTP
00:19:48.720
client with our backend implementation
00:19:51.919
so which the yeah requires the some
00:19:54.880
common configurations like proxy or
00:19:57.720
routing yeah or user agent or yeah
00:20:00.400
something and so we use use the this
00:20:04.240
define function feature to provide a
00:20:06.400
custom fetch function for the custom
00:20:08.799
code uh
00:20:10.200
environment also the exceptions can be
00:20:13.600
handled
00:20:15.400
transparently so let me demo
00:20:20.039
again so let's try define
00:20:23.720
something define function so lubiki
00:20:27.960
maybe and this can't take the the
00:20:30.880
argument
00:20:32.679
like maybe here
00:20:35.159
is and okay this part is total Ruby
00:20:41.000
and be
00:20:44.120
quy and uh yeah would be integer so try
00:20:49.440
to do this and
00:20:52.360
and then in JS and give you a
00:20:56.840
code so you can call Ruby
00:21:00.039
Kai and
00:21:07.240
2025 yeah it's running the yeah Lies
00:21:11.360
method from JS and also the Yeah let's
00:21:15.120
see the exception so if you have some
00:21:20.640
custom error based on the standard error
00:21:24.440
and so let's define something
00:21:28.679
to this is interesting that yeah we can
00:21:32.000
provide a lace function in JS uh so
00:21:37.440
maybe
00:21:39.400
message and uh send my
00:21:44.600
error
00:21:46.120
new
00:21:47.799
the
00:21:51.080
message and let's call
00:21:54.840
it
00:21:56.840
so late uh
00:22:00.600
s c s c s c s c s c s c s c s c s c s c
00:22:01.600
sess
00:22:08.280
Oh
00:22:10.679
oh
00:22:18.120
oh
00:22:20.919
sness sorry
00:22:24.760
uh
00:22:27.240
why then yeah you can see the exception
00:22:30.480
is
00:22:32.520
happen and uh also yeah it's interesting
00:22:36.159
but you can catch this within
00:22:43.480
the catch uh maybe you can take copy and
00:22:48.240
the console
00:22:51.640
error and let's take
00:22:55.000
the so exception doesn't happen in lay
00:22:58.880
Rudy's end but if you see the VM logs
00:23:03.440
last yeah it's corrected so this means
00:23:07.280
that yeah this exception was caught by
00:23:11.280
uh JS
00:23:16.760
end so yeah after some incremental
00:23:20.159
implementations
00:23:22.240
uh the end of last year and now replaced
00:23:25.919
existing our custom code system which
00:23:28.240
was powered by function as a
00:23:31.799
service for now the quickjs RB is
00:23:35.360
processing over 4 million per days of
00:23:38.840
invocations so you have cut the cost of
00:23:42.320
function as a service and seeing obvious
00:23:45.280
improvements by cutting HTTP request and
00:23:48.799
the real world usage is now the giving
00:23:51.280
more problems that I have to fix day by
00:23:53.840
day but but so yeah it's nice that real
00:23:56.960
world usage helps me a lot to implement
00:24:00.840
more and this was an expected outcome uh
00:24:05.200
while I was building and testing quickJS
00:24:08.240
RB my coworker adopted my gem for a
00:24:11.440
different purpose before I release in
00:24:14.960
personaliz platform there's DSL to
00:24:18.240
represent a query for data like data dog
00:24:22.320
to compile the DSL that she built uh
00:24:25.679
puzzle by JavaScript and use use quickJS
00:24:29.679
RB to run in back end but it's JS so it
00:24:34.080
can be used in front end as well so that
00:24:37.120
means uh yeah her purpose for the both
00:24:39.760
back end and the front end was achieved
00:24:41.840
by writing just a single uh source code
00:24:45.200
by
00:24:46.039
JS and this was totally unexpected for
00:24:49.120
me originally but I think I found more
00:24:52.559
possibilities of this
00:24:56.520
gem all right so let me lap up this
00:25:01.320
presentation and so QuickJS RB repo is
00:25:05.120
on GitHub and uh yeah for me the
00:25:08.080
building native extensions was so fun so
00:25:11.360
I to I highly recommend and uh I
00:25:15.279
appreciate for this opportunity speak up
00:25:17.440
here in Ruby Kai and lastly the yeah
00:25:20.559
persona is hiring nice rubists like you
00:25:24.000
and let me know if you are interested in
00:25:26.240
I have some swag like stickers and the
00:25:28.640
key caps for the yeah token of my
00:25:31.720
referral then that's it thank you