<<

Bachelor Degree Project

WebAssembly for Web

Developers

Author: Olle Lauri Boström ​ Supervisor: Francis Palma ​ Semester. VT 2019 ​ Subject: Science ​ Abstract

One of the latest tools in the strive troughwards a fast and secure Web is called WebAssembly. It is a low-level, assembly-like language that can run in the browser alongside JavaScript. WebAssembly is designed to load fast and aims to execute at near-native speed. Being a compilation target for system languages like , C++, and Rust, WebAssembly is not very accessible from a perspective. This project explores ways to generate WebAssembly directly from JavaScript code, in order to lower the learning curve, and allow for a more widespread adoption of WebAssembly. This has resulted in a utility tool called Esmbly, which can turn simple JavaScript ​ ​ ​ programs into WebAssembly binaries by collecting and utilizing type information from various flavours of statically typed JavaScript.

Keywords: WebAssembly, Web developers, JavaScript, TypeScript, ​ , JSDoc, V8, Transpiler

Contents

1 Introduction 5 1.1 Background 6 1.1.1 Static vs dynamic types 6 1.1.2 JavaScript type systems 7 1.1.3 TypeScript 7 1.1.4 Flow 7 1.1.5 JSDoc 8 1.1.6 V8 runtime type information 9 1.1.7 9 1.1.8 Transpiler 9 1.1.9 Abstract syntax 9 1.2 Related work 10 1.3 Problem formulation 11 1.4 Motivation 11 1.5 Objectives 12 1.6 13 1.7 Target group 14 1.8 Outline 14

2 Method 15 2.1 Design Science 15 2.2 Evaluation 15 3 Implementation 16 3.1 Project overview 16 3.1.1 Packages 16 3.1.2 repository 16 3.1.3 TypeScript 17 3.2 Esmbly core 17 3.2.1 Run configuration 18 3.2.2 Parsing 18 3.3 Transformers 18 3.3.1 Parser options 19 3.3.2 Input and Output formats 19

3.3.3 Transforming the AST 19 3.3.4 Creating output files 20 3.4 Flow transformer 20 3.5 JSDoc transformer 20 3.6 V8 transformer 21 3.7 WebAssembly transformer 21 3.8 Examples 21 3.8.1 Example of ‘Add’ function 22 3.8.2 Example of ‘Conway's Game of Life’ 22 3.8.3 Example of Insertion sort 22 3.8.4 Example of ‘String pad’ 22 3.8.5 Example of ‘Radians’ 23 3.8.6 Example of ‘String repeat’ 23 3.8.7 Example of ‘Custom rule’ 23 3.8.8 Example of ‘Custom transformer’ 23 3.8.9 Example of ‘Browser’ 23 3.9 Documentation and guides 23 3.10 Tests 24 3.11 Integration with WebAssembly Studio 24

4 Results 25 4.1 Transforming the examples 25 4.1.1 Add example 25 4.1.2 Conway's Game of Life example 25 4.1.3 Insertion sort example 25 4.1.4 String pad example 25 4.1.5 Radians example 26 4.1.6 String repeat example 26 4.2 Transforming popular open source projects 26 4.2.1 Yarn 26 4.2.2 26 4.2.3 ms 27 4.3 Extensibility 27 4.4 A tool for both .js and the Browser 27 4.5 Limitations 28 4.5.1 Flow transformer 28

4.5.2 JSDoc transformer 28 4.5.3 V8 transformer 28 4.5.4 WebAssembly transformer 28

5 Analysis 30 5.1 Lowers the WebAssembly-barrier for Web developers 30 5.2 Beyond the 30 5.3 A useful tool for migrating between (and working with) different type systems 31

6 Discussion 32

7 Conclusion 33 7.1 Future work 34

References 35

Appendix 38 A1 Add example 38 A2 Insertion sort example 40 A3 String pad example 42 A4 Radians example 44 A5 String repeat example 45

1 Introduction

As the capabilities of the increases, being able to write fast and secure code for the Web has become more important than ever. Demanding applications including 3D visualizations, and games, which are traditionally built using native techniques, are now being built for the Web. Even though the performance progress of JavaScript, in terms of execution speed, has been high for the last ten years, the language is not very well suited for many of these demanding use cases [1][2]. One of the latest tools for writing fast and secure Web applications is called WebAssembly, a collaborative effort by the four major browser vendors (i.e., , , , and Apple). It is a low-level, assembly-like language which can run in the browser alongside JavaScript. WebAssembly is designed to load fast and aims to execute at near-native speed. WebAssembly works as a compilation target for system languages like C, C++, and Rust which means that it is now possible to take a piece of code written in one of these languages, compile it to WebAssembly, and run it on the Web. WebAssembly aims to bring native speed to the Web, but for a large majority of Web developers who are not familiar with any of the initially supported system languages, getting started can be hard. This thesis aims to make it easier for Web developers to start working with WebAssembly, by implementing a tool which can generate WebAssembly directly from JavaScript code.

1.1 Background

1.1.1 Static vs dynamic types Most system languages like C, C++, and Rust are statically typed. This ​ ​ means that variable types are specified by the and known at compile time [4]. This is a requirement for compilation to WebAssembly. JavaScript, on the other hand, is dynamically typed without any built-in way ​ of expressing variable types. This means that type information is not available until the program is running [5].

1.1.2 JavaScript type systems Even though JavaScript lacks a built-in way of expressing variable types, most code is written with a certain type in mind. This has lead to the development of several external type systems. Even though these type ​ ​ systems differ in their goals, all of them lets the programmer specify variable types. Using a , commonly referred to as statically typed ​ JavaScript has become increasingly popular over the past few years [6]. The State of JavaScript Survey 2018 shows that almost half of the responding developers have used TypeScript and that they are excited about using it again [6]. This project targets the three most popular type systems at the moment, TypeScript, Flow, and JSDoc. These are presented below.

1.1.3 TypeScript TypeScript is a superset of the JavaScript language which adds support for optional static types. TypeScript code compiles to JavaScript, and any type errors are caught at compile time. TypeScript is developed and maintained by Microsoft and released under an open source [7]. Figure 1.1 shows an example the TypeScript syntax.

Figure 1.1: Code example showing a simple JavaScript function and the corresponding implementation in TypeScript.

1.1.4 Flow Flow is an static type checker developed by , released under an open source MIT license [8]. Flow uses a syntax that is similar to TypeScript, but unlike TypeScript it is not a . Type annotations are added to the to specify variable types, which enables Flow to check for any type errors. Flow does not include a compiler like TypeScript,

but there are tools for automatically removing the type annotations and output plain JavaScript. Figure 1.2 shows an example of a JavaScript function with Flow annotations.

Figure 1.2: Code example showing a simple JavaScript function and the corresponding implementation with Flow annotations.

1.1.5 JSDoc JSDoc is different from TypeScript and Flow in several ways. Firstly, as suggested by the name, JSDoc is mainly a way of documenting JavaScript code as opposed to TypeScript and Flow, which focuses on type checking. Furthermore, TypeScript and Flow syntax is not valid JavaScript which means that the code cannot run before it has been transformed to plain JavaScript. JSDoc on the other hand is written in the of regular JavaScript comments. This makes code that is annotated with JSDoc comments runnable without the need of any transformation. JSDoc is released under an open source Apache license and has been around for many years [9]. Figure 1.3 shows an example of a JavaScript function that has been annotated with a JSDoc comment.

Figure 1.3: Code example showing a simple JavaScript function annotated

with a JSDoc comment.

1.1.6 V8 runtime type information V8 is an open source JavaScript engine developed by Google that is used to power both and Node.js [10]. V8 exposes run time type ​ ​ information through the inspector protocol [11]. This means that when a ​ ​ JavaScript program is running on the V8 engine, we can use the inspector protocol to find out the parameter and return types in a program. This project aims to utilize this by experimenting with ways of collecting a type profile during test runs and use it to output WebAssembly.

1.1.7 Compiler A compiler is a which transforms source code written in one programming language to another. Most commonly, this transformation is performed from a high-level programming language to a low-level language like assembly or machine code to create an program [12]. Like from instance, transforming a C program to WebAssembly.

1.1.8 Transpiler A transpiler is a source-to-source compiler. It transforms source code written in one high-level language to another (or the same) high-level language [12]. Using transpilers are very common in the JavaScript community for converting ES2015+ (as well as other syntaxes like Flow, TypeScript, JSX etc) into a backwards compatible version of JavaScript [13].

1.1.9 Abstract syntax tree An abstract syntax tree (AST) is a that is commonly used to represent the structure of source code written in a programming language [16]. Each node in the tree represents a piece of the source code and may contain several child nodes. Abstract syntax trees are commonly used in , program analysis and program transformations [16]. This project will use the AST data structure to represent source code files which will be transformed between different type systems.

1.2 Related work In terms of academic research, little has been said about WebAssembly. Only a handful of scientific articles has been published regarding the subject - none which examines how to make it easier for Web developers to start working with WebAssembly. However, some efforts are being made by the open source community to make WebAssembly more accessible for Web developers. AssemblyScript is an open source, TypeScript to WebAssembly compiler which supports compiling a strictly-typed subset of TypeScript to WebAssembly [14]. AssemblyScript focuses on supporting the ahead-of-time-compatible parts of TypeScript that efficiently can be compiled to WebAssembly. This means that dynamic features such as union types and any or undefined types are not supported [17]. The benefit of AssemblyScript is limited to developers and projects that are using TypeScript. This project intends to use the AssemblyScript compiler but to support several common type systems beyond TypeScript and to experiment with extracting type information directly from the V8 runtime. Somewhat similar to AssemblyScript is a project called Walt, which ​ ​ offers a Flow-like syntax that compiles directly to WebAssembly binaries [18]. Compared to AssemblyScript, the status of Walt is a bit more experimental. It does not offer any memory management and is lacking support for many of the runtime built-ins as well as some of the numeric types that are supported by AssemblyScript [19]. Another open source project which aims to make it easier to get started with WebAssembly is WebAssembly Studio. It is an online IDE built ​ ​ by Mozilla, where developers can learn and experiment with WebAssembly directly in the browser, without the need to up any local development environment [20]. WebAssembly studio offers several preconfigured starter templates for C, C++, Rust and AssemblyScript. It also includes useful utilities for inspecting, validating and optimizing WebAssembly binaries. Also worth mentioning is , a JavaScript transpiler mainly ​ ​ focused on converting ES2015+ (as well as other syntaxes like Flow, TypeScript, JSX etc) into a backward compatible version of JavaScript [21]. This project plan to use several few parts of the babel infrastructure, like its

parser and traverser. One could argue that this project, while using several Babel parts, in some sense aims to be the opposite to Babel by transpiling code in the other direction, from JavaScript to TypeScript and beyond. ​ ​ ​ ​

1.3 Problem formulation Even tough WebAssembly runs on the Web - it is not very accessible from a Web developer perspective. As a Web developer without prior knowledge about any system language like C, C++, or Rust, writing code that can be compiled to WebAssembly is challenging. Before you can get started with even the most examples, you have to get familiar with a new language syntax and set up a new development environment. This degree project aims to lower this barrier by developing a tool that can collect type information from JavaScript programs and utilize it to output WebAssembly binaries. The goal is to offer support for several different type systems which will first be transpiled to an intermediate TypeScript representation before using the AssemblyScript compiler to output WebAssembly. This would make it easier for Web developers to start experimenting with WebAssembly - thinking more about how, and why, it might benefit an application - and less about the syntax of a new programming language.

1.4 Motivation The idea behind this degree project was born out of a previous attempt to study WebAssembly from a performance perspective. The plan was to study how WebAssembly execution times and memory usage compared to JavaScript for a few use cases identified by the WebAssembly Community Group [15]. With limited knowledge about C, the project quickly ran into problems. We were not able to write programs that were advanced enough to represent any real-life use cases and ended up with very basic examples. We tried using a framework to introduce more advanced functionality but soon realized that such an approach could lead to invalid conclusions. After a few failed attempts to finish the project, we started thinking - what if we could generate WebAssembly binaries directly from a program written in JavaScript? A way to generate WebAssembly directly from JavaScript code would lower the barrier for Web developers that want to start experimenting

with WebAssembly. There are a number of use cases for WebAssembly beyond the pursuit of increased performance [15]. Being able to generate WebAssembly directly from JavaScript code would make it easier for Web developers to discover these features and allow for more widespread adoption of WebAssembly. For Web developers working on demanding JavaScript applications - this would offer a way to compile isolated parts of the application to look at possible performance gains. Naturally, there are cases where implementations in a system language make more sense, but when migrating from an existing JavaScript implementation this would be a great first step. Instead of having to rewrite the functionality in a new language - being able to compile to WebAssembly straight away would at the very least result in a prototype that can be evaluated before moving further.

1.5 Objectives

O1 Set up the development environment (Build tools, Linting, Testing, CI, repo structure) O2 Write example programs that the tool is expected to handle O3 Design the overall structure of the tool, with extensibility and support for both browser and node environments in mind O4 Implement the core functionality needed for reading, parsing and transforming programs to WebAssembly O5 Implement functionality for transpiling a program with Flow annotations to an intermediate TypeScript representation O6 Implement functionality for transpiling a program with JSDoc comments to an intermediate TypeScript representation O7 Implement functionality for transpiling a program covered by a test suite to an intermediate TypeScript representation by collecting type information directly from the V8 runtime O8 Implement a wrapper around the AssemblyScript compiler to compile TypeScript to WebAssembly O9 Implement unit and integration tests that verify that the tool can successfully transform the example programs to WebAssembly O10 Add documentation and examples O11 Explore the use of WebAssembly Studio to provide in-browser examples

During Objective 1 the required development environment will be set up. ​ ​ This is expected to result in a repository with the necessary build tools for a TypeScript project. It is also expected to include tools for testing and linting as well as a continuous integration pipeline. Setting up a solid development environment early on in the project will encourage writing solid, tested code right from the start. Objective 2 is expected to result in a number of example programs for ​ the targeted type systems. These example programs will later on be used when manually testing the tool, and when writing unit and integration tests. Objective 3 is expected to result in a high level design for how the ​ tool should be implemented. This includes both UML diagrams, as well as text that describes the expected functionality. In Objective 4 the core ​ ​ functionality of the high level design will be implemented. This includes a CLI interface, utilities for reading, writing and parsing files. Objective 5 - 7 is expected to result in 3 separate packages which can ​ transform a file from the targeted type system to the intermediate TypeScript representation. The wrapper around the AssemblyScript compiler which will be implemented during Objective 8 is then responsible for generating ​ WebAssembly binaries based on the intermediate representation. Some basic unit tests are expected to be added along the way when different parts of the tool is implemented. In Objective 9, additional tests are ​ ​ expected to be added that verifies that the tool can handle the example programs that were created during Objective 2. ​ Finally, some documentation and examples of how the tool can be used is expected to be created during Objective 10 and Objective 11. ​ ​ ​

1.6 Scope To transform a JavaScript program to WebAssembly, we need to collect type information about the program. As described in Section 1.1.2 there are several different type systems in the JavaScript ecosystem. To limit the scope of this degree project, the three most common type systems are targeted. The tool is expected to be able to collect type information from Flow annotations, JSDoc comments, and from TypeScript programs. The tool is also expected to offer some experimental support for collecting type information directly from the V8 runtime, without explicitly using a type system.

The collected type information will then be used to transform the program into an intermediate TypeScript representation before using the AssemblyScript compiler to output WebAssembly binaries. The scope is therefore also limited by the capabilities of the AssemblyScript compiler which only supports a strictly-typed subset of TypeScript [14]. There is also some specific Flow syntax that cannot be expressed using TypeScript, making an intermediate representation impossible. Handling such edge cases are outside of the scope of this project.

1.7 Target group The target group of this thesis is the Web developers and companies who want to start working with WebAssembly without having to learn a system language like C, C++, or Rust.

1.8 Outline In the next chapter called Method, the Design Science method which is used ​ throughout this project is presented. The method chapter is followed by a chapter called Implementation where details about the implemented utility ​ ​ tool as well as number of example programs are presented. The results of transforming the example programs to WebAssembly using the implemented tool is presented in the Results chapter, and later on analyzed in the Analysis ​ ​ ​ chapter. In the Discussion chapter, the outcome of this project is discussed in ​ ​ relations to previous work in the area. The report is concluded by the Conclusions chapter that summarizes the project and discusses the relevance ​ of the results.

2 Method

As outlined in the Problem formulation, the goal of this degree project is to ​ ​ make it easier for Web developers to start working with WebAssembly, without having to learn a system language. This problem will be approached using the Design Science methodology. ​ ​

2.1 Design Science Design Science research is focused on the creation of an innovative and useful artifact for a specific problem domain. The created artifact can be an algorithm, a method, or as in the case of this project, a utility tool that makes it easier for Web developers to start working with WebAssembly. Design Science research is basically about adding something new and useful to the world, that solves relevant business problems. This is an exploratory process which includes generating new knowledge. Design Science research is therefore performed in iterations where knowledge from the knowledge base is iteratively applied to build, evaluate and refine the artifact. This finally results in two research contribution, 1. The artifact itself which can be put into real-world use and evaluated based on its ability to satisfy the real world needs. 2. New knowledge that can be added to the knowledge base.

2.2 Evaluation The created artifact has to be evaluated to verify that it satisfies the specified ​ real-world needs. Early on in the process of this project, a few different example programs will be implemented to represent what the utility tool is expected to handle. These examples will lead the way in the exploratory process and be used to verify that the outcome of the project solves the outlined problem.

3 Implementation

To make it easier for Web Developers to start working with WebAssembly, a utility tool called Esmbly1 has been implemented. The tool includes a set of ​ ​ ​ core functionality for parsing and transforming files, a CLI interface, as well as four transformers. It is publicly available and developed under an MIT license. The name Esmbly is a play on the words ES (short for ECMAScript) and assembly.

3.1 Project overview

3.1.1 Packages To allow Esmbly to work in both browser and Node.js environments, the tool has been split up into several different packages. Each package and their respective responsibilities are shown in Figure 3.1. Node.js specific functionality for reading and writing files has for the most part been placed inside the CLI package to make the core package able to run inside a .

Figure 3.1: Packages and their respective responsibilities

3.1.2 Mono repository Esmbly is structured as a mono repository which is managed by a tool called Lerna2. This means that the nine different packages that compose Esmbly all live in the same git repository, but that they are published to registry as individual packages. Using a mono repository approach makes it easier to make (and test) changes across packages as well as to share development

1 Esmbly, ://github.com/esmbly/esmbly ​ 2 Lerna, https://github.com/lerna/lerna ​

dependencies. The mono repository is hosted on GitHub and a continuous integration pipeline has been set up using Travis CI. Each time a new commit is pushed to the master branch, or when a new pull request is opened - Travis will build all packages, and test them using several different Node.js versions to make sure everything is still working as expected.

3.1.3 TypeScript Esmbly uses TypeScript as the intermediate format for transforming different flavours of statically typed JavaScript to WebAssembly binaries. For that reason, it felt like a natural choice to write the tool itself in TypeScript. Shared type definitions are placed in the types package which all other packages are dependent on.

3.2 Esmbly core The core package is designed to work in both browser and Node.js environments and is therefore not dependent on any Node.js core modules. It exposes a single function called run which parses the input files into abstract syntax trees before running each provided transformer as shown in Figure 3.2.

Figure 3.2: Sequence diagram of the run function.

3.2.1 Run configuration The run function accepts a configuration object where the following ​ properties must be provided.

Option Description Type

input An array of files that should be File[] transformed

transformers An array of transformer instances. Transformer[] The transformers will run in the order that they are specified.

output An array of output objects. Output[]

3.2.2 Parsing Each input file is parsed into an AST representation using a tool called Recast 3, and the Babel parser4. The first specified transformer tells the Babel parser which plugins to use when parsing the files, in order to correctly parse any language extensions like Flow or TypeScript.

3.3 Transformers Esmbly is built around the concept of transformers. A transformer is an object or a class that implements the transformer interface shown in figure 3.3. A transformer is responsible for transforming the ASTs from one format to another, as well as creating any specified output files. The AST transformation is a sequential process where the ASTs are passed to each specified transformer one after another. In other words, the AST is transformed from one format to the next until all transformers are done.

3 Recast, https://github.com/benjamn/recast ​ 4 Babel parser, https://babeljs.io/docs/en/next/babel-parser ​

Figure 3.3: The transformer interface.

3.3.1 Parser options The sequential transformation process means that the first transformer is responsible for specifying any custom options to the parser. The transformer can specify an array of parser plugins to deal with language extensions like Flow or TypeScript, or provide a custom parser which would overwrite the Babel parser altogether.

3.3.2 Input and Output formats A transformer specifies the expected input and output formats. In other words, the input AST is expected to represent a certain type of program, for instance, a Flow program. When the transformer is done, the AST is expected to have been transformed to represent a different type of program, for instance a TypeScript program. Specifying the input and output formats are important because this defines which transformers that are compatible with each other.

3.3.3 Transforming the AST The transform method is responsible for collecting the necessary type information and to transform the ASTs into the transformers specified output format. How the type information is collected, and which types of

transformations that are necessary depends a lot on the transformer. All transformers do however define a set of transformation rules, and uses babels traverser tool to carry them out by going through the AST and checking for nodes that need to be replaced. This set of rules can be extended or overridden by the user, by passing a set of custom rules when creating a new transformer instance.

3.3.4 Creating output files The createFiles method is responsible for turning the ASTs back into files. Depending on the array of output objects provided by the user, the method returns an array of files that match the user-specified formats. If the user has not specified any output formats that match the formats that can be created by the transformer - an empty array will be returned. For instance, if the user wants to output WebAssembly by chaining the Flow transformer and the WebAssembly transformer - only the WebAssembly transformer will create output files.

3.4 Flow transformer Since Flow and TypeScript have a similar syntax, most simple programs will look the same in both type systems. The Flow transformer can, therefore, traverse the AST and look for nodes where there is a difference between Flow and TypeScript. For example, when coming across a “mixed type annotation”-node, it is replaced with the TypeScript equivalent which is the “unknown keyword”-node. The Flow transformer is based on the flow-to- project, which has been customized and extended for the Esmbly context.

3.5 JSDoc transformer The JSDoc transformer traverses every node in the AST looking for function- and variable-nodes that are annotated with a leading JSDoc comment. When encountering such a node, the JSDoc comment is parsed using doctrine and the gathered type information is used to transform the function or variable to TypeScript by annotating it with types.

3.6 V8 transformer The V8 transformer offers an experimental way of transforming JavaScript ​ programs to TypeScript based on V8 runtime type information that is collected during test runs. The user specifies which test command to run in order to extract a type profile. The specified command is executed in a child process and once the program is running, type information can be collected from V8 via the V8 inspector protocol. Any function that has been executed ​ during the test run can be transformed into TypeScript by annotating it with the collected types. For example, consider a utility function for repeating a string which accepts two parameters - the string to repeat, and the number of times to repeat it. The utility function is covered by a test case which verifies that everything works as expected by calling the function with different strings and numbers. During executing of the test suite, V8 will collect and make this information available through the inspector protocol, knowing that the first function parameter is a string and the second one a number.

3.7 WebAssembly transformer The WebAssembly transformer transforms TypeScript programs to ​ WebAssembly, Wat, Asm.js by utilizing the AssemblyScript compiler. It can be used directly on TypeScript files, or chained together with other transformers that generate TypeScript output (which is the case for the Flow-, JSDoc- and V8 transformer). Before calling the AssemblyScript compiler, the input is transformed to AssemblyScript, a strictly typed subset of TypeScript. The ASTs are traversed to make sure that all functions are annotated with return types, that no types are declared as any or undefined, and that the delete keyword is not used anywhere. If the program contains any function parameters or variables that are annotated with the number type, these are converted to the f64 type. This is how AssemblyScript interprets a number that is not explicitly declared to be of a more precise integer or floating point type.

3.8 Examples A number of example programs have been implemented as part of this project. These examples represent programs that the different transformers

are expected to handle within the scope of this project. These programs have led the way through the implementation process and will be used to verify that the outcome of the project solves the outlined problem. Each example contains all of the files that are needed to run Esmbly. This includes a package. where the necessary Esmbly packages are listed as dependencies, an Esmbly - and one or several source files that will be used as input. All examples can be found in the examples directory in the repository.

3.8.1 Example of ‘Add’ function The add example is the most basic example in this project. The source file ​ exports a single function called add, which returns the sum of two provided numbers. It is the sort of program that most developers will come across as their first WebAssembly example. It has been implemented in three versions - a Flow version, a JSDoc version and one version written in plain JavaScript, covered by a test suite.

3.8.2 Example of ‘Conway's Game of Life’ The Conway’s Game of Life example is the most advanced example in this ​ project, dealing with intense calculations and memory management. The original TypeScript version, found in the AssemblyScript project has been ported to JSDoc comments.

3.8.3 Example of Insertion sort The insertion sort example contains a simple insertion sort algorithm, ​ annotated with JSDoc comments. It shows how to pass an array of integers from JavaScript to WebAssembly.

3.8.4 Example of ‘String pad’ The string pad example includes a small string pad program written in Flow. ​ ​ It shows how to pass string arguments from JavaScript to WebAssembly.

3.8.5 Example of ‘Radians’ The radians example contains a utility program for transforming between ​ radians and degrees. It is written in plain JavaScript, covered by a test suite.

3.8.6 Example of ‘String repeat’ The string repeat example contains a utility program for repeat a string a ​ specified number of times. It is written in plain JavaScript, covered by a test suite.

3.8.7 Example of ‘Custom rule’ The custom rule example shows how to create a custom rule and how to ​ ​ it to a transformer. The custom rule adds a default return type for functions that does not specify one.

3.8.8 Example of ‘Custom transformer’ The custom transformer example shows how to implement and use a custom ​ ​ transformer. The created transformer renames all functions called foo to bar.

3.8.9 Example of ‘Browser’ The browser example shows how to use Esmbly programatically in the ​ browser with .

3.9 Documentation and guides Documentation for each package is found in the respective packages README file. This includes detailed usage information, a list of the available configuration options, notes about any limitations as well as to relevant examples. In addition to this, a few step-by-step guides on how to use the transformers and the command line interface can be found in the docs directory in the repository.

3.10 Tests All packages in the Esmbly repository contains unit tests for quickly checking that new changes are not breaking any existing functionality. Each of the transformers also contains integration tests for verifying that the defined set of transformation rules are working as expected. In addition to this, a set of End-to-End (E2E) tests have been set up using the examples that are described above. Since all of the examples includes a configuration file and the necessary dependencies, the E2E tests can run Esmbly in each of the examples and then verify that the generated WebAssembly binaries (as well as other output files) are working as expected.

3.11 Integration with WebAssembly Studio In order to let users try Esmbly directly in the browser, an Esmbly version of WebAssembly Studio has been created. The Esmbly version is a customized fork of the WebAssembly Studio repository, which adds two Esmbly specific examples where the user can use Flow or JSDoc comments to generate WebAssembly binaries.

4 Results

4.1 Transforming the examples All of the example programs that are described in Section 3.8 have successfully be transformed into WebAssembly binaries using Esmbly. The results of the transformations that are described below can be easily be reproduced by running the corresponding examples, located in the examples directory in the repository - or by running the E2E tests.

4.1.1 Add example Esmbly can transform all three versions of the add example (Flow, JSDoc and the JavaScript version covered by a test suite) to TypeScript, AssemblyScript, WebAssembly and Wat according to their respective configuration files. Appendix A1 includes the input and test files that are ​ used in the different versions of the add example, and gives an example of how to use the generated WebAssembly binary.

4.1.2 Conway's Game of Life example Esmbly can transform the Game of Life example to WebAssembly and AssemblyScript by chaining the JSDoc and WebAssembly transformers.

4.1.3 Insertion sort example Esmbly can transform the insertion sort example to a WebAssembly binary by chaining the JSDoc and WebAssembly transformers. Appendix A2 ​ includes the input files that are used in the insertion sort example, and gives an example of how to use the generated WebAssembly binary.

4.1.4 String pad example Esmbly can transform the string pad example to TypeScript, AssemblyScript and WebAssembly by chaining the Flow and WebAssembly transformers. Appendix A3 includes the input file that is used in the string pad example, and gives an example of how to use the generated WebAssembly binary.

4.1.5 Radians example Esmbly can transform the radians example to a WebAssembly binary by chaining the V8 and WebAssembly transformers. Appendix A4 includes the ​ input and test files that are used in the radians example, and gives an example of how to use the generated WebAssembly binary.

4.1.6 String repeat example Esmbly can transform the string repeat example to a WebAssembly binary by chaining the V8 and WebAssembly transformers. Appendix A5 includes the ​ ​ input and test files that are used in the radians example, and gives an example of how to use the generated WebAssembly binary.

4.2 Transforming popular open source projects Except for the example programs that are described above, Esmbly has also been used to transform three popular open source JavaScript projects to TypeScript. The results of the transformations that are described below can be easily be reproduced by running the corresponding examples, located in the examples directory in the repository - or by running the E2E tests.

4.2.1 Yarn Yarn5 is a popular JavaScript . A subset of Yarn, the functionality for dealing with lock-files has been transformed to TypeScript by using Esmbly and the Flow transformer.

4.2.2 Lodash Lodash6 is a general purpose utility . It receives almost 25 million weekly downloads and is the most popular package in the npm registry, in terms of the number of packages being dependent on it [22][23]. Based on its JSDoc comments, the Lodash library has been transformed to TypeScript

5 Yarn, https://github.com/yarnpkg/yarn ​ 6 Lodash, https://github.com/lodash/lodash ​

using the JSDoc transformer. Lodash is divided in 252 different utility methods, out of which 227 methods have been correctly transformed to TypeScript. The clamp method for clamping a number between an upper and lower bound has also been transformed to a WebAssembly binary.

4.2.3 ms The ms7 package is a small utility package for converting various time ​ formats to milliseconds. It has over 27 million weekly downloads from the npm registry [24]. Based on the ms packages JSDoc comments - it has been transformed to TypeScript by using the JSDoc transformer.

4.3 Extensibility Esmbly is designed with extensibility in mind. The transformation rules defined by each of the transformers can easily be extended or overridden by the user, as shown in the custom rule example. It is also possible to create a custom transformer for dealing with type systems or scenarios that are not yet covered by any existing Esmbly transformer, as shown in the custom transformer example.

4.4 A tool for both Node.js and the Browser The core module is not dependent on any Node.js core modules which makes Esmbly able to run inside the browser. The Flow, JSDoc and WebAssembly transformers are all able to run in the browser, and are all used in the Esmbly version of WebAssembly Studio. In addition to the customized version of WebAssembly Studio, the browser example provides an example of how Esmbly and the Flow transformer can be used programmatically in the ​ browser together with Webpack.

7 ms, https://github.com/zeit/ms ​

4.5 Limitations

4.5.1 Flow transformer The Flow transformer can transform most Flow syntax to TypeScript. However, there are a few parts which are not yet supported. The function shorthand syntax, predicate functions, bounds and a majority of Flows utility types are not yet supported.

4.5.2 JSDoc transformer The JSDoc transformer supports the param and returns tags for describing function parameters and return types. It also supports the type and constant tags for describing the type of a variable or a constant. The JSDoc transformer does not yet support transforming object literals or classes to TypeScript.

4.5.3 V8 transformer The type information that can be retrieved from V8 is somewhat experimental. All primitive types are supported, as well as custom classes. However, V8 does not provide any detailed information about arrays or objects literals which will be interpreted as any[] and Object. The V8 ​ ​ ​ transformer currently supports running tests using Jest, Jasmine and Tape.

4.5.4 WebAssembly transformer Since the WebAssembly transformer uses the AssemblyScript compiler to output WebAssembly, Wat and Asm.js - the limitations of the AssemblyScript also applies to the WebAssembly transformer. The following limitations apply, - All functions must have return annotations. - Any and undefined types are not supported. - Union types are not supported. - The delete keyword is not supported. - Interfaces and object literals are not supported. - Modules must use the esm import/export syntax, and not the CommonJS module.exports syntax which is standard in Node.js.

- Variables must have either a type annotation or an initializer. - AssemblyScript deals with numeric values differently than JavaScript. Four native types are supported, i32, i64, f32 and f64 which map directly to WebAssembly types. AssemblyScript interprets the number type as f64.

5 Analysis

5.1 Lowers the WebAssembly-barrier for Web developers As shown by transforming the example programs to WebAssembly binaries, Esmbly is a useful tool for Web developers that want to start experimenting and prototyping with WebAssembly. Simple programs can be turned into WebAssembly binaries in a matter of minutes, with a tool that is just an npm install away. In comparison with setting up a new development environment for C programming and struggling with the syntax of a new programming language - this is much easier. Thanks to the utilities provided by the ​ AssemblyScript project, Esmbly can also deal with string and arrays arguments in a way that is far easier to understand for a Web developer than to figure of how the concept of pointers works in the context of C and WebAssembly. Esmbly broadens the possible ways that Web developers can provide type information about a program to output WebAssembly binaries. Before, developers were limited to using TypeScript and the AssemblyScript compiler, but now it is possible to use TypeScript, Flow, JSDoc comments or even a test suite. This means that developers can use what they already know, and utilize already existing type information in a code base.

5.2 Beyond the basics Most of the example programs that are used throughout this project are pretty simple, with the Game of Life example being the exception. The examples are meant to represent the sort of programs that developers might start with when trying out WebAssembly for the first time. For example, compiling a string pad function to WebAssembly is great for learning about WebAssembly and string arguments - but it would not make much sense in a production environment. Padding a string is a task that JavaScript is more than capable of performing. When moving beyond these basic examples, it is likely that some parts of a program have to be adapted to how WebAssembly works. The limitations of both WebAssembly and AssemblyScript (as described in Section 4.5) has to be taken into account. This means, for instance, that object literals and functions cannot be passed as function arguments - and that

number types have to be adapted to the different types of numbers that exist in WebAssembly. As an example of a scenario where Esmbly could be used to generate WebAssembly binaries for in-production use, consider a Node.js image processing library. The library exposes a single function which is called with an image path and a configuration object. It reads the image and processes it based on the configuration, like for instance adding a Gaussian blur filter or converting it to grayscale. Dealing with the configuration and reading the image into memory are tasks best suited for JavaScript, but the actual image processing algorithms (working on raw image data arrays) could benefit from being compiled into WebAssembly binaries. If the library is already using a static type system, existing type information can be utilized by Esmbly. If not, one option could be to add JSDoc comments where necessary, which would not introduce any new build steps. Before everything compiles, this would probably require some extra thought about the limitations of AssemblyScript, possibly adding additional type annotations and converting number types into any of the more specific WebAssembly numeric types. When moving beyond the basic examples, using Esmbly to output WebAssembly binaries will require some extra thought and configuration, but doing so is still lot easier than having to rewrite the entire program in C before compiling to WebAssembly.

5.3 A useful tool for migrating between (and working with) different type systems The Flow, JSDoc and V8 transformers all output TypeScript. During the course of this project, the main purpose of that has been to pass the output on to the WebAssembly transformer to generate WebAssembly binaries. But as a side effect, it also means that Esmbly can be used to transform code between different type systems. This has been shown by transforming Lodash and ms from JSDoc comments to TypeScript, and a subset of Yarn from Flow to TypeScript. The fact that Esmbly easily can be extended with custom transformers, and that the transformers are chainable, opens up for use cases such as automatically generating TypeScript declaration files based on existing type information in a code base.

6 Discussion

As outlined in the Problem formulation, the goal of this degree project has ​ ​ been to make it easier for Web developers to start working with WebAssembly, without having to learn a system language. This problem was approached using the Design Science methodology. By drawing knowledge ​ from the knowledge base, in this case, in the form of the previous work done on the AssemblyScript project and the Babel toolchain, a new innovative and useful artifact has been created. In other words, multiple existing tools and projects have been put together in a new way and utilized to implement the utility tool called Esmbly. ​ The implementation has been an explorative and iterative process where the tool has continuously been refined by applying existing knowledge from the knowledge base, and by evaluating against the implemented example programs. As shown by the results of this project, the implemented tool makes it easier for Web developers to start experimenting with WebAssembly, and can, therefore, be considered to satisfy the identified real-world needs. Esmbly can collect type information from different flavours of statically typed JavaScript and utilize it to output WebAssembly binaries. The project also contributes back new knowledge to the knowledge base which can be used for future work in the area. This includes techniques for transforming code between different JavaScript type systems as well as how to use the experimental V8 profiler for collecting type information at run time.

7 Conclusion

All of the initial objectives listed in Section 1.5 have been met. As shown by the results, the implemented tool called Esmbly, makes it easier for Web developers to start experimenting and prototyping with WebAssembly. Esmbly broadens the possible ways that developers can provide type information about a JavaScript program, in order to generate WebAssembly binaries. This means that developers can use familiar techniques, and utilize already existing type information in a code base. This is useful for Web developers who want to start working with WebAssembly, without having to learn a system language. It is also useful for companies and organizations that wants to investigate possible performance gains of compiling a demanding part of an application to WebAssembly. Instead of having to rewrite the entire functionality in a new language before compiling to WebAssembly, an initial prototype can be generated based on the current JavaScript implementation. This could potentially increase productivity and allow for more widespread adoption of WebAssembly among Web developers. The fact that Esmbly is designed to be extendable, and the fact that it could also be used to transform code between different type systems, makes the possible areas of applications for the tool very general. In order to fully investigate the usefulness of Esmbly for other purposes than generating WebAssembly binaries, the project would have benefited from doing a survey among Web developers. This has not been possible due to the limited scope of this project. In the current Esmbly implementation, each transformer is responsible for not only collecting type information about the input program - but also to apply the necessary transformations to the ASTs. A better approach would have been making the transformers responsible only for collecting type information and telling which nodes to transform - and to what kind of type system. This would make it possible to share more code between transformers, and to allow transformations in the opposite direction (e.g. from TypeScript to Flow). The project would also have benefited from some more advanced examples to back up some of the claims that are being made in Section 5.4. More advanced examples could also be used as benchmarks for comparing performance between the original JavaScript program, and the WebAssembly version.

7.1 Future work Esmbly is a useful tool in its current state, but the limited scope of this project means that there is still work to be done before it could be considered stable. Some future work includes, - Improving the command line to provide more information about the transformation process. - Improving the error messages. - Adding support for more test runners to the V8 transformer. - Adding support for more JSDoc tags and class methods to the JSDoc transformer. - Utilizing type information from TypeScript declaration files. - Adding support for transforming CommonJS modules to WebAssembly

The fact that Esmbly is based on the AssemblyScript project means that the continued development of AssemblyScript is highly relevant as well. Future ​ work on the AssemblyScript project includes adding garbage collection, improving the , improving support for classes and adding support for interfaces and object literals. In the strive to make WebAssembly more accessible for Web developers, this project has experimented with several different ways of collecting type information about a JavaScript program. The V8 transformer ​ uses the experimental V8 profiler for collecting type information at run time. This technique could potentially be interesting for both science and industry and be used to build smarter IDEs and better type checkers, that does not depend on static type information.

References

[1] A. Haas et al., “Bringing the Web up to Speed with WebAssembly”, ACM ​ SIGPLAN Notices, Vol.52(6), pp.185-200, September 2017. [Online]. ​ Available: ACM, https://dl.acm.org/citation.cfm?id=3062363. [Accessed: 27 March, 2019].

[2] . Eich, “New JavaScript Engine Module Owner – ”, Brendaneich.com, 2011. [Online]. Available: ​ https://brendaneich.com/2011/06/new-javascript-engine-module-owner/. [Accessed: 27 March, 2019].

[3] “WebAssembly”, Webassembly.org, 2019. [Online]. Available: ​ ​ ​ http://webassembly.org/. [Accessed: 27 March, 2019]. ​ ​

[4] L.Cardelli, “Type systems”, CRC Handbook of Computer Science and ​ Engineering, 2nd Edition, Ch. 97, February 2004. [Online]. Available: ​ http://lucacardelli.name/Papers/TypeSystems. [Accessed: 27 March, ​ 2019].

[5] “Dynamic typing”, MDN Web Docs, 2019. [Online]. Available: ​ ​ https://developer.mozilla.org/en-US/docs/Glossary/Dynamic_typing. [Accessed: 27 March, 2019].

[6] “The State of JavaScript 2018: JavaScript Flavors - Overview”, 2018.stateofjs.com, 2018. [Online]. Available: ​ https://2018.stateofjs.com/javascript-flavors/overview/. [Accessed: 27 March, 2019].

[7] “TypeScript”, Typescriptlang.org, 2019. [Online]. Available: ​ ​ https://www.typescriptlang.org/. [Accessed: 27 March, 2019].

[8] “Flow”, Flow.org, 2019. [Online]. Available: https://flow.org/en/ ​ ​ ​ [Accessed: 27 March, 2019].

[9] “Use JSDoc”, Jsdoc.app, 2019. [Online]. Available: https://jsdoc.app/ ​ ​ ​ [Accessed: 27 March, 2019].

[10]“V8 JavaScript engine”, V8.dev, 2019. [Online]. Available: ​ ​ https://v8.dev/ [Accessed: 27 March, 2019]. ​

[11]F.Hinkelmann, “Type Profile Design Doc”, September 2017. [Online]. Available: https://docs.google.com/document/d/1JY7pUCAk8gegyi6UkIdln6j_AeJqQuc Zg92advaMJY4/ [Accessed: 27 March, 2019]. ​

[12] “Systems and software engineering — Vocabulary.”, ISO/IEC/IEEE ​ 24765:2017, International Standard, Second edition, September 2017. ​ [Online]. Available: https://standards.iso.org/ittf/PubliclyAvailableStandards/c071952_ISO_IEC_ IEEE_24765_2017.zip [Accessed: 27 March, 2019]

[13]“What is Babel? · Babel”, Babeljs.io, 2019. [Online]. Available: ​ ​ https://babeljs.io/docs/en/. [Accessed: 27 March, 2019].

[14] “AssemblyScript ”, GitHub, 2019. [Online]. Available: ​ ​ https://github.com/AssemblyScript/assemblyscript/wiki. [Accessed: 27 March, 2019].

[15] “Use Cases - WebAssembly”, Webassembly.org, 2019. [Online]. ​ ​ Available: http://webassembly.org/docs/use-cases/. [Accessed: 27 March, 2019].

[16] “Abstract syntax tree”, En.wikipedia.org, 2019. [Online]. Available: ​ ​ https://en.wikipedia.org/wiki/Abstract_syntax_tree. [Accessed: 27 March, 2019].

[17] “AssemblyScript Wiki - Limitations”, GitHub, 2019. [Online]. ​ ​ Available: https://github.com/AssemblyScript/assemblyscript/wiki/Limitations. [Accessed: 27 March, 2019].

[18] “Walt”, GitHub, 2019. [Online]. Available: ​ ​ https://github.com/ballercat/walt [Accessed: 21 may, 2019]. ​

[19] “AssemblyScript - How does AssemblyScript compares to Walt?”, ​ Github, April 2018. [Online]. Available: ​ https://github.com/AssemblyScript/assemblyscript/issues/83 [Accessed: 21 ​ may, 2019].

[20] “WebAssembly Studio Wiki”, Github, February 2018. [Online]. ​ ​ Available: https://github.com/wasdk/WebAssemblyStudio/wiki [Accessed: ​ ​ 21 may, 2019].

[21] “What is Babel? · Babel”, Babeljs.io, 2019. [Online]. Available: ​ ​ https://babeljs.io/docs/en/. [Accessed: 27 March, 2019].

[22] "lodash", npm, 2019. [Online]. Available: ​ ​ https://www.npmjs.com/package/lodash. [Accessed: 24 may, 2019].

[23] "Most depended upon packages", npm, 2019. [Online]. Available: ​ ​ https://www.npmjs.com/browse/depended. [Accessed: 24 may, 2019]. ​

[23] npm, Most depended upon packages, [Online]. Available: ​ ​ https://www.npmjs.com/browse/depended [Accessed: 24 may, 2019]. ​

[24] "ms", npm, 2019. [Online]. Available: ​ ​ https://www.npmjs.com/package/ms. [Accessed: 24 may, 2019].

Appendix

A1 Add example This appendix section shows the input files and test files that are used in the Flow, JSDoc and V8 versions of the ‘Add’ function example8 9 10. It also ​ shows how to use the WebAssembly binary that is outputted when transforming the examples. The full examples including their corresponding configuration can be found in the examples directory in the Esmbly repository.

Flow version (add-flow-to-wasm) ​ src/add.js //@flow export function add(a: number, b: number): number { ​ ​ ​ ​ ​ ​ ​ ​ ​ return a + b; ​ ​ ​ ​ }

JSDoc version (add--to-wasm) ​ src/add.js /** * Add two numbers * @param {number} a ​ ​ ​ ​ ​ * @param {number} b ​ ​ ​ ​ ​ * @returns {number} ​ ​ ​ */ export function add(a, b) { ​ ​ ​ ​ ​ return a + b; ​ ​ ​ ​ }

V8 version (add--to-wasm) ​ src/add.js export function add(a, b) { ​ ​ ​ ​ ​

8 Add example (Flow), https://github.com/esmbly/esmbly/tree/master/examples/add-flow-to-wasm 9 Add example (JSDoc), https://github.com/esmbly/esmbly/tree/master/examples/add-jsdoc-to-wasm 10 Add example (V8), https://github.com/esmbly/esmbly/tree/master/examples/add-v8-to-wasm

return a + b; ​ ​ ​ ​ }

tests/add.test.js import { add } from '../src/add'; ​ ​ ​ ​ ​

describe('add', () => { ​ ​ ​ ​ ​ it('adds two numbers', () => { ​ ​ ​ ​ ​ ​ expect(add(2, 3)).toEqual(5); ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ }); });

Example usage

const fs = require('fs'); ​ ​ ​ ​ ​ ​ ​ ​ ​ const path = require('path'); ​ ​ ​ ​ ​ ​ ​ ​ ​ const sourcePath = path.join(__dirname, 'dist', 'add.wasm'); ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ const source = fs.readFileSync(sourcePath); ​ ​ ​ ​ ​ ​ ​

WebAssembly.instantiate(source, {}) ​ ​ .then(({ instance }) => { ​ ​ ​ ​ const result = instance.exports.add(2, 3); ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ console.log('2 + 3 = ' + result); // => 2 + 3 = 5 ​ ​ ​ ​ ​ ​ ​ ​ ​ }) .catch(err => console.log(err)); ​ ​ ​ ​ ​ ​ ​ ​

A2 Insertion sort example This appendix section shows the two input files for the Insertion sort ​ example11. It also shows how to use the WebAssembly binary that is outputted when transforming the example. The full example including the configuration can be found in the examples directory in the Esmbly repository. src/sort.js import { swap } from './utils'; ​ ​ ​ ​ ​

/** * Sorts the array using insertion sort * @param {Int32Array} arr ​ ​ ​ ​ ​ * @returns {Int32Array} ​ ​ ​ */ export function sort(arr) { ​ ​ ​ ​ ​ for (let i = 1; i < arr.length; i += 1) { ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ let j = i; ​ ​ ​ ​ while (j > 0 && arr[j - 1] > arr[j]) { ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ swap(arr, j, j - 1); ​ ​ ​ ​ ​ ​ j -= 1; ​ ​ ​ ​ } } return arr; ​ ​ } src/utils.js /** * @param {Int32Array} arr ​ ​ ​ ​ ​ * @param {i32} i ​ ​ ​ ​ ​ * @param {i32} j ​ ​ ​ ​ ​ * @returns {void} ​ ​ ​ */ export function swap(arr, i, j) { ​ ​ ​ ​ ​ const temp = arr[j]; ​ ​ ​ ​ ​ ​ arr[j] = arr[i]; ​ ​

11 Insertion sort example, https://github.com/esmbly/esmbly/tree/master/examples/insertion-sort

arr[i] = temp; ​ ​ }

Example usage

const fs = require('fs'); ​ ​ ​ ​ ​ ​ ​ ​ ​ const path = require('path'); ​ ​ ​ ​ ​ ​ ​ ​ ​ const { loader } = require('@esmbly/transformer-wasm'); ​ ​ ​ ​ ​ ​ ​ ​ ​ const sourcePath = path.join(__dirname, 'dist', 'sort.wasm'); ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ const source = fs.readFileSync(sourcePath); ​ ​ ​ ​ ​ ​ ​ const instance = loader.instantiateBuffer(source, {}); ​ ​ ​ ​ ​ ​ ​

const arr = new Int32Array([2, 1, 5, 3, 4]); ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ const pointer = instance.newArray(arr); ​ ​ ​ ​ ​ ​ ​ const resultPointer = instance.sort(pointer); ​ ​ ​ ​ ​ ​ ​ const sorted = instance.getArray(Int32Array, resultPointer); ​ ​ ​ ​ ​ ​ ​ ​ ​ console.log(sorted); // => [1, 2, 3, 4, 5] ​ ​ ​ ​

A3 String pad example This appendix section shows the input file for the String pad example12. It ​ also shows how to use the WebAssembly binary that is outputted when transforming the example. The full example including the configuration can be found in the examples directory in the Esmbly repository. src/pad.js // @flow

export function padLeft(str: string, maxLength: number): string { ​ ​ ​ ​ ​ ​ ​ ​ ​ let s = str; ​ ​ ​ ​ while (s.length < maxLength) { ​ ​ ​ ​ ​ ​ s = ' ' + s; ​ ​ ​ ​ ​ ​ } return s; ​ ​ }

export function padRight(str: string, maxLength: number): string { ​ ​ ​ ​ ​ ​ ​ ​ ​ let s = str; ​ ​ ​ ​ while (s.length < maxLength) { ​ ​ ​ ​ ​ ​ s = s + ' '; ​ ​ ​ ​ ​ ​ } return s; ​ ​ }

Example usage

const fs = require('fs'); ​ ​ ​ ​ ​ ​ ​ ​ ​ const path = require('path'); ​ ​ ​ ​ ​ ​ ​ ​ ​ const { loader } = require('@esmbly/transformer-wasm'); ​ ​ ​ ​ ​ ​ ​ ​ ​ const sourcePath = path.join(__dirname, 'dist', 'pad.wasm'); ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ const source = fs.readFileSync(sourcePath); ​ ​ ​ ​ ​ ​ ​ const instance = loader.instantiateBuffer(source, {}); ​ ​ ​ ​ ​ ​ ​

const str = 'abc'; ​ ​ ​ ​ ​ ​ ​

12 String pad example, https://github.com/esmbly/esmbly/tree/master/examples/pad ​

const maxLength = 5; ​ ​ ​ ​ ​ ​ ​ const pointer = instance.newString(str); ​ ​ ​ ​ ​ ​ ​ const resultPointer = instance.padRight(pointer, maxLength); ​ ​ ​ ​ ​ ​ ​ const padded = instance.getString(resultPointer); ​ ​ ​ ​ ​ ​ ​ console.log(padded); // => 'abc ' ​ ​ ​ ​

A4 Radians example This appendix section shows one of the input files, and its corresponding test suite, used in the Radians example13. It also shows how to use the ​ WebAssembly binary that is outputted when transforming the example. The full example including the configuration can be found in the examples directory in the Esmbly repository. src/toRadians.js export function toRadians(degrees) { ​ ​ ​ ​ ​ return degrees * (Math.PI / 180); ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ } tests/toRadians.test.js import { toRadians } from '../src/toRadians'; ​ ​ ​ ​ ​

test('toRadians', () => { ​ ​ ​ ​ ​ expect(toRadians(0)).toEqual(0); ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ expect(toRadians(45)).toEqual(0.7853981633974483); ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ });

Example usage

const fs = require('fs'); ​ ​ ​ ​ ​ ​ ​ ​ ​ const path = require('path'); ​ ​ ​ ​ ​ ​ ​ ​ ​ const sourcePath = path.join(__dirname, 'dist', 'radians.wasm'); ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ const source = fs.readFileSync(sourcePath); ​ ​ ​ ​ ​ ​ ​

WebAssembly.instantiate(source, {}) ​ ​ .then(({ instance }) => { ​ ​ ​ ​ const deg = 90; ​ ​ ​ ​ ​ ​ ​ ​ const rad = instance.exports.toRadians(deg); ​ ​ ​ ​ ​ ​ ​ ​ console.log(`${deg}° = ${rad.toFixed(2)} rad`); // => 90° = 1.57 rad ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ }) .catch(err => console.log(err)); ​ ​ ​ ​ ​ ​ ​ ​

13 Radians example, https://github.com/esmbly/esmbly/tree/master/examples/radians ​

A5 String repeat example This appendix section shows the input file, and its corresponding test suite, used in the String repeat example14. It also shows how to use the ​ WebAssembly binary that is outputted when transforming the example. The full example including the configuration can be found in the examples directory in the Esmbly repository. src/repeat.js export function repeat(str, times) { ​ ​ ​ ​ ​ let s = str; ​ ​ ​ ​ for (let i = 1; i < times; i += 1) { ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ s = s + str; ​ ​ ​ ​ } return s; ​ ​ } tests/repeat.test.js import { repeat } from '../src/repeat'; ​ ​ ​ ​ ​

describe('String repeat', () => { ​ ​ ​ ​ ​ it('repeats the string the specified amount of times', () => { ​ ​ ​ ​ ​ ​ expect(repeat('hello', 3)).toEqual('hellohellohello'); ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ }); });

Example usage

const fs = require('fs'); ​ ​ ​ ​ ​ ​ ​ ​ ​ const path = require('path'); ​ ​ ​ ​ ​ ​ ​ ​ ​ const { loader } = require('@esmbly/transformer-wasm'); ​ ​ ​ ​ ​ ​ ​ ​ ​ const sourcePath = path.join(__dirname, 'dist', 'repeat.wasm'); ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ const source = fs.readFileSync(sourcePath); ​ ​ ​ ​ ​ ​ ​ const instance = loader.instantiateBuffer(source, {}); ​ ​ ​ ​ ​ ​ ​

const str = 'hello'; ​ ​ ​ ​ ​ ​ ​ const times = 3; ​ ​ ​ ​ ​ ​ ​ const pointer = instance.newString(str); ​ ​ ​ ​ ​ ​ ​

14 String repeat example, https://github.com/esmbly/esmbly/tree/master/examples/repeat ​

const resultPointer = instance.repeat(pointer, times); ​ ​ ​ ​ ​ ​ ​ const result = instance.getString(resultPointer); ​ ​ ​ ​ ​ ​ ​ console.log(result); // => hellohellohello ​ ​ ​ ​