1use std::{marker::PhantomData, mem::MaybeUninit};
3
4use crate::Function;
5use crate::Local;
6use crate::Module;
7use crate::Object;
8use crate::ScriptOrigin;
9use crate::String;
10use crate::{Context, Isolate, Script, UnboundScript};
11use crate::{HandleScope, UniqueRef};
12
13extern "C" {
14 fn v8__ScriptCompiler__Source__CONSTRUCT(
15 buf: *mut MaybeUninit<Source>,
16 source_string: *const String,
17 origin: *const ScriptOrigin,
18 cached_data: *mut CachedData,
19 );
20 fn v8__ScriptCompiler__Source__DESTRUCT(this: *mut Source);
21 fn v8__ScriptCompiler__Source__GetCachedData<'a>(
22 this: *const Source,
23 ) -> *const CachedData<'a>;
24 fn v8__ScriptCompiler__CachedData__NEW<'a>(
25 data: *const u8,
26 length: i32,
27 ) -> *mut CachedData<'a>;
28 fn v8__ScriptCompiler__CachedData__DELETE<'a>(this: *mut CachedData<'a>);
29 fn v8__ScriptCompiler__CompileModule(
30 isolate: *mut Isolate,
31 source: *mut Source,
32 options: CompileOptions,
33 no_cache_reason: NoCacheReason,
34 ) -> *const Module;
35 fn v8__ScriptCompiler__Compile(
36 context: *const Context,
37 source: *mut Source,
38 options: CompileOptions,
39 no_cache_reason: NoCacheReason,
40 ) -> *const Script;
41 fn v8__ScriptCompiler__CompileFunctionInContext(
42 context: *const Context,
43 source: *mut Source,
44 arguments_count: usize,
45 arguments: *const *const String,
46 context_extensions_count: usize,
47 context_extensions: *const *const Object,
48 options: CompileOptions,
49 no_cache_reason: NoCacheReason,
50 ) -> *const Function;
51 fn v8__ScriptCompiler__CompileUnboundScript(
52 isolate: *mut Isolate,
53 source: *mut Source,
54 options: CompileOptions,
55 no_cache_reason: NoCacheReason,
56 ) -> *const UnboundScript;
57}
58
59#[repr(C)]
61#[derive(Debug)]
62pub struct Source([usize; 8]);
63
64#[repr(C)]
69#[derive(Debug)]
70pub struct CachedData<'a> {
71 data: *const u8,
72 length: i32,
73 rejected: bool,
74 buffer_policy: BufferPolicy,
75 _phantom: PhantomData<&'a ()>,
76}
77
78impl<'a> Drop for CachedData<'a> {
79 fn drop(&mut self) {
80 unsafe {
81 v8__ScriptCompiler__CachedData__DELETE(self);
82 }
83 }
84}
85
86impl<'a> CachedData<'a> {
87 pub fn new(data: &'a [u8]) -> UniqueRef<Self> {
88 unsafe {
89 UniqueRef::from_raw(v8__ScriptCompiler__CachedData__NEW(
90 data.as_ptr(),
91 data.len() as i32,
92 ))
93 }
94 }
95}
96
97impl<'a> std::ops::Deref for CachedData<'a> {
98 type Target = [u8];
99 fn deref(&self) -> &Self::Target {
100 unsafe { std::slice::from_raw_parts(self.data, self.length as usize) }
101 }
102}
103
104#[repr(C)]
105#[derive(Debug)]
106enum BufferPolicy {
107 BufferNotOwned = 0,
108 BufferOwned,
109}
110
111impl Source {
112 pub fn new(
113 source_string: Local<String>,
114 origin: Option<&ScriptOrigin>,
115 ) -> Self {
116 let mut buf = MaybeUninit::<Self>::uninit();
117 unsafe {
118 v8__ScriptCompiler__Source__CONSTRUCT(
119 &mut buf,
120 &*source_string,
121 origin.map(|x| x as *const _).unwrap_or(std::ptr::null()),
122 std::ptr::null_mut(),
123 );
124 buf.assume_init()
125 }
126 }
127
128 pub fn new_with_cached_data(
129 source_string: Local<String>,
130 origin: Option<&ScriptOrigin>,
131 cached_data: UniqueRef<CachedData>,
132 ) -> Self {
133 let mut buf = MaybeUninit::<Self>::uninit();
134 unsafe {
135 v8__ScriptCompiler__Source__CONSTRUCT(
136 &mut buf,
137 &*source_string,
138 origin.map(|x| x as *const _).unwrap_or(std::ptr::null()),
139 cached_data.into_raw(), );
141 buf.assume_init()
142 }
143 }
144
145 pub fn get_cached_data(&self) -> &CachedData {
146 unsafe { &*v8__ScriptCompiler__Source__GetCachedData(self) }
147 }
148}
149
150impl Drop for Source {
151 fn drop(&mut self) {
152 unsafe { v8__ScriptCompiler__Source__DESTRUCT(self) }
153 }
154}
155
156#[repr(C)]
157#[derive(Debug)]
158pub enum CompileOptions {
159 NoCompileOptions = 0,
160 ConsumeCodeCache,
161 EagerCompile,
162}
163
164#[repr(C)]
166#[derive(Debug)]
167pub enum NoCacheReason {
168 NoReason = 0,
169 BecauseCachingDisabled,
170 BecauseNoResource,
171 BecauseInlineScript,
172 BecauseModule,
173 BecauseStreamingSource,
174 BecauseInspector,
175 BecauseScriptTooSmall,
176 BecauseCacheTooCold,
177 BecauseV8Extension,
178 BecauseExtensionModule,
179 BecausePacScript,
180 BecauseInDocumentWrite,
181 BecauseResourceWithNoCacheHandler,
182 BecauseDeferredProduceCodeCache,
183}
184
185pub fn compile_module<'s>(
191 scope: &mut HandleScope<'s>,
192 source: Source,
193) -> Option<Local<'s, Module>> {
194 compile_module2(
195 scope,
196 source,
197 CompileOptions::NoCompileOptions,
198 NoCacheReason::NoReason,
199 )
200}
201
202pub fn compile_module2<'s>(
204 scope: &mut HandleScope<'s>,
205 mut source: Source,
206 options: CompileOptions,
207 no_cache_reason: NoCacheReason,
208) -> Option<Local<'s, Module>> {
209 unsafe {
210 scope.cast_local(|sd| {
211 v8__ScriptCompiler__CompileModule(
212 sd.get_isolate_ptr(),
213 &mut source,
214 options,
215 no_cache_reason,
216 )
217 })
218 }
219}
220
221pub fn compile<'s>(
222 scope: &mut HandleScope<'s>,
223 mut source: Source,
224 options: CompileOptions,
225 no_cache_reason: NoCacheReason,
226) -> Option<Local<'s, Script>> {
227 unsafe {
228 scope.cast_local(|sd| {
229 v8__ScriptCompiler__Compile(
230 &*sd.get_current_context(),
231 &mut source,
232 options,
233 no_cache_reason,
234 )
235 })
236 }
237}
238
239pub fn compile_function_in_context<'s>(
240 scope: &mut HandleScope<'s>,
241 mut source: Source,
242 arguments: &[Local<String>],
243 context_extensions: &[Local<Object>],
244 options: CompileOptions,
245 no_cache_reason: NoCacheReason,
246) -> Option<Local<'s, Function>> {
247 let arguments = Local::slice_into_raw(arguments);
248 let context_extensions = Local::slice_into_raw(context_extensions);
249 unsafe {
250 scope.cast_local(|sd| {
251 v8__ScriptCompiler__CompileFunctionInContext(
252 &*sd.get_current_context(),
253 &mut source,
254 arguments.len(),
255 arguments.as_ptr(),
256 context_extensions.len(),
257 context_extensions.as_ptr(),
258 options,
259 no_cache_reason,
260 )
261 })
262 }
263}
264
265pub fn compile_unbound_script<'s>(
266 scope: &mut HandleScope<'s>,
267 mut source: Source,
268 options: CompileOptions,
269 no_cache_reason: NoCacheReason,
270) -> Option<Local<'s, UnboundScript>> {
271 unsafe {
272 scope.cast_local(|sd| {
273 v8__ScriptCompiler__CompileUnboundScript(
274 sd.get_isolate_ptr(),
275 &mut source,
276 options,
277 no_cache_reason,
278 )
279 })
280 }
281}