1use js::jsapi::JSObject;
6use script_bindings::proxyhandler;
7use servo_config::pref;
8
9use crate::dom::bindings::codegen::RegisterBindings;
10use crate::dom::bindings::conversions::is_dom_proxy;
11use crate::dom::bindings::utils::is_platform_object_static;
12use crate::engine::handle::JSEngineSetup;
13
14#[cfg(unix)]
15#[expect(unsafe_code)]
16fn raise_file_handle_limit() {
17 const MAX_FILE_LIMIT: libc::rlim_t = 8192;
20
21 let mut rlimit = libc::rlimit {
24 rlim_cur: 0,
25 rlim_max: 0,
26 };
27
28 if unsafe { libc::getrlimit(libc::RLIMIT_NOFILE, &mut rlimit) } != 0 {
29 warn!("Failed to get file count limit");
30 return;
31 }
32
33 if rlimit.rlim_cur >= MAX_FILE_LIMIT {
34 return;
35 }
36
37 rlimit.rlim_cur = match rlimit.rlim_max {
38 libc::RLIM_INFINITY => MAX_FILE_LIMIT,
39 _ => rlimit.rlim_max.min(MAX_FILE_LIMIT),
40 };
41
42 if unsafe { libc::setrlimit(libc::RLIMIT_NOFILE, &rlimit) } != 0 {
43 warn!("Failed to set file count limit");
44 }
45}
46
47#[cfg(not(unix))]
48fn raise_file_handle_limit() {}
49
50#[expect(unsafe_code)]
51unsafe extern "C" fn is_dom_object(obj: *mut JSObject) -> bool {
52 !obj.is_null() && (is_platform_object_static(obj) || unsafe { is_dom_proxy(obj) })
53}
54
55#[cfg(target_env = "ohos")]
63#[expect(unsafe_code)]
64fn jit_forbidden() -> bool {
65 debug!("Testing if JIT is allowed.");
66
67 fn mem_is_writable(ptr: *mut core::ffi::c_void) -> std::io::Result<bool> {
68 debug!("Testing if ptr {ptr:?} is writable");
69 #[expect(unsafe_code)]
74 unsafe {
75 let fd = libc::open(c"/dev/zero".as_ptr(), libc::O_RDONLY);
76 if fd < 0 {
77 return Err(std::io::Error::last_os_error());
78 }
79 let writable = libc::read(fd, ptr, 1) > 0;
80 if !writable {
81 debug!(
82 "addr is not writable. Error: {}",
83 std::io::Error::last_os_error()
84 );
85 }
86 libc::close(fd);
87 Ok(writable)
88 }
89 }
90
91 let map_size: libc::size_t = unsafe { libc::sysconf(libc::_SC_PAGESIZE) as libc::size_t };
93 let flags = libc::MAP_NORESERVE | libc::MAP_PRIVATE | libc::MAP_ANON;
94 let first_mmap = unsafe {
97 libc::mmap(
98 core::ptr::null_mut(),
99 map_size,
100 libc::PROT_NONE,
101 flags,
102 -1,
103 0,
104 )
105 };
106 assert_ne!(first_mmap, libc::MAP_FAILED, "mmap not allowed?");
107
108 let remap_flags =
109 libc::MAP_ANONYMOUS | libc::MAP_FIXED | libc::MAP_PRIVATE | libc::MAP_EXECUTABLE;
110 let second_mmap = unsafe {
112 libc::mmap(
113 first_mmap,
114 map_size,
115 libc::PROT_READ | libc::PROT_EXEC,
116 remap_flags,
117 -1,
118 0,
119 )
120 };
121 let mut jit_forbidden = second_mmap == libc::MAP_FAILED;
122 if !jit_forbidden {
123 let res =
127 unsafe { libc::mprotect(first_mmap, map_size, libc::PROT_READ | libc::PROT_WRITE) };
128 if res != 0 {
129 jit_forbidden = true;
131 } else {
132 let is_writable = mem_is_writable(first_mmap)
136 .inspect_err(|_e| {
137 debug!("Failed to determine if JIT is allowed. Conservatively assuming it is forbidden.");
138 })
139 .unwrap_or(false); jit_forbidden = !is_writable;
141 }
142 }
143 let _ = unsafe { libc::munmap(first_mmap, map_size) };
147
148 jit_forbidden
149}
150
151#[cfg(not(target_env = "ohos"))]
152fn jit_forbidden() -> bool {
153 false
154}
155
156#[expect(unsafe_code)]
157#[servo_tracing::instrument(name = "script::init")]
158pub fn init() -> JSEngineSetup {
159 if pref!(js_disable_jit) || jit_forbidden() {
160 let reason = if pref!(js_disable_jit) {
161 "preference `js_disable_jit` is set to true"
162 } else {
163 "runtime test determined JIT is forbidden on this system"
164 };
165 warn!("Disabling JIT for Javascript, since {reason}. This may cause subpar performance");
166 unsafe {
168 js::jsapi::DisableJitBackend();
169 }
170 }
171 proxyhandler::init();
172
173 RegisterBindings::RegisterProxyHandlers::<crate::DomTypeHolder>();
176 RegisterBindings::InitAllStatics::<crate::DomTypeHolder>();
177
178 unsafe {
179 js::glue::InitializeMemoryReporter(Some(is_dom_object));
180 }
181
182 raise_file_handle_limit();
183
184 JSEngineSetup::default()
185}