kg_js/
bindings.rs

1use bitflags::bitflags;
2use crate::ctx::DukContext;
3use super::*;
4
5bitflags! {
6    pub struct DukCompileFlags: u32 {
7        const DUK_COMPILE_EVAL                  = (1 << 3);    /* compile eval code (instead of global code) */
8        const DUK_COMPILE_FUNCTION              = (1 << 4);    /* compile function code (instead of global code) */
9        const DUK_COMPILE_STRICT                = (1 << 5);    /* use strict (outer) context for global, eval, or function code */
10        const DUK_COMPILE_SHEBANG               = (1 << 6);    /* allow shebang ('#! ...') comment on first line of source */
11        const DUK_COMPILE_SAFE                  = (1 << 7);    /* (internal) catch compilation errors */
12        const DUK_COMPILE_NORESULT              = (1 << 8);    /* (internal) omit eval result */
13        const DUK_COMPILE_NOSOURCE              = (1 << 9);    /* (internal) no source string on stack */
14        const DUK_COMPILE_STRLEN                = (1 << 10);   /* (internal) take strlen() of src_buffer (avoids double evaluation in macro) */
15        const DUK_COMPILE_NOFILENAME            = (1 << 11);   /* (internal) no filename on stack */
16        const DUK_COMPILE_FUNCEXPR              = (1 << 12);   /* (internal) source is a function expression (used for Function constructor) */
17    }
18}
19
20bitflags! {
21    pub struct DukDefpropFlags: u32 {
22        const DUK_DEFPROP_WRITABLE              = (1 << 0);    /* set writable (effective if DUK_DEFPROP_HAVE_WRITABLE set) */
23        const DUK_DEFPROP_ENUMERABLE            = (1 << 1);    /* set enumerable (effective if DUK_DEFPROP_HAVE_ENUMERABLE set) */
24        const DUK_DEFPROP_CONFIGURABLE          = (1 << 2);    /* set configurable (effective if DUK_DEFPROP_HAVE_CONFIGURABLE set) */
25        const DUK_DEFPROP_HAVE_WRITABLE         = (1 << 3);    /* set/clear writable */
26        const DUK_DEFPROP_HAVE_ENUMERABLE       = (1 << 4);    /* set/clear enumerable */
27        const DUK_DEFPROP_HAVE_CONFIGURABLE     = (1 << 5);    /* set/clear configurable */
28        const DUK_DEFPROP_HAVE_VALUE            = (1 << 6);    /* set value (given on value stack) */
29        const DUK_DEFPROP_HAVE_GETTER           = (1 << 7);    /* set getter (given on value stack) */
30        const DUK_DEFPROP_HAVE_SETTER           = (1 << 8);    /* set setter (given on value stack) */
31        const DUK_DEFPROP_FORCE                 = (1 << 9);    /* force change if possible, may still fail for e.g. virtual properties */
32    }
33}
34
35bitflags! {
36    pub struct DukEnumFlags: u32 {
37        const DUK_ENUM_INCLUDE_NONENUMERABLE    = (1 << 0);    /* enumerate non-numerable properties in addition to enumerable */
38        const DUK_ENUM_INCLUDE_HIDDEN           = (1 << 1);    /* enumerate hidden symbols too (in Duktape 1.x called internal properties) */
39        const DUK_ENUM_INCLUDE_SYMBOLS          = (1 << 2);    /* enumerate symbols */
40        const DUK_ENUM_EXCLUDE_STRINGS          = (1 << 3);    /* exclude strings */
41        const DUK_ENUM_OWN_PROPERTIES_ONLY      = (1 << 4);    /* don't walk prototype chain, only check own properties */
42        const DUK_ENUM_ARRAY_INDICES_ONLY       = (1 << 5);    /* only enumerate array indices */
43        const DUK_ENUM_SORT_ARRAY_INDICES       = (1 << 6);    /* sort array indices (applied to full enumeration result, including inherited array indices) */
44        const DUK_ENUM_NO_PROXY_BEHAVIOR        = (1 << 7);    /* enumerate a proxy object itself without invoking proxy behavior */
45    }
46}
47
48bitflags! {
49    pub struct DukBufFlags: u32 {
50        const DUK_BUF_FLAG_DYNAMIC              = (1 << 0);    /* internal flag: dynamic buffer */
51        const DUK_BUF_FLAG_EXTERNAL             = (1 << 1);    /* internal flag: external buffer */
52        const DUK_BUF_FLAG_NOZERO               = (1 << 2);    /* internal flag: don't zero allocated buffer */
53    }
54}
55
56
57bitflags! {
58    pub struct DukGcFlags: u32 {
59        const NONE                        = 0;           /* No flags */
60        const DUK_GC_COMPACT              = (1 << 0);    /* compact heap objects */
61    }
62}
63
64bitflags! {
65    pub struct DukThreadFlags: u32 {
66        const DUK_THREAD_NEW_GLOBAL_ENV              = (1 << 0);    /* create a new global environment */
67    }
68}
69
70#[derive(Debug, PartialEq, Eq, Clone, Copy)]
71#[repr(i32)]
72#[allow(non_camel_case_types, dead_code)]
73pub enum DukType {
74    DUK_TYPE_NONE                     = 0,    /* no value, e.g. invalid index */
75    DUK_TYPE_UNDEFINED                = 1,    /* Ecmascript undefined */
76    DUK_TYPE_NULL                     = 2,    /* Ecmascript null */
77    DUK_TYPE_BOOLEAN                  = 3,    /* Ecmascript boolean: 0 or 1 */
78    DUK_TYPE_NUMBER                   = 4,    /* Ecmascript number: double */
79    DUK_TYPE_STRING                   = 5,    /* Ecmascript string: CESU-8 / extended UTF-8 encoded */
80    DUK_TYPE_OBJECT                   = 6,    /* Ecmascript object: includes objects, arrays, functions, threads */
81    DUK_TYPE_BUFFER                   = 7,    /* fixed or dynamic, garbage collected byte buffer */
82    DUK_TYPE_POINTER                  = 8,    /* raw void pointer */
83    DUK_TYPE_LIGHTFUNC                = 9,    /* lightweight function pointer */
84}
85
86impl From<i32> for DukType {
87    fn from(e: i32) -> Self {
88        if e >= DukType::DUK_TYPE_NONE as i32 && e <= DukType::DUK_TYPE_LIGHTFUNC as i32 {
89            unsafe { std::mem::transmute(e) }
90        } else {
91            panic!("incorrect DukType value: {}", e); //FIXME (jc)
92        }
93    }
94}
95
96
97#[allow(non_camel_case_types)]
98pub enum duk_context {}
99
100#[allow(non_camel_case_types)]
101pub type duk_fatal_function = extern "C" fn (udata: *mut c_void, msg: *const c_char);
102#[allow(non_camel_case_types)]
103pub type duk_alloc_function = extern "C" fn (udata: *mut c_void, size: usize) -> *mut c_void;
104#[allow(non_camel_case_types)]
105pub type duk_realloc_function = extern "C" fn (udata: *mut c_void, ptr: *mut c_void, size: usize) -> *mut c_void;
106#[allow(non_camel_case_types)]
107pub type duk_free_function = extern "C" fn (udata: *mut c_void, ptr: *mut c_void);
108
109#[allow(non_camel_case_types)]
110pub type duk_c_function = extern "C" fn(ctx: *mut duk_context) -> i32;
111
112#[allow(non_camel_case_types)]
113pub type duk_console_function = extern "C" fn(udata: *mut c_void, fun: u32, msg: *const c_char, msg_len: usize);
114
115#[allow(dead_code)]
116extern "C" {
117    pub fn duk_api_version() -> u32;
118    pub fn duk_api_git_describe() -> *const c_char;
119    pub fn duk_api_git_commit() -> *const c_char;
120    pub fn duk_api_git_branch() -> *const c_char;
121    pub fn duk_api_get_heap_udata(ctx: *mut duk_context) -> *mut c_void;
122    pub fn duk_api_console_init(ctx: *mut duk_context, console_func: Option<duk_console_function>);
123
124    pub fn duk_create_heap(alloc_func: Option<duk_alloc_function>,
125                       realloc_func: Option<duk_realloc_function>,
126                       free_func: Option<duk_free_function>,
127                       heap_udata: *mut c_void,
128                       fatal_handler: Option<duk_fatal_function>)
129                       -> *mut duk_context;
130
131    pub fn duk_destroy_heap(ctx: *mut duk_context);
132
133    pub fn duk_eval_raw(ctx: *mut duk_context, code: *const c_char, len: usize, flags: u32) -> i32;
134    pub fn duk_compile_raw(ctx: *mut duk_context, code: *const c_char, len: usize, flags: u32) -> i32;
135
136    pub fn duk_call(ctx: *mut duk_context, nargs: i32);
137    pub fn duk_call_method(ctx: *mut duk_context, nargs: i32);
138    pub fn duk_call_prop(ctx: *mut duk_context, obj_index: i32, nargs: i32);
139    pub fn duk_pcall(ctx: *mut duk_context, nargs: i32) -> i32;
140    pub fn duk_pcall_method(ctx: *mut duk_context, nargs: i32) -> i32;
141    pub fn duk_pcall_prop(ctx: *mut duk_context, obj_index: i32, nargs: i32) -> i32;
142
143    pub fn duk_safe_to_lstring(ctx: *mut duk_context,
144                           index: i32,
145                           out_len: *mut usize)
146                           -> *const c_char;
147
148    pub fn duk_get_top(ctx: *mut duk_context) -> i32;
149    pub fn duk_normalize_index(ctx: *mut duk_context, index: i32) -> i32;
150    pub fn duk_require_normalize_index(ctx: *mut duk_context, index: i32) -> i32;
151    pub fn duk_check_stack(ctx: *mut duk_context, extra: i32) -> bool;
152    pub fn duk_check_stack_top(ctx: *mut duk_context, top: i32) -> bool;
153
154    pub fn duk_dup(ctx: *mut duk_context, index: i32);
155    pub fn duk_remove(ctx: *mut duk_context, index: i32);
156
157    pub fn duk_pop(ctx: *mut duk_context);
158    pub fn duk_pop_1(ctx: *mut duk_context);
159    pub fn duk_pop_2(ctx: *mut duk_context);
160    pub fn duk_pop_n(ctx: *mut duk_context, n: i32);
161    pub fn duk_swap(ctx: *mut duk_context, idx1: i32, idx2: i32);
162    pub fn duk_xcopymove_raw(to_ctx: *mut duk_context, from_ctx: *mut duk_context, count: i32, is_copy: i32);
163
164    pub fn duk_push_null(ctx: *mut duk_context);
165    pub fn duk_push_undefined(ctx: *mut duk_context);
166    pub fn duk_push_boolean(ctx: *mut duk_context, val: i32);
167    pub fn duk_push_int(ctx: *mut duk_context, val: i32);
168    pub fn duk_push_uint(ctx: *mut duk_context, val: u32);
169    pub fn duk_push_number(ctx: *mut duk_context, val: f64);
170    pub fn duk_push_lstring(ctx: *mut duk_context, str: *const c_char, len: usize) -> *const c_char;
171    pub fn duk_push_array(ctx: *mut duk_context) -> i32;
172    pub fn duk_push_object(ctx: *mut duk_context) -> i32;
173    pub fn duk_push_pointer(ctx: *mut duk_context, p: *mut c_void);
174    pub fn duk_push_buffer_raw(ctx: *mut duk_context, len: usize, dynamic: u32) -> *mut c_void;
175    pub fn duk_push_c_function(ctx: *mut duk_context, func: Option<duk_c_function>, nargs: i32) -> i32;
176    pub fn duk_push_c_lightfunc(ctx: *mut duk_context, func: Option<duk_c_function>, nargs: i32, length: i32, magic: i32);
177    pub fn duk_push_current_function(ctx: *mut duk_context);
178    pub fn duk_push_this(ctx: *mut duk_context);
179    pub fn duk_push_thread_raw(ctx: *mut duk_context, flags: u32) -> i32;
180
181    pub fn duk_config_buffer(ctx: *mut duk_context, index: i32, ptr: *mut c_void, len: usize);
182
183    pub fn duk_get_type(ctx: *mut duk_context, index: i32) -> i32;
184    pub fn duk_get_length(ctx: *mut duk_context, index: i32) -> usize;
185    pub fn duk_get_context(ctx: *mut duk_context, index: i32) -> *mut duk_context;
186    pub fn duk_get_context_default(ctx: *mut duk_context, index: i32, def_value: *mut duk_context) -> *mut duk_context;
187    pub fn duk_samevalue(ctx: *mut duk_context, index1: i32, index2: i32) -> i32;
188
189    pub fn duk_is_array(ctx: *mut duk_context, index: i32) -> i32;
190    pub fn duk_is_object(ctx: *mut duk_context, index: i32) -> i32;
191    pub fn duk_is_number(ctx: *mut duk_context, index: i32) -> i32;
192    pub fn duk_is_string(ctx: *mut duk_context, index: i32) -> i32;
193    pub fn duk_is_function(ctx: *mut duk_context, index: i32) -> i32;
194    pub fn duk_is_thread(ctx: *mut duk_context, index: i32) -> i32;
195
196    pub fn duk_to_object(ctx: *mut duk_context, index: i32);
197    pub fn duk_to_number(ctx: *mut duk_context, index: i32) -> f64;
198    pub fn duk_to_string(ctx: *mut duk_context, index: i32) -> *const c_char;
199
200    pub fn duk_get_boolean(ctx: *mut duk_context, index: i32) -> i32;
201    pub fn duk_get_number(ctx: *mut duk_context, index: i32) -> f64;
202    pub fn duk_get_lstring(ctx: *mut duk_context, index: i32, len: Option<&mut usize>) -> *const c_char;
203    pub fn duk_get_buffer(ctx: *mut duk_context, index: i32, len: Option<&mut usize>) -> *mut c_void;
204    pub fn duk_get_pointer(ctx: *mut duk_context, index: i32) -> *mut c_void;
205
206    pub fn duk_get_prop(ctx: *mut duk_context, obj_index: i32) -> i32;
207    pub fn duk_put_prop(ctx: *mut duk_context, obj_index: i32) -> i32;
208    pub fn duk_def_prop(ctx: *mut duk_context, obj_index: i32, flags: u32);
209
210    pub fn duk_get_prop_lstring(ctx: *mut duk_context,
211                            obj_index: i32,
212                            key: *const c_char,
213                            len: usize)
214                            -> i32;
215    pub fn duk_put_prop_lstring(ctx: *mut duk_context,
216                            obj_index: i32,
217                            key: *const c_char,
218                            len: usize)
219                            -> i32;
220    pub fn duk_get_prop_index(ctx: *mut duk_context, obj_index: i32, index: u32) -> i32;
221    pub fn duk_put_prop_index(ctx: *mut duk_context, obj_index: i32, index: u32) -> i32;
222
223    pub fn duk_push_global_object(ctx: *mut duk_context);
224    pub fn duk_get_global_lstring(ctx: *mut duk_context, key: *const c_char, len: usize) -> i32;
225    pub fn duk_put_global_lstring(ctx: *mut duk_context, key: *const c_char, len: usize) -> i32;
226
227    pub fn duk_enum(ctx: *mut duk_context, obj_index: i32, flags: u32);
228    pub fn duk_next(ctx: *mut duk_context, enum_idx: i32, get_value: i32) -> i32;
229
230    pub fn duk_throw_raw(ctx: *mut duk_context);
231    pub fn duk_fatal(ctx: *mut duk_context, err_code: i32, err_msg: *const c_char);
232
233    pub fn duk_push_context_dump(ctx: *mut duk_context);
234    pub fn duk_set_global_object(ctx: *mut duk_context);
235
236    pub fn duk_gc(ctx: *mut duk_context, flags: u32);
237}
238
239
240#[inline(always)]
241unsafe fn interop<'a>(udata: *mut c_void) -> &'a mut InteropRef {
242    &mut (*(udata as *mut Userdata)).interop
243}
244
245pub extern "C" fn alloc_func(udata: *mut c_void, size: usize) -> *mut c_void {
246    unsafe {
247        interop(udata).alloc(size) as *mut c_void
248    }
249}
250
251pub extern "C" fn realloc_func(udata: *mut c_void, ptr: *mut c_void, size: usize) -> *mut c_void {
252    unsafe {
253        interop(udata).realloc(ptr as *mut u8, size) as *mut c_void
254    }
255}
256
257pub extern "C" fn free_func(udata: *mut c_void, ptr: *mut c_void) {
258    unsafe {
259        interop(udata).free(ptr as *mut u8);
260    }
261}
262
263pub extern "C" fn console_func(udata: *mut c_void, func: u32, msg: *const c_char, len: usize) {
264    use std::str;
265    use std::slice;
266    unsafe {
267        let msg = str::from_utf8_unchecked(slice::from_raw_parts(msg as *const u8, len));
268        interop(udata).console(ConsoleFunc::from(func), msg);
269    }
270}
271
272pub extern "C" fn func_dispatch(ctx: *mut duk_context) -> i32 {
273    use std::str;
274    use std::slice;
275    unsafe {
276        duk_push_current_function(ctx);
277        duk_get_prop_lstring(ctx, -1, FUNC_NAME_PROP.as_ptr() as *const c_char, FUNC_NAME_PROP.len());
278        let mut len: usize = 0;
279        let ptr = duk_get_lstring(ctx, -1, Some(&mut len)) as *const u8;
280        let name = str::from_utf8_unchecked(slice::from_raw_parts(ptr, len));
281        duk_pop_2(ctx);
282        let udata = duk_api_get_heap_udata(ctx);
283        let mut duk_ctx = DukContext::from_raw(ctx);
284        let r = match interop(udata).call(&mut duk_ctx, name) {
285            Ok(r) => r,
286            Err(err) => {
287                let msg = format!("{err}");
288                duk_push_lstring(ctx, msg.as_ptr() as *const c_char, msg.len());
289                duk_throw_raw(ctx);
290                Return::Error
291            },
292        };
293        r as i32
294    }
295}
296
297pub extern "C" fn fatal_handler(udata: *mut c_void, msg: *const c_char) {
298    unsafe {
299        let msg = CStr::from_ptr(msg).to_string_lossy();
300        interop(udata).fatal(&msg);
301    }
302}