titanpl-sdk 2.0.2 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,7 @@
1
+ //! External native extension loading and FFI.
2
+ //!
3
+ //! Supports loading `.dll` / `.so` extensions defined in `titan.json` files.
4
+
1
5
  use v8;
2
6
  use std::path::PathBuf;
3
7
  use std::collections::HashMap;
@@ -16,19 +20,15 @@ pub struct Registry {
16
20
  pub _libs: Vec<Library>,
17
21
  pub modules: Vec<ModuleDef>,
18
22
  pub natives: Vec<NativeFnEntry>,
19
- pub v8_natives: Vec<usize>,
20
23
  }
21
24
 
22
-
23
25
  #[derive(Clone)]
24
26
  pub struct ModuleDef {
25
27
  pub name: String,
26
28
  pub js: String,
27
29
  pub native_indices: HashMap<String, usize>,
28
- pub v8_native_indices: HashMap<String, usize>,
29
30
  }
30
31
 
31
-
32
32
  #[derive(Clone, Debug, PartialEq)]
33
33
  pub enum ParamType {
34
34
  String, F64, Bool, Json, Buffer,
@@ -60,18 +60,9 @@ struct TitanConfig {
60
60
  #[derive(serde::Deserialize)]
61
61
  struct TitanNativeConfig {
62
62
  path: String,
63
- #[serde(default)]
64
63
  functions: HashMap<String, TitanNativeFunc>,
65
- #[serde(default)]
66
- v8_functions: HashMap<String, TitanV8Func>,
67
- }
68
-
69
- #[derive(serde::Deserialize)]
70
- struct TitanV8Func {
71
- symbol: String,
72
64
  }
73
65
 
74
-
75
66
  #[derive(serde::Deserialize)]
76
67
  struct TitanNativeFunc {
77
68
  symbol: String,
@@ -108,8 +99,6 @@ pub fn load_project_extensions(root: PathBuf) {
108
99
  let mut modules = Vec::new();
109
100
  let mut libs = Vec::new();
110
101
  let mut all_natives = Vec::new();
111
- let mut all_v8_natives = Vec::new();
112
-
113
102
 
114
103
  let mut node_modules = root.join("node_modules");
115
104
  if !node_modules.exists() {
@@ -120,8 +109,7 @@ pub fn load_project_extensions(root: PathBuf) {
120
109
  }
121
110
 
122
111
  // Generic scanner helper
123
- let scan_dir = |path: PathBuf, modules: &mut Vec<ModuleDef>, libs: &mut Vec<Library>, all_natives: &mut Vec<NativeFnEntry>, all_v8_natives: &mut Vec<usize>| {
124
-
112
+ let scan_dir = |path: PathBuf, modules: &mut Vec<ModuleDef>, libs: &mut Vec<Library>, all_natives: &mut Vec<NativeFnEntry>| {
125
113
  if !path.exists() { return; }
126
114
  for entry in WalkDir::new(&path).follow_links(true).min_depth(1).max_depth(4) {
127
115
  let entry = match entry { Ok(e) => e, Err(_) => continue };
@@ -133,9 +121,7 @@ pub fn load_project_extensions(root: PathBuf) {
133
121
  Err(_) => continue,
134
122
  };
135
123
  let mut mod_natives_map = HashMap::new();
136
- let mut mod_v8_natives_map = HashMap::new();
137
124
  if let Some(native_conf) = config.native {
138
-
139
125
  let lib_path = dir.join(&native_conf.path);
140
126
  unsafe {
141
127
  // Try loading library
@@ -144,28 +130,17 @@ pub fn load_project_extensions(root: PathBuf) {
144
130
  // But usually absolute path from `dir` works.
145
131
  match lib_load {
146
132
  Ok(lib) => {
147
- for (fn_name, fn_conf) in &native_conf.functions {
133
+ for (fn_name, fn_conf) in native_conf.functions {
148
134
  let params = fn_conf.parameters.iter().map(|p| parse_type(&p.to_lowercase())).collect();
149
135
  let ret = parse_return(&fn_conf.result.to_lowercase());
150
136
  if let Ok(symbol) = lib.get::<*const ()>(fn_conf.symbol.as_bytes()) {
151
137
  let idx = all_natives.len();
152
138
  all_natives.push(NativeFnEntry { symbol_ptr: *symbol as usize, sig: Signature { params, ret } });
153
- mod_natives_map.insert(fn_name.clone(), idx);
139
+ mod_natives_map.insert(fn_name, idx);
154
140
  } else {
155
141
  println!("{} {} {} -> {}", blue("[Titan]"), red("Symbol not found:"), fn_conf.symbol, config.name);
156
142
  }
157
143
  }
158
-
159
- for (fn_name, fn_conf) in &native_conf.v8_functions {
160
- if let Ok(symbol) = lib.get::<*const ()>(fn_conf.symbol.as_bytes()) {
161
- let idx = all_v8_natives.len();
162
- all_v8_natives.push(*symbol as usize);
163
- mod_v8_natives_map.insert(fn_name.clone(), idx);
164
- } else {
165
- println!("{} {} {} -> {}", blue("[Titan]"), red("V8 Symbol not found:"), fn_conf.symbol, config.name);
166
- }
167
- }
168
-
169
144
  libs.push(lib);
170
145
  },
171
146
  Err(e) => {
@@ -175,13 +150,7 @@ pub fn load_project_extensions(root: PathBuf) {
175
150
  }
176
151
  }
177
152
  let js_path = dir.join(&config.main);
178
- modules.push(ModuleDef {
179
- name: config.name.clone(),
180
- js: fs::read_to_string(js_path).unwrap_or_default(),
181
- native_indices: mod_natives_map,
182
- v8_native_indices: mod_v8_natives_map
183
- });
184
-
153
+ modules.push(ModuleDef { name: config.name.clone(), js: fs::read_to_string(js_path).unwrap_or_default(), native_indices: mod_natives_map });
185
154
  println!("{} {} {}", blue("[Titan]"), green("Extension loaded:"), config.name);
186
155
  }
187
156
  }
@@ -189,18 +158,16 @@ pub fn load_project_extensions(root: PathBuf) {
189
158
 
190
159
  // Scan node_modules
191
160
  if node_modules.exists() {
192
- scan_dir(node_modules, &mut modules, &mut libs, &mut all_natives, &mut all_v8_natives);
161
+ scan_dir(node_modules, &mut modules, &mut libs, &mut all_natives);
193
162
  }
194
163
 
195
-
196
164
  // Scan .ext (Production / Docker)
197
165
  let ext_dir = root.join(".ext");
198
166
  if ext_dir.exists() {
199
- scan_dir(ext_dir, &mut modules, &mut libs, &mut all_natives, &mut all_v8_natives);
167
+ scan_dir(ext_dir, &mut modules, &mut libs, &mut all_natives);
200
168
  }
201
169
 
202
- *REGISTRY.lock().unwrap() = Some(Registry { _libs: libs, modules, natives: all_natives, v8_natives: all_v8_natives });
203
-
170
+ *REGISTRY.lock().unwrap() = Some(Registry { _libs: libs, modules, natives: all_natives });
204
171
  }
205
172
 
206
173
  pub fn inject_external_extensions(scope: &mut v8::HandleScope, global: v8::Local<v8::Object>, t_obj: v8::Local<v8::Object>) {
@@ -208,10 +175,9 @@ pub fn inject_external_extensions(scope: &mut v8::HandleScope, global: v8::Local
208
175
  let invoke_key = v8_str(scope, "__titan_invoke_native");
209
176
  global.set(scope, invoke_key.into(), invoke_fn.into());
210
177
 
211
- let (modules, v8_native_ptrs) = if let Ok(guard) = REGISTRY.lock() {
212
- (guard.as_ref().map(|r| r.modules.clone()).unwrap_or_default(), guard.as_ref().map(|r| r.v8_natives.clone()).unwrap_or_default())
213
- } else { (vec![], vec![]) };
214
-
178
+ let modules = if let Ok(guard) = REGISTRY.lock() {
179
+ guard.as_ref().map(|r| r.modules.clone()).unwrap_or_default()
180
+ } else { vec![] };
215
181
 
216
182
  for module in modules {
217
183
  let mod_obj = v8::Object::new(scope);
@@ -225,24 +191,6 @@ pub fn inject_external_extensions(scope: &mut v8::HandleScope, global: v8::Local
225
191
  }
226
192
  }
227
193
  }
228
-
229
- for (fn_name, &idx) in &module.v8_native_indices {
230
- if let Some(&ptr) = v8_native_ptrs.get(idx) {
231
- if ptr != 0 {
232
- unsafe {
233
- let ext = v8::External::new(scope, ptr as *mut std::ffi::c_void);
234
- let templ = v8::FunctionTemplate::builder(native_invoke_v8_proxy)
235
- .data(ext.into())
236
- .build(scope);
237
-
238
- if let Some(func) = templ.get_function(scope) {
239
- let key = v8_str(scope, fn_name);
240
- mod_obj.set(scope, key.into(), func.into());
241
- }
242
- }
243
- }
244
- }
245
- }
246
194
  let mod_key = v8_str(scope, &module.name);
247
195
  t_obj.set(scope, mod_key.into(), mod_obj.into());
248
196
 
@@ -330,20 +278,6 @@ fn native_invoke_extension(scope: &mut v8::HandleScope, args: v8::FunctionCallba
330
278
  }
331
279
  }
332
280
 
333
- fn native_invoke_v8_proxy(scope: &mut v8::HandleScope, args: v8::FunctionCallbackArguments, retval: v8::ReturnValue) {
334
- let val = args.data();
335
- if let Ok(ext) = v8::Local::<v8::External>::try_from(val) {
336
- let ptr = ext.value() as *mut std::ffi::c_void;
337
- if !ptr.is_null() {
338
- unsafe {
339
- type TitanV8Handler = extern "C" fn(&mut v8::HandleScope, v8::FunctionCallbackArguments, v8::ReturnValue);
340
- let handler: TitanV8Handler = std::mem::transmute(ptr);
341
- handler(scope, args, retval);
342
- }
343
- }
344
- }
345
- }
346
-
347
281
  fn arg_from_v8(scope: &mut v8::HandleScope, val: v8::Local<v8::Value>, ty: &ParamType) -> serde_json::Value {
348
282
  match ty {
349
283
  ParamType::String => serde_json::Value::String(val.to_rust_string_lossy(scope)),