2021-02-13 07:31:18 -05:00
|
|
|
// Copyright 2019-2021 the Deno authors. All rights reserved. MIT license.
|
2021-03-05 05:26:37 -05:00
|
|
|
use std::{marker::PhantomData, mem::MaybeUninit};
|
2020-05-31 12:45:00 -04:00
|
|
|
|
2021-04-27 14:32:40 -04:00
|
|
|
use crate::Function;
|
2019-12-20 14:54:20 -05:00
|
|
|
use crate::Local;
|
|
|
|
use crate::Module;
|
2021-04-27 14:32:40 -04:00
|
|
|
use crate::Object;
|
2019-12-20 14:54:20 -05:00
|
|
|
use crate::ScriptOrigin;
|
|
|
|
use crate::String;
|
2021-03-07 08:05:50 -05:00
|
|
|
use crate::{Context, Isolate, Script, UnboundScript};
|
2021-03-05 05:26:37 -05:00
|
|
|
use crate::{HandleScope, UniqueRef};
|
2019-12-20 14:54:20 -05:00
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
fn v8__ScriptCompiler__Source__CONSTRUCT(
|
2020-04-13 08:43:56 -04:00
|
|
|
buf: *mut MaybeUninit<Source>,
|
|
|
|
source_string: *const String,
|
|
|
|
origin: *const ScriptOrigin,
|
2021-03-05 05:26:37 -05:00
|
|
|
cached_data: *mut CachedData,
|
2019-12-20 14:54:20 -05:00
|
|
|
);
|
2020-04-13 08:43:56 -04:00
|
|
|
fn v8__ScriptCompiler__Source__DESTRUCT(this: *mut Source);
|
2021-03-05 05:26:37 -05:00
|
|
|
fn v8__ScriptCompiler__Source__GetCachedData<'a>(
|
|
|
|
this: *const Source,
|
|
|
|
) -> *const CachedData<'a>;
|
|
|
|
fn v8__ScriptCompiler__CachedData__NEW<'a>(
|
|
|
|
data: *const u8,
|
|
|
|
length: i32,
|
|
|
|
) -> *mut CachedData<'a>;
|
|
|
|
fn v8__ScriptCompiler__CachedData__DELETE<'a>(this: *mut CachedData<'a>);
|
2019-12-20 14:54:20 -05:00
|
|
|
fn v8__ScriptCompiler__CompileModule(
|
2020-04-13 08:43:56 -04:00
|
|
|
isolate: *mut Isolate,
|
|
|
|
source: *mut Source,
|
2019-12-20 14:54:20 -05:00
|
|
|
options: CompileOptions,
|
|
|
|
no_cache_reason: NoCacheReason,
|
2020-04-13 08:43:56 -04:00
|
|
|
) -> *const Module;
|
2021-03-07 08:05:50 -05:00
|
|
|
fn v8__ScriptCompiler__Compile(
|
|
|
|
context: *const Context,
|
|
|
|
source: *mut Source,
|
|
|
|
options: CompileOptions,
|
|
|
|
no_cache_reason: NoCacheReason,
|
|
|
|
) -> *const Script;
|
2021-04-27 14:32:40 -04:00
|
|
|
fn v8__ScriptCompiler__CompileFunctionInContext(
|
|
|
|
context: *const Context,
|
|
|
|
source: *mut Source,
|
|
|
|
arguments_count: usize,
|
|
|
|
arguments: *const *const String,
|
|
|
|
context_extensions_count: usize,
|
|
|
|
context_extensions: *const *const Object,
|
|
|
|
options: CompileOptions,
|
|
|
|
no_cache_reason: NoCacheReason,
|
|
|
|
) -> *const Function;
|
2021-03-07 08:05:50 -05:00
|
|
|
fn v8__ScriptCompiler__CompileUnboundScript(
|
|
|
|
isolate: *mut Isolate,
|
|
|
|
source: *mut Source,
|
|
|
|
options: CompileOptions,
|
|
|
|
no_cache_reason: NoCacheReason,
|
|
|
|
) -> *const UnboundScript;
|
2019-12-20 14:54:20 -05:00
|
|
|
}
|
|
|
|
|
2020-12-07 16:42:37 -05:00
|
|
|
/// Source code which can then be compiled to a UnboundScript or Script.
|
2020-11-18 09:17:25 -05:00
|
|
|
#[repr(C)]
|
|
|
|
#[derive(Debug)]
|
2019-12-20 14:54:20 -05:00
|
|
|
pub struct Source([usize; 8]);
|
|
|
|
|
2021-03-05 05:26:37 -05:00
|
|
|
/// Compilation data that the embedder can cache and pass back to speed up future
|
|
|
|
/// compilations. The data is produced if the CompilerOptions passed to the compilation
|
|
|
|
/// functions in ScriptCompiler contains produce_data_to_cache = true. The data to cache
|
|
|
|
/// can then can be retrieved from UnboundScript.
|
|
|
|
#[repr(C)]
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct CachedData<'a> {
|
|
|
|
data: *const u8,
|
|
|
|
length: i32,
|
|
|
|
rejected: bool,
|
|
|
|
buffer_policy: BufferPolicy,
|
|
|
|
_phantom: PhantomData<&'a ()>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> Drop for CachedData<'a> {
|
|
|
|
fn drop(&mut self) {
|
|
|
|
unsafe {
|
|
|
|
v8__ScriptCompiler__CachedData__DELETE(self);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> CachedData<'a> {
|
|
|
|
pub fn new(data: &'a [u8]) -> UniqueRef<Self> {
|
|
|
|
unsafe {
|
|
|
|
UniqueRef::from_raw(v8__ScriptCompiler__CachedData__NEW(
|
|
|
|
data.as_ptr(),
|
|
|
|
data.len() as i32,
|
|
|
|
))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> std::ops::Deref for CachedData<'a> {
|
|
|
|
type Target = [u8];
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
|
|
unsafe { std::slice::from_raw_parts(self.data, self.length as usize) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[repr(C)]
|
|
|
|
#[derive(Debug)]
|
|
|
|
enum BufferPolicy {
|
|
|
|
BufferNotOwned = 0,
|
|
|
|
BufferOwned,
|
|
|
|
}
|
|
|
|
|
2019-12-20 14:54:20 -05:00
|
|
|
impl Source {
|
2021-03-07 08:05:50 -05:00
|
|
|
pub fn new(
|
|
|
|
source_string: Local<String>,
|
|
|
|
origin: Option<&ScriptOrigin>,
|
|
|
|
) -> Self {
|
2019-12-20 14:54:20 -05:00
|
|
|
let mut buf = MaybeUninit::<Self>::uninit();
|
|
|
|
unsafe {
|
2021-03-05 05:26:37 -05:00
|
|
|
v8__ScriptCompiler__Source__CONSTRUCT(
|
|
|
|
&mut buf,
|
|
|
|
&*source_string,
|
2021-03-07 08:05:50 -05:00
|
|
|
origin.map(|x| x as *const _).unwrap_or(std::ptr::null()),
|
2021-03-05 05:26:37 -05:00
|
|
|
std::ptr::null_mut(),
|
|
|
|
);
|
2019-12-20 14:54:20 -05:00
|
|
|
buf.assume_init()
|
|
|
|
}
|
|
|
|
}
|
2021-03-05 05:26:37 -05:00
|
|
|
|
|
|
|
pub fn new_with_cached_data(
|
|
|
|
source_string: Local<String>,
|
2021-03-07 08:05:50 -05:00
|
|
|
origin: Option<&ScriptOrigin>,
|
2021-03-05 05:26:37 -05:00
|
|
|
cached_data: UniqueRef<CachedData>,
|
|
|
|
) -> Self {
|
|
|
|
let mut buf = MaybeUninit::<Self>::uninit();
|
|
|
|
unsafe {
|
|
|
|
v8__ScriptCompiler__Source__CONSTRUCT(
|
|
|
|
&mut buf,
|
|
|
|
&*source_string,
|
2021-03-07 08:05:50 -05:00
|
|
|
origin.map(|x| x as *const _).unwrap_or(std::ptr::null()),
|
2021-03-05 05:26:37 -05:00
|
|
|
cached_data.into_raw(), // Source constructor takes ownership.
|
|
|
|
);
|
|
|
|
buf.assume_init()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_cached_data(&self) -> &CachedData {
|
|
|
|
unsafe { &*v8__ScriptCompiler__Source__GetCachedData(self) }
|
|
|
|
}
|
2019-12-20 14:54:20 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Drop for Source {
|
|
|
|
fn drop(&mut self) {
|
|
|
|
unsafe { v8__ScriptCompiler__Source__DESTRUCT(self) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[repr(C)]
|
2020-11-18 09:17:25 -05:00
|
|
|
#[derive(Debug)]
|
2019-12-20 14:54:20 -05:00
|
|
|
pub enum CompileOptions {
|
|
|
|
NoCompileOptions = 0,
|
|
|
|
ConsumeCodeCache,
|
|
|
|
EagerCompile,
|
|
|
|
}
|
|
|
|
|
|
|
|
/// The reason for which we are not requesting or providing a code cache.
|
|
|
|
#[repr(C)]
|
2020-11-18 09:17:25 -05:00
|
|
|
#[derive(Debug)]
|
2019-12-20 14:54:20 -05:00
|
|
|
pub enum NoCacheReason {
|
|
|
|
NoReason = 0,
|
|
|
|
BecauseCachingDisabled,
|
|
|
|
BecauseNoResource,
|
|
|
|
BecauseInlineScript,
|
|
|
|
BecauseModule,
|
|
|
|
BecauseStreamingSource,
|
|
|
|
BecauseInspector,
|
|
|
|
BecauseScriptTooSmall,
|
|
|
|
BecauseCacheTooCold,
|
|
|
|
BecauseV8Extension,
|
|
|
|
BecauseExtensionModule,
|
|
|
|
BecausePacScript,
|
|
|
|
BecauseInDocumentWrite,
|
|
|
|
BecauseResourceWithNoCacheHandler,
|
|
|
|
BecauseDeferredProduceCodeCache,
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Compile an ES module, returning a Module that encapsulates the compiled
|
|
|
|
/// code.
|
|
|
|
///
|
|
|
|
/// Corresponds to the ParseModule abstract operation in the ECMAScript
|
|
|
|
/// specification.
|
2020-06-03 01:38:34 -04:00
|
|
|
pub fn compile_module<'s>(
|
|
|
|
scope: &mut HandleScope<'s>,
|
2019-12-20 14:54:20 -05:00
|
|
|
source: Source,
|
2020-06-03 01:38:34 -04:00
|
|
|
) -> Option<Local<'s, Module>> {
|
2019-12-23 20:23:55 -05:00
|
|
|
compile_module2(
|
2020-02-11 17:01:27 -05:00
|
|
|
scope,
|
2019-12-23 20:23:55 -05:00
|
|
|
source,
|
|
|
|
CompileOptions::NoCompileOptions,
|
|
|
|
NoCacheReason::NoReason,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Same as compile_module with more options.
|
2020-06-03 01:38:34 -04:00
|
|
|
pub fn compile_module2<'s>(
|
|
|
|
scope: &mut HandleScope<'s>,
|
2020-04-13 08:43:56 -04:00
|
|
|
mut source: Source,
|
2019-12-20 14:54:20 -05:00
|
|
|
options: CompileOptions,
|
|
|
|
no_cache_reason: NoCacheReason,
|
2020-06-03 01:38:34 -04:00
|
|
|
) -> Option<Local<'s, Module>> {
|
2019-12-20 14:54:20 -05:00
|
|
|
unsafe {
|
2020-06-03 01:38:34 -04:00
|
|
|
scope.cast_local(|sd| {
|
2020-05-31 09:00:23 -04:00
|
|
|
v8__ScriptCompiler__CompileModule(
|
2020-06-03 01:38:34 -04:00
|
|
|
sd.get_isolate_ptr(),
|
2020-05-31 09:00:23 -04:00
|
|
|
&mut source,
|
|
|
|
options,
|
|
|
|
no_cache_reason,
|
|
|
|
)
|
|
|
|
})
|
2019-12-20 14:54:20 -05:00
|
|
|
}
|
|
|
|
}
|
2021-03-07 08:05:50 -05:00
|
|
|
|
|
|
|
pub fn compile<'s>(
|
|
|
|
scope: &mut HandleScope<'s>,
|
|
|
|
mut source: Source,
|
|
|
|
options: CompileOptions,
|
|
|
|
no_cache_reason: NoCacheReason,
|
|
|
|
) -> Option<Local<'s, Script>> {
|
|
|
|
unsafe {
|
|
|
|
scope.cast_local(|sd| {
|
|
|
|
v8__ScriptCompiler__Compile(
|
|
|
|
&*sd.get_current_context(),
|
|
|
|
&mut source,
|
|
|
|
options,
|
|
|
|
no_cache_reason,
|
|
|
|
)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-27 14:32:40 -04:00
|
|
|
pub fn compile_function_in_context<'s>(
|
|
|
|
scope: &mut HandleScope<'s>,
|
|
|
|
mut source: Source,
|
|
|
|
arguments: &[Local<String>],
|
|
|
|
context_extensions: &[Local<Object>],
|
|
|
|
options: CompileOptions,
|
|
|
|
no_cache_reason: NoCacheReason,
|
|
|
|
) -> Option<Local<'s, Function>> {
|
|
|
|
let arguments = Local::slice_into_raw(arguments);
|
|
|
|
let context_extensions = Local::slice_into_raw(context_extensions);
|
|
|
|
unsafe {
|
|
|
|
scope.cast_local(|sd| {
|
|
|
|
v8__ScriptCompiler__CompileFunctionInContext(
|
|
|
|
&*sd.get_current_context(),
|
|
|
|
&mut source,
|
|
|
|
arguments.len(),
|
|
|
|
arguments.as_ptr(),
|
|
|
|
context_extensions.len(),
|
|
|
|
context_extensions.as_ptr(),
|
|
|
|
options,
|
|
|
|
no_cache_reason,
|
|
|
|
)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-07 08:05:50 -05:00
|
|
|
pub fn compile_unbound_script<'s>(
|
|
|
|
scope: &mut HandleScope<'s>,
|
|
|
|
mut source: Source,
|
|
|
|
options: CompileOptions,
|
|
|
|
no_cache_reason: NoCacheReason,
|
|
|
|
) -> Option<Local<'s, UnboundScript>> {
|
|
|
|
unsafe {
|
|
|
|
scope.cast_local(|sd| {
|
|
|
|
v8__ScriptCompiler__CompileUnboundScript(
|
|
|
|
sd.get_isolate_ptr(),
|
|
|
|
&mut source,
|
|
|
|
options,
|
|
|
|
no_cache_reason,
|
|
|
|
)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|