1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
use crate::ul;
use crate::helpers_internal::unpack_closure_hook_cb;

pub fn create_js_function<T> (
    view: crate::View,
    name: &'static str,
    mut hook: &mut T
) -> ul::JSObjectRef
    where T: FnMut(
        ul::JSContextRef,
        ul::JSObjectRef,
        ul::JSObjectRef,
        usize,
        *const ul::JSValueRef,
        *mut ul::JSValueRef,
    ) -> ul::JSValueRef
{
    unsafe {
        let (
            hook_closure,
            hook_function
        ) = unpack_closure_hook_cb(&mut hook);

        let classname_str = std::ffi::CString::new(name).unwrap();

        let jsclassdef = ul::JSClassDefinition {
            version: 0,
            attributes: 0,
            className: classname_str.as_ptr(),
            parentClass: std::ptr::null_mut() as ul::JSClassRef,
            staticValues: std::ptr::null() as *const ul::JSStaticValue,
            staticFunctions: std::ptr::null() as *const ul::JSStaticFunction,
            initialize: None,
            hasProperty: None,
            getProperty: None,
            setProperty: None,
            deleteProperty: None,
            getPropertyNames: None,
            callAsConstructor: None,
            hasInstance: None,
            convertToType: None,
            finalize: None,
            callAsFunction: Some(hook_function),
            // need to implement drop!
            //finalize: Some(|| std::mem::drop(jsclass)),
        };

        let jsclass = ul::JSClassCreate(
            &jsclassdef
        );

        let (jsgctx, ..) = getJSContextFromView(view);

        ul::JSObjectMake(
            jsgctx,
            jsclass,
            hook_closure
        )
    }
}

pub fn getJSContextFromView(
    view: crate::View
) -> (ul::JSContextRef, ul::JSObjectRef) {
    unsafe {
        let jsgctx = ul::ulViewGetJSContext(view);
        let jsgctx_object = ul::JSContextGetGlobalObject(jsgctx);

        (jsgctx, jsgctx_object)
    }
}

pub fn set_js_object_property(
    view: crate::View,
    name: &'static str,
    object: ul::JSObjectRef
) {
    unsafe {
        let (jsgctx, jsgctx_object) = getJSContextFromView(view);

        let c_name = std::ffi::CString::new(
            name
        ).unwrap();

        let propertyName = ul::JSStringCreateWithUTF8CString(
            c_name.as_ptr()
        );

        ul::JSObjectSetProperty(
            jsgctx,
            jsgctx_object,
            propertyName,
            object,
            0,
            std::ptr::null_mut() as *mut *const ul::OpaqueJSValue
        );
    }
}

// "window.styla={callbacks:[{render:global_spotfire_hook}]};"

pub fn evaluate_script(
    view: crate::View,
    script: &'static str
) -> ul::JSValueRef {
    unsafe {
        let (jsgctx, jsgctx_object) = getJSContextFromView(view);

        let script_c_str = std::ffi::CString::new(
            script
        ).unwrap();

        ul::JSEvaluateScript(
            jsgctx,
            ul::JSStringCreateWithUTF8CString(
                script_c_str.as_ptr()
            ),
            jsgctx_object,
            std::ptr::null_mut() as *mut ul::OpaqueJSString,
            ul::kJSPropertyAttributeNone as i32,
            std::ptr::null_mut() as *mut *const ul::OpaqueJSValue
        )
    }
}