<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[leaningtech - Medium]]></title>
        <description><![CDATA[Leaning Technologies&#39; Blog - everything WebVM, Cheerp, CheerpJ, CheerpX, compile-to-WebAssembly and WebAssembly virtualization - Medium]]></description>
        <link>https://medium.com/leaningtech?source=rss----469d4d2b1c11---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>leaningtech - Medium</title>
            <link>https://medium.com/leaningtech?source=rss----469d4d2b1c11---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Fri, 13 Nov 2026 22:09:22 GMT</lastBuildDate>
        <atom:link href="https://medium.com/feed/leaningtech" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Sunsetting our Developer's Blog on Medium]]></title>
            <link>https://medium.com/leaningtech/sunsetting-our-developers-blog-on-medium-61b09c00b409?source=rss----469d4d2b1c11---4</link>
            <guid isPermaLink="false">https://medium.com/p/61b09c00b409</guid>
            <category><![CDATA[cheerpx]]></category>
            <category><![CDATA[cheerp]]></category>
            <category><![CDATA[webassembly]]></category>
            <category><![CDATA[cheerpj]]></category>
            <dc:creator><![CDATA[Alessandro Pignotti]]></dc:creator>
            <pubDate>Fri, 10 Mar 2023 17:21:40 GMT</pubDate>
            <atom:updated>2023-03-10T17:25:24.576Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*ctLhzCQqtWVvOlfT" /></figure><p>Dear readers,</p><p>All future technical posts about our technologies, including Cheerp, CheerpJ, CheerpX, and WebVM will, from now on, be only published on our own blog <a href="https://leaningtech.com/news/?q=technicalblog">https://leaningtech.com/news/?q=technicalblog</a>.</p><p>The purpose of this short post is to make sure members of the Medium community are aware that we have continued moving the state of the art of compilers and virtual machines for the Web forward.</p><p>Over the last few years, our technical write-ups have received many thousands of visits here on Medium. That has made us proud and kept us motivated to publish high-quality technical content which, <a href="https://medium.com/p/5123117b1ee2">in some cases</a>, has become a reference of sorts for the whole field.</p><p>Around one year ago, we made the decision to prioritize <a href="https://leaningtech.com/news/?q=technicalblog">our own blog</a> and domain, as the primary source for all our posts. Although Medium is somewhat helpful in making content more visible, after looking at the statistics, we concluded that maintaining a Medium mirror of our content is not worth the effort.</p><p>To celebrate the impact that Medium had on us, let me share a small list. Here are the three most-read articles that we published:</p><ul><li><a href="https://medium.com/p/40a60170b361"><strong>WebVM: server-less x86 virtual machines in the browser</strong></a><strong>: </strong>Where we announced the launch of <a href="https://webvm.io/">https://webvm.io</a>, a virtual Linux environment running fully client-side in the browser. This was our most impactful post ever, which is not surprising considering the opportunities that this technology opens.</li><li><a href="https://medium.com/leaningtech/preserving-flash-content-with-webassembly-done-right-eb6838b7e36f"><strong>Preserving Flash content with WebAssembly done right</strong></a><strong>: </strong>Another significant milestone for Leaning Technologies: the first announcement for our plans of solving the problem of Flash content preservation by using our x86-to-WebAssembly virtual machine (CheerpX)</li><li><a href="https://medium.com/leaningtech/a-javascript-optimizing-compiler-3fd3f49bd071"><strong>A JavaScript optimizing compiler</strong></a><strong>: </strong>An example of our more research-oriented results. It’s interesting that a few other people have re-invented the same ideas in the meantime :-)</li></ul><p>To avoid missing any of our future posts, make sure to <a href="https://twitter.com/leaningtech">follow us on Twitter</a> and join our <a href="https://discord.leaningtech.com/">Discord server</a>.</p><p>Leaning Technologies’ developers, including myself, are always available to answer any questions you might have about our tech and products. See you there!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=61b09c00b409" width="1" height="1" alt=""><hr><p><a href="https://medium.com/leaningtech/sunsetting-our-developers-blog-on-medium-61b09c00b409">Sunsetting our Developer&#39;s Blog on Medium</a> was originally published in <a href="https://medium.com/leaningtech">leaningtech</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[WebVM: Linux virtual machine in the browser with full networking via Tailscale]]></title>
            <link>https://medium.com/leaningtech/webvm-linux-virtual-machine-in-the-browser-with-full-networking-via-tailscale-dac11f844b46?source=rss----469d4d2b1c11---4</link>
            <guid isPermaLink="false">https://medium.com/p/dac11f844b46</guid>
            <category><![CDATA[webassembly]]></category>
            <category><![CDATA[x86]]></category>
            <category><![CDATA[cheerpx]]></category>
            <category><![CDATA[virtual-machine]]></category>
            <category><![CDATA[networking]]></category>
            <dc:creator><![CDATA[Yuri Iozzelli]]></dc:creator>
            <pubDate>Thu, 06 Oct 2022 11:09:24 GMT</pubDate>
            <atom:updated>2022-10-07T06:57:42.873Z</atom:updated>
            <content:encoded><![CDATA[<h3>WebVM: Linux virtualization in WebAssembly with full networking via Tailscale</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zdFYYjkaPHApMIKlYN9zlA.png" /></figure><p><a href="https://webvm.io/">WebVM</a> is a virtual Linux environment running fully client-side in the browser.</p><p>It is based on CheerpX: our WebAssembly powered x86 virtualization technology. Thanks to a powerful JIT recompilation engine, and an ext2 block-based filesystem, it makes it possible to run large scale use cases: GCC / Clang / Python / Node.js / Ruby and many other things are supported out-of-the-box.</p><p>But something important was missing: networking.</p><p>Networking is the most requested feature of WebVM, and for good reasons: without it, you can only input and output data via the terminal, and you are limited to using what we included in the OS image.</p><p>The main difficulty in adding this feature is that the browser does not expose access to lower-level protocols such as UDP and TCP. You can only do HTTP(S), and even then, you are severely limited by CORS policies.</p><p>What about WebSockets then? A WebSocket connection starts with an HTTP connection with an “Upgrade” header. Then, if the upgrade is accepted, the WebSocket protocol takes over. WebSocket packets also have their own header. So they can’t be used transparently to connect to regular TCP sockets.</p><p>In order to connect to arbitrary sockets, we need a proxy server to perform the protocol upgrade and unwrap the WebSocket packets before sending them to the destination (and do the opposite in the other direction).</p><p>Hosting this proxy server spawns a new set of problems:</p><ul><li>We need to pay for and maintain a piece of server-side infrastructure, which needs to scale with the number of users.</li><li>Since our server performs the network requests on behalf of the users, we would become legally responsible for the traffic. The service could be abused by malicious actors.</li></ul><p>To solve the second issue, we would need to require users to authenticate, keep track of their network usage, and effectively become a VPN provider.</p><p>What if we could offload this “VPN provider” business to someone more qualified, then?</p><p>If we could find a VPN service that can be used directly from the browser, we could even eliminate the first issue, and avoid the need to host any server infrastructure ourselves.</p><h3>Meet Tailscale</h3><p><a href="https://tailscale.com/">Tailscale</a> is a VPN service based on the <a href="https://www.wireguard.com/">WireGuard</a> protocol. It includes a control plane that manages the WireGuard keys of all the machines in the network and takes care of authenticating users.</p><p>Since it’s built on top of WireGuard, and WireGuard uses UDP for communication, you would think that we are back to square one.</p><p>One of the features of Tailscale, though, is the ability to let machines connect with each other directly in a mesh network. It achieves this by providing <a href="https://en.wikipedia.org/wiki/STUN">STUN</a> servers for <a href="https://en.wikipedia.org/wiki/Network_address_translation">NAT</a> traversal.</p><p>Sometimes even the STUN server can’t punch through the NAT, so as a fallback mechanism, Tailscale provides DERP servers.</p><p>A <a href="https://tailscale.com/blog/how-tailscale-works/#encrypted-tcp-relays-derp">DERP</a> (Detoured Encrypted Routing Protocol) server is used to relay traffic when two peers cannot connect directly. Since it’s designed to circumvent even the most annoying firewalls, it communicates using regular HTTPS and Websockets.</p><p>That’s exactly what we need!</p><p>Now we just need to reimplement the Tailscale control plane protocol, the DERP protocol, and the WireGuard protocol in the browser, and we are set.</p><p>Just kidding! Luckily for us, the official Tailscale client (written in Go) <a href="https://github.com/tailscale/tailscale/tree/main/cmd/tsconnect">compiles to Wasm</a>.</p><p>By slightly modifying their browser ssh client (tsconnect), and implementing a custom Tun device, we successfully communicated with a Tailscale network by just sending/receiving IP packets on a JavaScript MessageChannel!</p><h4>About Go and Wasm</h4><p>I was pleasantly surprised by how easy it is to compile Go code to Wasm.</p><p>You just need to set the environmental variables GOOS=js GOARCH=wasm, and ship $(go env GOROOT)/misc/wasm/wasm_exec.js alongside the wasm module.</p><p>Of course, your dependencies need to support the wasm target (and in my case, the folks at Tailscale did all the work).</p><p>One downside is the size of the compiled wasm module: 16MB!</p><p>Wasm-opt didn’t help much either: it shaved just 1MB. For comparison, the whole CheerpX VM fits under 6MB.</p><p>For this reason, the networking code is lazily loaded only if you attempt to log in to Tailscale.</p><h3>TCP/IP Stack</h3><p>With surprisingly little work, we can now exchange IP packets from a Browser. Unfortunately, most applications don’t send raw IP packets, but use TCP or UDP to communicate.</p><p>We could build a TCP/IP stack from scratch, but hopefully, we can find an existing one.</p><p><a href="https://savannah.nongnu.org/projects/lwip/">Lwip</a> (written in C) seems to be a common choice in the embedded world. It was pretty easy to compile it to Wasm with <a href="https://github.com/leaningtech/cheerp-meta">Cheerp</a>, and to add a “driver” for our MessageChannel network interface.</p><p>The only missing part is to implement a bunch of network-related syscalls in CheerpX using lwip, and we are good to go.</p><h3>Demos</h3><p>Enough with the theory, what can we do with this thing?</p><h4>SSH</h4><p>The most straightforward use of a network-enabled WebVM is to use it as an ssh client:</p><p>You can access other machines in your Tailscale network (and beyond, if you have an exit node) from any browser, in a privacy-preserving way. Your keystrokes are not only encrypted, but they don’t touch our servers at all.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*i2Oc_qU4D2vE6khxp8xmeA.gif" /></figure><p>You can also use ssh to easily move files in and out of WebVM. This increases the scope of what you can practically do in WebVM, since you can now import code/data to execute and export the result of your work.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*2HFiFR_Ilmx-FZTpQpWFKg.gif" /></figure><h4>Full stack web development</h4><p>A more ambitious goal is to use WebVM as a full-stack development platform.</p><p>Admittedly, we are not really there yet, but networking is an important step towards that goal.</p><p>In the next demo gifs, you can see me:</p><ul><li>downloading a Python git repository from github.com</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*zrRHnw6rv_NJ-Jjsnplo6A.gif" /></figure><ul><li>installing dependencies with pip</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*qUHuLcyMSb-Jq8XnmmMGZg.gif" /></figure><ul><li>running a Flask web application that includes a Sqlite database for persistent storage, and access it from a second browser tab</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*hgQ2TCZmiC20RDb_gRlElA.gif" /></figure><ul><li>access it from another WebVM tab, with lynx</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*NtYa51VuelasYzNYAEpRVw.gif" /></figure><ul><li>edit the application, commit to git, and push back to github</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*rYNrQnj6ZpclYOVJUyrb-g.gif" /></figure><p>It is certainly not fast to install the pip dependencies (some setup scripts are compiling native code there!), but thanks to our IndexedDB-backed filesystem, you only need to do that once.</p><p>And there are of course many more limitations. For example, npm is not working yet, nor is apt. But none of these issues is particularly complex to solve, and our syscall emulation layer is constantly improving (thanks also to the expanded set of applications that we can run with network support).</p><h3>Try it yourself</h3><p>If you want to give it a try yourself, here are the steps to enable network access in WebVM:</p><ul><li>Go to <a href="http://webvm.io/">webvm.io</a> and click “Tailscale Login” in the top right.</li><li>Depending on your network speed, you may need to wait a few moments for the Tailscale Wasm module to be downloaded.</li><li>Log in with your Tailscale credentials.</li><li>If you want to access the public internet, you need an Exit Node. See <a href="https://tailscale.com/kb/1103/exit-nodes/">here</a> for how to set one up. If you just want to access a machine in your Tailscale Network, you don’t need it.</li><li>Go back to the WebVM tab. You will see your IP address in the top right.</li><li>Start firing network requests!</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*cnS8b9PwDO6FPfT5VZjaEQ.gif" /></figure><p>Given the short-lived nature of WebVM, we log into Tailscale as an Ephemeral Node. This means that the node will disappear from your Tailscale Network after a period of inactivity. It also means that when you reload the tab, you need to log in again. It should be faster the second time.</p><h3>What’s next?</h3><p>We are very excited about the possibilities that network support unlocks for WebVM.</p><p>And while we have ideas on what to do next (hint: X11), we are also curious to hear about what you would like to use WebVM for.</p><p>You can get in touch by <a href="http://info@leaningtech.com/">email</a> or on <a href="https://twitter.com/leaningtech">Twitter</a>, or have a chat on our <a href="http://discord.leaningtech.com/">Discord channel</a>.</p><p>If you try something, and it doesn’t work, feel free to open an issue on <a href="https://github.com/leaningtech/webvm">GitHub</a>.</p><p>Discussion on Reddit: <a href="https://www.reddit.com/r/programming/comments/xx3r83/webvm_linux_virtualization_in_webassembly_with/">https://www.reddit.com/r/programming/comments/xx3r83/webvm_linux_virtualization_in_webassembly_with/</a></p><p>Discussion on Hacker News: <a href="https://news.ycombinator.com/item?id=33116245">https://news.ycombinator.com/item?id=33116245</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=dac11f844b46" width="1" height="1" alt=""><hr><p><a href="https://medium.com/leaningtech/webvm-linux-virtual-machine-in-the-browser-with-full-networking-via-tailscale-dac11f844b46">WebVM: Linux virtual machine in the browser with full networking via Tailscale</a> was originally published in <a href="https://medium.com/leaningtech">leaningtech</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[PythonFiddle: Fully private client-side sample code execution and sharing]]></title>
            <link>https://medium.com/leaningtech/pythonfiddle-fully-private-client-side-sample-code-execution-and-sharing-7ee649a392e4?source=rss----469d4d2b1c11---4</link>
            <guid isPermaLink="false">https://medium.com/p/7ee649a392e4</guid>
            <category><![CDATA[compilers]]></category>
            <category><![CDATA[java]]></category>
            <category><![CDATA[vm]]></category>
            <category><![CDATA[cheerpx]]></category>
            <category><![CDATA[python]]></category>
            <dc:creator><![CDATA[Jules Saarikoski]]></dc:creator>
            <pubDate>Wed, 14 Sep 2022 14:40:30 GMT</pubDate>
            <atom:updated>2022-09-14T14:41:39.987Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*9AHfna4BUEsZ8Fc6s_m9DA.png" /><figcaption>PythonFiddle in action</figcaption></figure><p>A recurrent need for anybody practicing programming is running (and sharing) small snippets of code to quickly test an idea or ask for feedback. These kinds of Web applications are generally called ‘fiddles’, and there are plenty of them out there. The common use cases for fiddles are in education, but anyone can find themselves needing to use one to avoid having to set up a full native execution environment.</p><p>Most of these types of fiddles work by sending user code to a virtual machine that runs in the cloud. The program is then executed remotely and the result is sent back. Using a modern cloud environment has lots of advantages, in particular scalability and relatively low costs, but it does leave the developer open to a few issues:</p><ul><li><strong>Privacy</strong>: There are two parties who need to be concerned about privacy: the user and the service provider. For users the main concern is what is done with their data. Will it be stored on the servers or possibly left accessible in logs. The provider on the other hand will need to know what they can and cannot do with user data, and if they’ll need to inform or ask the user for consent. This is particularly true in cases where the data isn’t just code snippets.</li><li><strong>Security</strong>: Allowing execution of arbitrary, user-written code can leave service providers vulnerable to abuse. It’s possible to harness the computational power meant for running the application for malicious purposes, like DDoS attacks or crypto mining. These are real problems for any platform that allows anonymous execution. This problem is extremely difficult to solve, since users are fundamentally unpredictable, whether we are speaking of the code they produce or their intentions with the application. Often primitive solutions such as timeouts, quotas and banning packages or libraries are used as a workaround.</li><li><strong>Cost</strong>: As low as the computing costs might be, somebody will still need to fork over the payment for those servers. The scalable nature of the cloud implies that, as the project gains more success, the costs will also scale. This may become an issue for single developers, Free and open-source software projects, or non-profit organizations.</li></ul><p>An ideal alternative to cloud-based execution would be to take an existing language implementation and port it to the browser environment. The effort required will of course depend on the language ported and complexity of implementation, but it’s reasonable to expect it will be significant. On top of the effort put into the porting process, it will be easy to introduce brand new issues, and none of the work will automatically translate to supporting a new language.</p><p>Several years ago we released <a href="http://javafiddle.leaningtech.com/">JavaFiddle</a>, a client-side execution environment, that was able to address most of the problems mentioned above. It’s based on <a href="http://leaningtech.com/cheerpj">CheerpJ</a>, our solution to compile and execute Java bytecode on the browser in <a href="https://webassembly.org/">WebAssembly</a> and JavaScript. Because of this, JavaFiddle is able to run Java applications sandboxed in the browser. This solution worked very well and the application gained quite some use.</p><p>Now we’re releasing <a href="http://pythonfiddle.leaningtech.com/">PythonFiddle</a>, a similar environment, that allows the user to play around with python. This time, however, it’s based on <a href="http://leaningtech.com/cheerpx">CheerpX</a>, our WebAssembly based x86 virtual machine, that is able to run any program that is compiled to x86 assembly. This solution will allow us to bring a similar solution to many different language implementations, and much more.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/852/0*o-URuAfTdPnfXd_T" /><figcaption>A fiddle implementation using the cloud vs using CheerpX</figcaption></figure><h3>What is CheerpX?</h3><p>CheerpX is a virtual machine that is able to run x86 executable programs in the browser. It’s based on WebAssembly, a new bytecode for the browser intended to be used as a compilation target for programming languages. CheerpX has a two tiered execution engine composed of an interpreter and a just-in-time compiler. The interpreter runs rarely executed assembly instructions and generates metadata for the JIT, which in turn can generate efficient Wasm modules for frequently run code.</p><p>Working directly with machine code has several advantages for CheerpX:</p><ul><li><strong>Robustness</strong>: most programs will just work without issues. Compiling from source to Wasm is technically possible, but would lead to us needing to support many more individual use cases, and a lot of software wouldn’t be viable for execution.</li><li><strong>Versatility</strong>: There are also cases where there is no source code available for compilation, like Flash. This will not be an issue for CheerpX either.</li><li><strong>Accuracy</strong>: Applications will run identically to the way they work in native.</li></ul><p>As an added bonus, CheerpX provides extensive support for file manipulation using a virtualized file system based on Ext2. The disk blocks are downloaded on demand from our CDN to minimize network usage. The blocks are themselves cached using <a href="https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API">IndexedDB</a> to avoid redundant downloads on later visits. As the file system and all the changes made in it are stored in the browser’s local IndexedDB, none of this data will appear on our servers either, which makes this solution both extremely scalable and privacy preserving.</p><h3>What is PythonFiddle?</h3><p>PythonFiddle is composed of a few components:</p><ul><li><strong>CheerpX</strong>: runs the python interpreter with the user-written code snippet in real time in the browser.</li><li><strong>Debian buster disk image</strong>: gives access to a complete file system.</li><li><strong>Xterm.js</strong>: provides a full terminal experience, including formatting and support for curses-based apps.</li></ul><p>Being able to leverage the features mentioned above gives us a slew of advantages on this project:</p><ul><li><strong>Native-like execution</strong>: with access to a proper file system and multiprocessing capabilities, the users will be able to take advantage of most functionalities of python without issues. This includes read/write access to a full Debian file system image, multithreading, subprocess and most python libraries.</li><li><strong>Privacy-preserving code sharing</strong>: To share code, it is compressed and encoded as a hash of the url using lz-string, and then decoded on the receiving side directly from the url. This way users can share their code without it having to pass through our servers. You can test it by using this <a href="https://pythonfiddle.leaningtech.com/#A4JwlgdgLgFARACTAAgGYgPYFtkEMRRgDGANgKZwCUQA">link</a>.</li><li><strong>Robust against abuse</strong>: since code execution occurs entirely sandboxed to client-side and nothing will be sent to our servers, we are safe from any form of undesired usage.</li><li><strong>Scalability without costs</strong>: all processing and execution occurs client-side, which means that a minimal amount of our resources will be spent, even if the amount of users grows considerably.</li></ul><p>Although we believe PythonFiddle (and the updated JavaFiddle) to be useful in themselves, CheerpX has the potential to be used in much more sophisticated applications. The possibilities are not limited to language implementations either, but any x86 code can run safely client-side. It’s a stable technology already exposed to the public via the many demos we’ve released over the past months. The most recent demo, WebVM, runs a full terminal session in a debian distribution in the browser. This shows just how complex the tasks CheerpX can achieve are.</p><p>Integrating CheerpX in web apps isn’t complicated either. The fiddle itself is just a thin layer on top of the CheerpX API. To run any program, you’ll only need to call the `CheerpX.run(…)` API call with the program, and CheerpX will take care of everything.</p><pre>CheerpX.run(“python3”, [“-c”, “print(’Hello world!’)”], env); </pre><p>CheerpX is already incredibly versatile technology, but nevertheless we’re continuously adding more functionality. Currently we’re implementing networking capabilities and support for running graphical applications. This would allow the creation of even more complex demos and applications. The possibilities are endless.</p><p>As CheerpX is so adaptable, there are certainly many use cases we have not thought of yet, and therefore we are looking for partners who will bring CheerpX to unexplored markets. If you have a fantastic idea that could be made into a reality using CheerpX, please get in touch:</p><p><strong>Email</strong>: <a href="/service/mailto:info@leaningtech.com">info@leaningtech.com</a></p><p><strong>Twitter</strong>:<a href="https://twitter.com/leaningtech"> https://twitter.com/leaningtech</a></p><p><strong>Discord</strong>: <a href="http://discord.leaningtech.com/">discord.leaningtech.com</a></p><p><strong>Web</strong>:<a href="https://leaningtech.com/cheerpx"> https://leaningtech.com/cheerpx</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7ee649a392e4" width="1" height="1" alt=""><hr><p><a href="https://medium.com/leaningtech/pythonfiddle-fully-private-client-side-sample-code-execution-and-sharing-7ee649a392e4">PythonFiddle: Fully private client-side sample code execution and sharing</a> was originally published in <a href="https://medium.com/leaningtech">leaningtech</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Fantastic tail calls, and how to implement them.]]></title>
            <link>https://medium.com/leaningtech/fantastic-tail-calls-and-how-to-implement-them-8c6bd52fd271?source=rss----469d4d2b1c11---4</link>
            <guid isPermaLink="false">https://medium.com/p/8c6bd52fd271</guid>
            <category><![CDATA[webassembly]]></category>
            <category><![CDATA[compilation]]></category>
            <category><![CDATA[cheerpx]]></category>
            <category><![CDATA[webkit]]></category>
            <dc:creator><![CDATA[Tom Tartarin]]></dc:creator>
            <pubDate>Mon, 11 Jul 2022 15:07:05 GMT</pubDate>
            <atom:updated>2022-07-11T15:07:05.020Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*uGnCVzfFHDbTzozcC-_hpw.png" /><figcaption><em>Think about your memory: recycle your frame!</em></figcaption></figure><p>Recursion is one of the fundamental primitives of computer science. Many algorithms came to life by simplifying a general problem into recursive sub-problems. From the perspective of code, recursion implies that a function would call itself as part of its logic. Since stack is consumed for each instance of the function, excessive recursion depth will cause what is known as a stack overflow: a problem significant enough to become the namesake of the biggest programming Q&amp;A platform on the planet!</p><p>If a recursive call happens to be in tail position (i.e. just before the function returns), this issue can be solved by using <em>tail recursion</em>. In this context, we could assume the caller’s stack frame can be reused before jumping into the callee, turning these calls into <em>tail calls</em>. This is a key concept in CPS (Continuation Passing Style), used by some functional programming languages where functions do not return but instead invoke a routine on their result, using tail calls to avoid exhausting the stack.</p><p><a href="https://medium.com/leaningtech/extreme-webassembly-1-pushing-browsers-to-their-absolute-limits-56a393435323">WebAssembly</a> is a modern bytecode that can be natively and efficiently run in browsers. It is designed to be a suitable compiler target for most other programming languages, including functional ones. Speed and efficiency being at the core of WebAssembly’s design, it is unsurprising that tail calls were <a href="https://github.com/WebAssembly/tail-call">proposed as an extension to the standard.</a></p><p>For a proposal to become a fully approved standard, a few steps are required, including being implemented by two different browser engines. V8, the engine used in Chrome and Edge, added support for WebAssembly tail calls in 2020. It was a step in the right direction, but since then, <a href="https://medium.com/leaningtech/extreme-webassembly-2-the-sad-state-of-webassembly-tail-calls-f5d48ef82a87">the state of the proposal has been stagnating</a>.</p><p>As Apple’s <a href="https://webkit.org/blog/6240/ecmascript-6-proper-tail-calls-in-webkit/#:~:text=What%20is%20a%20Proper%20Tail,is%20called%20a%20stack%20frame.).,">Webkit already implements proper tail calls in ECMAScript 6</a>, we thought it would be a good target to implement the feature and try to move the status of the proposal forward, eventually towards full standardisation.</p><p><strong>This article aims at demystifying WebAssembly tail calls while giving the reader an idea of how we have implemented the feature in WebKit.</strong></p><h3>Let’s refresh our memory…</h3><p>There are different ways of representing function arguments at the machine level, these are named “calling conventions”. We will focus on how the call stack is allocated and how arguments are passed in JavaScriptCore, Safari’s JavaScript engine. Similar reasonings can apply to other environments.</p><p>The following C code shows a classic example of a tail-recursive solution to compute and print the factorial of a number.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/03c9e5f24b4309cb7059f1ae6f53dafc/href">https://medium.com/media/03c9e5f24b4309cb7059f1ae6f53dafc/href</a></iframe><p>Let’s focus on the first recursive call in factorial.</p><p>Two definitions are needed:</p><ul><li>The caller: factorial 0, the first instance of factorial.</li><li>The callee: factorial 1, the first tail-recursive call to factorial.</li></ul><p>To understand what happens at the machine level, we need to introduce two players: the frame pointer, which refers to the first byte of the current frame, and the stack pointer, which represents the top of the stack. Between them lies the data of our function. In JavaScriptCore, this would include stack values, virtual registers, local variables and the call frame header. The latter contains the state required to “return”, including the previous frame pointer and the caller’s instruction pointer.</p><p>Arguments are used to carry information from the caller to the callee. There are two ways of passing them: in registers or on the stack. The register approach is ideal since operations on them are much cheaper. This cannot be always done though, since we might have more values than registers available, in which case they will be “spilled” onto the stack. Managing stack space is one of the critical aspects of implementing tail calls.</p><p>When factorial 0 calls factorial 1, we will first go through the callee’s prologue:</p><pre>push $arg0          \<br>push $arg...        |   caller’s frame (factorial 0)<br>push $argN          |<br>call $factorial     /<br>    push %rbp        \<br>    mov %rsp, %rbp    |  callee’s frame (factorial 1)</pre><p><em>Note: this is a tracing representation of pseudo assembly instructions in x86 AT&amp;T syntax.</em></p><p>This grows the stack by the size of a register, and stores the previous frame pointer (%rbp). The return address is already written on the stack automatically by the CPU.</p><p>After that, anything can happen in the function as long as we reach the epilogue, symmetrically opposite:</p><pre>push $arg0           \<br>push $arg...         |   caller’s frame (factorial 0)<br>push $argN           |<br>call $factorial      /<br>    push %rbp         \<br>    mov %rsp, %rbp    |<br>    ...               |    callee’s frame (factorial 1)<br>    mov %rbp, %rsp    |<br>    pop %rbp          |<br>    ret               /</pre><p>The first instruction resets the stack pointer to the address of the previous frame. The pop instruction corresponds to the push in the prologue and it will restore the stack frame as it was before entering the callee, allowing the caller to access its local data again. ret will redirect the control flow using the address stored at the top of stack by the last call instruction, allowing us to go back to the caller’s frame.</p><p>If we call factorial with 1 as an argument, factorial 1 ends the recursion and we go through two epilogues:</p><pre>push $arg0    \<br>push $arg...  |   caller’s frame (factorial 0)<br>push $argN    |<br>call fib      /<br>    push %rbp         \<br>    mov %rsp, %rbp    |<br>    ...               |    callee’s frame (factorial 1)<br>    mov %rbp, %rsp    |<br>    pop %rbp          |<br>    ret               /<br>mov %rbp, %rsp \<br>pop %rbp       |   caller’s frame (factorial 0)<br>ret            /</pre><p>This is wasteful and can be optimized. Here lies the concept of tail call elimination, through which we consider the callee as an extension of the caller.</p><h3>How it can be done in WebAssembly: return_call</h3><p>The following shows the WebAssembly equivalent of our factorial example, with tail calls enabled.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/285b8a883b0610044c1b0ce6ff95a20e/href">https://medium.com/media/285b8a883b0610044c1b0ce6ff95a20e/href</a></iframe><p>In JavaScriptCore, WebAssembly would be first parsed and validated, then native code would be generated to delegate execution to the machine.</p><p>Since tail calls are a variant of regular calls, we could reuse most of the existing infrastructure in the engine. A new routine was added to prepare the frame before entering the callee’s prologue. These modifications do not require runtime gathered information, thanks to WebAssembly’s static typing.</p><p>Let’s examine the stack at factorial 1 call site: the first time factorial 0 recursively calls itself. For the sake of simplicity, we will abstract the call chain <strong>print_factorial → factorial 0 → factorial 1</strong> to <strong>A → B → C</strong>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/866/1*8tuklMtmc-G1tzJK6o_5pA.png" /><figcaption><strong>Figure 1. </strong><em>The stack at C (factorial 1) call site.</em></figcaption></figure><p><strong>B</strong> contains the return_call instruction, so it must be responsible for adapting the stack. We don’t need its frame after it performs a tail call.</p><p>We will thus merge <strong>B</strong> and<strong> A</strong>, before jumping into <strong>C</strong>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/810/1*-xRpQOiwI79zHbFfx9cFdQ.png" /><figcaption><strong>Figure 2.<em> </em></strong><em>The stack after rearrangement, before tail calling into C (factorial 1).</em></figcaption></figure><p>Notice what changed in<strong> B</strong>’s data. We made sure <strong>C </strong>will return to <strong>A</strong>, by preserving the value that was pushed into the stack when<strong> A</strong> first called <strong>B</strong> (Fig. 1). Later on, we will make sure to start <strong>C</strong> with a jmp instruction instead of call to prevent the CPU from overwriting the saved return address.</p><p>While <strong>C</strong> is an extension of <strong>B</strong>, it still depends on information that<strong> B</strong> is responsible for. That is why we reused <strong>A</strong>’s stack space to store <strong>C</strong>’s arguments (Fig. 2). To carry this out, we needed to know how much stack slots <strong>B</strong> and <strong>C</strong> required. We could get that information by reasoning on the functions’ signatures during static analysis.</p><p>Fortunately, we didn’t have to worry about variable arguments, since they are not part of WebAssembly’s design. We could then compute a new stack offset, and copy what is needed from <strong>B </strong>to <strong>A</strong>.</p><p>Interestingly, from the perspective of <strong>A</strong>, we could say that <strong>A </strong>and<strong> B</strong> have been merged. At this point, we are ready to jump into <strong>C</strong>.</p><p>We will now compare a deeply recursive call to factorial, both with and without using return_call.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*x9de8JweKzwBZwOiB-4BQw.png" /><figcaption><strong>Figure 3.<em> </em></strong><em>Comparison of the stack in a deeply recursive routine.</em></figcaption></figure><p>It becomes apparent that with return_call, we only use one frame for factorial and all potential recursions of it.</p><h3>Arguments vs. Return values</h3><p>WebAssembly also supports multiple return values. This implies that the stack used by arguments equally stores the callee’s return values. This plays well with tail calls, since we can assume that <strong>A</strong> has enough space for <strong>B</strong>’s return values (Fig. 4). The tail calls specification also ensures that <strong>B</strong> can only tail call a function that returns the same number of values. However, this raises a concern regarding their offsets on the stack</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/386/1*d3jpYbO9TPmNtU1GxhapTw.png" /><figcaption><strong>Figure 4.<em> </em></strong><em>Stack at B call site. A reserved space for B’s return values</em></figcaption></figure><p>The previous convention implemented by JavaScriptCore would prepare the frame as in Fig. 4, placing the return values closer to the stack pointer. With tail calls, we introduce the possibility of the frame being reused, which changes the size of the stack in case of a chain of calls with a varying number of arguments. In such a situation,<strong> A</strong> won’t be able to find the return values at the expected offsets (Fig. 5).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/954/1*oPumHN1qARa23hPPQO1dog.png" /><figcaption><strong>Figure 5.<em> </em></strong><em>Stack at different stages of the </em><strong><em>A</em></strong><em> -&gt; </em><strong><em>B</em></strong><em> -&gt; </em><strong><em>C</em></strong><em> tail call chain. </em><strong><em>C</em></strong><em>’s number of arguments modified the stack size of </em><strong><em>A</em></strong><em>. Even if the return count was preserved with </em><strong><em>C</em></strong><em>’s signature, </em><strong><em>A</em></strong><em> expects the return values at incorrect offsets when </em><strong><em>C</em></strong><em> returns.</em></figcaption></figure><p>This is due to the fact that offsets for stack values are computed statically when parsing code for a function. As a solution, we changed the convention to encode return values at the opposite side of the stack, closer to the caller’s frame pointer.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/951/1*DcEHV1nJyX-wJZLGtVI1iA.png" /><figcaption><strong>Figure 6.<em> </em></strong><em>Same depiction as in Fig. 5, with offsets that allow </em><strong><em>A </em></strong><em>to properly collect return values.</em></figcaption></figure><p>When <strong>A</strong> restores the stack pointer as if it had called<strong> B</strong>, it is able to find the return values where expected.</p><p>We therefore have demonstrated a viable implementation of tail calls in WebAssembly. While being rather straightforward conceptually, the feature has to find its place in a complex codebase with many moving parts involving the stack, for example: exception handling. The implementation is still going through reviews at the time of writing and I invite you to <a href="https://github.com/WebKit/WebKit/pull/2065">consult the pull request</a> for a more technical follow-up.</p><h3>The next steps</h3><p>We hope to see WebAssembly tail calls land in JavaScriptCore soon. This would effectively push the proposal to the next phase, paving the way for a full standardisation.</p><p>Our original motivation for making tail calls available in WebKit / Safari, and eventually in the WebAssembly standard, is improving the performance of CheerpX: our virtual machine designed to <a href="https://webvm.io/">run x86 binaries in the browser</a>. As stated in <a href="https://medium.com/leaningtech/extreme-webassembly-2-the-sad-state-of-webassembly-tail-calls-f5d48ef82a87">our previous article</a>, enabling tail calls in WebAssembly would allow us to reduce the JIT-ted code overhead in the case of indirect jumps, which are commonly used to implement library calls.</p><p>Broadly speaking, the standardisation will help modern browsers in supporting modern programming language features such as C++20 coroutines, which LLVM represents as a call with the ‘musttail’ marker. This cannot be appropriately represented in WebAssembly without tail calls.</p><p>Through this contribution, we aim to move WebAssembly tail calls from an experimental state to a fully standardized feature, making it available for everyone on all major browsers.</p><p>If you are interested in the ever-evolving world of in-browser virtualization, we invite you to follow us on <a href="https://twitter.com/leaningtech">Twitter</a> and <a href="https://medium.com/leaningtech">Medium</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8c6bd52fd271" width="1" height="1" alt=""><hr><p><a href="https://medium.com/leaningtech/fantastic-tail-calls-and-how-to-implement-them-8c6bd52fd271">Fantastic tail calls, and how to implement them.</a> was originally published in <a href="https://medium.com/leaningtech">leaningtech</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[CheerpJ 2.3 released]]></title>
            <link>https://medium.com/leaningtech/about-cheerpj-658669c77330?source=rss----469d4d2b1c11---4</link>
            <guid isPermaLink="false">https://medium.com/p/658669c77330</guid>
            <category><![CDATA[applet]]></category>
            <category><![CDATA[compilers]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[java]]></category>
            <category><![CDATA[cheerpj]]></category>
            <dc:creator><![CDATA[Lorenzo Marsicano]]></dc:creator>
            <pubDate>Tue, 03 May 2022 10:23:57 GMT</pubDate>
            <atom:updated>2022-05-03T10:39:05.913Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*VyVHbGaj0UsdqLdgWMsOGA.png" /></figure><p>CheerpJ is a solution to run unmodified Java applications on the browser, in WebAssembly and JavaScript.</p><p>It is based on two components: a full Java runtime environment in WebAssembly and JavaScript, and an ahead-of-time Java bytecode to JavaScript compiler. By combining these two elements, CheerpJ provides an environment to run any type of Java application (stand-alone, Java Applet, Java libraries) as a pure HTML5 Web application.</p><p>CheerpJ, originally released around 5 years ago, is trusted by <a href="https://leaningtech.com/cheerpj/">many large organizations</a> to:</p><ol><li>Preserve access to critical internal Java clients (Java applets and stand-alone applications) without relying on legacy browsers, and without a client-side Java installation;</li><li>Convert existing Java products into HTML5, and provide them to external users as a browser-based experience;</li><li>Integrate complex Java components as part of web applications, or develop new web-based interfaces to Java-based products.</li></ol><p>CheerpJ 2.3 is the only solution on the market to migrate real-world large-scale Java applications to modern HTML5 with pixel perfect accuracy.</p><h3>CheerpJ at a glance</h3><p>CheerpJ can be used to run Java bytecode on the browser as WebAssembly/JavaScript.</p><p>It is intended to work as a pure-HTML5 replacement to the JVM, and allow any type of unmodified Java client to run on the browser.</p><p>Being compatible with 100% of the Java 8 language (including reflection and all dynamic features), as well as with the full Java 8 runtime, it can run any application including Swing clients, AWT clients, and any complex frameworks, including Oracle Forms.</p><p>Thanks to Java-JavaScript bidirectional interoperability, CheerpJ can also be used to integrate Java libraries as part of web applications, or to rewrite UIs to legacy Java clients.</p><p>CheerpJ provides several browser-based system functions, including virtualized file systems, I/O, networking and audio.</p><p>Since release 2.2 (release notes <a href="https://leaningtech.com/cheerpj-2-2-released/">here</a>), there have been improvements in how files are read and written in our custom file system, class generation now allows for non-ASCII fields to be present and improvements in how network connections are handled have been made. The full Change log for version 2.3 of CheerpJ is available <a href="https://docs.leaningtech.com/cheerpj/Changelog">here</a>.</p><h3>Getting started</h3><p>CheerpJ 2.3 is <a href="https://leaningtech.com/cheerpj/#download">available</a> for Windows, macOS and Linux. You can download it, integrate it and test it with no restrictions.</p><p>You can head to our <a href="https://docs.leaningtech.com/cheerpj/">Documentation</a> for examples and tutorials.</p><h3>How to upgrade to CheerpJ 2.3</h3><p>To try out or update to CheerpJ 2.3, simply download the compiler <a href="https://leaningtech.com/download-cheerpj/">here</a> , and rebuild your project with the new compiler.</p><p>If using the CheerpJ cloud runtime, make sure to change your CheerpJ runtime header to</p><p>&lt;script src=”<a href="https://cjrtnc.leaningtech.com/2.3/loader.js">https://cjrtnc.leaningtech.com/2.3/loader.js</a>&quot;&gt;&lt;/script&gt;</p><p>The old 2.2 version will keep working, but the only way to gain the benefits of this new release is to change the runtime endpoint and regenerate the jar.js files.</p><p>Please notice that using the new runtime with a jar.js generated with the 2.2 compiler is unsupported and might lead to unexpected behaviors.</p><h3>Download and try CheerpJ</h3><p>If you have never tried our compiler before it’s really easy!</p><p>Just only have to use our compiler that you can find here and update your HTML page hosting the applet or create a simple HTML for it.</p><p>You can follow <a href="https://docs.leaningtech.com/cheerpj/">this link</a> to our wiki and follow the <a href="https://docs.leaningtech.com/cheerpj/Getting-Started">Getting Started</a> for detailed instructions.</p><p>You can also try CheerpJ online using our <a href="https://javafiddle.leaningtech.com/">Java Fiddle</a>.</p><h3>Future releases</h3><p>We have exciting news for the next release, more of which will be shared in the coming months!</p><p>For CheerpJ 3.0 we are planning a complete redesign of the compiler based on the lessons we learned from working on <a href="https://medium.com/leaningtech/running-flash-in-webassembly-using-cheerpx-an-update-d500b6fbc44e">CheerpX</a> and <a href="https://medium.com/leaningtech/webvm-client-side-x86-virtual-machines-in-the-browser-40a60170b361">WebVM</a>.</p><p>The new architecture, that we are currently designing, will bring improvements to startup time, download size and compatibility with sophisticated Java frameworks.</p><p>CheerpJ 3.0 will, one more time, redefine what running Java in the browser means.</p><h3>Get in touch!</h3><p>To report any issues, please use our issue tracker. For any question or comment, you can find us on the <a href="https://gitter.im/leaningtech/cheerpj">CheerpJ Gitter channel.</a></p><p>Feel free to get in touch also on:</p><p><strong>Email</strong>: <a href="/service/mailto:info@leaningtech.com">info@leaningtech.com</a></p><p><strong>Twitter</strong>: <a href="https://twitter.com/leaningtech">https://twitter.com/leaningtech</a></p><p><strong>Github</strong>: <a href="https://github.com/leaningtech/cheerpj-meta/">https://github.com/leaningtech/cheerpj-meta/</a></p><p><strong>Web</strong>: <a href="https://leaningtech.com/cheerpx">https://leaningtech.com/cheerp</a>j</p><p>Thank you!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=658669c77330" width="1" height="1" alt=""><hr><p><a href="https://medium.com/leaningtech/about-cheerpj-658669c77330">CheerpJ 2.3 released</a> was originally published in <a href="https://medium.com/leaningtech">leaningtech</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[PartialExecuter: Reducing WebAssembly size by exploring all executions in LLVM]]></title>
            <link>https://medium.com/leaningtech/partialexecuter-reducing-webassembly-size-by-exploring-all-executions-in-llvm-f1ee295e8ba?source=rss----469d4d2b1c11---4</link>
            <guid isPermaLink="false">https://medium.com/p/f1ee295e8ba</guid>
            <category><![CDATA[llvm]]></category>
            <category><![CDATA[webassembly]]></category>
            <category><![CDATA[benchmark]]></category>
            <category><![CDATA[cheerp]]></category>
            <category><![CDATA[compilers]]></category>
            <dc:creator><![CDATA[Carlo Piovesan]]></dc:creator>
            <pubDate>Thu, 10 Mar 2022 15:40:33 GMT</pubDate>
            <atom:updated>2022-03-10T15:41:38.367Z</atom:updated>
            <content:encoded><![CDATA[<p>Partial Executer is a brand-new LLVM optimization pass that uses an Interpreter-like engine to prove some code will never be executed, making it safe to eliminate it.</p><p>In this article, I will explain the ideas behind it, the engineering challenges, and the results of this work.</p><h3>LLVM basics</h3><p>Some basic understanding of LLVM internals will be helpful, if you are already familiar with such concepts feel free to skip ahead.</p><p>The basic process of compiling is:</p><ul><li>a program is first represented as a collection of source files</li><li>code is transformed by the front end into an equivalent IR (=Intermediate Representation)</li><li>optimization passes transform the original IR into a more compact and performant IR</li><li>the optimized IR is converted into an executable for a given target</li></ul><figure><img alt="Schema for LLVM compilation model" src="https://cdn-images-1.medium.com/max/1024/0*4cATbGCD39v7J292" /></figure><p>The advantage of this architecture is that different concerns are separated in different components:</p><p>Language specific semantics and checks are only needed in the first step (source -&gt; IR).<br>Target specific information is only needed in the last step (IR -&gt; executable)</p><p>We will concentrate now on the “middle-end”, where IR to IR transformations are performed.</p><p>One of the core features of the LLVM framework is the vast amount of sophisticated optimizations which are done in this stage.<br>The Intermediate Representation of functions will be a graph (representing the control flow) connecting groups of statements that are executed sequentially (Basic Blocks).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/811/1*jOc7kIsYj-P1P76Lp5KfcA.png" /><figcaption>Example of Control Flow Graph linking together blocks of Instructions: the IR for left_shift and cos</figcaption></figure><h3>The problem: reducing code size</h3><p>I work on a C++ to WebAssembly &amp; JavaScript compiler, <a href="https://leaningtech.com/cheerp/">Cheerp</a>.</p><p>There is quite some magic involved in the various details, but at a high level this is just another compiler. The source code is parsed, optimized, and code-generated. The main visible difference is that instead of a native executable, <a href="https://docs.leaningtech.com/cheerp/">Cheerp</a> generates a .js and a .wasm file.</p><p>The code is then embedded, either directly or as dependency, in a HTML page and it’s loaded on first use before being executed. Load time will directly impact users and reducing the code size is a more critical concern compared to your typical native target.</p><p>An important part of the development of Cheerp is working on improving the generated code size, and so there was I, tasked with staring at LLVM’s IR and looking for new optimization possibilities.</p><h3>Getting a baseline</h3><p>I knew there had to be code that was never actually executed since other optimizations I touched in the past started from this assumption.</p><p>You might have heard of dead-code elimination, an LLVM optimization pass that removes code proven as unreachable. I was actually interested in less-obvious situations. In particular blocks that are reachable on the control flow graph, but not when consider wider execution invariants.</p><p>If there was a way to prove that certain blocks are never executed, they could be then removed and this change would not be observable.</p><p>To get started, I first played a bit with the generated code, adding some assert(false) in the suspicious parts. I executed the code and the assertion seemed to never be triggered.</p><p>Then I took a more systematic approach: instrumenting the generated code, running it on a diverse set of inputs, and collecting statistics about never executed blocks. I then removed such code completely and compared the output size to the original one. The potential size improvement seemed significant. I knew I was onto something.</p><p>There were obviously false positives, but I identified a significant test case to start with: printf.</p><h3>Printf</h3><p>printf is a standard C library function that takes a format string and a variable number of other arguments.</p><pre>int printf(const char* format, ...);</pre><pre>printf(“Here a somewhat random number: %i\n”, rand());</pre><p><a href="https://en.wikipedia.org/wiki/Printf_format_string">printf</a> is complex enough to have been shown to be Turing complete (see <a href="https://www.ioccc.org/2020/carlini/index.html">IOCCC</a> or the <a href="https://www.usenix.org/system/files/conference/usenixsecurity15/sec15-paper-carlini.pdf">paper</a>).</p><p>The format string could come from anywhere or be generated at runtime. But in many cases it will be just a string literal, known at compile time.</p><p>Can we use information on the call-sites and the corresponding format strings to prove that some code paths, for example formatting for floating point numbers, are actually never taken?</p><p>And can we do it in a way that is fully agnostic of the actual implementation of printf?</p><p>And can we generalize the approach so that it works on any function?</p><p>It turns out the answer to all 3 questions is “Yes”.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/960/1*vxHhaQ83s1gjNHrIq3HO9A.png" /><figcaption>Control Flow Graph of printf, before and after running PartialExecuter</figcaption></figure><h3>Partial Executer: game plan</h3><pre>runPartialExecuter(Function&amp; Fn)<br>{<br>    Set&lt;BasicBlock&gt; visited;<br>    for each CallSite CS of Fn:<br>        partialExecute(CS, Fn, visited)</pre><pre>    for each BasicBlock BB of Fn:<br>        if visited.count(BB) == 0:<br>            BB.replaceWith(unreachable)<br>}</pre><p>The logic that we have to perform is: keep a set of visited blocks across all functions, iterate all call-sites, and then eventually remove blocks that have never been visited.</p><p>Simple enough. The devil is then in the implementation of the partialExecute function, but we can start with a simpler problem and see whether we can make any progress in solving printf.</p><h3>Step 1: arguments known, no interaction with global state</h3><p>Say a function doesn’t load or store global data, and all its call sites have known arguments.</p><p>Then it’s only a matter of using an interpreter and executing one instruction after the other. Eventually, branches will be interpreted and correctly predicted, so it is trivial to follow the flow of the function.</p><p>Fortunately as part of the LLVM framework there is an interpreter for LLVM’s IR, so we can reuse the existing ExecutionEngine / Interpreter infrastructure.</p><p>We start by populating the arguments with the known values and registering a callback to inform us about instructions that have been visited, and let the ExecutionEngine do its job.</p><p>Another problem we have to solve is a Computer Science classic: “Is this function ever going to terminate?” (<a href="https://en.wikipedia.org/wiki/Halting_problem">the halting problem</a>).<br>Here we will use a trivial approach, whenever a Basic Block (= sequence of Instructions) is executed more than a fixed amount of times, we stop the interpreter while marking all Basic Blocks in the function as visited.</p><h3>Step 2: allowing Stores to global state</h3><p>Say that we store to global memory but we never load (= read) values from it.</p><p>Since we will never load, there is no way to observe whether a value has actually been stored or not. So while interpreting we can ignore stores, since they are not observable.</p><p>Here we are adding a new insight: at interpreter time we are not actually interested in full execution. A more relaxed <em>partial execution</em> is sufficient.</p><p>Consider as an example this code:</p><pre>void someFunc(int n)<br>{<br>    someGlobal = 42;<br>    if (n == 57)<br>        //some stuff<br>}</pre><p>And we know that for all call sites the argument ’n’ will be different than 57.</p><p>Here we could safely transform someFunc to:</p><pre>void someFunc(int n)<br>{<br>     someGlobal = 42;<br>}</pre><p>Setting someGlobal to 42 will be observable by the rest of the program, so it has to remain in the function, but we can still process the rest of the function and possibly optimize it.</p><h3>Step 3: allowing Loads from non-mutable global state</h3><p>Here things will start getting interesting.</p><pre>void processString(const char* ptr)<br>{<br>    if (*ptr)<br>        // do something with ptr<br>    else<br>        // String it’s empty, fail <br>}</pre><p>Say that the interpreter needs to decide what branch should be executed. Doing so requires loading from the memory pointed by ptr and checking its value.</p><p>Can the load be actually performed by the interpreter?</p><p>While initializing the ExecutionEngine we will determine (using IR information) that certain ranges in memory are known to be read-only, and while performing Loads we can query whether the loaded pointer is included in those ranges.</p><h3>Step 4: skipping Instructions</h3><p>In step 2 we used the fact that Stores are not observable to skip them over, but we can generalize the logic further, since there are many more reasons that could cause an Instruction not to be evaluated by the interpreter, for example:</p><ul><li>some of its operands might not be known (e.g. a function argument that is unknown at interpreter time)</li><li>it’s a load from a memory location we can’t prove read-only</li><li>it’s an instruction that can’t be interpreted (e.g. gettimeofday())</li></ul><p>Bailing out and marking any Instruction in the current function as visited is always a valid fallback, but we can do better and try to preserve information further.</p><p>We can mark a given Instruction as unknown, and go to the following one. Note that instruction with unknown operands will themselves tagged as unknown.</p><p>This logic is sound, given that we are never loading from mutable state, all observable effects an Instruction can have are encoded on its computed value. If we keep track of which values have been computed, we can use the information to decide which Instructions have to be skipped.</p><p>With this approach we can robustly deal with any instruction we cannot interpret, as long as it does not impact the control flow.</p><p>Handling non-predicted control flow is the next step.</p><p>To recap, the visiting algorithm at this point has the following components:</p><ol><li>a set of visited Basic Blocks</li><li>a map between Instructions and their computed values (for a given call site)</li><li>a function to decide what Instructions have to be skipped (informed by the map 2)</li><li>the Interpreter logic that from an instruction and its operands compute the value</li></ol><h3>Step 5: Fun with graphs</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_TK3DR7hSon508wo9UVE6g.png" /></figure><p>Here is how printf begins. It performs some allocations, then checks whether some global state has been properly initialized and branches based on that.</p><p>In our current model, this is a big show stopper.</p><p>Fortunately, it is possible to expand the logic further to non-predicted control flow instructions.</p><p>Looking at the control flow graph, it seems like we could just say “skip the first two blocks”, but we would need a formal way to decide where in the CFG we should resume execution.</p><p>It’s time for Strongly Connected Components.</p><p>The basic algorithm for <a href="https://en.wikipedia.org/wiki/Strongly_connected_component">SCC decomposition</a> works as following:</p><pre>1. assign each Basic Block to its own component. Edges between blocks becomes edges between components</pre><pre>2. as long as there are cycles in the component graph, merge them in a single (connected!) component</pre><pre>3. the SCC graph will have now no cycles, and each component will represent a group of Basic Blocks.</pre><p>Absence of cycles means the SCC-graph is now a Direct Acyclic Graph (<a href="https://en.wikipedia.org/wiki/Directed_acyclic_graph">link</a>), that has the useful property to be topologically sortable.</p><p>Intuitively we can treat each Strongly Connected Component as a separate sub-function, and visit them in order.</p><p>We will start from the component containing the entry point. We will visit it, collecting the outgoing edges.</p><p>While visiting a given component we will iterate over the edges that reach it from outside, determining how many possible entry points there are.</p><p>If there are none, the component (and so the blocks it represent) will never be visited, so we can go to the next one.</p><p>If there is a single possible starting Basic Block, we will treat it as the entry point of the function, and proceed from there.</p><p>In some rare cases, there might be more than one. In such case, we bail out marking every Block in the component as reachable (also including every outgoing edge).</p><p>I know we are already deeply in graph territory here, but we have to dig further, stay with me for the very last step.</p><h3>Step 6: Recursive fun with graphs</h3><p>Some of you may have noticed a gap in the previous reasoning: how do we treat edges that loop back in what we considered an entry point of a component?</p><p>Back-edges will invalidate whatever knowledge we gained. Any way to avoid that?</p><p>At the very high level, what we will be doing is making a copy of the (unique) starting block for a given component. All edges from within the component to the starting block will be routed to its copy.</p><p>Now the starting block has no incoming edges any more, so we can proceed to interpret it without fears that eventual back-edges will force us to backtrack.</p><p>Even better, since there will be no incoming edges from within the component, we can use the SCC algorithm once again to further split the blocks, recursion!!</p><p>What we will be doing is basically visiting loops in depth, hoping that they terminate in a given number of iterations. If that happens, great, we can propagate information downstream. Otherwise we backtrack, mark the current component and all its outgoing edges as visited and go to the next Strongly Connected Component.</p><p>To guarantee termination, we will use the same approach as step 1: we keep a counter of how many times a given Basic Block is visited, bailing out if greater than a fixed amount. This bounds the total running time of this optimization to linear in the number of Instructions. (<em>waving hands</em>)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/960/1*vxHhaQ83s1gjNHrIq3HO9A.png" /><figcaption>Before and after PartialExecuter has been performed on printf.</figcaption></figure><h3>Recap</h3><p>Partial Executer allows the removal of proven unused code, decreasing code size.</p><p>To get there, we have used the fact that Functions are mostly independent to partially execute them and prove that some Basic Blocks are never part of any possible execution path.</p><p>Removing code has an indirect benefit as it might unlock further optimizations. Compilers are a game of small gains, and any additional piece of information may be leveraged by the following stages.</p><h3>The End!!</h3><p>Thanks for following me to here, I will be looking forward to any feedback (<a href="https://twitter.com/carlo_piovesan">@carlo_piovesan</a>).</p><p>Partial Executer has been shipped together with the <a href="https://medium.com/leaningtech/cheerp-2-7-compile-cpp-to-webassembly-plus-javascript-c9b3ef7e318b">Cheerp 2.7 (rc1) release</a>. Code is available <a href="https://github.com/leaningtech/cheerp-compiler/blob/master/llvm/lib/CheerpWriter/PartialExecuter.cpp">here</a>, issues <a href="https://github.com/leaningtech/cheerp-meta">here</a>, benchmarks and release article <a href="https://medium.com/leaningtech/cheerp-2-7-compile-cpp-to-webassembly-plus-javascript-c9b3ef7e318b">here</a>.</p><p>I would like to thank all my colleagues at <a href="https://leaningtech.com/">Leaning Technologies</a> for the brainstorming sessions, guidance and reviews that helped put this optimization together.</p><p>Kitchen sink for loosely related information that did not fit in the article or have been added afterwards:<br>- Yuri Iozzelli’s work on <a href="https://docs.leaningtech.com/cheerp/Cheerp-PreExecuter.html">PreExecuter</a> had a different angle while using the same components<br>- <a href="https://webvm.io/">WebVM</a> / <a href="https://leaningtech.com/cheerpx-for-flash/">CheerpX</a> developments by Alessandro Pignotti informed the choices made here</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f1ee295e8ba" width="1" height="1" alt=""><hr><p><a href="https://medium.com/leaningtech/partialexecuter-reducing-webassembly-size-by-exploring-all-executions-in-llvm-f1ee295e8ba">PartialExecuter: Reducing WebAssembly size by exploring all executions in LLVM</a> was originally published in <a href="https://medium.com/leaningtech">leaningtech</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Cheerp 2.7: compile C++ to WebAssembly + JavaScript]]></title>
            <link>https://medium.com/leaningtech/cheerp-2-7-compile-cpp-to-webassembly-plus-javascript-c9b3ef7e318b?source=rss----469d4d2b1c11---4</link>
            <guid isPermaLink="false">https://medium.com/p/c9b3ef7e318b</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[cpp]]></category>
            <category><![CDATA[webassembly]]></category>
            <category><![CDATA[cheerp]]></category>
            <category><![CDATA[compilers]]></category>
            <dc:creator><![CDATA[Carlo Piovesan]]></dc:creator>
            <pubDate>Thu, 24 Feb 2022 13:38:13 GMT</pubDate>
            <atom:updated>2023-07-27T14:16:32.499Z</atom:updated>
            <content:encoded><![CDATA[<h3>Cheerp 2.7: compile C++ to WebAssembly plus JavaScript</h3><p>Today we are releasing Cheerp 2.7, an unique tool for creating WebAssembly and JavaScript-based libraries from C++ code bases.</p><p>UPDATE, 10th March: <a href="https://medium.com/leaningtech/partialexecuter-reducing-webassembly-size-by-exploring-all-executions-in-llvm-f1ee295e8ba">in depth article on PartialExecuter</a> is out.</p><p>Powerful JavaScript-C++ interoperability, support for exceptions and for ES6 modules, and performance and code generation improvements built on top of LLVM’s clang are now available at these links:</p><p><a href="https://github.com/leaningtech/cheerp-compiler">GitHub</a> | <a href="https://github.com/leaningtech/cheerp-meta/issues">Issues</a> | <a href="https://leaningtech.com/cheerp/#download">Install links</a> | <a href="https://docs.leaningtech.com/cheerp/">Documentation</a> | <a href="https://discord.leaningtech.com/">Discord server</a></p><p>The whole team at <a href="https://leaningtech.com/">Leaning Technologies</a> is proud to share the progress done in the last year of development, the benchmark’s results, documentation and tutorials.</p><figure><img alt="Cheerp logo" src="https://cdn-images-1.medium.com/max/959/1*FfXFkzlq8GOCgi6odSh-nQ.png" /></figure><h3>Cheerp in use</h3><ul><li>a Virtual Machine that runs arbitrary x86 exes in-browser -&gt;<a href="https://webvm.io/">WebVM</a></li><li>the Web-based version of an architectural CAD -&gt; <a href="https://home.by.me/en/">home.by.me</a></li><li>a cartoonish multiplayer game (WebRTC included!) -&gt; <a href="https://teeworlds.leaningtech.com/">TeeWorlds-web</a></li></ul><p>What have these projects in common?</p><p>Those are complex Web applications, they all rely heavily on interactions with a multitude of browser APIs and external libraries (interoperability ✔), they all require to be lean and performant (optimizations ✔), and all have central components that are C++-based (compiler ✔). And they are made with Cheerp.</p><figure><img alt="Example of Cheerp results: WebVM, home.by.me and TeeWorlds web" src="https://cdn-images-1.medium.com/max/925/1*fRM6TDU-6jJzcukE2BwYoQ.png" /></figure><p>The examples are diverse, but the intuition is the same:</p><ul><li>Browsers are among the most widely available technology, and they act as a standardisation layer allowing both existing tools and new projects to reach new users.</li></ul><p>JavaScript engines (Chrome’s V8, Safari’s JavaScriptCore or Firefox’s SpiderMonkey), are an efficient sandbox mechanism that allows code to be executed directly on-device.</p><p>Code running in browsers is restricted to be either JavaScript or, since its introduction in 2018, <a href="https://github.com/WebAssembly/design">WebAssembly</a>.</p><p>How to transform a C/C++ codebase (normally compiled as a native executable) to a WebAssembly or JavaScript-based library encoding the same logic?</p><p>Cheerp is based on LLVM’s clang, an industry standard compiler, and the same process that allows C++ code to be compiled to native is followed:</p><ul><li>code is parsed, eventual warnings and errors are emitted, and then a equivalent IR (=Internal Representation) encoding the input program is generated</li><li>the IR is optimised by a series of transformations into more compact &amp; more performant IR</li><li>the optimised IR is finally code-generated as a combination of JavaScript and WebAssembly functions and variables</li></ul><figure><img alt="Diagram of compilation pipeline: C++ to Cheerp to JavaScript and WebAssembly" src="https://cdn-images-1.medium.com/max/1024/1*b7t77tQOMQoXszaGrDlvyA.png" /><figcaption>C++ codebase -&gt; Cheerp (with LLVM’s optimizations) -&gt; JS + Wasm</figcaption></figure><p>Once the .js and .wasm files are generated, it’s a matter of serving those 2 static files, embedding them into the relevant HTML pages, building functionality on top of the library’s API, and testing whether all is in order.</p><p>Invoking Cheerp again after any change or iteration on your C++ codebase leads to regenerating the files, ready to served instead of the previous versions.</p><h3>Why Cheerp?</h3><p>A wide array of other tools exist to help developers create better JavaScript and WebAssembly libraries, but Cheerp is a powerful bridge between two very different models: garbage-collected JavaScript and linear-memory based WebAssembly. And Cheerp’s capabilities unify across the JavaScript / WebAssembly divide, allowing projects developed with Cheerp to be completely encoded in C++.</p><p>Why is this fundamental?</p><ul><li>Whole program optimizations and analysis are enabled (improving performances and footprint in way that would be otherwise not reachable)</li><li>Allows all output to be code generated by a single tool, that means simplifying the process and allow for simpler debugging</li><li>The same tool will perform checks in all different components (emitting errors and warnings when things get out of sync). This can significantly improve developers productivity.</li><li>Allows to leverage both C++ and JavaScript ecosystems</li><li>Allows to leverage WebAssembly capabilities as efficient compilation-target</li><li>Allows your libraries to have more powerful interfaces</li></ul><p>One example to get more concrete:</p><pre>typedef bool(JSComparator)(client::Object* a, client::Object* b);</pre><pre>[[cheerp::jsexport]]<br>void stableSort(client::Array&amp; array, JSComparator compareFunc)<br>{<br>    const unsigned int len = array.get_length();<br>    std::stable_sort(&amp;array[0], &amp;array[0] + len, compareFunc);<br>}</pre><p>What is this about?</p><p>This port the implementation of std::stableSort to JavaScript.</p><p>Example of usage while integrated is:</p><pre>var someArray = [];<br>//populate someArray<br>stableSort(someArray, (a,b) =&gt; (a &lt; b));</pre><p>The input is “regular” C++ with just two additional features:</p><ul><li>client::Array and client::Object classes, forward declared by cheerp-provided libraries</li><li>the <a href="https://docs.leaningtech.com/cheerp/JSExport-attribute">[[cheerp::jsexport]] attribute</a> (used to signal that the function should be part of the external interface)</li></ul><p>The output is also “regular” JavaScript, ready to be included in whatever project or library.<br>Here in particular we generated a function taking a JS-callback and modifying an arbitrary Array-like object.</p><p>It could have been adding CSS properties or classes, interacting with the DOM when a callback is fired, creating objects of the same class either in C++ code or in JavaScript code, or basically whatever is required in your domain. Cheerp’s flexibility in both using and producing powerful interfaces means less constraints are put on how your program could behave.</p><p>The main advantage from using compile-from-C++ components is that the exact same logic is first ported and then executed. This means that non-trivial-to implement algorithms and data structures can easily be ported over.</p><p>Performance wise? This is likely to be the fastest user-land implementation available for a non-adaptive stable sort.</p><p>Then Array.sort it’s already provided, so that should be the recommended solution, but you will be positively surprised to discover how compilation-from-C++ might be a powerful, efficient and performant solution in your toolbox.</p><h3>A year of development</h3><p>As with any code base, also Cheerp undergoes iterations of improvements, fixes, added features and round of optimizations.</p><p>There have been many significant contributions since release 2.6, the most visible work from an user perspective has been done on:</p><h4>Rebase to the upstream branch of LLVM</h4><p>Cheerp is an open source fork of LLVM’s clang, rebasing allows any upstream improvement to be enjoyed by Cheerp-processed codebases. New C++ features (eg. -std=c++20) and new optimizations and enhanced warning messages will be up-to-speed with the latest developments.</p><h4>Exception support</h4><p>Cheerp now supports throwing and catching of both C++ exceptions and ‘native’ JavaScript exceptions, allowing both porting of exception-based C++ codebases and easier interaction with any JavaScript library.</p><p>Here an example:</p><pre>[[cheerp::genericjs]]<br>void someAlgorithm(void (*func)(int)) {<br>     //Some arbitrary code<br>}</pre><pre>[[cheerp::genericjs]][[cheerp::jsexport]]<br>void someFunction(void (*userProvidedCallback)(int))<br>{<br>    try<br>    {<br>        someAlgorithm(userProvidedCallback);<br>    }<br>    catch (cheerp::JSException&amp; ex)<br>    {<br>        console.log(“There has been a native JavaScript throw&quot;);<br>    }<br>    catch (...)<br>    {<br>        console.log(“There has been a throw in the C++ code”);<br>    }<br>}</pre><p>Once compiled, this code can be used in JavaScript like this:</p><pre>someFunction(myFunction);<br>someFunction((a) =&gt; {if (a &lt; 0) throw &quot;Argh, a negative number&quot;;});</pre><p>To enable exception support pass the -fexceptions flag at compile time.</p><h4>ES6 modules support</h4><p>Cheerp code generation has gained the ability to generate ES6 modules. This allows Cheerp-compiled libraries to be more easily included in module-based JavaScript deployments. The command line option -cheerp-make-module=es6 allows opt-in, with other options being commonjs, closure or no-module.</p><p>Example of usage at: <a href="https://docs.leaningtech.com/cheerp/ES6-Modules">https://docs.leaningtech.com/cheerp/ES6-Modules</a></p><h4>Removal of -cheerp-cfg-legacy and cheerp-mode</h4><p>We decided to discontinue two command line options.</p><p>-cfg-legacy had effect only in the selection of the internal stackifier algorithm. -cheerp-mode has been replaced already in Cheerp 2.6 by -target option that accepts either cheerp-wasm (the default) or cheerp (equivalent to -cheerp-mode=genericjs).</p><p>On our documentation <a href="https://docs.leaningtech.com/cheerp/Cheerp-specific-clang-options">the complete list of clang options</a>.</p><h4>Correctness, performance &amp; size improvements</h4><p>Following feedback from users and clients, we are always on the lookout for improvements to the parser, adding optimizations or improving code generation. In a year of work there have been plenty of local improvements that will be invisible but for the fact that error messages will be more informative, the code generated will be faster and leaner.</p><p>The other products developed by Leaning Technologies are all based on Cheerp, this means that all the experience we acquired by using our own technology over the last year is reflected in today’s release.</p><h4>Partial Executer</h4><p>In every release cycle we balance expanding the scope of the compiler with new features and improving it’s signature optimization capabilities.</p><p>We are very proud to introduce an innovative optimization technique acting at the LLVM’s IR level: Partial Executer.</p><p>We will soon write a more detailed article, but the basic idea is:</p><blockquote>Given (partial) knowledge of the call-sites, it’s possible to prove that some edges in the Control Flow Graph are never taken?</blockquote><p>If so, then it’s trivial to remove those edges and consequently remove unreachable BasicBlocks.</p><p>The basic idea expands on <a href="https://docs.leaningtech.com/cheerp/Cheerp-PreExecuter">PreExecute</a>, a Cheerp pass that uses LLVM’s own ExecutionEngine to try to complete the execution of the Globals initializers. If successful then it removes those calls while updating the global state.</p><p>Somehow similarly here we use the infrastructure that comes with the ExecutionEngine to execute Instructions coupled with a new components that navigates a function Control Flow Graph doing partial-execution starting from a given Call Site.</p><p>Practical example: printf. Printf takes a format string, that in most cases is known at compile time, plus other arguments that will be generally dependent on information available only at run-time. Can we partially-execute the printf logic that is dependent on the format string while skipping over parts that depends on the actual values to be printed? It turns out we can:</p><figure><img alt="Control Flow Graph diagram for printf function before and after PartialExecuter" src="https://cdn-images-1.medium.com/max/960/1*3byvEa5LGHe5mPBrxmoXgQ.png" /><figcaption>Control Flow Graphs before and after PartialExecuter is run. The arrows connect 3 BasicBlocks showing their position before and after. Most other BBs are proven never visited and removed.</figcaption></figure><p>Current version of PartialExecuter is centered around discover edges that are never taken, but we believe this infrastructure to open up a whole new class of optimizations. Stay tuned.</p><p><em>Note: We will update the article to the detailed explanation. If you are curious, check the code: </em><a href="https://github.com/leaningtech/cheerp-compiler/blob/master/llvm/lib/CheerpWriter/PartialExecuter.cpp"><em>PartialExecuter.cpp</em></a><em>.</em></p><h3>Benchmark results</h3><p><a href="https://emscripten.org/">Emscripten</a>, an alternative C++ to the Web compiler, has an extensive benchmark suite that we have adopted to provide fair comparison.</p><p>Benchmarks have been done between <a href="https://github.com/leaningtech/cheerp-compiler/commit/c8e21713e3f1599440644fc3827004dc034bbca6">Cheerp 2.7 rc1</a> and <a href="https://github.com/emscripten-core/emscripten/commit/26480f25ea7dba78d5968b45fcb3ab0d8d1400e6">Emscripten 3.1.5</a>.</p><p>There are two metrics to be considered, total size of the generated output and execution time.</p><p>For each of the test-cases the sum of JavaScript and WebAssembly output has been computed, normalised to the maximum. Lower is better.</p><figure><img alt="Bar diagram of Cheerp and Emscripten total output size (normalized)" src="https://cdn-images-1.medium.com/max/679/0*nWjfhPHr7-1FF6vz" /><figcaption>Lower is better</figcaption></figure><p>Execution time has been measured against the latest available <a href="https://v8.dev/">V8</a> (the JavaScript engine that powers Chrome and Edge) and <a href="https://spidermonkey.dev/">SpiderMonkey</a> (Firefox), using the latest available packaged versions (<a href="https://storage.googleapis.com/chromium-v8/official/canary/v8-linux64-rel-10.0.139.zip">v8 10.0.139</a> and <a href="https://archive.mozilla.org/pub/firefox/releases/98.0b7/jsshell/jsshell-linux-x86_64.zip">sm 98.0b7</a>). Timing has been measured on a server with TurboBoost disabled and using standard good practices to obtain benchmarks numbers.</p><p>Also here lower is better, and barring some inevitable noise, results should mostly be reproducible even in other settings.</p><figure><img alt="Bar diagram of Cheerp and Emscripten performance on V8" src="https://cdn-images-1.medium.com/max/679/0*yScf4mqRgtukGH1-" /><figcaption>Lower is better</figcaption></figure><figure><img alt="Bar diagram of Cheerp and Emscripten performance on SpiderMonkey" src="https://cdn-images-1.medium.com/max/679/0*aObYQeelnW5Prgez" /><figcaption>Lower is better</figcaption></figure><h3>How to install</h3><p>For instruction and guidance, please visit:</p><p>Install: <a href="https://docs.leaningtech.com/cheerp/Ubuntu-Debian-installation-using-PPA">Ubuntu or Debian</a>| <a href="https://docs.leaningtech.com/cheerp/RHEL8-and-CentOS-8-installation">Red Hat Linux</a>| <a href="https://docs.leaningtech.com/cheerp/Windows-and-macOS-installation">Windows</a> | <a href="https://docs.leaningtech.com/cheerp/Windows-and-macOS-installation">MacOS</a></p><p>Or build directly from source: <a href="https://docs.leaningtech.com/cheerp/Linux-build-instructions">Linux</a> | <a href="https://docs.leaningtech.com/cheerp/Windows-build-instructions">Windows</a></p><p>To get started, why not follow one of the examples (<a href="https://docs.leaningtech.com/cheerp/Getting-started">here</a>). Then just take some simpler component in your domain, write (or adapt) a simple C++ implementation, generate an equivalent component, and substitute the old piece with the new one.</p><p><a href="https://gitter.im/leaningtech/cheerp">Gitter</a> or <a href="https://github.com/leaningtech/cheerp-meta/issues">Github’s issues</a> are the fastest way to get in contact.</p><p>If you prefer to check the code, the Cheerp fork of LLVM is at <a href="https://github.com/leaningtech/cheerp-compiler">cheerp-compiler</a>, while <a href="https://github.com/leaningtech/cheerp-utils">cheerp-utils</a>, <a href="https://github.com/leaningtech/cheerp-libs">cheerp-libs</a> and <a href="https://github.com/leaningtech/cheerp-newlib">cheerp-newlib</a> are external components.</p><h3>Summary</h3><p><a href="https://leaningtech.com/">Leaning Technologies</a> is a technology company with extensive experience in solutions for the Web as a platform.</p><p>We participate in WebAssembly standardisation, pushing the standard to enable further optimizations (branch_hinting and soon tail calls), we improve browser engines (<a href="https://chromium-review.googlesource.com/c/v8/v8/+/3412082">V8</a> and the recently started work on <a href="https://bugs.webkit.org/show_bug.cgi?id=235581">JSC</a>), and we develop and evolve three unique WebAssembly+JavaScript based solutions: <a href="https://leaningtech.com/cheerp/">Cheerp</a>, <a href="https://leaningtech.com/cheerpj/">CheerpJ</a> and <a href="https://leaningtech.com/cheerpx/">CheerpX</a>.</p><p>With Cheerp 2.7, we are giving developers access to the same powerful too we use to make the <a href="https://webvm.io/">WebVM</a> — an in-browser Debian terminal.</p><p>Update your Cheerp version, or give try it for the first time getting started on our <a href="https://docs.leaningtech.com/cheerp/">documentation</a>.</p><p><a href="https://discord.leaningtech.com/">Join our Discord community</a> or <a href="https://leaningtech.com/contact-us/">get in contact</a>, to discover how Cheerp can bring your code to any browser.</p><p>For more of this follow us on T<a href="https://twitter.com/leaningtech">witter</a> and on our <a href="https://leaningtech.com/">website</a>. For additional information, please visit <a href="https://docs.leaningtech.com/cheerp/">Cheerp’s documentation</a>.</p><p><em>Thanks to Alessandro, Jules, Lorenzo, Serena, Yuri and Tom.</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/960/1*Rs6UKG4DSjaMfWHgnXPjNA.png" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c9b3ef7e318b" width="1" height="1" alt=""><hr><p><a href="https://medium.com/leaningtech/cheerp-2-7-compile-cpp-to-webassembly-plus-javascript-c9b3ef7e318b">Cheerp 2.7: compile C++ to WebAssembly + JavaScript</a> was originally published in <a href="https://medium.com/leaningtech">leaningtech</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[WebVM: Client side X86 virtual machines in the browser]]></title>
            <link>https://medium.com/leaningtech/webvm-client-side-x86-virtual-machines-in-the-browser-40a60170b361?source=rss----469d4d2b1c11---4</link>
            <guid isPermaLink="false">https://medium.com/p/40a60170b361</guid>
            <category><![CDATA[virtualization]]></category>
            <category><![CDATA[debian]]></category>
            <category><![CDATA[cheerpx]]></category>
            <category><![CDATA[webassembly]]></category>
            <category><![CDATA[virtual-machine]]></category>
            <dc:creator><![CDATA[Alessandro Pignotti]]></dc:creator>
            <pubDate>Tue, 01 Feb 2022 13:02:10 GMT</pubDate>
            <atom:updated>2023-07-27T14:13:31.773Z</atom:updated>
            <content:encoded><![CDATA[<h3>WebVM: server-less x86 virtual machines in the browser</h3><blockquote>TL;DR — We made a server-less virtual Linux environment that runs unmodified Debian binaries in the browser. This is powered by CheerpX, a WebAssembly virtualization platform. Feel free to play with it and report bugs: <a href="https://webvm.io/">https://webvm.io</a></blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*en0eK_11xULHPZftaG7aPQ.png" /><figcaption>WebVM — a server-less virtual Linux environment running fully client-side in HTML5/WebAssembly.</figcaption></figure><p>The web platform is well on its way to becoming the dominant platform for application distribution. While clear for a long time, this trend has accelerated since the standardization of <a href="https://webassembly.org/">WebAssembly</a>: a new programming language, supported by all modern browsers and designed to fulfil the performance needs of large-scale Web applications.</p><p>WebAssembly brings real innovation to the world of browsers, together with a shift in perspective and responsibilities.</p><p>Engines are traditionally expected to squeeze performance from (potentially poorly) human-written JavaScript. WebAssembly, on the other hand, is designed as a compilation target. Achieving a high level of runtime performance is mainly the responsibility of the <em>compiler generating it</em>. When running WebAssembly, engines can avoid expensive checks and quickly generate high-quality native code. Ultimately, this enables the delivery of much more complex applications via the Web.</p><p>While the vast majority of WebAssembly-generating toolchains are native and used ahead of time, this is not a requirement<em>. </em>As a matter of fact, we believe<em> </em>that <strong>JIT-compiled WebAssembly is the real key to fulfilling the vision of running any application in the browser</strong>.</p><p>Here at Leaning Technologies, our mission is to enable running <em>existing </em>applications:</p><ul><li>without modifications;</li><li>without recompilation;</li><li>fully client-side.</li></ul><p>A few months ago we released the <a href="https://repl.leaningtech.com/">REPL demo</a>, proving that our CheerpX x86-to-WebAssembly virtualization technology could be used to run multiple different REPLs in the browser without any language-specific intervention.</p><p>Today we are proud to announce a major step towards realizing our vision: <a href="https://webvm.io/">WebVM</a>, a full Debian based virtual machine running in the browser, powered by CheerpX.</p><h3>So, what is CheerpX?</h3><p><a href="https://leaningtech.com/cheerpx/">CheerpX</a> is a x86 virtual machine, written in C++ and compiled to a combination of JavaScript and WebAssembly with the <a href="https://leaningtech.com/cheerp/">Cheerp</a> compiler.</p><p>CheerpX has been in development for over three years, and it is already used in production as part of <a href="https://leaningtech.com/cheerpx-for-flash/">CheerpX for Flash</a>, an Enterprise solution to run legacy Adobe Flash content.</p><p>At a high level, CheerpX is composed of</p><ul><li><strong>An efficient interpreter for x86</strong> used to run rarely executed code and to discover the structure of hot code for the purpose of guiding JIT compilation</li><li><strong>A sophisticated x86-to-Wasm JIT compiler</strong>, that generates new WebAssembly modules on the fly from hot x86 code. Although the JIT compiler has some x86 specialized logic, it is mostly target independent.</li><li><strong>A Linux syscalls emulation layer</strong> is used to bridge the gap between the unmodified x86 binaries and the Web environment.</li><li><strong>A block-based filesystem backend</strong>, based on Ext2. Disk images are static resources distributed via HTTP and the CloudFlare CDN. Ext2 was chosen for its proven design and extensibility, and we can easily extend its features over time to be compatible with the more modern Ext3 and Ext4 formats without a full rewrite.</li><li><strong>Privacy-preserving storage for modified blocks</strong>, based on IndexedDB. This client-side-only technology allows any modification made to the filesystem to be persistent, but only to the browser. We don’t see or store any of your data.</li></ul><p>CheerpX is a very complex system with many moving parts. It correctly deals with tricky situations such as self-modifying code, multithreading, multiprocessing, and inter-process communication. Notwithstanding this complexity, CheerpX has already reached a high level of stability.</p><p>Now it feels like the perfect time to release our most-complex demo, yet: WebVM.</p><h3>So, what is WebVM?</h3><p>If you have seen our previous REPL demo, you might notice that WebVM is not conceptually much different. The same core components are used:</p><ul><li><strong>CheerpX</strong> as the execution engine. JavaScript APIs, in particular cx.run(…), are used to start (and restart if required) a <em>bash </em>process. bash can then start other processes as the user types commands.</li><li><strong>Xterm.js </strong>as the main UI component. Xterm.js takes care of interpreting terminal escapes used by applications such as <em>vim, </em>and also sends back user input into CheerpX. Input is made available to the applications via their standard input file descriptor.</li><li><strong>A Debian buster disk image</strong>, in the ext2 format and with a bunch of packages installed. This is distributed over a CDN to maximize scalability.</li></ul><p>WebVM is effectively server-less and has no <em>active</em> server-side component. All users access the same disk image from the CDN, with their individual changes being preserved locally to the browser. This means that we could support even millions of concurrent users with minimal costs and resources.</p><p>Our previous demos were intended as snapshots of CheerpX progress and showcases of the technology potential. WebVM is different in that we consider this to be a <em>living demo </em>that we will evolve over time<em>. </em>Bug reports and feedback are very welcome, over multiple channels:</p><p><strong>GitHub issues</strong>: <a href="https://github.com/leaningtech/webvm/issues">https://github.com/leaningtech/webvm/issues</a></p><p><strong>Gitter chat</strong>: <a href="https://gitter.im/leaningtech/cheerpx">https://gitter.im/leaningtech/cheerpx</a></p><p>CheerpX has been, so far, only exposed to users in a relatively controlled fashion. One single application at a time. WebVM is the first time we really give control to a wider public and we do expect problems to arise. But public feedback will make it possible to discover many more bugs and, ultimately, deliver a more robust solution.</p><h3>What can I do with WebVM right now?</h3><p>We think the <a href="https://webvm.io/">demo</a> will, most likely, speak for itself. If case you are unsure, try this:</p><pre># Run a short python program<br><strong>python3 examples/python3/fibonacci.py</strong></pre><pre># Compile a small C example using gcc<br><strong>gcc -o helloworld examples/c/helloworld.c</strong></pre><pre># Run it!<br><strong>./helloworld</strong></pre><pre># Dump the code, to verify this is actually an x86 binary<br><strong>objdump -d ./helloworld</strong></pre><pre># Edit the helloworld.c file, and try again<br><strong>vim examples/c/helloworld.c</strong></pre><p>Example files for various languages are available in the examples directory. If, for any reason, you don’t like to use gcc, feel free to try clang as well!</p><h3>Where can I run it?</h3><p>WebVM and CheerpX are compatible with any browser, both on Desktop (Chrome/Chromium, Edge, Firefox, Safari), and Mobile (Chrome, Safari), provided support for <a href="https://caniuse.com/?search=SharedArrayBuffer">SAB</a> is present, and the device has sufficient memory.</p><h3>Is this all?</h3><p>This release of WebVM is really just a first step. We plan to improve and evolve WebVM over time, and feedback from users will be guiding our efforts.</p><p>In the short term, this is what the pipeline for the next features of WebVM and CheerpX looks like:</p><ul><li><strong>HTTP servers (microservices)</strong>: By combining Service Workers with virtualized TCP sockets, we will allow HTTP servers inside the WebVM to be reachable from the browser itself. A JavaScript API will be exposed allowing to connect an iframe to the internal servers. This is mostly supported already, although not exposed on the current demo page. A similar solution could be used to support <strong>REST microservices</strong> as well since Service Workers also handle fetch/XHR requests.</li><li><strong>Graphical Linux applications</strong>: CheerpX will soon allow Xorg applications to run in WebVM. Xorg communicates with X clients over <strong>UNIX sockets</strong>, which are already supported. To actually display graphics we will need to emulate a Linux device that Xorg can talk to. The best solution seems to be using KMS devices. Getting to a basic level of support for graphical output to work is mostly a matter of allocating a framebuffer that Xorg can use, and blit that over to an HTML5 canvas for display.</li><li><strong>Windows applications and games</strong>: Using <strong>WINE</strong>, which is a binary-compatible re-implementation of the Windows API libraries. Similarly to Xorg WINE uses UNIX sockets to coordinate applications with the wineserver, which is broadly equivalent to the Windows kernel. In terms of CheerpX support, there might be some fine-tuning needed for our mmap implementation, since WINE needs careful control over a process’ address space. Some specialized features of UNIX sockets, for example, passing of file descriptors, might also need some work. Still, all of these would be small improvements to the existing infrastructure.</li></ul><p>We hope you’ll find WebVM as exciting as we do!</p><p><strong>Join our community on Discord 👉 </strong><a href="https://discord.leaningtech.com/">https://discord.leaningtech.com</a></p><p>Do you think that you have the <em>perfect </em>use case for our technology? Feel free to get in touch: <a href="https://leaningtech.com/contact-us/">https://leaningtech.com/contact-us/</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=40a60170b361" width="1" height="1" alt=""><hr><p><a href="https://medium.com/leaningtech/webvm-client-side-x86-virtual-machines-in-the-browser-40a60170b361">WebVM: Client side X86 virtual machines in the browser</a> was originally published in <a href="https://medium.com/leaningtech">leaningtech</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[CheerpX: Using WebAssembly to run any programming language in the browser]]></title>
            <link>https://medium.com/leaningtech/cheerpx-using-webassembly-to-run-any-programming-language-in-the-browser-3306e1b68f06?source=rss----469d4d2b1c11---4</link>
            <guid isPermaLink="false">https://medium.com/p/3306e1b68f06</guid>
            <category><![CDATA[webassembly]]></category>
            <category><![CDATA[cheerpx]]></category>
            <category><![CDATA[virtualization]]></category>
            <category><![CDATA[repl]]></category>
            <category><![CDATA[python]]></category>
            <dc:creator><![CDATA[Alessandro Pignotti]]></dc:creator>
            <pubDate>Tue, 16 Nov 2021 12:39:33 GMT</pubDate>
            <atom:updated>2021-11-16T12:58:55.730Z</atom:updated>
            <content:encoded><![CDATA[<blockquote>TL;DR — We built a WebAssembly based virtual machine to run X86 binaries in the browser. It’s called CheerpX. You can run any REPL environment with it. Example: <a href="https://repl.leaningtech.com/?python3">https://repl.leaningtech.com/?python3</a></blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*I51GiIvHC4VJmy_H5NVv4A.png" /></figure><p>Historically, JavaScript has been <em>the</em> programming language of the Web. This changed with the introduction of WebAssembly, albeit in a fairly indirect way. WebAssembly itself is not intended to be written manually. You certainly <em>can</em> do that, but similarly to traditional assembly languages, it’s really not advised.</p><p>WebAssembly is, fundamentally, a <strong>compiler target</strong>: a binary representation emitted by a specialized program from a different <strong>source language</strong>.</p><p>This is also reflected in the design of WebAssembly engines themselves, which assume that the incoming bytecode is already well optimized, and most of their internal optimization pipeline is disabled. This is in stark contrast to JavaScript compilation, where decades of work from the best minds in the field have been invested to make low quality JavaScript run <em>fast</em>.</p><p>At the time of this writing, WebAssembly is most commonly generated from C/C++ code using LLVM-based toolchains. When effort has been made to port modern dynamic programming languages, such as Python, the preferred solution has been to compile a C/C++ implementation. To achieve this, stripped down versions may be used, for example disabling JIT support or modules that depend on natively built components.</p><p>Porting a significant C/C++ codebase to WebAssembly is not necessarily a simple endeavor. A programming language implementation will most likely have multiple target-dependent code paths or definition, so the effort required is not dissimilar from porting the language to a new native architecture.</p><p>Then, of course, if after porting Python, you want to port Ruby… well, you need to start from scratch.</p><h3>A better solution</h3><p>It is already possible to find browser based REPLs for some of the most popular programming languages. Some of them are, more or less, complete ports of the corresponding engines from C/C++. Some other services “cheat”, by running the program somewhere on a cloud VM and only using the browser to interact with the user. Cloud based solutions are trivial to implement but also have significant drawbacks in terms of computational costs and user data ownership.</p><p>At <a href="https://leaningtech.com/">Leaning Technologies</a>, we like to build products that solve difficult, general problems and can support multiple use cases at the same time. An example is our flagship technology <a href="https://leaningtech.com/cheerpx/">CheerpX</a>, a WebAssembly powered Virtual Machine whose goal is to safely and efficiently run unmodified X86 binary code in the browser.</p><p>At its core, CheerpX is an emulator for the X86 architecture. Obviously a simple emulator will not get you very far in terms of performance, so we implemented a sophisticated JIT compiler that is able to generate efficient WebAssembly representations for hot code. The whole process is 100% automated and requires no metadata or assumptions whatsoever. The system is so robust that it can actually deal with applications that generate new code internally at runtime, and even with self-modifying code. This means that you can actually run things like NodeJS, including the full V8 engine with its remarkable JIT and code garbage collection.</p><p>As you can imagine, this is a fiendishly complicated problem. When designing CheerpX we decided to only focus on user-mode code (Ring 3), ignoring (for now) the complexities of system level (Ring 0) features. To close the gap and let real world applications run, we have implemented (a subset) of the Linux system calls interface.</p><blockquote>By now it is probably clear that CheerpX can be used to run any programming language REPL in the browser. Instead of porting each language environment manually to WebAssembly, we simply let the whole Linux/X86 build run on top of the CheerpX VM.</blockquote><p>To reach a satisfactory performance and UX, a couple of additional problems had to be solved:</p><p><strong>Terminal output: </strong>CheerpX provides partial support for terminal interaction in the host web page. REPLs tend to use advanced terminal manipulation to enhance the user experience, most usually by including <strong>libreadline</strong>. Instead of investing effort in improving our terminal implementation we have decided, for once, to use an external library: <a href="https://xtermjs.org/">XTerm.js</a>. It works great in most cases, although we had encountered some issues with a couple of the demos.</p><p><strong>Data storage</strong>: Our first iteration of these demos stored data by unzipping an archive into an IndexedDB powered file-system, with each entry in the database being a file or directory.</p><p>This solution did not scale well. Isolating the minimal archive to run a given REPL is, in general, an error-prone process. By shipping too few files we could cause runtime failures, while too many files would increase the download time needlessly. Actually, both situations could even happen at the same time! Moreover REPLs seem to like prodding the filesystem all over the place, with the worst offender being probably NodeJS.</p><p>We have seen even mildly complex scenarios attempting to access thousands of files. IndexedDB did not seem to be very happy about such access patterns.</p><blockquote>The solution to this problem was to integrate a custom <strong>Ext2 </strong>implementation in CheerpX. Disks are represented by HTTP assets, which can be downloaded block-by-block and are cached by a CDN. Since only the required blocks are downloaded we can avoid any effort in optimizing the image size.</blockquote><p>We were actually able to stop maintaining different images for each REPL. We can literally <strong>debootstrap </strong>a Debian setup inside an Ext2 image, install the packages we want and copy it over to an HTTP blob storage. Downloaded blocks are internally cached in IndexedDB to both reduce download time on page reloads while also allowing privacy preserving disk write support. Any data you edit with this configuration is private to your own browser. We don’t see anything.</p><p>Let’s see what we can do by putting all this machinery together, shall we?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*z128Lqgwa4gza2J2YniYug.png" /><figcaption>An overview of the architecture used for these demos.</figcaption></figure><h3>Python3</h3><p>REPL: <a href="https://repl.leaningtech.com/?python3">https://repl.leaningtech.com/?python3</a></p><p>Python is an interpreted, high-level, general-purpose programming language. It’s dynamically typed and garbage collected. It supports both procedural, object-oriented and functional programming.</p><p>This demo features the standard CPython implementation, which does not include a JIT. It compiles the source files (.py) into intermediate bytecode files (.pyc). This is an interesting point: it means that whatever implementation of the underlying filesystem we use, it has to support persistent writes.</p><p>Somewhat surprisingly, we found a possible <a href="https://twitter.com/alexpignotti/status/1438033874572005380">POSIX non-compliance in the way pyc files</a> are written. In our first implementation of the <em>write</em> syscall CheerpX would only save up to a disk block, expecting the application to try again if data was only partially written.</p><p>We believe this to be allowed by POSIX, but real world code seems to have a different opinion. We have since then improved CheerpX to allow “unbounded” writes and reads. Generally speaking nothing can truly be unbounded, neither in CheerpX or on native, so we wonder if Python3 only works because the cache files are relatively small in practice.</p><p>But don’t worry, this bug is<em> most likely </em>not exploitable, and worst case it should be a denial of service. Nothing critical runs on Python right?</p><h3>NodeJS</h3><p>REPL: <a href="https://repl.leaningtech.com/?nodejs">https://repl.leaningtech.com/?nodejs</a></p><p>NodeJS is a server-side JavaScript environment built on top of the state-of-the-art JavaScript engine, <strong>V8</strong>. A REPL is included, as usual, for convenience.</p><p>In the past, whenever we mentioned running NodeJS/V8 in the browser, we have seen people expecting a stripped down pure-interpreter version. That is <em>not </em>what you see here. <strong>This is the unmodified executable shipped with Debian, where the JIT is enabled and used.</strong></p><p>Curiously, the Debian build is not as optimized as it should be. It ships a very thin <em>nodejs </em>executable whose only purpose is to load <em>libnode.so</em> containing the whole program. The shared library does not make proper use of internalized symbols, which means that most (all?) of the function calls happen via the PLT. After noticing this, we have improved the existing support for inlining and devirtualization in CheerpX to effectively convert these indirect calls to direct calls in most cases.</p><h3>Ruby</h3><p>REPL: <a href="https://repl.leaningtech.com/?ruby">https://repl.leaningtech.com/?ruby</a></p><p>A run of-the-mill interpreter. Nothing very interesting was found while working on this. One of my side projects is to actually run the full Rails environment as well, including opening rendered pages inside a separate <em>iframe</em>. This can be done and I have a working prototype already. If there is some interest we may get to publish it as well.</p><h3>Cling</h3><p>REPL: <a href="https://repl.leaningtech.com/?cling">https://repl.leaningtech.com/?cling</a></p><p>C++ is not traditionally interpreted, but like any other programming language it is possible to do so. We used cling (<a href="https://root.cern/cling/">https://root.cern/cling/</a>), an interactive C++ interpreter built on top of LLVM/Clang and developed by CERN. It has a command-line prompt and uses a JIT compiler to evaluate the input line-by-line. Since it’s built on top of Clang, it can parse everything that Clang can parse.</p><p>It’s an extremely complex piece of software that adds to the normal C++ instructions a series of interpreter-specific C++ extensions aimed at making the use of Cling’s shell easier. It features an internal set of commands to print the current AST and to load and execute files. It additionally manipulates the user code into valid C++ code so that it’s possible to compile it with the underlying Clang.</p><p>Example:</p><blockquote>cling$ int i = 1; fun(i++) // perfectly valid Cling instruction</blockquote><p>Becomes</p><blockquote>int i = 1; // global declaration</blockquote><blockquote>void wrap_0() { fun(i++); }</blockquote><p>Of all these demos, Cling is the only one that does <em>not</em> ship by default with Debian. It was installed separately from archives provided by the developers. The cling executable itself is 100+ MBs. To get this monster to load in a reasonable amount of time we implemented lazy loading of ELF executables in CheerpX.</p><p>Most likely the excessive size is caused by the executable not being properly stripped of debug info. We could have stripped it ourselves, but since the point of this exercise is proving that CheerpX works on binaries without any intervention, we decided against it. Just be aware that this demo is not as speedy as others.</p><h3>Lua / Luajit</h3><p>(Lua) REPL: <a href="https://repl.leaningtech.com/?lua">https://repl.leaningtech.com/?lua</a></p><p>(Luajit) REPL: <a href="https://repl.leaningtech.com/?luajit">https://repl.leaningtech.com/?luajit</a></p><p>Lua ships with a very simple interpreter that worked on CheerpX out of the box. Since we like to do complex stuff, we decided to add Luajit to the mix too. We understand it to be a completely separate project from the official Lua interpreter.</p><p>The main issue we found for these demos was user input handling. All the other REPLs use <em>raw</em> terminal input: they are happy to receive control characters such as backspace and newline and process them internally. Lua/Luajit expects <em>cooked</em> terminal input. Xterm.js is not designed for this use case, and has no line-editing support. We have worked the problem around by supporting keystroke <em>echo </em>on our side, and remapping the <em>ENTER</em> key to the expected character. Please note that full line-editing support in CheerpX is lacking, although it can be certainly implemented if need be.</p><h3>What’s next?</h3><p>Of course, we did not go through all the complexity of implementing CheerpX just for these demos.</p><p>CheerpX is the foundational technology to <a href="https://leaningtech.com/cheerpx-for-flash/">CheerpX for Flash</a>, a Flash emulator to run legacy Adobe Flash content in pure HTML5. CheerpX for Flash works by running the Flash player (an X86 binary for Linux) in a way not dissimilar to what we have shown in this post.</p><p>We believe that the REPLs themselves may be useful in the education / training sector, or to let users fiddle with any library (for any programming language) directly from the documentation page. If this sound useful to you, or you have even better ideas, get in touch: <a href="/service/mailto:info@leaningtech.com">info@leaningtech.com</a></p><p>But, really, this is intended to be just the first step of a <em>much</em> more ambitious demo. As we said, we have a full Debian disk image, with dozens of packages installed, and a solid solution to run a single app from it. We want to get to a point where we can drop the users into <em>bash</em>, and let them do what they want.</p><p><strong>We are talking about an always available, zero-cost, virtual machine with guaranteed data privacy</strong>.</p><p>Does that sound not interesting enough? Well, what if you could spawn XOrg and graphical applications on top? What about a full desktop environment?</p><p>I hope this is as exciting for you, as it is for us. And if you think you have the <em>perfect</em> use case for our tech, let us know.</p><p><a href="https://twitter.com/alexpignotti">https://twitter.com/alexpignotti</a></p><p><a href="https://twitter.com/leaningtech">https://twitter.com/leaningtech</a></p><p><a href="https://leaningtech.com/">https://leaningtech.com/</a></p><p><a href="/service/mailto:info@leaningtech.com">info@leaningtech.com</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=3306e1b68f06" width="1" height="1" alt=""><hr><p><a href="https://medium.com/leaningtech/cheerpx-using-webassembly-to-run-any-programming-language-in-the-browser-3306e1b68f06">CheerpX: Using WebAssembly to run any programming language in the browser</a> was originally published in <a href="https://medium.com/leaningtech">leaningtech</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The Bottomless Pit of Disappointment: A Chrome Extension Tale]]></title>
            <link>https://medium.com/leaningtech/the-bottomless-pit-of-disappointment-a-chrome-extension-tale-21e5cf84da0?source=rss----469d4d2b1c11---4</link>
            <guid isPermaLink="false">https://medium.com/p/21e5cf84da0</guid>
            <category><![CDATA[html5]]></category>
            <category><![CDATA[java]]></category>
            <category><![CDATA[webassembly]]></category>
            <category><![CDATA[java-applet]]></category>
            <category><![CDATA[cheerpj]]></category>
            <dc:creator><![CDATA[Alessandro Pignotti]]></dc:creator>
            <pubDate>Tue, 10 Aug 2021 08:43:00 GMT</pubDate>
            <atom:updated>2021-08-10T10:34:14.179Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*HgKDiPFVOmnhzzRCjW5X6w.jpeg" /></figure><p>A bit of a “learn from our pain” / rant / sharing our experience-type blogpost, but here goes.</p><p>At <a href="https://leaningtech.com/">Leaning Technologies</a>, we make compilers and VMs that target JavaScript and WebAssembly. Our tooling is used both to extend the life of existing applications allowing them to run on modern browsers, but also to port and develop new web applications in languages that are traditionally a prerogative of native applications (such as C/C++ and Java).</p><p>As we typically work at the limits of what modern browsers and HTML5 specs allow, we have found (and fixed!) <a href="https://bugs.chromium.org/p/chromium/issues/detail?id=1231027">more</a> <a href="https://bugs.chromium.org/p/v8/issues/detail?id=11861&amp;q=alessandro%40leaningtech.com&amp;can=2">browser</a> <a href="https://bugs.chromium.org/p/v8/issues/detail?id=8384&amp;q=alexpigna.dev%40gmail.com&amp;can=1">bugs</a> <a href="https://bugs.chromium.org/p/chromium/issues/detail?id=896713&amp;q=alexpigna.dev%40gmail.com&amp;can=2">than</a> we’d like, helped improve the performance of <a href="https://bugs.chromium.org/p/v8/issues/detail?id=8508&amp;q=alessandro%40leaningtech.com&amp;can=2">more than one</a> <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1248163">JavaScript</a> engine, and are an active part of the <a href="https://github.com/WebAssembly/branch-hinting">standardization process</a> for WebAssembly.</p><p>Generally speaking, we work in a niche where it’s easy to develop PoCs and small toy projects, and very hard to make robust products. Having a majority enterprise clientele, but also because of our nature, we are the sort of people that always try doing things The Right Way™.</p><p><a href="https://leaningtech.com/cheerpj/">CheerpJ</a>, in particular, is our solution to convert and run any Java client application, fully client-side, in the browser. And when we say “any”, we mean: reflection, proxies, dynamically generated classes, full runtime support (AWT, Swing, etc), threads, you-name-it. CheerpJ is the only tool in the market with these capabilities, and is mostly used by enterprise customers with complex porting and migration requirements.</p><p>As an offshoot of this technology, we have for several years offered a free-to-use Chrome extension (for non-commercial purposes), called <a href="https://chrome.google.com/webstore/detail/cheerpj-applet-runner/bbmolahhldcbngedljfadjlognfaaein">CheerpJ Applet Runner</a>.</p><p>This lets users seamlessly access fully deprecated Java Applets on modern versions of Chrome, without a local Java installation, or a plugin. This is achieved, in essence, by converting the Applet bytecode to HTML5 on the fly, and providing a full Java runtime environment in JavaScript and Wasm.</p><p>Originally developed to have our tech tested as much as possible <em>in the wild</em>, it has become very widely used by people, from all walks of life, who still need to use Java applets on a daily basis. We have helped over 40,000 students, senior card players, artists, law enforcement officers and even major US federal institutions to access content that is way past its selling date. And with a 4.4/5 rating and wide adoption, I think we have been quite successful at that.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*XGehqaRJGxpqMVqS0ZbdEA.png" /><figcaption>Just to be clear, we don’t buy reviews.</figcaption></figure><h3>Not the best way to begin your day</h3><p>In March 2020, as the COVID-19 pandemic began to rage over the planet, I woke up one day to find what any extension developer dreads the most. Two emails, in rapid succession:</p><ol><li>Your recently published update was rejected for policy violations;</li><li>Upon review, your product was found to violate our policies and it has been removed from the store.</li></ol><p>The second email offered us a shimmer of hope: it was possible to reply and appeal to the decision, which we immediately did. We received an automated response that, due to the (at the time) new pandemic and general congestion of the Chrome Web Store, it might have taken a few days to receive an answer.</p><p><strong>Almost 18 months later, we are still to receive an answer to our appeal. </strong>The extension is still up on the store somehow, with a <em>Rejected </em>update in the Dashboard. Because of this, we have decided not to update the extension, or try again with the same update, being worried that the extension might be taken down altogether.</p><p>What this has meant was leaving users with unresolved bugs, and leaving us without the extensive testing that only thousands of end-users can provide to our new releases. Not only that, but there have been several major releases to CheerpJ, the big-sister technology behind this extension, which we have not been able to propagate to the Applet Runner.</p><p>After such a long time, we can’t postpone updates any longer, and can’t continue stalling.</p><blockquote>This post is about our plan to get out of this quagmire, about the inevitable costs of this situation (both for us and our users), and the massive amount of frustration, pointless limitations and ugly bugs that we have found along the way. Hopefully, this will be useful for other developers of Chrome extensions. At the very least, they might find some comfort from seeing other people having their fair share of pain.</blockquote><h3>Are we the bad guys?</h3><p>Chrome Web Store policies change frequently, mostly getting stricter by the day, and for very good reasons.</p><p>Extensions are powerful, and can easily have a serious negative impact on user security and privacy. This can happen both directly (i.e. a plain malware/spyware extension), but also indirectly, by compromising the developer account or remote assets of an otherwise legit extension.</p><p>There is also the grey area of “extension acquisitions” by shady companies: we very regularly receive inquiries to purchase the CheerpJ Applet Runner extension, most of them not looking exactly kosher.</p><p>Anyway, as a form of defense in depth, the Chrome Web Store policies require that the least possible amount of permissions are requested. In this way, even a compromised extension can still do limited damage. This makes complete sense. Extensions developers are incentivized by a “warning” system: when installing an extension a worrying message is shown to the user if the extension requires heavy-handed permissions. Moreover, developers have to justify each and every requested permission when submitting an item to the store.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/886/1*mVYJ7ntU4UYRkd70w4LkJw.png" /><figcaption>uBlock Origin: A very popular extension that shows quite a worrying message at install time</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/884/1*cK-3HhCa1CHcyTIgAHTs1w.png" /><figcaption>CheerpJ Applet Runner gets no warning at install time</figcaption></figure><p>For us, the idea of sticking to these guidelines not only made sense — it was a no-brainer. We care hugely about user privacy, and we certainly do not want our users to think that CheerpJ Applet Runner will “read and change all their data on the websites they visit”. To be fully honest, we don’t even want the responsibility that comes with that.</p><p>That said, our extension needs to be able to do some tricky stuff just to work as expected. In particular:</p><ul><li>Many Java powered websites will try to detect if Java is supported before creating the relevant &lt;applet&gt;/&lt;object&gt; elements. Plugins have been unsupported in modern browsers for quite a while at this point. To work around this, the extension needs to “spoof” that the plugin exists, to let such pages fully load. Usually, this check is done synchronously and very early in the page life cycle. For this reason, the extension needs to be able to inject the spoofing code <em>very early.</em></li><li>It’s not possible to predict which domains may still use Java applets. They could be anywhere, although most likely not on major, well maintained sites. We know from user’s bug reports that an immense number of obscure pages still include Java applets. Inevitably, our extension needs to be able to run (potentially) on any website, but should only be actually enabled on the small subset of domains that the user requires.</li><li>Finally, our extension needs to do the magic trick of “converting and running Java Applets” as HTML5 in the browser, without a plugin. While this is our bread and butter, and we know this is not only possible, but also safe to do, we can imagine that an overworked extension reviewer may have a different impression, and with little time available may just opt for the safer option of declining approval.</li></ul><h3>We don’t need no weird permission</h3><p>With quite a bit of effort, we settled on the following permissions scheme, which worked well for us for years, up until the unsettling emails of March 2020.</p><ul><li><strong>optional_permissions &lt;all_urls&gt;: </strong>Our solution to let users run the extension on any domain, was to use <strong>optional_permissions</strong>. This feature allows extensions to declare the maximal amount of permissions needed, without having them actually granted at installation time. In terms of UX the user will need to selectively enable CheerpJ Applet Runner on his chosen useful domains, most likely just a handful. This is done via a single click in the extension popup. The extension would then be automatically enabled on any follow-up visit to the same domain, as Chrome will remember the granted permission. The user is always free to drop permissions, by using the standard Chrome UI.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/888/1*gqU3eLHcvD6AT9yQ4jegLg.png" /><figcaption>The permission is only requested after a user action, and the scope is clearly stated</figcaption></figure><ul><li><strong>declarativeContent</strong>: This permission was used to provide a visual hint whenever a Java applet is detected, or about the status of CheerpJ when already enabled. Using the <strong>declarativeContent</strong> API it is possible to select different icons depending on which CSS selector matches on the page. This is fully privacy preserving, since the extension only <em>declares </em>the rules to the browser, without actually accessing the page contents. Ideally, this behavior should be specified statically in the manifest.json file, and no permission would be required. Unfortunately, specifying icons in the manifest is only possible using a <a href="https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/extensions/api/declarative_content/content_action.cc;l=406;bpv=1;bpt=1?q=%5C%22imageData%5C%22&amp;ss=chromium%2Fchromium%2Fsrc&amp;start=21">deeply undocumented base64/binary format</a> (which I managed to figure out only recently). Not that it matters, since the whole feature <a href="https://bugs.chromium.org/p/chromium/issues/detail?id=1231027">has been <strong>completely broken </strong>since April 2018</a>, without anybody noticing.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/620/1*udMZGEVMBbdOf1MnYmCSiw.png" /><figcaption>The previous extension popup, describing the meaning of each icon</figcaption></figure><ul><li><strong>activeTab: </strong>A very lightweight permission, just used to query the current tab id and bootstrap the process. Although using <em>activeTab </em>is recommended, and possibly the least invasive thing you can ask for, Google still requires a justification for using it.</li></ul><h3>No good deed goes unpunished</h3><p>To the best of our understanding, by following this scheme we were playing well within the rules. Certainly above the industry average. Getting so close to losing our extension after all this effort has been very painful and frustrating, and has essentially forced us to delay updates for a very long time, to avoid risking the extension being banned.</p><p>My best guess about what happened is a change in policy that made <strong>remotely hosted code </strong>frowned upon, and fully banned in the upcoming Manifest V3 revision of the APIs.</p><p>CheerpJ runs Java, and as such, it needs a full ‘equivalent’ of the Java runtime. In CheerpJ, this is provided as a fully static set of JavaScript/WebAssembly files, distributed by us on a CDN, with each version fully immutable once published. The extension itself is very lightweight, with most of the actual logic being provided by the remote modular runtime. Of course, all this logic would run in the context of the page,</p><p>The Chrome Web Store process for submitting extensions does allow developers to justify whenever permissions are required. As much as we believe that the CheerpJ Applet Runner already plays by the rules, we also suspect that our use case is just too unique and unexpected to be fully understood in the limited time allocated by reviewers.</p><p>Moreover, as far as we understand the extension is currently living on borrowed time, and it is very unclear if another rejected update may cause it to go down for good. We have tens of thousands of users which may need this tool, and we don’t want to let them down.</p><p>This is our plan to update the CheerpJ Applet Runner extension, in the hope of a successful and quick review and approval on the Chrome Web store.</p><h3>The plan (1/4): Be as light as a feather</h3><p>As you can imagine, we are extremely worried about the risks of getting the next update to the CheerpJ Applet Runner rejected, and about the risks of the extension getting taken down for no reason.</p><p>To make sure to avoid a second rejection, we have decided to re-engineer the extension to reduce the permissions required to its absolute minimum. Ideally to zero.</p><p>This has come with a cost that we were previously not happy to pay, but can’t avoid any longer. In particular, new versions of the extension won’t be able to use the “enable once / run always” feature. The user will need to click the extension icon<em> every single time he needs to use an applet</em>.</p><p>To minimise the required permissions, and hopefully maximize the chances of getting the update approved, we had to make several major changes:</p><p><strong>Adopt Manifest V3</strong>: <a href="https://developer.chrome.com/docs/extensions/mv3/intro/mv3-overview/">Manifest V3</a> is a new revision of the Chrome extensions platform, which introduces new rules and limitations to enhance user security and privacy. Using V3 is currently optional, as V2 is still supported, but it’s clear that at some point in the future V2 will be deprecated.</p><p>We decided to adopt V3 in the hope that its stricter limitations will make the revision process more straightforward and less subject to arbitrary decisions from reviewers. Moreover, we are also future-proofing the extension to a future deprecation of V2.</p><p><strong>Include the whole runtime in the extension</strong>: This is a requirement in manifest V3, since <em>remotely hosted code </em>is now banned. Previous versions of the CheerpJ Applet Runner used to fetch individual runtime components from a CDN, on demand. This avoided unnecessary downloads when only small parts of the runtime were required.</p><p>Technically, this limitation is enforced using <strong>very strict </strong>Content-Security-Policy requirements in the extension manifest. To be fair, this might be an improvement for some users on slow connections. On the other hand, we will need to be more careful in planning our updates, as the extension is no longer a few kilobytes, and we don’t want to spam our users with large background downloads.</p><p><strong>Drop Google Analytics</strong>: Previously, the CheerpJ Applet Runner used GA for <em>very</em> minimal tracking of usage (not users), with a single-click opt-out, and no logging of URLs.</p><p>Due to the new CSP, loading the normal GA script is forbidden. It would have been technically possible to use GA (or another analytics provider) by bundling the script with the extension, or by just sending events manually. Nonetheless, we went one step further and decided to <em>drop any form of tracking</em>.</p><p><strong>Drop optional access to any host</strong>: This is the most expensive choice we had to do in terms of UX. As far as we understand a special review process is imposed to extensions that use <strong>&lt;all_urls&gt;</strong>, even if only as part of the<strong> optional_permissions </strong>section.</p><p>To avoid this more in-depth review altogether, we are dropping this capability, and that’s the reason why enabling the extension only once for a domain is not possible anymore. We have devised a new approach, and we will only use the <strong>activeTab</strong> permission to inject our loader script into the currently used tab.</p><p>One of our biggest disappointments was discovering that the whole concept of optional host permissions has disappeared with Manifest V3. The manifest format has been reorganized to have <strong>permissions</strong>, <strong>optional_permissions</strong> and <strong>host_permission</strong>, with all hosts being considered non-optional right now.</p><p>There is some<a href="https://developer.chrome.com/docs/extensions/mv3/intro/platform-vision/#future-related-changes"> vague wording</a> about making all <strong>host_permissions </strong>optional in the future, but as things stand right now it is impossible to make a Manifest V3 extension that can potentially run on any host without triggering the scary warning at install time <em>or</em> forcing the user to enable to extension any single time even for the same domain.</p><p><strong>Drop the storage permission</strong>: CheerpJ Applet Runner has pretty much only one setting that requires storage: which<a href="https://github.com/leaningtech/cheerpj-meta/wiki/Runtime-API#clipboardmode"> clipboard mode</a> to use (a single binary value). <strong>Storage</strong> used to be one of those permissions that required no justification. This has now changed, but we have been able to find a new strategy and use the <em>localStorage</em> feature of the private extension domain to save these settings. This has not been trivial, since for reasons which are hard to fathom, <em>localStorage</em> is not available in the background service worker that powers extensions.</p><p><strong>Drop declarativeContent permission</strong>: Programmatically adding declarative content rules was used for two reasons. First, it made it possible to automatically inject the CheerpJ loader scripts after a domain was explicitly enabled once by the user. As discussed above we have sadly dropped this feature anyway.</p><p>Secondly, it was used to provide visual feedback to the user about the status of running applets by changing the colour of the extension icon. In particular we would use CSS selectors as triggers to show a yellow icon if Java applets were detected on a page, and a green icon if CheerpJ Applet Runner could successfully run. The great thing about <strong>declarativeContent</strong>, is that the extension only declares the rules, and the browser does the matching. This means that the extension does not need to peek into the page, and user privacy is preserved.</p><p>As crazy as this might sound, dropping this feature had no real cost since <a href="https://bugs.chromium.org/p/chromium/issues/detail?id=1231027"><em>the whole thing has been completely broken in Chrome since April 2018</em></a>! We have actually bisected the issue and found out that a single line of code was misplaced as part of a maintenance commit. And that’s not all, even after fixing this two-liner on our side, we have found out that the feature broke <strong>again</strong> at some later point. How this feature could stay broken for so long (and even break TWICE) without anybody noticing goes beyond my understanding, and I wonder if the extension platform of Chrome is actually held to the same high standards as the rest of the project.</p><p>After all these, somewhat painful, choices we are left with an extension that only requires the <strong>activeTab</strong> and <strong>scripting</strong> permissions, which work together to spoof the availability of the Java plugin, and inject the CheerpJ loader in the page. There is nothing else we can remove at this point, and we can only hope that the review deities will appreciate our sacrifices and be kind with us.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/462/1*T6SayXjhOf9UEBSJUYp1sg.png" /><figcaption>The new popup UI, some elements were removed to reflect the lost functionalities</figcaption></figure><h3><strong>The plan (2/4): Prepare for the worst</strong></h3><p>Even with all the precautions that we have taken, unfortunately we can’t be sure that CheerpJ Applet Runner will not be taken down by the Chrome Web Store.</p><p>To make sure that another option is available to our users, we have just released the CheerpJ Applet Runner on the Edge Add-ons Store. It is safe to assume that the vast majority of users will be on Windows, and Edge will be already available on their Desktop anyway. Edge is currently just a fork of Chrome, so this has not required any further technical effort on our side. I have to say that the review process was fair, speedy and efficient.</p><p>We have also prototyped extensions for Firefox and Safari. As things stands, though, manifest V3 is not supported by either, so we would need to provide a specifically downgraded version for them. At this time we have decided against supporting Firefox/Safari, but we plan to revise our decision when V3 is supported. Firefox in particular has <a href="https://blog.mozilla.org/addons/2021/05/27/manifest-v3-update/">announced a beta</a> of the feature later in 2021/early 2022.</p><h3>The plan (3/4): Make some noise</h3><p>The main point of this post is to be open about the whole process of maintaining and updating a Chrome extension.</p><p>As a consequence of the “difficulties” of this process, the next version of the CheerpJ Applet Runner will have to be a significantly inferior UX compared to what our users are used to. I felt we owed an explanation as to why this is the case.</p><p>We hope that this post will raise awareness on the very sorry state of the Chrome Web Store, and of the approval process for updates. We are not the first developers to be negatively impacted by the extension review process (and we won’t be the last), and we have seen how, in previous cases, getting some attention from the community can go a long way. Hopefully this will apply to the CheerpJ Applet Runner as well.</p><h3>The plan (4/4): Roll the dice</h3><p>Once updated, we will try to reintroduce some of the lost UX, in particular we’d like the <strong>declarativeContent </strong>support in Chromium to be fixed, so that we can restore the use of color-coded icons to better inform the users.</p><p>Having found the issue, and once a fix gets applied to Chrome (<a href="https://bugs.chromium.org/p/chromium/issues/detail?id=1231027">things are not looking particularly promising</a> by the way..), it will take around a couple of months for the patch to trickle across the release cycle.</p><p>About requiring a click every single time you want to use the extension, while not ideal, we don’t really see a way to avoid that. Any proper solution would require heavy handed permissions and warnings, especially with Manifest v3 having dropped optional host permissions. We have hopes that future revisions of the APIs will restore this feature.</p><p>If you can think of a good way of solving the problem, I’d be very interested to chat. Feel free to ping me on <a href="https://twitter.com/alexpignotti">Twitter</a>.</p><h3>The end, for now</h3><p>If you made it to the end of this post, thanks a lot for your patience.</p><p>If you have any ideas or workarounds for any of the issues described in this post, or you have your own Chrome-extension related woes, please get in touch with us, we’d love to chat!</p><p>{<a href="https://twitter.com/leaningtech">Twitter</a>, <a href="https://gitter.im/leaningtech/cheerpj">Gitter</a>, <a href="https://leaningtech.com/">website</a>, <a href="/service/mailto:info@leaningtech.com">email</a>}</p><p>And if you want to know <em>even</em> more about what we do you can find plenty more to chew on, visit our <a href="https://medium.com/leaningtech">tech blog</a>!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=21e5cf84da0" width="1" height="1" alt=""><hr><p><a href="https://medium.com/leaningtech/the-bottomless-pit-of-disappointment-a-chrome-extension-tale-21e5cf84da0">The Bottomless Pit of Disappointment: A Chrome Extension Tale</a> was originally published in <a href="https://medium.com/leaningtech">leaningtech</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>