summaryrefslogtreecommitdiff
path: root/core/extensions.rs
diff options
context:
space:
mode:
Diffstat (limited to 'core/extensions.rs')
-rw-r--r--core/extensions.rs133
1 files changed, 90 insertions, 43 deletions
diff --git a/core/extensions.rs b/core/extensions.rs
index ab0578106..fa6d7851e 100644
--- a/core/extensions.rs
+++ b/core/extensions.rs
@@ -1,15 +1,32 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
use crate::modules::ModuleCode;
use crate::OpState;
+use anyhow::Context as _;
+use anyhow::Error;
use std::cell::RefCell;
+use std::path::PathBuf;
use std::rc::Rc;
use std::task::Context;
use v8::fast_api::FastFunction;
#[derive(Clone, Debug)]
+pub enum ExtensionFileSourceCode {
+ /// Source code is included in the binary produced. Either by being defined
+ /// inline, or included using `include_str!()`. If you are snapshotting, this
+ /// will result in two copies of the source code being included - one in the
+ /// snapshot, the other the static string in the `Extension`.
+ IncludedInBinary(&'static str),
+
+ // Source code is loaded from a file on disk. It's meant to be used if the
+ // embedder is creating snapshots. Files will be loaded from the filesystem
+ // during the build time and they will only be present in the V8 snapshot.
+ LoadedFromFsDuringSnapshot(PathBuf),
+}
+
+#[derive(Clone, Debug)]
pub struct ExtensionFileSource {
pub specifier: &'static str,
- pub code: &'static str,
+ pub code: ExtensionFileSourceCode,
}
impl ExtensionFileSource {
@@ -17,14 +34,29 @@ impl ExtensionFileSource {
s.chars().filter(|c| !c.is_ascii()).collect::<String>()
}
- pub fn load(&self) -> ModuleCode {
- debug_assert!(
- self.code.is_ascii(),
- "Extension code must be 7-bit ASCII: {} (found {})",
- self.specifier,
- Self::find_non_ascii(self.code)
- );
- ModuleCode::from_static(self.code)
+ pub fn load(&self) -> Result<ModuleCode, Error> {
+ match &self.code {
+ ExtensionFileSourceCode::IncludedInBinary(code) => {
+ debug_assert!(
+ code.is_ascii(),
+ "Extension code must be 7-bit ASCII: {} (found {})",
+ self.specifier,
+ Self::find_non_ascii(code)
+ );
+ Ok(ModuleCode::from_static(code))
+ }
+ ExtensionFileSourceCode::LoadedFromFsDuringSnapshot(path) => {
+ let msg = || format!("Failed to read \"{}\"", path.display());
+ let s = std::fs::read_to_string(path).with_context(msg)?;
+ debug_assert!(
+ s.is_ascii(),
+ "Extension code must be 7-bit ASCII: {} (found {})",
+ self.specifier,
+ Self::find_non_ascii(&s)
+ );
+ Ok(s.into())
+ }
+ }
}
}
@@ -155,7 +187,6 @@ macro_rules! extension {
$(, esm = [ $( dir $dir_esm:literal , )? $( $esm:literal ),* $(,)? ] )?
$(, esm_setup_script = $esm_setup_script:expr )?
$(, js = [ $( dir $dir_js:literal , )? $( $js:literal ),* $(,)? ] )?
- $(, force_include_js_sources $($force_include_js_sources:block)? )? // dummy variable
$(, options = { $( $options_id:ident : $options_type:ty ),* $(,)? } )?
$(, middleware = $middleware_fn:expr )?
$(, state = $state_fn:expr )?
@@ -180,9 +211,9 @@ macro_rules! extension {
#[inline(always)]
#[allow(unused_variables)]
fn with_js(ext: &mut $crate::ExtensionBuilder) {
- ext.esm(
- $crate::include_js_files!( $name $( force_include_js_sources $($force_include_js_sources)?, )? $( $( dir $dir_esm , )? $( $esm , )* )? )
- );
+ $( ext.esm(
+ $crate::include_js_files!( $name $( dir $dir_esm , )? $( $esm , )* )
+ ); )?
$(
ext.esm(vec![ExtensionFileSource {
specifier: "ext:setup",
@@ -192,9 +223,9 @@ macro_rules! extension {
$(
ext.esm_entry_point($esm_entry_point);
)?
- ext.js(
- $crate::include_js_files!( $name $( force_include_js_sources $($force_include_js_sources)?, )? $( $( dir $dir_js , )? $( $js , )* )? )
- );
+ $( ext.js(
+ $crate::include_js_files!( $name $( dir $dir_js , )? $( $js , )* )
+ ); )?
}
// If ops were specified, add those ops to the extension.
@@ -254,7 +285,7 @@ macro_rules! extension {
}
#[allow(dead_code)]
- pub fn init $( < $( $param : $type + 'static ),+ > )? ( $( $( $options_id : $options_type ),* )? ) -> $crate::Extension
+ pub fn init_ops_and_esm $( < $( $param : $type + 'static ),+ > )? ( $( $( $options_id : $options_type ),* )? ) -> $crate::Extension
$( where $( $bound : $bound_type ),+ )?
{
let mut ext = Self::ext();
@@ -265,6 +296,17 @@ macro_rules! extension {
Self::with_customizer(&mut ext);
ext.take()
}
+
+ #[allow(dead_code)]
+ pub fn init_ops $( < $( $param : $type + 'static ),+ > )? ( $( $( $options_id : $options_type ),* )? ) -> $crate::Extension
+ $( where $( $bound : $bound_type ),+ )?
+ {
+ let mut ext = Self::ext();
+ Self::with_ops $( ::< $( $param ),+ > )?(&mut ext);
+ Self::with_state_and_middleware $( ::< $( $param ),+ > )?(&mut ext, $( $( $options_id , )* )? );
+ Self::with_customizer(&mut ext);
+ ext.take()
+ }
}
};
@@ -566,49 +608,54 @@ impl ExtensionBuilder {
/// - "ext:my_extension/js/01_hello.js"
/// - "ext:my_extension/js/02_goodbye.js"
/// ```
-#[cfg(not(all(
- feature = "exclude_js_sources",
- not(feature = "force_include_js_sources")
-)))]
+#[cfg(not(feature = "include_js_files_for_snapshotting"))]
#[macro_export]
macro_rules! include_js_files {
- ($name:ident $(force_include_js_sources $($dummy:block)?,)? $(dir $dir:literal,)? $($file:literal,)*) => {
- $crate::force_include_js_files!($name $(dir $dir,)? $($file,)*)
- };
-}
-
-#[cfg(all(
- feature = "exclude_js_sources",
- not(feature = "force_include_js_sources")
-))]
-#[macro_export]
-macro_rules! include_js_files {
- ($name:ident force_include_js_sources $($dummy:block)?, $(dir $dir:literal,)? $($file:literal,)*) => {
- $crate::force_include_js_files!($name $(dir $dir,)? $($file,)*)
+ ($name:ident dir $dir:literal, $($file:literal,)+) => {
+ vec![
+ $($crate::ExtensionFileSource {
+ specifier: concat!("ext:", stringify!($name), "/", $file),
+ code: $crate::ExtensionFileSourceCode::IncludedInBinary(
+ include_str!(concat!($dir, "/", $file)
+ )),
+ },)+
+ ]
};
- ($name:ident $(dir $dir:literal,)? $($file:literal,)*) => {
- vec![]
+ ($name:ident $($file:literal,)+) => {
+ vec![
+ $($crate::ExtensionFileSource {
+ specifier: concat!("ext:", stringify!($name), "/", $file),
+ code: $crate::ExtensionFileSourceCode::IncludedInBinary(
+ include_str!($file)
+ ),
+ },)+
+ ]
};
}
+#[cfg(feature = "include_js_files_for_snapshotting")]
#[macro_export]
-macro_rules! force_include_js_files {
- ($name:ident dir $dir:literal, $($file:literal,)*) => {
+macro_rules! include_js_files {
+ ($name:ident dir $dir:literal, $($file:literal,)+) => {
vec![
$($crate::ExtensionFileSource {
specifier: concat!("ext:", stringify!($name), "/", $file),
- code: include_str!(concat!($dir, "/", $file)),
- },)*
+ code: $crate::ExtensionFileSourceCode::LoadedFromFsDuringSnapshot(
+ std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")).join($dir).join($file)
+ ),
+ },)+
]
};
- ($name:ident $($file:literal,)*) => {
+ ($name:ident $($file:literal,)+) => {
vec![
$($crate::ExtensionFileSource {
specifier: concat!("ext:", stringify!($name), "/", $file),
- code: include_str!($file),
- },)*
+ code: $crate::ExtensionFileSourceCode::LoadedFromFsDuringSnapshot(
+ std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")).join($file)
+ ),
+ },)+
]
};
}