DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

Cover image for There's a Mountain to Climb
jtenner
jtenner

Posted on

There's a Mountain to Climb

AssemblyScript is a TypeScript to Web Assembly compiler. It's currently maturing at a very fast rate, but like all projects, it requires a lot of hard work and dedication to become better. The call of responsibility must be heeded to obtain the gold from the dragon's den.

GitHub logo AssemblyScript / assemblyscript

Definitely not a TypeScript to WebAssembly compiler πŸš€

AssemblyScript logo

Test status Publish status npm compiler version npm loader version Discord online

AssemblyScript compiles a strict variant of TypeScript (basically JavaScript with types) to WebAssembly using Binaryen. It generates lean and mean WebAssembly modules while being just an npm install away.

About Β Β·Β  Introduction Β Β·Β  QuickΒ start Β Β·Β  DevelopmentΒ instructions

Contributors

Contributor logos

Thanks to our sponsors!

Most of the core team members and most contributors do this open source work in their free time. If you use AssemblyScript for a serious task or plan to do so, and you'd like us to invest more time on it, please donate to our OpenCollective. By sponsoring this project, your logo will show up below. Thank you so much for your support!

Sponsor logos






Some of the functions in the std library are currently incomplete. This isn't because the creators are incompetent at all! There's just a mountain of work to be done. If you happen to be an expert in the algorithms required to implement the JavaScript prototypes, there is a very large possibility you could contribute to AssemblyScript in a very big way! There is plenty of low hanging fruit you could grab at!

Some of the functions that I personally helped implement are quite large and hard to read, but the payoff was worth it. For example, I helped introduce the MAP<T>() higher-order function last year that enabled the TypedArray.prototype.map function to get implemented in an earlier version of AssemblyScript. Since then, the function had to be reimplemented because the memory model for AssemblyScript changed (for the better.) As an example, this is what the MAP higher-order function looks like today.

// @ts-ignore: This is a top level decorator that can be used in AssemblyScript
@inline
// ArrayBufferView is the parent class for Array<T> and TypedArray.
// AssemblyScript uses ArrayBuffers to represent raw heap allocations. 
function MAP<TArray extends ArrayBufferView, T>(
  array: TArray,
  fn: (value: T, index: i32, self: TArray) => T,
): TArray {
  var length = array.length;
  // get the usize pointer to the start of the source ArrayBuffer
  var dataStart = array.dataStart;

  // create a new array to store the results
  var out = instantiate<TArray>(length);
  // get the usize pointer to the start of the result array
  var outDataStart = out.dataStart;

  // for each item in the source array
  for (let i = 0; i < length; i++) {
    // store it in the result array
    store<T>(
      // This calculation depends on the type of the TypedArray.
      // alignof<T>() helps us to calculate how many bytes are needed to store
      // the result in Web Assembly linear memory.
      outDataStart + (<usize>i << alignof<T>()),
      // call the function for each source element
      fn(load<T>(dataStart + (<usize>i << alignof<T>())), i, array)
    );
  }

  // return the result
  return out;
}

The ArrayBuffer class is the cornerstone of this function. Using a specialized ArrayBufferView class, we can store a pointer to the start of the data in linear Web Assembly memory and treat it like JavaScript treats ArrayBuffer instances.

It even comes with it's own array accessor methods.

  @operator("[]") // unchecked is built-in
  private __get(index: i32): f64 {
    if (<u32>index >= <u32>this.dataLength >>> alignof<f64>()) throw new RangeError(E_INDEXOUTOFRANGE);
    return load<f64>(this.dataStart + (<usize>index << alignof<f64>()));
  }

  @operator("[]=") // unchecked is built-in
  private __set(index: i32, value: f64): void {
    if (<u32>index >= <u32>this.dataLength >>> alignof<f64>()) throw new RangeError(E_INDEXOUTOFRANGE);
    store<f64>(this.dataStart + (<usize>index << alignof<f64>()), value);
  }

This is the Float64Array __get and __set methods currently used in the std library. These functions are hard to read if you're a beginner and know nothing about bitwise operators, but that doesn't mean you won't understand it with a little studying and elbow grease.

If you think you have the time and energy to help out, you can also check out the following project to see what is possible using AssemblyScript.

GitHub logo AssemblyScript / node

Implementations of the node.js APIs for use with AssemblyScript.

AS node

Implementations of the node.js APIs for AssemblyScript, utilizing WASI.

Introduction

This library aims to provide a convenient node.js-like environment for AssemblyScript programs Please note that it is still in its early stages and that both the library and WASI are not even close to be finalized.

As always, if the idea sounds appealing to you, feel free to improve existing APIs or to contribute additional ones.

Instructions

Install the library components as a dependency of your project

$> npm install --save-dev AssemblyScript/node

and include it in your build step to gain access to the implementations it provides:

$> asc --lib ./node_modules/@assemblyscript/node/assembly [...]

Doing so will automatically register common globals like the Buffer class and enables requiring for example the filesystem module through import * as fs from "fs".

Documentation

Building

To run the tests, first make sure that…

This library was born because the community was asking for a node Buffer implementation. It plans on using the WASI interfaces to access the system level APIs while cutting corners where it makes sense. At the moment, the Buffer class could use plenty of work, and people who are experts in the algorithms currently used by node.js could find a deep challenge in implementing these modules and functions.

If testing is your thing, and you want to help AssemblyScript develop its tooling, there's a whole testing framework I developed called as-pect.

GitHub logo jtenner / as-pect

πŸ”₯BlazingπŸ”₯ fast testing with AssemblyScript

jtenner/as-pect

This package is a monorepo that contains the cli and the core for the @as-pect packages.

Greenkeeper badge Build Status Coverage Status lerna

Write your module in AssemblyScript and get blazing fast bootstrapped tests with WebAssembly speeds!

Documentation

To view the documentation, it's located here on the gitbook. If there are any issues with the docs, please feel free to file an issue!

Contributors

To contribute please see CONTRIBUTING.md.

Thanks to @willemneal and @MaxGraey for all their support in making as-pect the best software it can be.

Other Contributors:

Special Thanks

Special thanks to the AssemblyScript team for creating AssemblyScript itself.




This cli tool is designed to help developers bootstrap their tests with as little downtime as possible.

Are you afraid to get started or need to immerse yourself in the community first? Feel free to message me here on dev.to to get access to our Slack server. There are plenty of people waiting to help you get started and we definitely don't want to do this all the hard work ourselves.

There's a mountain waiting to be climbed, and you could climb it. That is, if you think you're up for the challenge. πŸ˜‰

Best Regards,
@jtenner

Top comments (2)

Collapse
 
seanmclem profile image
Seanmclem

Am I to understand this makes binaries from Typescript?

Collapse
 
jtenner profile image
jtenner Author

The TypeScript that it generates the Web Assembly binaries from has to be formatted with some extra rules. If you're interested in lending a hand, you can start by reading the documentation here.

You can also get an invitation to our Slack server if you message me directly.

πŸ— We built a 100% open source community software called Forem.

Β 
You can contribute to the codebase or host your own.