Pure MoonBit cross-target embedded JavaScript engine
Dependencies
moon run cmd/main -- 'console.log(1 + 2)'
# 3moon run cmd/main -- '
function fib(n) {
if (n <= 1) { return n; }
return fib(n - 1) + fib(n - 2);
}
console.log(fib(10));
'
# 55///|
test "README stateful rule engine" {
let engine = @js_engine.Engine()
let source =
#|let evaluations = 0;
#|function allow(request) {
#| evaluations += 1;
#| return { allowed: request.role === "admin", evaluations };
#|}
engine.eval(source)
let admin = Json::object({ "role": Json::string("admin") })
let member_request = Json::object({ "role": Json::string("member") })
json_inspect(engine.call_json("allow", [admin]), content={
"allowed": true,
"evaluations": 1,
})
json_inspect(engine.call_json("allow", [member_request]), content={
"allowed": false,
"evaluations": 2,
})
}///|
test "README one-shot facade" {
let (output, _) = @js_engine.run("console.log(1 + 2)")
json_inspect(output, content=["3"])
}let interp = @interpreter.new_interpreter()
// Build query_selector with realm_state=Some(interp.realm_state) — see guide.
let document = @runtime.make_host_object(
name="Document",
proto=@runtime.get_obj_proto(realm_state=Some(interp.realm_state)),
methods={ "querySelector": query_selector },
)
interp.global.def_builtin("document", document)
// Then parse, interp.run, interp.run_microtasks(), interp.run_timers().| Edition | Discovered | Skipped | Executed | Passed | Failed | Timeout/Err | Passed / Executed | Passed / Discovered |
|---|---|---|---|---|---|---|---|---|
| Pre-ES2015 (baseline) | 13,281 | 0 | 13,277 | 13,057 | 220 | 4 | 98.3% | 98.3% |
| ES2015 | 10,300 | 161 | 10,131 | 10,033 | 98 | 8 | 99.0% | 97.4% |
| ES2016 | 100 | 0 | 99 | 99 | 0 | 1 | 100.0% | 99.0% |
| ES2017 | 736 | 344 | 392 | 392 | 0 | 0 | 100.0% | 53.3% |
| ES2018 | 4,725 | 727 | 3,998 | 3,822 | 176 | 0 | 95.6% | 80.9% |
| ES2019 | 128 | 0 | 128 | 106 | 22 | 0 | 82.8% | 82.8% |
| ES2020 | 1,784 | 1,537 | 247 | 244 | 3 | 0 | 98.8% | 13.7% |
| ES2021 | 468 | 128 | 340 | 326 | 14 | 0 | 95.9% | 69.7% |
| ES2022 | 5,065 | 34 | 5,031 | 2,765 | 2,266 | 0 | 55.0% | 54.6% |
| ES2023 | 254 | 33 | 221 | 218 | 3 | 0 | 98.6% | 85.8% |
| ES2024 | 1,072 | 866 | 206 | 108 | 98 | 0 | 52.4% | 10.1% |
| ES2025 | 1,148 | 779 | 369 | 296 | 73 | 0 | 80.2% | 25.8% |
| Annex B | 365 | 44 | 319 | 265 | 54 | 2 | 83.1% | 72.6% |
| Stage 3 | 5,531 | 5,519 | 12 | 6 | 6 | 0 | 50.0% | 0.1% |
| Total | 44,986 | 10,201 | 34,770 | 31,737 | 3,033 | 15 | 91.3% | 70.5% |
| Edition | Discovered | Skipped | Executed | Passed | Failed | Timeout/Err | Passed / Executed | Passed / Discovered |
|---|---|---|---|---|---|---|---|---|
| Pre-ES2015 (baseline) | 13,917 | 0 | 13,909 | 13,544 | 365 | 8 | 97.4% | 97.3% |
| ES2015 | 10,788 | 160 | 10,620 | 10,498 | 122 | 8 | 98.9% | 97.3% |
| ES2016 | 100 | 0 | 99 | 99 | 0 | 1 | 100.0% | 99.0% |
| ES2017 | 775 | 344 | 431 | 431 | 0 | 0 | 100.0% | 55.6% |
| ES2018 | 4,781 | 735 | 4,046 | 3,870 | 176 | 0 | 95.7% | 80.9% |
| ES2019 | 127 | 0 | 127 | 105 | 22 | 0 | 82.7% | 82.7% |
| ES2020 | 1,984 | 1,604 | 380 | 377 | 3 | 0 | 99.2% | 19.0% |
| ES2021 | 444 | 128 | 316 | 302 | 14 | 0 | 95.6% | 68.0% |
| ES2022 | 5,361 | 296 | 5,065 | 2,788 | 2,277 | 0 | 55.0% | 52.0% |
| ES2023 | 277 | 56 | 221 | 218 | 3 | 0 | 98.6% | 78.7% |
| ES2024 | 1,077 | 870 | 207 | 109 | 98 | 0 | 52.7% | 10.1% |
| ES2025 | 1,180 | 813 | 367 | 294 | 73 | 0 | 80.1% | 24.9% |
| Annex B | 1,156 | 44 | 1,110 | 909 | 201 | 2 | 81.9% | 78.6% |
| Stage 3 | 5,696 | 5,593 | 103 | 10 | 93 | 0 | 9.7% | 0.2% |
| Total | 47,692 | 10,672 | 37,001 | 33,554 | 3,447 | 19 | 90.7% | 70.4% |
token/ Token types and source locations
errors/ JavaScript error variants and formatting helpers
lexer/ Tokenizer
ast/ AST node definitions
parser/ Recursive descent parser with Pratt precedence
static_semantics/ Early-error and declaration-fact analysis
compiler/ Opt-in closure-conversion prototype
interpreter/ Wiring layer for runtime + standard library
interpreter/runtime/ Tree-walking evaluator, value model, host state
interpreter/stdlib/ JavaScript built-ins
cmd/main/ CLI entry point
cmd/test262_runner/ Native test262 runner
cmd/report_test262/ CI artifact report generator
benchmarks/ Benchmark workloads and runner
example/rule_engine/ Canonical stateful JSON rule-engine embeddingmoon check # Type check
moon test # Run unit tests
moon fmt # Format code
moon info # Update .mbti interface files
moon build # Buildpub(all) suberror EngineError {
ParseError(String)
JavaScriptException(String)
MissingGlobal(String)
NotCallable(String)
JsonConversionError(String)
InternalError(String)
} derive(Debug)impl Show for EngineErrorfn Engine::call_json_bounded(self : Engine, name : String, args : Array[Json], policy : ExecutionPolicy) -> Result[Json, EngineDiagnostic]fn Engine::eval_bounded(self : Engine, source : String, policy : ExecutionPolicy, source_id? : String) -> Result[Unit, EngineDiagnostic]fn Engine::eval_diagnostic(self : Engine, source : String, source_id? : String) -> Result[Unit, EngineDiagnostic]fn Engine::inject_json(self : Engine, name : String, value : Json) -> Result[Unit, EngineDiagnostic]fn Engine::run_microtask_checkpoint_bounded(self : Engine, policy : ExecutionPolicy) -> Result[Bool, EngineDiagnostic]fn Engine::run_timer_checkpoint_bounded(self : Engine, policy : ExecutionPolicy) -> Result[Unit, EngineDiagnostic]pub struct EngineDiagnostic {
failure_kind_code_ : String
message_ : String
operation_code_ : String
phase_code_ : String
source_identity_ : String?
source_location_ : SourceLocation?
engine_integrity_ : EngineIntegrity
retained_effects_ : RetainedEffects
pending_jobs_ : PendingJobs
}pub(all) enum EngineIntegrity {
Reusable
Discard
Unknown
NotApplicable
}pub(all) enum PendingJobs {
None
Present
Unknown
}pub(all) enum RetainedEffects {
None
MayRemain
Unknown
}pub struct SourcePosition {
line_ : Int
column_ : Int
offset_ : Int
}fn run_diagnostic(source : String, source_id? : String, annex_b? : Bool) -> Result[(Array[String], String), EngineDiagnostic]Pure MoonBit cross-target embedded JavaScript engine
Dependencies