Vue's template compiler reimplemented in Rust!

Overview

Vue Compiler in Rust

https://github.com/vuejs/rfcs/discussions/369#discussioncomment-1192421

Maybe in the long run we want the whole transform (and even the Vue compiler!) to be implemented in native Go/Rust so performance would no longer be a concern ;)

Future is now!

Architecture

The original design in vue-next mixes code generation and ast parsing in the same data structure. As we can see, the transform pass will in-place mutate ast nodes, leaving the node with both code generation node and ssr code generation node.

This is typically a sign of leaky abstraction.

So in the Rust version I decided to take another approach.

The design targets at three different levels of developers in Vue ecosystem:

  • Lib/App creator: every Vue developers who write component library or application code.
  • Platform developer: Devs who write compiler implementation for DOM/SSR/Native platform.
  • Framework author: Vue core lib author a.k.a Evan.

The core framework targets multiple platforms and can be extended to support more. Core framework components span all platforms and are hardwired to the core lib runtime.

Platforms are usually DOM or SSR environment. Hosts are browser and node, respectively. Developing a platform needs to write code for both vue-compiler and vue-runtime. Optionally platform developer can write code in host, e.g. in hybrid app or mini-program.

And finally lib or app creators can write component library, business code or application components targeted to certain platforms.

The compilation has several phases:

  • Scan (output: Tokens): Hardwired in the compiler at framework level.
  • Parse (output: template AST): Hardwired in the compiler at framework level.
  • Convert (output: intermediate representation): Customizable for platform developers with sensible default.
  • Transform (input/output: customizable IR): Customizable with default by using generic/traits.
  • Code Generate (customizable output: e.g. JS/TS): Customizable with default.

Other Design different from the original compiler

  • Directive parsing is implemented manually instead of by regexp.
  • nodeTransforms is not supported. It's too hard for app creator to use and maintain IR invariants. Platform devs can still customize by implementing converter/transformer.
  • directiveTransforms now can returns not only Props but also SimpleExpression. The extra flexibility makes a more cohesive v-bind/v-on conversion: the logic for processing the directives now resides in one single file without regard to the presence of an argument.
  • Runtime helper collection context.helper/helperString is moved out from convert and tracked in transform phase, avoiding several methods and reducing HashMap to a bitflag.

Intended Usage

  • Rust library
  • CLI binary
  • napi based nodejs library
  • wasm based npm package: a fallback if napi fails to work and a toy for browser.
  • No Browser build No support since most features in full build are additional except for browser based expression checking or HTML escaping. Browser build removed them for size. But template compiler in browser is already for toy project. For browser specific summary see this google sheet.

Implementation Detail

  • Plenty of debug_asserts to maintain compiler state invariants.
  • The library seeks minimal allocation by using &str, Cow<'_, str> and smallvec.
  • A customized VStr is used to minimize string manipulation.
  • Fxhash is preferred over default hasher since hash collision is not a concern.
  • The bitflags crate is used to represent runtime helper and vnode patch flags.
  • Use heavily optimized routines for string search primitives. (Perf reference)
  • Benchmark with criterion.rs.
  • Test compiler output by snapshot test.
  • Use alternative allocator like wee_alloc or mi_malloc.
  • Use Box<[T]> instead of Vec to reduce type size.
  • Use Arean to minimize allocation.
  • A Future like stack-allocated transformation Pass composition.
  • Use Rc to manage error handler. Don't optimize wrong code.
  • Parallelized conversion with Rayon.

Reference

  • vue-next: ご本家様
  • html spec is the definitive guide for parsing HTML-like files.
  • Vue Template Explorer gives instant results for code generation and error reporting.
  • Nu html checker is the official html validator from W3C. This is the canonical error reporter for html parsing, when there is a discrepancy between the framework and the spec.
  • AST explorer can inspect AST nodes interactively.

Roadmap

Todo tasks grouped by scopes.

[util]

  • VStr
    • string intern
    • camel/pascal cache
    • str ops

[core]

  • scanner
    • UTF8 support
  • parser
  • IR converter
    • v-if
    • v-for
    • v-slot
    • v-model
    • slot outlet
    • element
    • build props
  • transformer
    • SWC RSLint integration
    • Rewrite MergePass struct
  • code generator
    • module preamble
  • wrap error handler in Rc
  • compile option
  • Arena allocation
  • Parallelization

[dom]

  • IR converter
    • v-on
    • v-once
    • v-memo
  • transformer
  • code generator

[ssr]

  • TODO

[sfc]

  • TODO

[test]

  • scanner test
  • parser test
    • dir parser test
  • Add insta snapshot
  • Move snapshot outside of src

[bench]

  • Add benchmark framework
  • Micro benchmarks for scanner
  • Micro benchmarks for parser
  • Micro benchmarks for converter
  • Micro benchmarks for transformer
  • Micro benchmarks for codegen
  • Integrated benchmarks using repos like Element-Plus

[infra]

  • Add pre-commit hooks.
  • Add Github Actions for various checks.
  • Change single lib to cargo workspaces.

[community]

  • TODO. not ready for contribution for now.
Comments
Owner
Herrington Darkholme
闇と森の妖精
Herrington Darkholme
swc is a super-fast compiler written in rust; producing widely-supported javascript from modern standards and typescript.

Make the web (development) faster. SWC (stands for Speedy Web Compiler) is a super-fast TypeScript / JavaScript compiler written in Rust. It's a libra

swc 25.4k Dec 31, 2022
My 'Lugli' language compiler for learning purposes, written in rust. 🥰🤠

Lugli language compiler My 'Lugli' language compiler for learning purposes, written in rust. This language is to be a subset for other purposes, for e

Vinicios Lugli 3 Nov 2, 2022
A parser, compiler, and virtual machine evaluator for a minimal subset of Lua; written from scratch in Rust.

lust: Lua in Rust This project implements a parser, compiler, and virtual machine evaluator for a minimal subset of Lua. It is written from scratch in

Phil Eaton 146 Dec 16, 2022
Osmon's compiler crate. Programming language made for starter & novice Uzbek audience.

Osmon Tili Osmon bu registrlarga asoslangan virtual mashinalik va yengil dasturlash tili Osmon boshqa o'zbek open source dasturchisi Sukhrob Khakimovn

Osmon 31 Dec 22, 2022
📝 A template for creating WASM + Typescript + Rust workflow libraries.

Create Rust + TypeScript libraries with ease! PR'S WELCOMED! ✨ Inspiration I wanted to create a WebAssembly/Rust library with additional JS features,

Shaoru Ian Huang 25 Dec 24, 2022
Slitter is a C- and Rust-callable slab allocator implemented primarily in Rust, with some C for performance or to avoid unstable Rust features.

Slitter is a less footgunny slab allocator Slitter is a classically structured thread-caching slab allocator that's meant to help write reliable long-

Backtrace Labs 133 Dec 5, 2022
A Rust crate for automatically generating C header files from Rust source file.

Please be aware that this crate is no longer actively maintained, please look into the much more feature rich cbindgen instead. rusty-cheddar rusty-ch

Sean Marshallsay 190 Nov 12, 2022
Rust-ffi-guide - A guide for doing FFI using Rust

Using unsafe for Fun and Profit A guide to traversing the FFI boundary between Rust and other languages. A rendered version is available here. This gu

Michael Bryan 261 Dec 1, 2022
Rust library for build scripts to compile C/C++ code into a Rust library

A library to compile C/C++/assembly into a Rust library/application.

Alex Crichton 1.3k Dec 21, 2022
Rust based WASM/JS bindings for ur-rust

ur-wasm-js WASM/JS bindings for the ur-rust rust library Getting started Installation Either build the library yourself with wasm-pack or install for

Lightning Digital Entertainment 5 Feb 28, 2024
A project for generating C bindings from Rust code

cbindgen   Read the full user docs here! cbindgen creates C/C++11 headers for Rust libraries which expose a public C API. While you could do this by h

Ryan Hunt 1.7k Jan 3, 2023
Automatically generates Rust FFI bindings to C (and some C++) libraries.

bindgen bindgen automatically generates Rust FFI bindings to C (and some C++) libraries. For example, given the C header doggo.h: typedef struct Doggo

The Rust Programming Language 3.2k Jan 4, 2023
Safe interop between Rust and C++

CXX — safe FFI between Rust and C++ This library provides a safe mechanism for calling C++ code from Rust and Rust code from C++, not subject to the m

David Tolnay 4.4k Jan 7, 2023
Safe Rust bridge for creating Erlang NIF functions

Rustler Documentation | Getting Started | Example Rustler is a library for writing Erlang NIFs in safe Rust code. That means there should be no ways t

Rusterlium 3.5k Jan 7, 2023
Bridge the gap between Haskell and Rust

Curryrs Curryrs (a play on the name of Haskell Curry, rs for Rust libraries, and it's pronunciation couriers) is a library for providing easy to use b

Michael Gattozzi 296 Oct 18, 2022
Rust in Haskell FFI Example

Provides an example for using Rust in Haskell. To use this you'll need cargo, rustc, cabal and GHC installed. To execute the example run the following

Michael Gattozzi 21 Oct 1, 2022
Run Java code from Rust!

Java Native Interface Bindings for Rust This library provides complete FFI bindings to the Java Native Interface, as well as a safe and intuitive wrap

Ben Anderson 66 Nov 28, 2022
Embedding Rust in Java

Java/Rust Example An example project showing how to call into Rust code from Java. OSX Linux Windows Requirements Java 7+ Rust (tested with 1.0, night

drrb 318 Jan 1, 2023
Rust-JDBC bindings

jdbc A Rust library that allows you to use JDBC and JDBC drivers. Usage First, add the following to your Cargo.toml: [dependencies] jdbc = "0.1" Next,

Aurora 18 Feb 9, 2022