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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
use crate::callback::init_context_with_callback;
use crate::callback::G_VARS;
use crate::common::*;
use crate::common::{collect_js_files, collect_module_dirs, str_2_v8};
use crate::session_cache::CallbackSharedData;
use rusty_v8 as v8;
use rusty_v8::{Context, HandleScope, Isolate, Local};
use std::collections::HashMap;
use std::fs;
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::path::Path;
use v_module::module::Module;

pub fn script_origin<'a>(s: &mut v8::HandleScope<'a>, resource_name: v8::Local<'a, v8::String>) -> v8::ScriptOrigin<'a> {
    let resource_line_offset = 0;
    let resource_column_offset = 0;
    let resource_is_shared_cross_origin = false;
    let script_id = 123;
    let source_map_url = v8::String::new(s, "").unwrap();
    let resource_is_opaque = true;
    let is_wasm = false;
    let is_module = false;
    v8::ScriptOrigin::new(
        s,
        resource_name.into(),
        resource_line_offset,
        resource_column_offset,
        resource_is_shared_cross_origin,
        script_id,
        source_map_url.into(),
        resource_is_opaque,
        is_wasm,
        is_module,
    )
}

impl<'a, T: Default> ScriptInfo<'a, T> {
    pub fn new_with_src(id: &str, src: &str) -> Self {
        Self {
            id: id.to_string(),
            str_script: src.to_string(),
            compiled_script: None,
            dependency: Default::default(),
            context: Default::default(),
        }
    }

    pub fn compile_script(&mut self, js_name: &str, parent_scope: &mut HandleScope<'a>) {
        let source = str_2_v8(parent_scope, &self.str_script);
        let name = v8::String::new(parent_scope, js_name).unwrap();
        let origin = script_origin(parent_scope, name);

        match v8::Script::compile(parent_scope, source, Some(&origin)) {
            Some(script) => {
                self.compiled_script = Some(script);
            }
            None => {
                error!("fail compile script {}", self.str_script);
                self.compiled_script = None;
            }
        }
    }
}

pub struct ScriptsWorkPlace<'a, T> {
    pub scripts: HashMap<String, ScriptInfo<'a, T>>,
    pub scripts_order: Vec<String>,
    pub module: Module,
    pub scope: HandleScope<'a, ()>,
    pub context: Local<'a, Context>,
}

impl<'a, T: Default> ScriptsWorkPlace<'a, T> {
    pub fn load_ext_scripts(&mut self, sys_ticket: &str) {
        let mut modules_de = vec![];
        let mut o_files = vec![];

        collect_module_dirs("./public/modules", &mut modules_de);

        let scripts_location = if let Some(s) = Module::get_property("scripts_location") {
            vec![s]
        } else {
            vec!["./public/js/common".to_owned(), "./public/js/server".to_owned()]
        };

        for p in scripts_location.iter() {
            let path = p.to_owned() + "/";
            let seq = path.to_string() + ".seq";

            if Path::new(&seq).exists() {
                match File::open(&seq) {
                    Ok(f) => {
                        let file = BufReader::new(&f);
                        for line in file.lines() {
                            match line {
                                Ok(file_name) => {
                                    if file_name == "$modules" {
                                        for x in modules_de.iter() {
                                            o_files.push(x.to_owned());
                                        }
                                    } else {
                                        collect_js_files(&(path.to_string() + &file_name), &mut o_files);
                                    }
                                }
                                Err(e) => error!("{:?}", e),
                            }
                        }
                    }
                    Err(e) => error!("{:?}", e),
                }
            } else {
                collect_js_files(&path, &mut o_files);
            }
        }

        let mut session_data = CallbackSharedData::default();
        session_data.g_key2attr.insert("$ticket".to_owned(), sys_ticket.to_owned());
        let mut sh_g_vars = G_VARS.lock().unwrap();
        let g_vars = sh_g_vars.get_mut();
        *g_vars = session_data;
        drop(sh_g_vars);

        for x in o_files.iter() {
            match fs::read_to_string(x) {
                Ok(f) => {
                    info!("{}", x);
                    let mut scr_inf: ScriptInfo<T> = ScriptInfo::new_with_src(x, &f);

                    let scope = &mut v8::ContextScope::new(&mut self.scope, self.context);
                    scr_inf.compile_script(x, scope);

                    if let Some(i_script) = scr_inf.compiled_script {
                        i_script.run(scope);
                    }

                    //self.scripts.insert(x.to_owned(), scr_inf);
                }
                Err(e) => error!("{:?}", e),
            }
        }
    }

    pub fn new(isolate: &'a mut Isolate) -> Self {
        let mut scope = v8::HandleScope::new(isolate);

        let context = init_context_with_callback(&mut scope);
        Self {
            scripts: Default::default(),
            scripts_order: vec![],
            module: Module::default(),
            scope,
            context,
        }
    }

    pub fn add_to_order(&mut self, scr_inf: &ScriptInfo<T>) {
        let mut count_find_dependency = 0;
        let mut inserted = false;

        let mut new_scripts_order = vec![];

        for oo in self.scripts_order.iter() {
            if count_find_dependency < scr_inf.dependency.vec.len() {
                if let Some(soo) = self.scripts.get(oo) {
                    for dp in soo.dependency.vec.iter() {
                        if scr_inf.id == *dp {
                            count_find_dependency += 1;
                        }
                    }
                }
            }

            if !inserted && count_find_dependency >= scr_inf.dependency.vec.len() {
                new_scripts_order.push(scr_inf.id.to_owned());
                inserted = true;
            }

            if *oo != scr_inf.id {
                new_scripts_order.push(oo.to_owned());
            }
        }
        if !inserted {
            new_scripts_order.push(scr_inf.id.to_owned());
        }

        self.scripts_order = new_scripts_order;
    }
}