← Dolaima← Docs indexJavaScript原文中文

JavaScript

Close in style, but you have to call the entry point yourself.

How to run it on your phone

vml run examples/javascript/test/sysinfo.js

Compiling takes a while (one to two minutes for C, a few seconds for scripting languages). Once the program is running, the gamepad is at the bottom of the screen - the D-pad and the four action buttons are all there. Tap the back arrow in the top-right corner to return to the Shell.

What to know before you write

Examples

FileWhat it shows
test/bench.jsBenchmark
test/catch.jsCatch the blocks
test/sysinfo.jsDevice information

Also in this folder: app/maze.js, app/typing_rain.js, demo/demo_std.js, test/libs.js, tty/demo_tty.js, ui/demo_ui.js


The rest of this page is taken straight from the VML source (third_party/vml/VMLPrepares/JavaScriptCompiler/): the README covers what this front end supports and how to compile it, and the language reference covers the syntax itself. When upstream changes, regenerating this page brings it up to date.

Language reference

JavaScript Language Compiler Specification

Version: v1.0 | Date: 2026-07-06 | Revised by: Shenzhen Tanso Intelligent Technology Co., Ltd.

Specification standard

FieldValue
Target standardECMAScript 5.1 subset (2011)
Release year2011
Completeness~94%
MCU completeness~92%
Tests0 (the test directory is to be created)
Update2026-05-18: corrected the completeness and implementation-status descriptions

Keywords

break case catch continue debugger default delete do else finally for function if in instanceof new return switch this throw try typeof var void while with class const export import let super yield true false null undefined NaN Infinity

Overview

This compiler supports a subset of the JavaScript (ECMAScript 5) language and compiles JavaScript source code into VML (Virtual Machine Language) assembly. The compiler uses a statically-compiled architecture and supports the core JavaScript features, including functions, objects, arrays and asynchronous programming.

Supported language features

1. Data types
Primitive types
Object types
2. Variable declarations
Declaration forms
// var (function scope)
var x = 10;
var y, z = 20;

// let (block scope, ES6)
let counter = 0;
for (let i = 0; i < 10; i++) {
    console.log(i);
}

// const (constant, ES6)
const PI = 3.14159;
const MAX_SIZE = 100;

// Destructuring assignment (ES6)
const [a, b] = [1, 2];
const {name, age} = {name: "Alice", age: 30};
Scope
// Global scope
var globalVar = "global";

function testScope() {
    // Function scope
    var functionVar = "function";
    
    if (true) {
        // Block scope (let/const)
        let blockVar = "block";
        console.log(blockVar); // accessible
    }
    // console.log(blockVar); // error: blockVar is not defined
}
3. Functions
Function definitions
// Function declaration
function add(a, b) {
    return a + b;
}

// Function expression
const multiply = function(x, y) {
    return x * y;
};

// Arrow function (ES6)
const divide = (x, y) => x / y;
const square = x => x * x;

// Immediately invoked function expression (IIFE)
(function() {
    console.log("立即执行");
})();

// Generator function (ES6)
function* generator() {
    yield 1;
    yield 2;
    yield 3;
}
Parameter handling
// Default parameters (ES6)
function greet(name = "Guest") {
    console.log(`Hello, ${name}`);
}

// Rest parameters (ES6)
function sum(...numbers) {
    return numbers.reduce((total, num) => total + num, 0);
}

// Parameter destructuring (ES6)
function printUser({name, age, city = "Unknown"}) {
    console.log(`${name}, ${age}岁, 来自${city}`);
}
4. Objects and classes
Object literals
// Object creation
const person = {
    name: "Alice",
    age: 30,
    greet() {
        console.log(`Hello, I'm ${this.name}`);
    },
    // Computed property name (ES6)
    ["id_" + Date.now()]: "unique-id"
};

// Property access
console.log(person.name);      // dot notation
console.log(person["age"]);    // bracket notation

// Object spread (ES6)
const extended = {
    ...person,
    city: "Beijing",
    job: "Developer"
};
Class definitions (ES6)
// Class declaration
class Animal {
    constructor(name) {
        this.name = name;
    }
    
    speak() {
        console.log(`${this.name} makes a sound`);
    }
    
    // Static method
    static isAnimal(obj) {
        return obj instanceof Animal;
    }
}

// Inheritance
class Dog extends Animal {
    constructor(name, breed) {
        super(name);
        this.breed = breed;
    }
    
    speak() {
        console.log(`${this.name} barks`);
    }
    
    // Getter/Setter
    get description() {
        return `${this.name} the ${this.breed}`;
    }
    
    set age(years) {
        this._age = years;
    }
}

// Using the class
const dog = new Dog("Buddy", "Golden Retriever");
dog.speak();
console.log(dog.description);
5. Arrays and collections
Array operations
// Array creation
const numbers = [1, 2, 3, 4, 5];
const empty = new Array(10);
const fromString = Array.from("hello");
const ofArray = Array.of(1, 2, 3);

// Array methods
numbers.push(6);           // add an element
numbers.pop();             // remove the last one
numbers.unshift(0);        // add to the front
numbers.shift();           // remove from the front

// Higher-order functions
const doubled = numbers.map(x => x * 2);
const evens = numbers.filter(x => x % 2 === 0);
const sum = numbers.reduce((total, x) => total + x, 0);
numbers.forEach(x => console.log(x));

// Array destructuring
const [first, second, ...rest] = numbers;
Set and Map (ES6)
// Set - a collection of unique values
const set = new Set([1, 2, 3, 3, 4]); // {1, 2, 3, 4}
set.add(5);
set.delete(2);
console.log(set.has(3)); // true
set.forEach(value => console.log(value));

// Map - a collection of key-value pairs
const map = new Map();
map.set("name", "Alice");
map.set("age", 30);
console.log(map.get("name")); // "Alice"
console.log(map.size); // 2

// WeakSet and WeakMap
const weakSet = new WeakSet();
const weakMap = new WeakMap();
6. Control flow
Conditionals
// if-else
if (condition) {
    // true branch
} else if (anotherCondition) {
    // else-if branch
} else {
    // false branch
}

// Ternary operator
const result = condition ? "true" : "false";

// switch
switch (value) {
    case 1:
        console.log("One");
        break;
    case 2:
        console.log("Two");
        break;
    default:
        console.log("Other");
}
Loops
// for loop
for (let i = 0; i < 10; i++) {
    console.log(i);
}

// for...of (ES6)
for (const item of array) {
    console.log(item);
}

// for...in (iterating over object properties)
for (const key in object) {
    console.log(key, object[key]);
}

// while loop
while (condition) {
    // loop body
}

// do...while loop
do {
    // the loop body runs at least once
} while (condition);
7. Asynchronous programming
Promise
// Creating a promise
const promise = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve("成功");
        // or reject(new Error("失败"));
    }, 1000);
});

// Using a promise
promise
    .then(result => {
        console.log(result);
        return result.toUpperCase();
    })
    .then(upper => console.log(upper))
    .catch(error => console.error(error))
    .finally(() => console.log("完成"));
async/await (ES2017)
async function fetchData() {
    try {
        const response = await fetch("https://api.example.com/data");
        const data = await response.json();
        console.log(data);
        return data;
    } catch (error) {
        console.error("获取数据失败:", error);
        throw error;
    }
}

// Immediately invoke an async function
(async () => {
    const result = await fetchData();
    console.log("结果:", result);
})();
8. Module system
ES6 modules
// math.js - exporting module
export const PI = 3.14159;

export function add(a, b) {
    return a + b;
}

export default class Calculator {
    multiply(x, y) {
        return x * y;
    }
}

// app.js - importing module
import Calculator, { PI, add } from './math.js';
import * as math from './math.js';

const calc = new Calculator();
console.log(calc.multiply(2, 3));
console.log(add(PI, 1));
CommonJS modules (Node.js style)
// Export
module.exports = {
    add: function(a, b) { return a + b; },
    subtract: function(a, b) { return a - b; }
};

// Or
exports.multiply = function(a, b) { return a * b; };

// Import
const math = require('./math.js');
console.log(math.add(2, 3));
9. Error handling
// try-catch-finally
try {
    // code that may throw
    riskyOperation();
    throw new Error("自定义错误");
} catch (error) {
    // handle the error
    console.error("捕获错误:", error.message);
    console.error("堆栈:", error.stack);
} finally {
    // cleanup code, always runs
    cleanup();
}

// Custom error type
class ValidationError extends Error {
    constructor(message, field) {
        super(message);
        this.name = "ValidationError";
        this.field = field;
        this.timestamp = new Date();
    }
}

// Using the custom error
try {
    throw new ValidationError("无效输入", "username");
} catch (error) {
    if (error instanceof ValidationError) {
        console.error(`验证错误在字段 ${error.field}: ${error.message}`);
    }
}
10. Standard library support
Global objects
Array methods
String methods
Object methods
11. Compilation target
Structure of the generated VML code
.entry main
.stack 1048572

.data
hello_string: .string "Hello from JavaScript!"

.text
main:
    MOVE R0, hello_string
    SYSCALL #1    ; output the string
    SYSCALL #3    ; exit the program
Function calling convention
12. Limitations and notes
Current limitations
  1. Unsupported features:
    • The eval() function
    • with statements
    • Dynamic property names (partially supported)
    • Proxy objects
    • The Reflect API
  2. Simplified implementation:
    • The prototype chain is a simplified version
    • The closure implementation has limitations
    • Asynchronous operations are simulated
    • Garbage collection is managed by the VML runtime
  3. Performance considerations:
    • Static compilation, no JIT optimization
    • Object layout is fixed
    • No dynamic code execution
Best practices
  1. Use const and let instead of var
  2. Use arrow functions to preserve the this context
  3. Avoid deeply nested callbacks
  4. Use Promise and async/await to handle asynchronous work
  5. Use modules sensibly to organize code
13. Example programs
Hello World
console.log("Hello, World!");
Computing the Fibonacci sequence
function fibonacci(n) {
    if (n <= 1) return n;
    return fibonacci(n - 1) + fibonacci(n - 2);
}

console.log("斐波那契数列前10项:");
for (let i = 0; i < 10; i++) {
    console.log(`F(${i}) = ${fibonacci(i)}`);
}
Fetching data asynchronously
async function fetchUserData(userId) {
    try {
        console.log(`开始获取用户 ${userId} 的数据...`);
        
        // simulate an asynchronous API call
        const user = await new Promise(resolve => {
            setTimeout(() => {
                resolve({
                    id: userId,
                    name: "Alice",
                    email: "alice@example.com"
                });
            }, 1000);
        });
        
        console.log("用户数据:", user);
        return user;
    } catch (error) {
        console.error("获取用户数据失败:", error);
        throw error;
    }
}

// Using the async function
(async () => {
    const user = await fetchUserData(123);
    console.log(`欢迎, ${user.name}!`);
})();

Floating point and 64-bit compilation modes

The VML toolchain controls the handling strategy for floating point and 64-bit integers through three compilation parameters:

ParameterAllowed valuesDefaultDescription
--float32hard / soft / nonehard32-bit floating point handling mode
--float64hard / soft / nonesoft64-bit floating point (Number) handling mode
--int64hard / soft / nonesoft64-bit integer handling mode
32-bit floating point (float32)

In JavaScript every number is of type Number (IEEE 754 double precision). At VML compile time, 32-bit floating-point operations are handled in the following modes:

64-bit floating point (double)

In JavaScript the Number type is natively IEEE 754 double-precision 64-bit floating point. At VML compile time it is handled in the following modes:

64-bit integers (int64)

JavaScript does not distinguish between integer and floating-point types; every number is a Number. The VML compilation layer reserves the --int64 parameter for future BigInt extension support:

Software emulation libraries

All of the software emulation libraries above live in the Lib/shared/ directory, are written in C and are compiled to VML by the C compiler, and are shared by every language:

Library filePurposeCore functions
softfloat.cQ15.16 fixed-point 32-bit floating-point emulation__vml_float_add/sub/mul/div/neg/abs/cmp, __vml_int2float/float2int
softdouble.cIEEE 754 double-precision 64-bit floating-point emulation__vml_double_add/sub/mul/div/neg/abs/cmp, __vml_int2double/double2int, __vml_float2double/double2float
softint64.c64-bit integer two-register emulation__vml_i64_add/sub/neg/and/or/xor/not/shl/shr

Compiler implementation status

Current completeness: ~94%
Development roadmap
  1. Stage 1: basic syntax support (var, functions, control flow) — ✅ done
  2. Stage 2: object and array support — ⚠️ basically done
  3. Stage 3: class and module support — ❌ to be implemented
  4. Stage 4: asynchronous programming support — ❌ to be implemented
  5. Stage 5: performance optimization and standard library completion — ❌ to be implemented

Compiling and running

Using the JavaScript compiler
# Compile a JavaScript program
dotnet run --project VMLPrepares/JavaScriptCompiler -L Lib/javascript app.js -o output.vml

# Run the generated VML program
dotnet run --project VMLEmulators/FullDevicesEmulator output.vml
Using VMLTool (plugin architecture)
# Automatically recognize a JavaScript file
vmltool app.js -o output.vml

# Specify the JavaScript language
vmltool app.js -o output.vml --lang javascript

Related documents

🆕 String types (v1.65.19)

This language compiler uses .wstring (UTF-16LE) as its internal string storage by default.

ModeDefault encodingVML pseudo-opSYSCALL output
MCU (default).string (UTF-8).string#1
OS.wstring (UTF-16LE).wstring#391

Predefined macro: VML_WSTRING — defined automatically in OS mode, undefined in MCU mode Output function: OS mode uses shared_print_wstr automatically (UTF-16LE to UTF-8 automatic conversion)

// User code can test the encoding through the macro
#ifdef VML_WSTRING
  // the default string is wstring (UTF-16LE)
#else
  // the default string is UTF-8
#endif

Compiler README

JavaScript (ECMAScript 5) Compiler

Path: VMLPrepares/JavaScriptCompiler/ Completeness: ~94% | 🟢 Production ready Standard library: Lib/javascript/ (to be created)

Features

Compilation modes

MCU mode (default --mode mcu)

MCU mode is optimized for microcontroller/bare-metal environments (Arduino/STM32/8051 etc.) and automatically skips features that are incompatible with an operating system.

Skipped (no code is generated for these):

Retained (implemented at the BIOS level):

OS mode (--mode os, reserved)

OS mode targets environments that have an operating system (such as embedded Linux, RTOS). It will then support the full set of language features (file system, threads, async, exceptions, reflection, etc.).

RAM levels
MCU-safe coding tips

Usage

dotnet run --project VMLPrepares/JavaScriptCompiler input.Js -o output.vml

Tests

Test/Js/ — 0 test files (the test directory is to be created; use Js to avoid clashing with the Java Test/Jv)