2024-01-01 19:58:21 +00:00
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
2024-01-15 01:28:46 +00:00
use std ::collections ::HashMap ;
2023-01-05 19:29:50 +00:00
use std ::rc ::Rc ;
2023-12-24 13:44:40 +00:00
use std ::sync ::atomic ::AtomicBool ;
2023-01-05 19:29:50 +00:00
use std ::sync ::atomic ::AtomicI32 ;
use std ::sync ::atomic ::Ordering ::Relaxed ;
use std ::sync ::Arc ;
2023-12-05 16:26:06 +00:00
use std ::time ::Duration ;
2023-11-10 17:41:24 +00:00
use std ::time ::Instant ;
2023-01-05 19:29:50 +00:00
2021-05-22 16:08:24 +00:00
use deno_broadcast_channel ::InMemoryBroadcastChannel ;
2022-09-28 12:11:12 +00:00
use deno_cache ::CreateCache ;
use deno_cache ::SqliteBackedCache ;
2023-04-04 12:46:31 +00:00
use deno_core ::ascii_str ;
2020-09-14 16:48:57 +00:00
use deno_core ::error ::AnyError ;
2022-04-26 23:06:10 +00:00
use deno_core ::error ::JsError ;
2023-11-10 17:41:24 +00:00
use deno_core ::merge_op_metrics ;
2022-12-18 20:34:33 +00:00
use deno_core ::v8 ;
2021-09-29 08:47:24 +00:00
use deno_core ::CompiledWasmModuleStore ;
2021-04-28 16:41:50 +00:00
use deno_core ::Extension ;
2023-10-12 15:55:50 +00:00
use deno_core ::FeatureChecker ;
2022-10-15 21:19:03 +00:00
use deno_core ::FsModuleLoader ;
2020-12-13 18:45:53 +00:00
use deno_core ::GetErrorClassFn ;
2020-09-06 19:44:29 +00:00
use deno_core ::JsRuntime ;
2021-05-26 19:07:12 +00:00
use deno_core ::LocalInspectorSession ;
2024-01-10 04:18:40 +00:00
use deno_core ::ModuleCodeString ;
2020-02-18 15:08:18 +00:00
use deno_core ::ModuleId ;
2020-11-30 19:35:12 +00:00
use deno_core ::ModuleLoader ;
2020-01-05 16:56:18 +00:00
use deno_core ::ModuleSpecifier ;
2023-11-10 17:41:24 +00:00
use deno_core ::OpMetricsFactoryFn ;
2023-11-05 21:27:36 +00:00
use deno_core ::OpMetricsSummaryTracker ;
2023-12-05 16:26:06 +00:00
use deno_core ::PollEventLoopOptions ;
2020-09-11 13:18:49 +00:00
use deno_core ::RuntimeOptions ;
2021-07-06 17:42:52 +00:00
use deno_core ::SharedArrayBufferStore ;
2022-11-10 11:46:26 +00:00
use deno_core ::Snapshot ;
2022-04-15 14:08:09 +00:00
use deno_core ::SourceMapGetter ;
2023-11-01 18:57:55 +00:00
use deno_cron ::local ::LocalCronHandler ;
2023-05-04 18:28:42 +00:00
use deno_fs ::FileSystem ;
2023-05-10 14:23:26 +00:00
use deno_http ::DefaultHttpPropertyExtractor ;
2023-03-05 00:39:48 +00:00
use deno_io ::Stdio ;
2023-08-22 05:56:00 +00:00
use deno_kv ::dynamic ::MultiBackendDbHandler ;
2023-05-01 20:42:05 +00:00
use deno_tls ::RootCertStoreProvider ;
2021-07-05 13:34:37 +00:00
use deno_web ::BlobStore ;
2021-03-26 16:34:25 +00:00
use log ::debug ;
2023-01-05 19:29:50 +00:00
use crate ::inspector_server ::InspectorServer ;
use crate ::ops ;
2023-01-07 16:25:34 +00:00
use crate ::permissions ::PermissionsContainer ;
2023-08-28 21:30:46 +00:00
use crate ::shared ::runtime ;
2023-01-05 19:29:50 +00:00
use crate ::BootstrapOptions ;
2018-10-05 17:21:15 +00:00
2022-04-26 23:06:10 +00:00
pub type FormatJsErrorFn = dyn Fn ( & JsError ) -> String + Sync + Send ;
2023-12-28 19:37:10 +00:00
pub fn import_meta_resolve_callback (
loader : & dyn deno_core ::ModuleLoader ,
specifier : String ,
referrer : String ,
) -> Result < ModuleSpecifier , AnyError > {
loader . resolve (
& specifier ,
& referrer ,
deno_core ::ResolutionKind ::DynamicImport ,
)
}
2024-01-15 01:28:46 +00:00
// TODO(bartlomieju): temporary measurement until we start supporting more
// module types
pub fn validate_import_attributes_callback (
scope : & mut v8 ::HandleScope ,
attributes : & HashMap < String , String > ,
) {
for ( key , value ) in attributes {
let msg = if key ! = " type " {
Some ( format! ( " \" {key} \" attribute is not supported. " ) )
} else if value ! = " json " {
Some ( format! ( " \" {value} \" is not a valid module type. " ) )
} else {
None
} ;
let Some ( msg ) = msg else {
continue ;
} ;
let message = v8 ::String ::new ( scope , & msg ) . unwrap ( ) ;
let exception = v8 ::Exception ::type_error ( scope , message ) ;
scope . throw_exception ( exception ) ;
return ;
}
}
2022-06-30 00:26:58 +00:00
#[ derive(Clone, Default) ]
2022-06-08 15:45:38 +00:00
pub struct ExitCode ( Arc < AtomicI32 > ) ;
impl ExitCode {
pub fn get ( & self ) -> i32 {
self . 0. load ( Relaxed )
}
pub fn set ( & mut self , code : i32 ) {
self . 0. store ( code , Relaxed ) ;
}
}
2023-05-28 18:44:41 +00:00
2020-11-26 14:17:45 +00:00
/// This worker is created and used by almost all
/// subcommands in Deno executable.
2020-01-21 16:50:06 +00:00
///
2020-11-26 14:17:45 +00:00
/// It provides ops available in the `Deno` namespace.
2020-01-21 16:50:06 +00:00
///
2020-11-26 14:17:45 +00:00
/// All `WebWorker`s created during program execution
/// are descendants of this worker.
pub struct MainWorker {
2020-12-11 17:49:26 +00:00
pub js_runtime : JsRuntime ,
2020-09-19 23:17:35 +00:00
should_break_on_first_statement : bool ,
2022-12-12 14:33:30 +00:00
should_wait_for_inspector_session : bool ,
2022-06-08 15:45:38 +00:00
exit_code : ExitCode ,
2023-02-22 00:55:31 +00:00
bootstrap_fn_global : Option < v8 ::Global < v8 ::Function > > ,
2018-09-18 00:41:13 +00:00
}
2020-12-11 17:49:26 +00:00
pub struct WorkerOptions {
2021-10-05 20:41:14 +00:00
pub bootstrap : BootstrapOptions ,
2022-12-19 02:55:50 +00:00
/// JsRuntime extensions, not to be confused with ES modules.
///
2023-03-10 00:22:27 +00:00
/// Extensions register "ops" and JavaScript sources provided in `js` or `esm`
/// configuration. If you are using a snapshot, then extensions shouldn't
/// provide JavaScript sources that were already snapshotted.
pub extensions : Vec < Extension > ,
2022-12-19 02:55:50 +00:00
/// V8 snapshot that should be loaded on startup.
2022-11-10 11:46:26 +00:00
pub startup_snapshot : Option < Snapshot > ,
2023-06-05 09:22:32 +00:00
2023-11-11 17:01:48 +00:00
/// Should op registration be skipped?
pub skip_op_registration : bool ,
2023-06-05 09:22:32 +00:00
/// Optional isolate creation parameters, such as heap limits.
pub create_params : Option < v8 ::CreateParams > ,
2021-08-10 11:19:45 +00:00
pub unsafely_ignore_certificate_errors : Option < Vec < String > > ,
2023-05-01 20:42:05 +00:00
pub root_cert_store_provider : Option < Arc < dyn RootCertStoreProvider > > ,
2020-12-11 17:49:26 +00:00
pub seed : Option < u64 > ,
2022-12-19 02:55:50 +00:00
2023-05-04 18:28:42 +00:00
pub fs : Arc < dyn FileSystem > ,
2022-12-19 02:55:50 +00:00
/// Implementation of `ModuleLoader` which will be
/// called when V8 requests to load ES modules.
///
/// If not provided runtime will error if code being
/// executed tries to load modules.
2020-12-11 17:49:26 +00:00
pub module_loader : Rc < dyn ModuleLoader > ,
2023-04-24 23:44:35 +00:00
pub npm_resolver : Option < Arc < dyn deno_node ::NpmResolver > > ,
2022-02-11 12:41:56 +00:00
// Callbacks invoked when creating new instance of WebWorker
2020-12-11 17:49:26 +00:00
pub create_web_worker_cb : Arc < ops ::worker_host ::CreateWebWorkerCb > ,
2022-04-26 23:06:10 +00:00
pub format_js_error_fn : Option < Arc < FormatJsErrorFn > > ,
2022-12-19 02:55:50 +00:00
/// Source map reference for errors.
2022-04-15 14:08:09 +00:00
pub source_map_getter : Option < Box < dyn SourceMapGetter > > ,
2020-12-11 17:49:26 +00:00
pub maybe_inspector_server : Option < Arc < InspectorServer > > ,
2022-12-12 14:33:30 +00:00
// If true, the worker will wait for inspector session and break on first
// statement of user code. Takes higher precedence than
// `should_wait_for_inspector_session`.
2020-12-11 17:49:26 +00:00
pub should_break_on_first_statement : bool ,
2022-12-12 14:33:30 +00:00
// If true, the worker will wait for inspector session before executing
// user code.
pub should_wait_for_inspector_session : bool ,
2023-11-10 17:41:24 +00:00
/// If Some, print a low-level trace output for ops matching the given patterns.
pub strace_ops : Option < Vec < String > > ,
2022-12-19 02:55:50 +00:00
/// Allows to map error type to a string "class" used to represent
/// error in JavaScript.
2020-12-13 18:45:53 +00:00
pub get_error_class_fn : Option < GetErrorClassFn > ,
2022-09-28 12:11:12 +00:00
pub cache_storage_dir : Option < std ::path ::PathBuf > ,
2021-05-27 05:23:12 +00:00
pub origin_storage_dir : Option < std ::path ::PathBuf > ,
2023-07-01 22:52:30 +00:00
pub blob_store : Arc < BlobStore > ,
2021-05-22 16:08:24 +00:00
pub broadcast_channel : InMemoryBroadcastChannel ,
2022-12-19 02:55:50 +00:00
/// The store to use for transferring SharedArrayBuffers between isolates.
/// If multiple isolates should have the possibility of sharing
/// SharedArrayBuffers, they should use the same [SharedArrayBufferStore]. If
/// no [SharedArrayBufferStore] is specified, SharedArrayBuffer can not be
/// serialized.
2021-07-06 17:42:52 +00:00
pub shared_array_buffer_store : Option < SharedArrayBufferStore > ,
2022-12-19 02:55:50 +00:00
/// The store to use for transferring `WebAssembly.Module` objects between
/// isolates.
/// If multiple isolates should have the possibility of sharing
/// `WebAssembly.Module` objects, they should use the same
/// [CompiledWasmModuleStore]. If no [CompiledWasmModuleStore] is specified,
/// `WebAssembly.Module` objects cannot be serialized.
2021-09-29 08:47:24 +00:00
pub compiled_wasm_module_store : Option < CompiledWasmModuleStore > ,
2022-04-26 23:00:04 +00:00
pub stdio : Stdio ,
2023-10-12 15:55:50 +00:00
pub feature_checker : Arc < FeatureChecker > ,
2020-12-11 17:49:26 +00:00
}
2020-11-30 19:35:12 +00:00
2022-10-15 21:19:03 +00:00
impl Default for WorkerOptions {
fn default ( ) -> Self {
Self {
create_web_worker_cb : Arc ::new ( | _ | {
unimplemented! ( " web workers are not supported " )
} ) ,
2023-05-04 18:28:42 +00:00
fs : Arc ::new ( deno_fs ::RealFs ) ,
2022-10-15 21:19:03 +00:00
module_loader : Rc ::new ( FsModuleLoader ) ,
2023-11-11 17:01:48 +00:00
skip_op_registration : false ,
2022-10-15 21:19:03 +00:00
seed : None ,
unsafely_ignore_certificate_errors : Default ::default ( ) ,
should_break_on_first_statement : Default ::default ( ) ,
2022-12-12 14:33:30 +00:00
should_wait_for_inspector_session : Default ::default ( ) ,
2023-11-10 17:41:24 +00:00
strace_ops : Default ::default ( ) ,
2022-10-15 21:19:03 +00:00
compiled_wasm_module_store : Default ::default ( ) ,
shared_array_buffer_store : Default ::default ( ) ,
maybe_inspector_server : Default ::default ( ) ,
format_js_error_fn : Default ::default ( ) ,
get_error_class_fn : Default ::default ( ) ,
origin_storage_dir : Default ::default ( ) ,
cache_storage_dir : Default ::default ( ) ,
broadcast_channel : Default ::default ( ) ,
source_map_getter : Default ::default ( ) ,
2023-05-01 20:42:05 +00:00
root_cert_store_provider : Default ::default ( ) ,
2022-10-15 21:19:03 +00:00
npm_resolver : Default ::default ( ) ,
blob_store : Default ::default ( ) ,
extensions : Default ::default ( ) ,
2022-11-10 11:46:26 +00:00
startup_snapshot : Default ::default ( ) ,
2023-06-05 09:22:32 +00:00
create_params : Default ::default ( ) ,
2022-10-15 21:19:03 +00:00
bootstrap : Default ::default ( ) ,
stdio : Default ::default ( ) ,
2023-10-12 15:55:50 +00:00
feature_checker : Default ::default ( ) ,
2022-10-15 21:19:03 +00:00
}
}
}
2023-11-10 17:41:24 +00:00
fn create_op_metrics (
enable_op_summary_metrics : bool ,
strace_ops : Option < Vec < String > > ,
) -> (
Option < Rc < OpMetricsSummaryTracker > > ,
Option < OpMetricsFactoryFn > ,
) {
let mut op_summary_metrics = None ;
let mut op_metrics_factory_fn : Option < OpMetricsFactoryFn > = None ;
let now = Instant ::now ( ) ;
let max_len : Rc < std ::cell ::Cell < usize > > = Default ::default ( ) ;
if let Some ( patterns ) = strace_ops {
/// Match an op name against a list of patterns
fn matches_pattern ( patterns : & [ String ] , name : & str ) -> bool {
let mut found_match = false ;
let mut found_nomatch = false ;
for pattern in patterns . iter ( ) {
if let Some ( pattern ) = pattern . strip_prefix ( '-' ) {
if name . contains ( pattern ) {
return false ;
}
} else if name . contains ( pattern . as_str ( ) ) {
found_match = true ;
} else {
found_nomatch = true ;
}
}
found_match | | ! found_nomatch
}
op_metrics_factory_fn = Some ( Box ::new ( move | _ , _ , decl | {
// If we don't match a requested pattern, or we match a negative pattern, bail
if ! matches_pattern ( & patterns , decl . name ) {
return None ;
}
max_len . set ( max_len . get ( ) . max ( decl . name . len ( ) ) ) ;
let max_len = max_len . clone ( ) ;
Some ( Rc ::new (
move | op : & deno_core ::_ops ::OpCtx , event , source | {
eprintln! (
" [{: >10.3}] {name:max_len$}: {event:?} {source:?} " ,
now . elapsed ( ) . as_secs_f64 ( ) ,
name = op . decl ( ) . name ,
max_len = max_len . get ( )
) ;
} ,
) )
} ) ) ;
}
if enable_op_summary_metrics {
let summary = Rc ::new ( OpMetricsSummaryTracker ::default ( ) ) ;
let summary_metrics = summary . clone ( ) . op_metrics_factory_fn ( | _ | true ) ;
op_metrics_factory_fn = Some ( match op_metrics_factory_fn {
Some ( f ) = > merge_op_metrics ( f , summary_metrics ) ,
None = > summary_metrics ,
} ) ;
op_summary_metrics = Some ( summary ) ;
}
( op_summary_metrics , op_metrics_factory_fn )
}
2020-12-11 17:49:26 +00:00
impl MainWorker {
2021-10-05 20:41:14 +00:00
pub fn bootstrap_from_options (
main_module : ModuleSpecifier ,
2023-01-07 16:25:34 +00:00
permissions : PermissionsContainer ,
2021-10-05 20:41:14 +00:00
options : WorkerOptions ,
) -> Self {
let bootstrap_options = options . bootstrap . clone ( ) ;
let mut worker = Self ::from_options ( main_module , permissions , options ) ;
2023-11-13 04:52:59 +00:00
worker . bootstrap ( bootstrap_options ) ;
2021-10-05 20:41:14 +00:00
worker
}
2020-11-30 19:35:12 +00:00
pub fn from_options (
main_module : ModuleSpecifier ,
2023-01-07 16:25:34 +00:00
permissions : PermissionsContainer ,
2021-10-08 15:03:49 +00:00
mut options : WorkerOptions ,
2020-11-30 19:35:12 +00:00
) -> Self {
2023-03-17 18:22:15 +00:00
deno_core ::extension! ( deno_permissions_worker ,
2023-03-17 22:15:27 +00:00
options = {
2023-03-17 18:22:15 +00:00
permissions : PermissionsContainer ,
enable_testing_features : bool ,
} ,
2023-03-17 22:15:27 +00:00
state = | state , options | {
state . put ::< PermissionsContainer > ( options . permissions ) ;
state . put ( ops ::TestingFeaturesEnabled ( options . enable_testing_features ) ) ;
2023-03-17 18:22:15 +00:00
} ,
) ;
2023-11-10 17:41:24 +00:00
// Get our op metrics
let ( op_summary_metrics , op_metrics_factory_fn ) = create_op_metrics (
options . bootstrap . enable_op_summary_metrics ,
options . strace_ops ,
) ;
2021-05-02 23:22:57 +00:00
// Permissions: many ops depend on this
2021-10-05 20:41:14 +00:00
let enable_testing_features = options . bootstrap . enable_testing_features ;
2022-06-08 15:45:38 +00:00
let exit_code = ExitCode ( Arc ::new ( AtomicI32 ::new ( 0 ) ) ) ;
2023-03-09 20:09:45 +00:00
let create_cache = options . cache_storage_dir . map ( | storage_dir | {
let create_cache_fn = move | | SqliteBackedCache ::new ( storage_dir . clone ( ) ) ;
CreateCache ( Arc ::new ( create_cache_fn ) )
} ) ;
2023-03-08 11:43:26 +00:00
2023-03-16 17:36:53 +00:00
// NOTE(bartlomieju): ordering is important here, keep it in sync with
2024-01-10 15:30:50 +00:00
// `runtime/web_worker.rs` and `runtime/snapshot.rs`!
2023-03-09 20:09:45 +00:00
let mut extensions = vec! [
// Web APIs
2023-08-05 23:47:15 +00:00
deno_webidl ::deno_webidl ::init_ops_and_esm ( ) ,
deno_console ::deno_console ::init_ops_and_esm ( ) ,
deno_url ::deno_url ::init_ops_and_esm ( ) ,
deno_web ::deno_web ::init_ops_and_esm ::< PermissionsContainer > (
2023-03-09 20:09:45 +00:00
options . blob_store . clone ( ) ,
options . bootstrap . location . clone ( ) ,
) ,
2023-12-09 00:19:16 +00:00
deno_webgpu ::deno_webgpu ::init_ops_and_esm ( ) ,
2023-08-05 23:47:15 +00:00
deno_fetch ::deno_fetch ::init_ops_and_esm ::< PermissionsContainer > (
2023-03-17 18:22:15 +00:00
deno_fetch ::Options {
user_agent : options . bootstrap . user_agent . clone ( ) ,
2023-05-01 20:42:05 +00:00
root_cert_store_provider : options . root_cert_store_provider . clone ( ) ,
2023-03-17 18:22:15 +00:00
unsafely_ignore_certificate_errors : options
. unsafely_ignore_certificate_errors
. clone ( ) ,
file_fetch_handler : Rc ::new ( deno_fetch ::FsFetchHandler ) ,
.. Default ::default ( )
} ,
) ,
2023-08-05 23:47:15 +00:00
deno_cache ::deno_cache ::init_ops_and_esm ::< SqliteBackedCache > (
create_cache ,
) ,
deno_websocket ::deno_websocket ::init_ops_and_esm ::< PermissionsContainer > (
2023-03-09 20:09:45 +00:00
options . bootstrap . user_agent . clone ( ) ,
2023-05-01 20:42:05 +00:00
options . root_cert_store_provider . clone ( ) ,
2023-03-09 20:09:45 +00:00
options . unsafely_ignore_certificate_errors . clone ( ) ,
) ,
2023-08-05 23:47:15 +00:00
deno_webstorage ::deno_webstorage ::init_ops_and_esm (
2023-03-17 18:22:15 +00:00
options . origin_storage_dir . clone ( ) ,
) ,
2023-08-05 23:47:15 +00:00
deno_crypto ::deno_crypto ::init_ops_and_esm ( options . seed ) ,
deno_broadcast_channel ::deno_broadcast_channel ::init_ops_and_esm (
2023-03-09 20:09:45 +00:00
options . broadcast_channel . clone ( ) ,
) ,
2023-10-04 19:42:17 +00:00
deno_ffi ::deno_ffi ::init_ops_and_esm ::< PermissionsContainer > ( ) ,
2023-08-05 23:47:15 +00:00
deno_net ::deno_net ::init_ops_and_esm ::< PermissionsContainer > (
2023-05-01 20:42:05 +00:00
options . root_cert_store_provider . clone ( ) ,
2023-03-09 20:09:45 +00:00
options . unsafely_ignore_certificate_errors . clone ( ) ,
) ,
2023-08-05 23:47:15 +00:00
deno_tls ::deno_tls ::init_ops_and_esm ( ) ,
deno_kv ::deno_kv ::init_ops_and_esm (
2023-08-22 05:56:00 +00:00
MultiBackendDbHandler ::remote_or_sqlite ::< PermissionsContainer > (
2023-03-22 04:13:24 +00:00
options . origin_storage_dir . clone ( ) ,
2023-10-31 11:13:57 +00:00
options . seed ,
deno_kv ::remote ::HttpOptions {
user_agent : options . bootstrap . user_agent . clone ( ) ,
root_cert_store_provider : options . root_cert_store_provider . clone ( ) ,
unsafely_ignore_certificate_errors : options
. unsafely_ignore_certificate_errors
. clone ( ) ,
client_cert_chain_and_key : None ,
proxy : None ,
} ,
2023-03-22 04:13:24 +00:00
) ,
) ,
2023-11-01 18:57:55 +00:00
deno_cron ::deno_cron ::init_ops_and_esm ( LocalCronHandler ::new ( ) ) ,
2023-08-05 23:47:15 +00:00
deno_napi ::deno_napi ::init_ops_and_esm ::< PermissionsContainer > ( ) ,
deno_http ::deno_http ::init_ops_and_esm ::< DefaultHttpPropertyExtractor > ( ) ,
deno_io ::deno_io ::init_ops_and_esm ( Some ( options . stdio ) ) ,
deno_fs ::deno_fs ::init_ops_and_esm ::< PermissionsContainer > (
2023-05-05 16:44:24 +00:00
options . fs . clone ( ) ,
) ,
2023-08-05 23:47:15 +00:00
deno_node ::deno_node ::init_ops_and_esm ::< PermissionsContainer > (
2023-03-17 18:22:15 +00:00
options . npm_resolver ,
2023-05-05 16:44:24 +00:00
options . fs ,
2023-03-17 18:22:15 +00:00
) ,
2023-03-16 17:36:53 +00:00
// Ops from this crate
2023-08-05 23:47:15 +00:00
ops ::runtime ::deno_runtime ::init_ops_and_esm ( main_module . clone ( ) ) ,
ops ::worker_host ::deno_worker_host ::init_ops_and_esm (
2023-03-16 17:36:53 +00:00
options . create_web_worker_cb . clone ( ) ,
options . format_js_error_fn . clone ( ) ,
) ,
2023-08-05 23:47:15 +00:00
ops ::fs_events ::deno_fs_events ::init_ops_and_esm ( ) ,
ops ::os ::deno_os ::init_ops_and_esm ( exit_code . clone ( ) ) ,
ops ::permissions ::deno_permissions ::init_ops_and_esm ( ) ,
ops ::process ::deno_process ::init_ops_and_esm ( ) ,
ops ::signal ::deno_signal ::init_ops_and_esm ( ) ,
ops ::tty ::deno_tty ::init_ops_and_esm ( ) ,
ops ::http ::deno_http_runtime ::init_ops_and_esm ( ) ,
2023-11-20 13:00:05 +00:00
ops ::bootstrap ::deno_bootstrap ::init_ops_and_esm ( {
#[ cfg(feature = " __runtime_js_sources " ) ]
{
Some ( Default ::default ( ) )
}
#[ cfg(not(feature = " __runtime_js_sources " )) ]
{
None
}
} ) ,
2023-08-05 23:47:15 +00:00
deno_permissions_worker ::init_ops_and_esm (
2023-03-17 18:22:15 +00:00
permissions ,
enable_testing_features ,
) ,
2023-08-05 23:47:15 +00:00
runtime ::init_ops_and_esm ( ) ,
2023-03-09 20:09:45 +00:00
] ;
2023-03-08 11:43:26 +00:00
2023-08-05 23:47:15 +00:00
for extension in & mut extensions {
#[ cfg(not(feature = " __runtime_js_sources " )) ]
{
extension . js_files = std ::borrow ::Cow ::Borrowed ( & [ ] ) ;
extension . esm_files = std ::borrow ::Cow ::Borrowed ( & [ ] ) ;
extension . esm_entry_point = None ;
}
#[ cfg(feature = " __runtime_js_sources " ) ]
{
2023-08-28 21:30:46 +00:00
use crate ::shared ::maybe_transpile_source ;
2023-08-05 23:47:15 +00:00
for source in extension . esm_files . to_mut ( ) {
maybe_transpile_source ( source ) . unwrap ( ) ;
}
for source in extension . js_files . to_mut ( ) {
maybe_transpile_source ( source ) . unwrap ( ) ;
}
}
}
2021-10-08 15:03:49 +00:00
extensions . extend ( std ::mem ::take ( & mut options . extensions ) ) ;
2021-04-28 16:41:50 +00:00
2024-01-10 15:30:50 +00:00
#[ cfg(all(
feature = " include_js_files_for_snapshotting " ,
not ( feature = " __runtime_js_sources " )
) ) ]
options
. startup_snapshot
. as_ref ( )
. expect ( " Sources are not embedded and a user snapshot was not provided. " ) ;
#[ cfg(not(feature = " dont_use_runtime_snapshot " )) ]
options . startup_snapshot . as_ref ( ) . expect ( " A user snapshot was not provided, if you want to create a runtime without a snapshot use 'dont_use_runtime_snapshot' Cargo feature. " ) ;
2023-02-20 20:45:34 +00:00
2023-12-24 13:44:40 +00:00
let has_notified_of_inspector_disconnect = AtomicBool ::new ( false ) ;
let wait_for_inspector_disconnect_callback = Box ::new ( move | | {
if ! has_notified_of_inspector_disconnect
. swap ( true , std ::sync ::atomic ::Ordering ::SeqCst )
{
println! ( " Program finished. Waiting for inspector to disconnect to exit the process... " ) ;
}
} ) ;
2020-10-07 15:20:20 +00:00
let mut js_runtime = JsRuntime ::new ( RuntimeOptions {
2020-12-11 17:49:26 +00:00
module_loader : Some ( options . module_loader . clone ( ) ) ,
2024-01-10 15:30:50 +00:00
startup_snapshot : options . startup_snapshot ,
2023-06-05 09:22:32 +00:00
create_params : options . create_params ,
2022-04-15 14:08:09 +00:00
source_map_getter : options . source_map_getter ,
2023-11-11 17:01:48 +00:00
skip_op_registration : options . skip_op_registration ,
2020-12-13 18:45:53 +00:00
get_error_class_fn : options . get_error_class_fn ,
2021-07-06 17:42:52 +00:00
shared_array_buffer_store : options . shared_array_buffer_store . clone ( ) ,
2021-09-29 08:47:24 +00:00
compiled_wasm_module_store : options . compiled_wasm_module_store . clone ( ) ,
2021-04-28 16:41:50 +00:00
extensions ,
2022-10-26 11:37:50 +00:00
inspector : options . maybe_inspector_server . is_some ( ) ,
2022-11-26 22:09:48 +00:00
is_main : true ,
2023-10-12 15:55:50 +00:00
feature_checker : Some ( options . feature_checker . clone ( ) ) ,
2023-11-05 21:27:36 +00:00
op_metrics_factory_fn ,
2023-12-24 13:44:40 +00:00
wait_for_inspector_disconnect_callback : Some (
wait_for_inspector_disconnect_callback ,
) ,
2023-12-28 19:37:10 +00:00
import_meta_resolve_callback : Some ( Box ::new (
import_meta_resolve_callback ,
) ) ,
2024-01-15 01:28:46 +00:00
validate_import_attributes_cb : Some ( Box ::new (
validate_import_attributes_callback ,
) ) ,
2020-09-11 13:18:49 +00:00
.. Default ::default ( )
} ) ;
2020-09-25 08:24:51 +00:00
2023-11-05 21:27:36 +00:00
if let Some ( op_summary_metrics ) = op_summary_metrics {
js_runtime . op_state ( ) . borrow_mut ( ) . put ( op_summary_metrics ) ;
}
2021-06-21 17:37:51 +00:00
if let Some ( server ) = options . maybe_inspector_server . clone ( ) {
2021-12-17 17:43:25 +00:00
server . register_inspector (
main_module . to_string ( ) ,
& mut js_runtime ,
2022-12-12 14:33:30 +00:00
options . should_break_on_first_statement
| | options . should_wait_for_inspector_session ,
2021-12-17 17:43:25 +00:00
) ;
2022-11-28 20:59:36 +00:00
// Put inspector handle into the op state so we can put a breakpoint when
// executing a CJS entrypoint.
let op_state = js_runtime . op_state ( ) ;
let inspector = js_runtime . inspector ( ) ;
op_state . borrow_mut ( ) . put ( inspector ) ;
2021-05-26 19:07:12 +00:00
}
2023-02-22 00:55:31 +00:00
let bootstrap_fn_global = {
2023-07-23 13:42:41 +00:00
let context = js_runtime . main_context ( ) ;
2023-02-22 00:55:31 +00:00
let scope = & mut js_runtime . handle_scope ( ) ;
let context_local = v8 ::Local ::new ( scope , context ) ;
let global_obj = context_local . global ( scope ) ;
2023-03-06 16:37:46 +00:00
let bootstrap_str =
v8 ::String ::new_external_onebyte_static ( scope , b " bootstrap " ) . unwrap ( ) ;
2023-02-22 00:55:31 +00:00
let bootstrap_ns : v8 ::Local < v8 ::Object > = global_obj
. get ( scope , bootstrap_str . into ( ) )
. unwrap ( )
. try_into ( )
. unwrap ( ) ;
2023-03-06 16:37:46 +00:00
let main_runtime_str =
v8 ::String ::new_external_onebyte_static ( scope , b " mainRuntime " ) . unwrap ( ) ;
2023-02-22 00:55:31 +00:00
let bootstrap_fn =
bootstrap_ns . get ( scope , main_runtime_str . into ( ) ) . unwrap ( ) ;
let bootstrap_fn =
v8 ::Local ::< v8 ::Function > ::try_from ( bootstrap_fn ) . unwrap ( ) ;
v8 ::Global ::new ( scope , bootstrap_fn )
} ;
2021-05-02 23:22:57 +00:00
Self {
2020-10-11 11:20:40 +00:00
js_runtime ,
2021-06-21 17:37:51 +00:00
should_break_on_first_statement : options . should_break_on_first_statement ,
2022-12-12 14:33:30 +00:00
should_wait_for_inspector_session : options
. should_wait_for_inspector_session ,
2022-06-08 15:45:38 +00:00
exit_code ,
2023-02-22 00:55:31 +00:00
bootstrap_fn_global : Some ( bootstrap_fn_global ) ,
2020-06-02 02:44:17 +00:00
}
2020-12-11 17:49:26 +00:00
}
2023-11-13 04:52:59 +00:00
pub fn bootstrap ( & mut self , options : BootstrapOptions ) {
2023-12-15 10:50:05 +00:00
// Setup bootstrap options for ops.
{
let op_state = self . js_runtime . op_state ( ) ;
let mut state = op_state . borrow_mut ( ) ;
state . put ( options . clone ( ) ) ;
if let Some ( node_ipc_fd ) = options . node_ipc_fd {
state . put ( deno_node ::ChildPipeFd ( node_ipc_fd ) ) ;
}
}
2023-02-22 00:55:31 +00:00
let scope = & mut self . js_runtime . handle_scope ( ) ;
2023-03-28 08:27:17 +00:00
let args = options . as_v8 ( scope ) ;
2023-02-22 00:55:31 +00:00
let bootstrap_fn = self . bootstrap_fn_global . take ( ) . unwrap ( ) ;
let bootstrap_fn = v8 ::Local ::new ( scope , bootstrap_fn ) ;
let undefined = v8 ::undefined ( scope ) ;
2023-08-15 19:36:36 +00:00
bootstrap_fn . call ( scope , undefined . into ( ) , & [ args ] ) . unwrap ( ) ;
2020-01-21 16:50:06 +00:00
}
2020-09-28 10:14:11 +00:00
2021-06-21 23:45:41 +00:00
/// See [JsRuntime::execute_script](deno_core::JsRuntime::execute_script)
2023-04-04 12:46:31 +00:00
pub fn execute_script (
2021-06-21 23:45:41 +00:00
& mut self ,
2023-03-21 22:33:12 +00:00
script_name : & 'static str ,
2024-01-10 04:18:40 +00:00
source_code : ModuleCodeString ,
2022-12-18 20:34:33 +00:00
) -> Result < v8 ::Global < v8 ::Value > , AnyError > {
self . js_runtime . execute_script ( script_name , source_code )
2020-09-28 10:14:11 +00:00
}
2022-08-10 22:10:51 +00:00
/// Loads and instantiates specified JavaScript module as "main" module.
pub async fn preload_main_module (
2020-11-26 14:17:45 +00:00
& mut self ,
module_specifier : & ModuleSpecifier ,
) -> Result < ModuleId , AnyError > {
2022-08-10 22:10:51 +00:00
self
. js_runtime
. load_main_module ( module_specifier , None )
. await
}
/// Loads and instantiates specified JavaScript module as "side" module.
pub async fn preload_side_module (
& mut self ,
module_specifier : & ModuleSpecifier ,
) -> Result < ModuleId , AnyError > {
self
. js_runtime
. load_side_module ( module_specifier , None )
. await
2020-09-28 10:14:11 +00:00
}
2022-06-19 21:29:48 +00:00
/// Executes specified JavaScript module.
pub async fn evaluate_module (
& mut self ,
id : ModuleId ,
) -> Result < ( ) , AnyError > {
2022-08-10 22:10:51 +00:00
self . wait_for_inspector_session ( ) ;
2021-03-04 12:19:47 +00:00
let mut receiver = self . js_runtime . mod_evaluate ( id ) ;
tokio ::select! {
2022-04-13 09:50:57 +00:00
// Not using biased mode leads to non-determinism for relatively simple
// programs.
biased ;
2021-07-30 11:36:43 +00:00
maybe_result = & mut receiver = > {
2021-03-04 12:19:47 +00:00
debug! ( " received module evaluate {:#?} " , maybe_result ) ;
2023-11-27 23:01:27 +00:00
maybe_result
2021-03-04 12:19:47 +00:00
}
2021-05-26 19:07:12 +00:00
event_loop_result = self . run_event_loop ( false ) = > {
2021-03-04 12:19:47 +00:00
event_loop_result ? ;
2023-11-27 23:01:27 +00:00
receiver . await
2021-03-04 12:19:47 +00:00
}
}
2020-09-28 10:14:11 +00:00
}
2023-12-05 16:26:06 +00:00
/// Run the event loop up to a given duration. If the runtime resolves early, returns
/// early. Will always poll the runtime at least once.
pub async fn run_up_to_duration (
& mut self ,
duration : Duration ,
) -> Result < ( ) , AnyError > {
match tokio ::time ::timeout (
duration ,
2023-12-13 15:07:26 +00:00
self
. js_runtime
. run_event_loop ( PollEventLoopOptions ::default ( ) ) ,
2023-12-05 16:26:06 +00:00
)
. await
{
Ok ( Ok ( _ ) ) = > Ok ( ( ) ) ,
Err ( _ ) = > Ok ( ( ) ) ,
Ok ( Err ( e ) ) = > Err ( e ) ,
}
}
2021-09-18 01:44:53 +00:00
/// Loads, instantiates and executes specified JavaScript module.
pub async fn execute_side_module (
& mut self ,
module_specifier : & ModuleSpecifier ,
) -> Result < ( ) , AnyError > {
2022-08-10 22:10:51 +00:00
let id = self . preload_side_module ( module_specifier ) . await ? ;
2021-09-18 01:44:53 +00:00
self . evaluate_module ( id ) . await
}
/// Loads, instantiates and executes specified JavaScript module.
///
/// This module will have "import.meta.main" equal to true.
pub async fn execute_main_module (
& mut self ,
module_specifier : & ModuleSpecifier ,
) -> Result < ( ) , AnyError > {
2022-08-10 22:10:51 +00:00
let id = self . preload_main_module ( module_specifier ) . await ? ;
2021-09-18 01:44:53 +00:00
self . evaluate_module ( id ) . await
}
2020-11-26 14:17:45 +00:00
fn wait_for_inspector_session ( & mut self ) {
if self . should_break_on_first_statement {
self
2021-05-26 19:07:12 +00:00
. js_runtime
. inspector ( )
2022-09-02 10:43:39 +00:00
. borrow_mut ( )
2022-12-12 14:33:30 +00:00
. wait_for_session_and_break_on_next_statement ( ) ;
} else if self . should_wait_for_inspector_session {
self . js_runtime . inspector ( ) . borrow_mut ( ) . wait_for_session ( ) ;
2020-09-28 10:14:11 +00:00
}
}
2020-11-26 14:17:45 +00:00
/// Create new inspector session. This function panics if Worker
/// was not configured to create inspector.
2021-05-26 15:47:33 +00:00
pub async fn create_inspector_session ( & mut self ) -> LocalInspectorSession {
2022-10-26 11:37:50 +00:00
self . js_runtime . maybe_init_inspector ( ) ;
2022-09-02 10:43:39 +00:00
self . js_runtime . inspector ( ) . borrow ( ) . create_local_session ( )
2020-09-28 10:14:11 +00:00
}
2021-05-26 19:07:12 +00:00
pub async fn run_event_loop (
& mut self ,
wait_for_inspector : bool ,
) -> Result < ( ) , AnyError > {
2023-11-26 23:09:04 +00:00
self
. js_runtime
2023-12-13 15:07:26 +00:00
. run_event_loop ( deno_core ::PollEventLoopOptions {
2023-11-26 23:09:04 +00:00
wait_for_inspector ,
.. Default ::default ( )
} )
. await
2020-10-11 11:20:40 +00:00
}
2021-05-26 15:47:33 +00:00
2021-12-11 14:56:45 +00:00
/// Return exit code set by the executed code (either in main worker
/// or one of child web workers).
2023-01-05 19:29:50 +00:00
pub fn exit_code ( & self ) -> i32 {
2022-06-08 15:45:38 +00:00
self . exit_code . get ( )
2021-12-11 14:56:45 +00:00
}
2021-12-21 14:49:27 +00:00
/// Dispatches "load" event to the JavaScript runtime.
///
/// Does not poll event loop, and thus not await any of the "load" event handlers.
pub fn dispatch_load_event (
& mut self ,
2023-03-21 22:33:12 +00:00
script_name : & 'static str ,
2021-12-21 14:49:27 +00:00
) -> Result < ( ) , AnyError > {
2023-04-04 12:46:31 +00:00
self . js_runtime . execute_script (
2022-01-17 23:13:14 +00:00
script_name ,
// NOTE(@bartlomieju): not using `globalThis` here, because user might delete
// it. Instead we're using global `dispatchEvent` function which will
// used a saved reference to global scope.
2023-04-04 12:46:31 +00:00
ascii_str! ( " dispatchEvent(new Event('load')) " ) ,
2022-12-18 20:34:33 +00:00
) ? ;
Ok ( ( ) )
2021-12-21 14:49:27 +00:00
}
/// Dispatches "unload" event to the JavaScript runtime.
///
/// Does not poll event loop, and thus not await any of the "unload" event handlers.
pub fn dispatch_unload_event (
& mut self ,
2023-03-21 22:33:12 +00:00
script_name : & 'static str ,
2021-12-21 14:49:27 +00:00
) -> Result < ( ) , AnyError > {
2023-04-04 12:46:31 +00:00
self . js_runtime . execute_script (
2022-01-17 23:13:14 +00:00
script_name ,
// NOTE(@bartlomieju): not using `globalThis` here, because user might delete
// it. Instead we're using global `dispatchEvent` function which will
// used a saved reference to global scope.
2023-04-04 12:46:31 +00:00
ascii_str! ( " dispatchEvent(new Event('unload')) " ) ,
2022-12-18 20:34:33 +00:00
) ? ;
Ok ( ( ) )
2021-12-21 14:49:27 +00:00
}
2022-06-28 14:49:30 +00:00
/// Dispatches "beforeunload" event to the JavaScript runtime. Returns a boolean
/// indicating if the event was prevented and thus event loop should continue
/// running.
pub fn dispatch_beforeunload_event (
& mut self ,
2023-03-21 22:33:12 +00:00
script_name : & 'static str ,
2022-06-28 14:49:30 +00:00
) -> Result < bool , AnyError > {
let value = self . js_runtime . execute_script (
script_name ,
// NOTE(@bartlomieju): not using `globalThis` here, because user might delete
// it. Instead we're using global `dispatchEvent` function which will
// used a saved reference to global scope.
2023-04-04 12:46:31 +00:00
ascii_str! (
" dispatchEvent(new Event('beforeunload', { cancelable: true })); "
) ,
2022-06-28 14:49:30 +00:00
) ? ;
let local_value = value . open ( & mut self . js_runtime . handle_scope ( ) ) ;
Ok ( local_value . is_false ( ) )
}
2020-10-11 11:20:40 +00:00
}