Files
NeoTachyon/docs/knowledge-base/12_UCODE_PROGRAMMING_PATTERNS.md
T

82 lines
2.7 KiB
Markdown

# 12. ucode Programming Patterns & Conventions
A developer's guide to writing safe, high-performance, and idiomatic **ucode** modules for Tachyon on OpenWrt.
---
## 1. ucode vs JavaScript: Critical Distinctions
While ucode syntax resembles JavaScript, its runtime semantics differ significantly:
1. **Variables & Scope**:
* Always declare variables with `let` or `const`.
* Unassigned variables are `null` (not `undefined`).
2. **Arrays vs Dictionaries**:
* Arrays: `[1, 2, 3]`. Iterated with `for (let item in array)`.
* Dictionaries (Objects): `{"key": "value"}`. Iterated with `for (let key, val in dict)`.
3. **Regular Expressions**:
* Use `match(str, /regex/)` or `replace(str, /regex/g, "replacement")`.
* Global flag `/g` works with `replace()`, while `match()` returns capture groups array `[full_match, group1, ...]`.
4. **Boolean Coercion**:
* Empty strings `""`, `0`, and `null` are falsy. Everything else is truthy.
---
## 2. Mandatory Core Design Patterns
### 2.1. Atomic Configuration Writes
Never overwrite active configuration files in-place. Always write to a temporary file in `/tmp/` and atomically rename:
```ucode
let fs = require("fs");
function write_atomic(path, content) {
let tmp_path = path + ".tmp." + int(time());
let f = fs.open(tmp_path, "w");
if (!f) return false;
f.write(content);
f.close();
return fs.rename(tmp_path, path);
}
```
### 2.2. Shell Argument Quoting
When executing external shell commands, all user inputs must be quoted safely:
```ucode
function shell_quote(value) {
return "'" + replace("" + value, /'/g, "'\\''") + "'";
}
function safe_exec(cmd_args) {
let parts = [];
for (let arg in cmd_args)
push(parts, shell_quote(arg));
return system(join(" ", parts));
}
```
### 2.3. Safe Error Handling (`try-catch`)
All external library loading or file parsing must be wrapped in `try-catch` blocks to avoid unhandled script panics:
```ucode
let uci_data = null;
try {
let uci = require("uci").cursor();
uci_data = uci.get_all("tachyon", "settings");
}
catch (e) {
warn("Failed to load UCI settings: " + e + "\n");
}
```
---
## 3. Performance & Memory Optimization Guidelines
1. **Stream Large Files**: Avoid loading multi-megabyte blocklists entirely into RAM with `fs.readfile()`. Use line-by-line streaming via `fs.open()` and `f.read("line")`.
2. **Avoid Spawning Subprocesses in Loops**: Invoking `system()` or `fs.popen()` spawns a fork-exec sequence in Linux. Use native ucode functions for string manipulation and path operations whenever possible.
3. **Keep Modules Stateless**: Module files under `usr/lib/tachyon/` should export reusable pure functions or class definitions rather than maintaining mutable global state.