tsn-0.1.1 is not a library.
tsn
TypeScript to native executable compiler.
Quick start with cargo-tsn:
See cargo-tsn README for project management.
What is it
A compiler that converts TypeScript to native executable (10-14KB), no Node.js required.
What can it do
- Compile TypeScript to native
.exe - Generate dependency-free executables
- Call Rust FFI functions
- No runtime overhead
How to use
Output:
a.o- Object filea.exe- Native executable
Limitations
tsn has very few built-in functions (only print).
Solution
Extend capabilities by integrating existing Rust crates via FFI.
Extension mechanism
tsn scans ./tsnp/ directory for plugin configurations:
project/
├── tsnp/
│ └── my-plugin/
│ └── ts-native.toml
└── main.ts
tsn main.ts # Automatically loads plugins from tsnp/
Using cargo-tsn (Recommended)
# Create project
# Add Rust crate dependency
# Interactively add FFI functions
# Compile
See cargo-tsn for details.
Using tsnp directly
# Generate plugin from Rust crate
# Output: tsnp/my-plugin/ts-native.toml
See tsnp for details.
How it works
Compilation pipeline
TypeScript source
↓
Lexer
↓
Parser
↓
HIR (High-level IR)
↓
Codegen (Cranelift)
↓
Object file (.o)
↓
Linker (.exe)
↓
Native executable
Value representation: NaN-boxing
All JavaScript values fit in 64 bits using NaN-boxing:
STRING_TAG = 0x7FFC_0000_0000_0000
ARRAY_TAG = 0x7FFB_0000_0000_0000
OBJECT_TAG = 0x7FFA_0000_0000_0000
UNDEFINED = 0x7FFF_8000_0000_0001
NULL = 0x7FFF_8000_0000_0002
TRUE = 0x7FFF_0000_0000_0001
FALSE = 0x7FFF_0000_0000_0000
Benefits:
- No boxing/unboxing overhead
- Type checks are bitmask operations
- Pointers stored directly in value
Backend: Cranelift
- Modern code generator
- Optimized x86_64 output
- No LLVM dependency
- Fast compilation
Memory management
- Arena allocation for AST
- Heap allocation for strings/arrays/objects
- No garbage collector (manual memory management)
FFI integration
When tsn encounters a function call:
- Check if function exists in
tsnp/*/ts-native.toml - Load function signature (args, return type)
- Generate FFI call to Rust function
- Handle type conversions
Example:
// TypeScript
const result = add(1, 2);
// Rust FFI
pub extern "C"
tsn generates:
- Load arguments to registers
- Call Rust function
- Store return value
Supported TypeScript features
Data types
- ✅ Numbers (integers, floats)
- ✅ Strings (dynamic allocation, concatenation)
- ✅ Arrays (dynamic allocation, nested)
- ✅ Objects (dynamic allocation)
- ✅ Boolean, null, undefined
Operators
- ✅ Arithmetic:
+ - * / % - ✅ Comparison:
== != < > <= >= - ✅ Logical:
&& || ! - ✅ Ternary:
cond ? then : else - ✅
typeofoperator
Control flow
- ✅
ifstatement - ✅
if-elsestatement - ✅
whileloop - ✅
forloop - ✅
returnstatement
Functions
- ✅ Function definition
- ✅ Function call
- ✅ Multiple parameters
- ✅ Return values
- ✅ Recursion
Data structures
- ✅ Array literals
[1, 2, 3] - ✅ Array indexing
arr[i] - ✅ Array assignment
arr[i] = value - ✅ Object literals
{x: 10} - ✅ Property access
obj.x - ✅ Property assignment
obj.x = value
Not implemented
break,continueswitchstatementclasssyntaxasync/await- Modules
- Generics
Installation
Project structure
tsn/
├── src/
│ ├── main.rs # CLI entry point
│ ├── ts_parser.rs # TypeScript lexer & parser
│ ├── codegen.rs # Cranelift code generation
│ ├── linker.rs # Native linker
│ ├── extension.rs # Plugin loading
│ └── runtime.rs # Runtime helpers
└── Cargo.toml
Links
License
MIT