1#![allow(clippy::mutable_key_type, clippy::cloned_ref_to_slice_refs)]
2mod arithmetic;
3mod async_ops;
4mod bitwise;
5mod bytevector;
6mod comparison;
7mod context;
8mod crypto;
9mod csv_ops;
10mod datetime;
11#[cfg(not(target_arch = "wasm32"))]
12mod http;
13#[cfg(not(target_arch = "wasm32"))]
14mod io;
15pub(crate) mod json;
16#[cfg(not(target_arch = "wasm32"))]
17mod kv;
18mod list;
19mod map;
20mod math;
21mod meta;
22#[cfg(not(target_arch = "wasm32"))]
23mod pdf;
24mod pio;
25mod predicates;
26mod regex_ops;
27#[cfg(not(target_arch = "wasm32"))]
28mod serial;
29#[cfg(not(target_arch = "wasm32"))]
30mod server;
31#[cfg(not(target_arch = "wasm32"))]
32mod sqlite;
33mod stream;
34mod string;
35#[cfg(not(target_arch = "wasm32"))]
36mod system;
37#[cfg(not(target_arch = "wasm32"))]
38mod terminal;
39mod text;
40mod toml_ops;
41mod typed_array;
42
43#[cfg(not(target_arch = "wasm32"))]
44use sema_core::Caps;
45use sema_core::{Env, Sandbox, Value};
46
47pub fn register_stdlib(env: &Env, sandbox: &Sandbox) {
48 #[cfg(target_arch = "wasm32")]
49 let _ = sandbox;
50
51 arithmetic::register(env);
52 comparison::register(env);
53 context::register(env);
54 list::register(env);
55 string::register(env);
56 predicates::register(env);
57 map::register(env);
58 #[cfg(not(target_arch = "wasm32"))]
59 io::register(env, sandbox);
60 math::register(env);
61 #[cfg(not(target_arch = "wasm32"))]
62 system::register(env, sandbox);
63 json::register(env);
64 toml_ops::register(env);
65 meta::register(env);
66 regex_ops::register(env);
67 #[cfg(not(target_arch = "wasm32"))]
68 http::register(env, sandbox);
69 #[cfg(not(target_arch = "wasm32"))]
70 server::register(env, sandbox);
71 bitwise::register(env);
72 crypto::register(env);
73 datetime::register(env);
74 csv_ops::register(env);
75 bytevector::register(env);
76 #[cfg(not(target_arch = "wasm32"))]
77 terminal::register(env);
78 text::register(env);
79 stream::register(env);
80 pio::register(env);
81 typed_array::register(env);
82 async_ops::register(env);
83 #[cfg(not(target_arch = "wasm32"))]
84 stream::register_io(env, sandbox);
85 #[cfg(not(target_arch = "wasm32"))]
86 kv::register(env, sandbox);
87 #[cfg(not(target_arch = "wasm32"))]
88 pdf::register(env, sandbox);
89 #[cfg(not(target_arch = "wasm32"))]
90 sqlite::register(env, sandbox);
91 #[cfg(not(target_arch = "wasm32"))]
92 serial::register(env, sandbox);
93}
94
95#[cfg(not(target_arch = "wasm32"))]
96fn register_fn_gated(
97 env: &Env,
98 sandbox: &Sandbox,
99 cap: Caps,
100 name: &str,
101 f: impl Fn(&[Value]) -> Result<Value, sema_core::SemaError> + 'static,
102) {
103 if sandbox.is_unrestricted() {
104 register_fn(env, name, f);
105 } else {
106 let sandbox = sandbox.clone();
107 let fn_name = name.to_string();
108 register_fn(env, name, move |args| {
109 sandbox.check(cap, &fn_name)?;
110 f(args)
111 });
112 }
113}
114
115#[cfg(not(target_arch = "wasm32"))]
116fn register_fn_path_gated(
117 env: &Env,
118 sandbox: &Sandbox,
119 cap: Caps,
120 name: &str,
121 path_args: &[usize],
122 f: impl Fn(&[Value]) -> Result<Value, sema_core::SemaError> + 'static,
123) {
124 if sandbox.is_unrestricted() {
125 register_fn(env, name, f);
126 } else {
127 let sandbox = sandbox.clone();
128 let fn_name = name.to_string();
129 let path_indices: Vec<usize> = path_args.to_vec();
130 register_fn(env, name, move |args| {
131 sandbox.check(cap, &fn_name)?;
132 for &idx in &path_indices {
133 if let Some(val) = args.get(idx) {
134 if let Some(p) = val.as_str() {
135 sandbox.check_path(p, &fn_name)?;
136 }
137 }
138 }
139 f(args)
140 });
141 }
142}
143
144fn register_fn(
145 env: &Env,
146 name: &str,
147 f: impl Fn(&[Value]) -> Result<Value, sema_core::SemaError> + 'static,
148) {
149 env.set(
150 sema_core::intern(name),
151 Value::native_fn(sema_core::NativeFn::simple(name, f)),
152 );
153}