Skip to main content

php_wasm/
lib.rs

1use serde::Serialize;
2use wasm_bindgen::prelude::*;
3
4#[derive(Serialize)]
5struct WasmError {
6    message: String,
7    start: u32,
8    end: u32,
9}
10
11#[derive(Serialize)]
12struct ParseOutput {
13    ast: serde_json::Value,
14    errors: Vec<WasmError>,
15    formatted: String,
16}
17
18fn php_version_from_str(s: &str) -> Option<php_rs_parser::PhpVersion> {
19    match s {
20        "7.4" => Some(php_rs_parser::PhpVersion::Php74),
21        "8.0" => Some(php_rs_parser::PhpVersion::Php80),
22        "8.1" => Some(php_rs_parser::PhpVersion::Php81),
23        "8.2" => Some(php_rs_parser::PhpVersion::Php82),
24        "8.3" => Some(php_rs_parser::PhpVersion::Php83),
25        "8.4" => Some(php_rs_parser::PhpVersion::Php84),
26        "8.5" => Some(php_rs_parser::PhpVersion::Php85),
27        _ => None,
28    }
29}
30
31/// Parse PHP source and return `{ ast, errors, formatted }` as a JS object.
32///
33/// `version` is an optional PHP target version string like `"8.4"`. Defaults
34/// to the latest supported version when omitted or unrecognised.
35#[wasm_bindgen]
36pub fn parse(source: &str, version: Option<String>) -> Result<JsValue, JsError> {
37    let php_version = version
38        .as_deref()
39        .and_then(php_version_from_str)
40        .unwrap_or(php_rs_parser::PhpVersion::Php85);
41
42    let arena = bumpalo::Bump::new();
43    let result = php_rs_parser::parse_versioned(&arena, source, php_version);
44
45    let errors: Vec<WasmError> = result
46        .errors
47        .iter()
48        .map(|e| {
49            let span = e.span();
50            WasmError {
51                message: e.to_string(),
52                start: span.start,
53                end: span.end,
54            }
55        })
56        .collect();
57
58    let ast = serde_json::to_value(&result.program).unwrap_or(serde_json::Value::Null);
59    let formatted = php_printer::pretty_print(&result.program);
60
61    let output = ParseOutput {
62        ast,
63        errors,
64        formatted,
65    };
66    let serializer = serde_wasm_bindgen::Serializer::json_compatible();
67    Ok(output.serialize(&serializer)?)
68}
69
70/// Pretty-print PHP source without returning the AST.
71#[wasm_bindgen]
72pub fn format(source: &str) -> String {
73    let arena = bumpalo::Bump::new();
74    let result = php_rs_parser::parse(&arena, source);
75    php_printer::pretty_print(&result.program)
76}
77
78/// Crate version from Cargo.toml, e.g. `"0.9.4"`.
79#[wasm_bindgen]
80pub fn parser_version() -> String {
81    env!("CARGO_PKG_VERSION").to_string()
82}
83
84/// Short git commit hash captured at WASM build time, e.g. `"a1b2c3d"`.
85#[wasm_bindgen]
86pub fn build_commit() -> String {
87    option_env!("BUILD_COMMIT").unwrap_or("unknown").to_string()
88}