mirror of
https://github.com/denoland/deno.git
synced 2024-11-24 15:19:26 -05:00
feat(core): allow to specify entry point for snapshotted ES modules (#17771)
This commit adds "ExtensionBuilder::esm_entry_point()" function that allows to specify which of the extension files should be treated as an entry point. If the entry point is not provided all modules are loaded and evaluated, but if it is provided then only the entry point is explicitly loaded and evaluated. Co-authored-by: Leo Kettmeir <crowlkats@toaxl.com>
This commit is contained in:
parent
f917d2e2c1
commit
bd6ddd9b46
4 changed files with 83 additions and 30 deletions
|
@ -43,6 +43,7 @@ impl OpDecl {
|
|||
pub struct Extension {
|
||||
js_files: Option<Vec<ExtensionFileSource>>,
|
||||
esm_files: Option<Vec<ExtensionFileSource>>,
|
||||
esm_entry_point: Option<&'static str>,
|
||||
ops: Option<Vec<OpDecl>>,
|
||||
opstate_fn: Option<Box<OpStateFn>>,
|
||||
middleware_fn: Option<Box<OpMiddlewareFn>>,
|
||||
|
@ -100,6 +101,10 @@ impl Extension {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_esm_entry_point(&self) -> Option<&'static str> {
|
||||
self.esm_entry_point
|
||||
}
|
||||
|
||||
/// Called at JsRuntime startup to initialize ops in the isolate.
|
||||
pub fn init_ops(&mut self) -> Option<Vec<OpDecl>> {
|
||||
// TODO(@AaronO): maybe make op registration idempotent
|
||||
|
@ -158,6 +163,7 @@ impl Extension {
|
|||
pub struct ExtensionBuilder {
|
||||
js: Vec<ExtensionFileSource>,
|
||||
esm: Vec<ExtensionFileSource>,
|
||||
esm_entry_point: Option<&'static str>,
|
||||
ops: Vec<OpDecl>,
|
||||
state: Option<Box<OpStateFn>>,
|
||||
middleware: Option<Box<OpMiddlewareFn>>,
|
||||
|
@ -197,6 +203,11 @@ impl ExtensionBuilder {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn esm_entry_point(&mut self, entry_point: &'static str) -> &mut Self {
|
||||
self.esm_entry_point = Some(entry_point);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn ops(&mut self, ops: Vec<OpDecl>) -> &mut Self {
|
||||
self.ops.extend(ops);
|
||||
self
|
||||
|
@ -234,6 +245,7 @@ impl ExtensionBuilder {
|
|||
Extension {
|
||||
js_files,
|
||||
esm_files,
|
||||
esm_entry_point: self.esm_entry_point.take(),
|
||||
ops,
|
||||
opstate_fn: self.state.take(),
|
||||
middleware_fn: self.middleware.take(),
|
||||
|
|
|
@ -275,21 +275,27 @@ pub struct NoopModuleLoader;
|
|||
impl ModuleLoader for NoopModuleLoader {
|
||||
fn resolve(
|
||||
&self,
|
||||
_specifier: &str,
|
||||
_referrer: &str,
|
||||
specifier: &str,
|
||||
referrer: &str,
|
||||
_kind: ResolutionKind,
|
||||
) -> Result<ModuleSpecifier, Error> {
|
||||
Err(generic_error("Module loading is not supported"))
|
||||
Err(generic_error(
|
||||
format!("Module loading is not supported; attempted to resolve: \"{specifier}\" from \"{referrer}\"")
|
||||
))
|
||||
}
|
||||
|
||||
fn load(
|
||||
&self,
|
||||
_module_specifier: &ModuleSpecifier,
|
||||
_maybe_referrer: Option<ModuleSpecifier>,
|
||||
module_specifier: &ModuleSpecifier,
|
||||
maybe_referrer: Option<ModuleSpecifier>,
|
||||
_is_dyn_import: bool,
|
||||
) -> Pin<Box<ModuleSourceFuture>> {
|
||||
async { Err(generic_error("Module loading is not supported")) }
|
||||
.boxed_local()
|
||||
let err = generic_error(
|
||||
format!(
|
||||
"Module loading is not supported; attempted to load: \"{module_specifier}\" from \"{maybe_referrer:?}\"",
|
||||
)
|
||||
);
|
||||
async move { Err(err) }.boxed_local()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2720,14 +2726,20 @@ if (import.meta.url != 'file:///main_with_code.js') throw Error();
|
|||
.resolve("file://foo", "file://bar", ResolutionKind::Import)
|
||||
.err()
|
||||
.map(|e| e.to_string()),
|
||||
Some("Module loading is not supported".to_string())
|
||||
Some(
|
||||
"Module loading is not supported; attempted to resolve: \"file://foo\" from \"file://bar\""
|
||||
.to_string()
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
loader
|
||||
.resolve("file://foo", "internal:bar", ResolutionKind::Import)
|
||||
.err()
|
||||
.map(|e| e.to_string()),
|
||||
Some("Module loading is not supported".to_string())
|
||||
Some(
|
||||
"Module loading is not supported; attempted to resolve: \"file://foo\" from \"internal:bar\""
|
||||
.to_string()
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_helper(
|
||||
|
|
|
@ -829,26 +829,39 @@ impl JsRuntime {
|
|||
|
||||
/// Initializes JS of provided Extensions in the given realm
|
||||
fn init_extension_js(&mut self, realm: &JsRealm) -> Result<(), Error> {
|
||||
fn load_and_evaluate_module(
|
||||
runtime: &mut JsRuntime,
|
||||
file_source: &ExtensionFileSource,
|
||||
) -> Result<(), Error> {
|
||||
futures::executor::block_on(async {
|
||||
let id = runtime
|
||||
.load_side_module(
|
||||
&ModuleSpecifier::parse(&file_source.specifier)?,
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
let receiver = runtime.mod_evaluate(id);
|
||||
runtime.run_event_loop(false).await?;
|
||||
receiver.await?
|
||||
})
|
||||
.with_context(|| format!("Couldn't execute '{}'", file_source.specifier))
|
||||
}
|
||||
|
||||
// Take extensions to avoid double-borrow
|
||||
let extensions = std::mem::take(&mut self.extensions_with_js);
|
||||
for ext in &extensions {
|
||||
{
|
||||
let esm_files = ext.get_esm_sources();
|
||||
for file_source in esm_files {
|
||||
futures::executor::block_on(async {
|
||||
let id = self
|
||||
.load_side_module(
|
||||
&ModuleSpecifier::parse(&file_source.specifier)?,
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
let receiver = self.mod_evaluate(id);
|
||||
self.run_event_loop(false).await?;
|
||||
receiver.await?
|
||||
})
|
||||
.with_context(|| {
|
||||
format!("Couldn't execute '{}'", file_source.specifier)
|
||||
})?;
|
||||
if let Some(entry_point) = ext.get_esm_entry_point() {
|
||||
let file_source = esm_files
|
||||
.iter()
|
||||
.find(|file| file.specifier == entry_point)
|
||||
.unwrap();
|
||||
load_and_evaluate_module(self, file_source)?;
|
||||
} else {
|
||||
for file_source in esm_files {
|
||||
load_and_evaluate_module(self, file_source)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1770,7 +1783,11 @@ impl JsRuntime {
|
|||
.map(|handle| v8::Local::new(tc_scope, handle))
|
||||
.expect("ModuleInfo not found");
|
||||
let mut status = module.get_status();
|
||||
assert_eq!(status, v8::ModuleStatus::Instantiated);
|
||||
assert_eq!(
|
||||
status,
|
||||
v8::ModuleStatus::Instantiated,
|
||||
"Module not instantiated {id}"
|
||||
);
|
||||
|
||||
let (sender, receiver) = oneshot::channel();
|
||||
|
||||
|
@ -4974,7 +4991,7 @@ Deno.core.ops.op_async_serialize_object_with_numbers_as_keys({
|
|||
_is_dyn_import: bool,
|
||||
) -> Pin<Box<ModuleSourceFuture>> {
|
||||
let source = r#"
|
||||
// This module doesn't really exist, just verifying that we'll get
|
||||
// This module doesn't really exist, just verifying that we'll get
|
||||
// an error when specifier starts with "internal:".
|
||||
import { core } from "internal:core.js";
|
||||
"#;
|
||||
|
|
|
@ -22,6 +22,7 @@ pub struct CreateSnapshotOptions {
|
|||
}
|
||||
|
||||
pub fn create_snapshot(create_snapshot_options: CreateSnapshotOptions) {
|
||||
let start = std::time::Instant::now();
|
||||
let js_runtime = JsRuntime::new(RuntimeOptions {
|
||||
will_snapshot: true,
|
||||
startup_snapshot: create_snapshot_options.startup_snapshot,
|
||||
|
@ -33,7 +34,12 @@ pub fn create_snapshot(create_snapshot_options: CreateSnapshotOptions) {
|
|||
|
||||
let snapshot = js_runtime.snapshot();
|
||||
let snapshot_slice: &[u8] = &snapshot;
|
||||
println!("Snapshot size: {}", snapshot_slice.len());
|
||||
println!(
|
||||
"Snapshot size: {}, took {}s ({})",
|
||||
snapshot_slice.len(),
|
||||
start.elapsed().as_secs_f64(),
|
||||
create_snapshot_options.snapshot_path.display()
|
||||
);
|
||||
|
||||
let maybe_compressed_snapshot: Box<dyn AsRef<[u8]>> =
|
||||
if let Some(compression_cb) = create_snapshot_options.compression_cb {
|
||||
|
@ -47,7 +53,12 @@ pub fn create_snapshot(create_snapshot_options: CreateSnapshotOptions) {
|
|||
|
||||
(compression_cb)(&mut vec, snapshot_slice);
|
||||
|
||||
println!("Snapshot compressed size: {}", vec.len());
|
||||
println!(
|
||||
"Snapshot compressed size: {}, took {}s ({})",
|
||||
vec.len(),
|
||||
start.elapsed().as_secs_f64(),
|
||||
create_snapshot_options.snapshot_path.display()
|
||||
);
|
||||
|
||||
Box::new(vec)
|
||||
} else {
|
||||
|
@ -60,8 +71,9 @@ pub fn create_snapshot(create_snapshot_options: CreateSnapshotOptions) {
|
|||
)
|
||||
.unwrap();
|
||||
println!(
|
||||
"Snapshot written to: {} ",
|
||||
create_snapshot_options.snapshot_path.display()
|
||||
"Snapshot written to: {}, took: {}s",
|
||||
create_snapshot_options.snapshot_path.display(),
|
||||
start.elapsed().as_secs_f64()
|
||||
);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue