mirror of
https://github.com/denoland/deno
synced 2024-08-24 18:47:06 +00:00
refactor(core): Improve ergonomics of managing ASCII strings (#18498)
This is a follow-on to the earlier work in reducing string copies, mainly focused on ensuring that ASCII strings are easy to provide to the JS runtime. While we are replacing a 16-byte reference in a number of places with a 24-byte structure (measured via `std::mem::size_of`), the reduction in copies wins out over the additional size of the arguments passed into functions. Benchmarking shows approximately the same if not slightly less wallclock time/instructions retired, but I believe this continues to open up further refactoring opportunities.
This commit is contained in:
parent
2dc2016837
commit
a1764f7690
|
@ -117,6 +117,6 @@ pub fn bench_js_async_with(
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn inner_async(src: &'static str, runtime: &mut JsRuntime) {
|
async fn inner_async(src: &'static str, runtime: &mut JsRuntime) {
|
||||||
runtime.execute_script("inner_loop", src).unwrap();
|
runtime.execute_script_static("inner_loop", src).unwrap();
|
||||||
runtime.run_event_loop(false).await.unwrap();
|
runtime.run_event_loop(false).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ mod tests {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
js_runtime
|
js_runtime
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
"<anon>",
|
"<anon>",
|
||||||
r#"
|
r#"
|
||||||
if (!(bootstrap.mainRuntime && bootstrap.workerRuntime)) {
|
if (!(bootstrap.mainRuntime && bootstrap.workerRuntime)) {
|
||||||
|
|
|
@ -2899,7 +2899,7 @@ fn start(runtime: &mut JsRuntime, debug: bool) -> Result<(), AnyError> {
|
||||||
let init_config = json!({ "debug": debug });
|
let init_config = json!({ "debug": debug });
|
||||||
let init_src = format!("globalThis.serverInit({init_config});");
|
let init_src = format!("globalThis.serverInit({init_config});");
|
||||||
|
|
||||||
runtime.execute_script(located_script_name!(), init_src)?;
|
runtime.execute_script(located_script_name!(), init_src.into())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3493,7 +3493,7 @@ pub fn request(
|
||||||
};
|
};
|
||||||
let mark = performance.mark("request", Some(request_params.clone()));
|
let mark = performance.mark("request", Some(request_params.clone()));
|
||||||
let request_src = format!("globalThis.serverRequest({request_params});");
|
let request_src = format!("globalThis.serverRequest({request_params});");
|
||||||
runtime.execute_script(located_script_name!(), request_src)?;
|
runtime.execute_script(located_script_name!(), request_src.into())?;
|
||||||
|
|
||||||
let op_state = runtime.op_state();
|
let op_state = runtime.op_state();
|
||||||
let mut op_state = op_state.borrow_mut();
|
let mut op_state = op_state.borrow_mut();
|
||||||
|
|
|
@ -78,7 +78,7 @@ impl CliModuleLoader {
|
||||||
fn load_prepared_module(
|
fn load_prepared_module(
|
||||||
&self,
|
&self,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
maybe_referrer: Option<ModuleSpecifier>,
|
maybe_referrer: Option<&ModuleSpecifier>,
|
||||||
) -> Result<ModuleCodeSource, AnyError> {
|
) -> Result<ModuleCodeSource, AnyError> {
|
||||||
if specifier.scheme() == "node" {
|
if specifier.scheme() == "node" {
|
||||||
unreachable!(); // Node built-in modules should be handled internally.
|
unreachable!(); // Node built-in modules should be handled internally.
|
||||||
|
@ -92,7 +92,7 @@ impl CliModuleLoader {
|
||||||
specifier,
|
specifier,
|
||||||
..
|
..
|
||||||
})) => Ok(ModuleCodeSource {
|
})) => Ok(ModuleCodeSource {
|
||||||
code: source.into(),
|
code: source.clone().into(),
|
||||||
found_url: specifier.clone(),
|
found_url: specifier.clone(),
|
||||||
media_type: *media_type,
|
media_type: *media_type,
|
||||||
}),
|
}),
|
||||||
|
@ -107,7 +107,7 @@ impl CliModuleLoader {
|
||||||
| MediaType::Unknown
|
| MediaType::Unknown
|
||||||
| MediaType::Cjs
|
| MediaType::Cjs
|
||||||
| MediaType::Mjs
|
| MediaType::Mjs
|
||||||
| MediaType::Json => source.into(),
|
| MediaType::Json => source.clone().into(),
|
||||||
MediaType::Dts | MediaType::Dcts | MediaType::Dmts => {
|
MediaType::Dts | MediaType::Dcts | MediaType::Dmts => {
|
||||||
Default::default()
|
Default::default()
|
||||||
}
|
}
|
||||||
|
@ -154,7 +154,7 @@ impl CliModuleLoader {
|
||||||
fn load_sync(
|
fn load_sync(
|
||||||
&self,
|
&self,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
maybe_referrer: Option<ModuleSpecifier>,
|
maybe_referrer: Option<&ModuleSpecifier>,
|
||||||
is_dynamic: bool,
|
is_dynamic: bool,
|
||||||
) -> Result<ModuleSource, AnyError> {
|
) -> Result<ModuleSource, AnyError> {
|
||||||
let code_source = if self.ps.npm_resolver.in_npm_package(specifier) {
|
let code_source = if self.ps.npm_resolver.in_npm_package(specifier) {
|
||||||
|
@ -210,15 +210,15 @@ impl CliModuleLoader {
|
||||||
// because we don't need it
|
// because we don't need it
|
||||||
code_without_source_map(code_source.code)
|
code_without_source_map(code_source.code)
|
||||||
};
|
};
|
||||||
Ok(ModuleSource {
|
Ok(ModuleSource::new_with_redirect(
|
||||||
code,
|
match code_source.media_type {
|
||||||
module_url_specified: specifier.to_string(),
|
|
||||||
module_url_found: code_source.found_url.to_string(),
|
|
||||||
module_type: match code_source.media_type {
|
|
||||||
MediaType::Json => ModuleType::Json,
|
MediaType::Json => ModuleType::Json,
|
||||||
_ => ModuleType::JavaScript,
|
_ => ModuleType::JavaScript,
|
||||||
},
|
},
|
||||||
})
|
code,
|
||||||
|
specifier,
|
||||||
|
&code_source.found_url,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,7 +240,7 @@ impl ModuleLoader for CliModuleLoader {
|
||||||
fn load(
|
fn load(
|
||||||
&self,
|
&self,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
maybe_referrer: Option<ModuleSpecifier>,
|
maybe_referrer: Option<&ModuleSpecifier>,
|
||||||
is_dynamic: bool,
|
is_dynamic: bool,
|
||||||
) -> Pin<Box<deno_core::ModuleSourceFuture>> {
|
) -> Pin<Box<deno_core::ModuleSourceFuture>> {
|
||||||
// NOTE: this block is async only because of `deno_core` interface
|
// NOTE: this block is async only because of `deno_core` interface
|
||||||
|
|
|
@ -25,6 +25,7 @@ use deno_core::url::Url;
|
||||||
use deno_core::v8_set_flags;
|
use deno_core::v8_set_flags;
|
||||||
use deno_core::ModuleLoader;
|
use deno_core::ModuleLoader;
|
||||||
use deno_core::ModuleSpecifier;
|
use deno_core::ModuleSpecifier;
|
||||||
|
use deno_core::ModuleType;
|
||||||
use deno_core::ResolutionKind;
|
use deno_core::ResolutionKind;
|
||||||
use deno_graph::source::Resolver;
|
use deno_graph::source::Resolver;
|
||||||
use deno_runtime::fmt_errors::format_js_error;
|
use deno_runtime::fmt_errors::format_js_error;
|
||||||
|
@ -165,7 +166,7 @@ impl ModuleLoader for EmbeddedModuleLoader {
|
||||||
fn load(
|
fn load(
|
||||||
&self,
|
&self,
|
||||||
module_specifier: &ModuleSpecifier,
|
module_specifier: &ModuleSpecifier,
|
||||||
_maybe_referrer: Option<ModuleSpecifier>,
|
_maybe_referrer: Option<&ModuleSpecifier>,
|
||||||
_is_dynamic: bool,
|
_is_dynamic: bool,
|
||||||
) -> Pin<Box<deno_core::ModuleSourceFuture>> {
|
) -> Pin<Box<deno_core::ModuleSourceFuture>> {
|
||||||
let is_data_uri = get_source_from_data_url(module_specifier).ok();
|
let is_data_uri = get_source_from_data_url(module_specifier).ok();
|
||||||
|
@ -173,33 +174,33 @@ impl ModuleLoader for EmbeddedModuleLoader {
|
||||||
.eszip
|
.eszip
|
||||||
.get_module(module_specifier.as_str())
|
.get_module(module_specifier.as_str())
|
||||||
.ok_or_else(|| type_error("Module not found"));
|
.ok_or_else(|| type_error("Module not found"));
|
||||||
|
// TODO(mmastrac): This clone can probably be removed in the future if ModuleSpecifier is no longer a full-fledged URL
|
||||||
let module_specifier = module_specifier.clone();
|
let module_specifier = module_specifier.clone();
|
||||||
|
|
||||||
async move {
|
async move {
|
||||||
if let Some((source, _)) = is_data_uri {
|
if let Some((source, _)) = is_data_uri {
|
||||||
return Ok(deno_core::ModuleSource {
|
return Ok(deno_core::ModuleSource::new(
|
||||||
code: source.into(),
|
deno_core::ModuleType::JavaScript,
|
||||||
module_type: deno_core::ModuleType::JavaScript,
|
source.into(),
|
||||||
module_url_specified: module_specifier.to_string(),
|
&module_specifier,
|
||||||
module_url_found: module_specifier.to_string(),
|
));
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let module = module?;
|
let module = module?;
|
||||||
let code = module.source().await;
|
let code = module.source().await;
|
||||||
let code = std::str::from_utf8(&code)
|
let code = std::str::from_utf8(&code)
|
||||||
.map_err(|_| type_error("Module source is not utf-8"))?
|
.map_err(|_| type_error("Module source is not utf-8"))?
|
||||||
.to_owned();
|
.to_owned()
|
||||||
|
.into();
|
||||||
|
|
||||||
Ok(deno_core::ModuleSource {
|
Ok(deno_core::ModuleSource::new(
|
||||||
code: code.into(),
|
match module.kind {
|
||||||
module_type: match module.kind {
|
eszip::ModuleKind::JavaScript => ModuleType::JavaScript,
|
||||||
eszip::ModuleKind::JavaScript => deno_core::ModuleType::JavaScript,
|
eszip::ModuleKind::Json => ModuleType::Json,
|
||||||
eszip::ModuleKind::Json => deno_core::ModuleType::Json,
|
|
||||||
},
|
},
|
||||||
module_url_specified: module_specifier.to_string(),
|
code,
|
||||||
module_url_found: module_specifier.to_string(),
|
&module_specifier,
|
||||||
})
|
))
|
||||||
}
|
}
|
||||||
.boxed_local()
|
.boxed_local()
|
||||||
}
|
}
|
||||||
|
|
|
@ -691,7 +691,7 @@ pub async fn cover_files(
|
||||||
| MediaType::Unknown
|
| MediaType::Unknown
|
||||||
| MediaType::Cjs
|
| MediaType::Cjs
|
||||||
| MediaType::Mjs
|
| MediaType::Mjs
|
||||||
| MediaType::Json => file.source.into(),
|
| MediaType::Json => file.source.clone().into(),
|
||||||
MediaType::Dts | MediaType::Dmts | MediaType::Dcts => Default::default(),
|
MediaType::Dts | MediaType::Dmts | MediaType::Dcts => Default::default(),
|
||||||
MediaType::TypeScript
|
MediaType::TypeScript
|
||||||
| MediaType::Jsx
|
| MediaType::Jsx
|
||||||
|
@ -718,7 +718,7 @@ pub async fn cover_files(
|
||||||
let source_map = source_map_from_code(&transpiled_code);
|
let source_map = source_map_from_code(&transpiled_code);
|
||||||
let coverage_report = generate_coverage_report(
|
let coverage_report = generate_coverage_report(
|
||||||
&script_coverage,
|
&script_coverage,
|
||||||
transpiled_code.take_as_string(),
|
transpiled_code.as_str().to_owned(),
|
||||||
&source_map,
|
&source_map,
|
||||||
&out_mode,
|
&out_mode,
|
||||||
);
|
);
|
||||||
|
|
|
@ -13,6 +13,7 @@ use crate::util::path::mapped_specifier_for_tsc;
|
||||||
use deno_ast::MediaType;
|
use deno_ast::MediaType;
|
||||||
use deno_core::anyhow::anyhow;
|
use deno_core::anyhow::anyhow;
|
||||||
use deno_core::anyhow::Context;
|
use deno_core::anyhow::Context;
|
||||||
|
use deno_core::ascii_str;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::located_script_name;
|
use deno_core::located_script_name;
|
||||||
use deno_core::op;
|
use deno_core::op;
|
||||||
|
@ -131,8 +132,8 @@ fn get_asset_texts_from_new_runtime() -> Result<Vec<AssetText>, AnyError> {
|
||||||
extensions: vec![deno_cli_tsc::init_ops()],
|
extensions: vec![deno_cli_tsc::init_ops()],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
let global =
|
let global = runtime
|
||||||
runtime.execute_script("get_assets.js", "globalThis.getAssets()")?;
|
.execute_script("get_assets.js", ascii_str!("globalThis.getAssets()"))?;
|
||||||
let scope = &mut runtime.handle_scope();
|
let scope = &mut runtime.handle_scope();
|
||||||
let local = deno_core::v8::Local::new(scope, global);
|
let local = deno_core::v8::Local::new(scope, global);
|
||||||
Ok(serde_v8::from_v8::<Vec<AssetText>>(scope, local)?)
|
Ok(serde_v8::from_v8::<Vec<AssetText>>(scope, local)?)
|
||||||
|
@ -792,15 +793,14 @@ pub fn exec(request: Request) -> Result<Response, AnyError> {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
let startup_source = "globalThis.startup({ legacyFlag: false })";
|
let startup_source = ascii_str!("globalThis.startup({ legacyFlag: false })");
|
||||||
let request_value = json!({
|
let request_value = json!({
|
||||||
"config": request.config,
|
"config": request.config,
|
||||||
"debug": request.debug,
|
"debug": request.debug,
|
||||||
"rootNames": root_names,
|
"rootNames": root_names,
|
||||||
"localOnly": request.check_mode == TypeCheckMode::Local,
|
"localOnly": request.check_mode == TypeCheckMode::Local,
|
||||||
});
|
});
|
||||||
let request_str = request_value.to_string();
|
let exec_source = format!("globalThis.exec({request_value})").into();
|
||||||
let exec_source = format!("globalThis.exec({request_str})");
|
|
||||||
|
|
||||||
let mut runtime = JsRuntime::new(RuntimeOptions {
|
let mut runtime = JsRuntime::new(RuntimeOptions {
|
||||||
startup_snapshot: Some(compiler_snapshot()),
|
startup_snapshot: Some(compiler_snapshot()),
|
||||||
|
@ -974,7 +974,7 @@ mod tests {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
js_runtime
|
js_runtime
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
"<anon>",
|
"<anon>",
|
||||||
r#"
|
r#"
|
||||||
if (!(startup)) {
|
if (!(startup)) {
|
||||||
|
|
|
@ -160,7 +160,9 @@ mod tests {
|
||||||
|
|
||||||
fn run_test(input: &'static str, output: &'static str) {
|
fn run_test(input: &'static str, output: &'static str) {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
code_without_source_map(input.into()).take_as_string(),
|
code_without_source_map(ModuleCode::from_static(input))
|
||||||
|
.as_str()
|
||||||
|
.to_owned(),
|
||||||
output
|
output
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use deno_ast::ModuleSpecifier;
|
use deno_ast::ModuleSpecifier;
|
||||||
|
use deno_core::ascii_str;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::futures::task::LocalFutureObj;
|
use deno_core::futures::task::LocalFutureObj;
|
||||||
use deno_core::futures::FutureExt;
|
use deno_core::futures::FutureExt;
|
||||||
|
@ -184,7 +185,7 @@ impl CliMainWorker {
|
||||||
// Enable op call tracing in core to enable better debugging of op sanitizer
|
// Enable op call tracing in core to enable better debugging of op sanitizer
|
||||||
// failures.
|
// failures.
|
||||||
if self.ps.options.trace_ops() {
|
if self.ps.options.trace_ops() {
|
||||||
self.worker.js_runtime.execute_script(
|
self.worker.js_runtime.execute_script_static(
|
||||||
located_script_name!(),
|
located_script_name!(),
|
||||||
"Deno[Deno.internal].core.enableOpCallTracing();",
|
"Deno[Deno.internal].core.enableOpCallTracing();",
|
||||||
)?;
|
)?;
|
||||||
|
@ -231,7 +232,7 @@ impl CliMainWorker {
|
||||||
|
|
||||||
self.worker.execute_script(
|
self.worker.execute_script(
|
||||||
located_script_name!(),
|
located_script_name!(),
|
||||||
"Deno[Deno.internal].core.enableOpCallTracing();",
|
ascii_str!("Deno[Deno.internal].core.enableOpCallTracing();"),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
if mode != TestMode::Documentation {
|
if mode != TestMode::Documentation {
|
||||||
|
|
|
@ -345,7 +345,7 @@ pub extern "C" fn host_initialize_import_meta_object_callback(
|
||||||
.expect("Module not found");
|
.expect("Module not found");
|
||||||
|
|
||||||
let url_key = v8::String::new_external_onebyte_static(scope, b"url").unwrap();
|
let url_key = v8::String::new_external_onebyte_static(scope, b"url").unwrap();
|
||||||
let url_val = v8::String::new(scope, &info.name).unwrap();
|
let url_val = info.name.v8(scope);
|
||||||
meta.create_data_property(scope, url_key.into(), url_val.into());
|
meta.create_data_property(scope, url_key.into(), url_val.into());
|
||||||
|
|
||||||
let main_key =
|
let main_key =
|
||||||
|
@ -616,7 +616,7 @@ pub fn module_resolve_callback<'s>(
|
||||||
let referrer_info = module_map
|
let referrer_info = module_map
|
||||||
.get_info(&referrer_global)
|
.get_info(&referrer_global)
|
||||||
.expect("ModuleInfo not found");
|
.expect("ModuleInfo not found");
|
||||||
let referrer_name = referrer_info.name.to_string();
|
let referrer_name = referrer_info.name.as_str();
|
||||||
|
|
||||||
let specifier_str = specifier.to_rust_string_lossy(scope);
|
let specifier_str = specifier.to_rust_string_lossy(scope);
|
||||||
|
|
||||||
|
@ -628,7 +628,7 @@ pub fn module_resolve_callback<'s>(
|
||||||
let maybe_module = module_map.resolve_callback(
|
let maybe_module = module_map.resolve_callback(
|
||||||
scope,
|
scope,
|
||||||
&specifier_str,
|
&specifier_str,
|
||||||
&referrer_name,
|
referrer_name,
|
||||||
assertions,
|
assertions,
|
||||||
);
|
);
|
||||||
if let Some(module) = maybe_module {
|
if let Some(module) = maybe_module {
|
||||||
|
|
|
@ -22,6 +22,6 @@ fn main() {
|
||||||
|
|
||||||
// Deno.core.print() will now be a NOP
|
// Deno.core.print() will now be a NOP
|
||||||
runtime
|
runtime
|
||||||
.execute_script("<usage>", r#"Deno.core.print("I'm broken")"#)
|
.execute_script_static("<usage>", r#"Deno.core.print("I'm broken")"#)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ fn eval(
|
||||||
context: &mut JsRuntime,
|
context: &mut JsRuntime,
|
||||||
code: &'static str,
|
code: &'static str,
|
||||||
) -> Result<serde_json::Value, String> {
|
) -> Result<serde_json::Value, String> {
|
||||||
let res = context.execute_script("<anon>", code);
|
let res = context.execute_script_static("<anon>", code);
|
||||||
match res {
|
match res {
|
||||||
Ok(global) => {
|
Ok(global) => {
|
||||||
let scope = &mut context.handle_scope();
|
let scope = &mut context.handle_scope();
|
||||||
|
|
|
@ -41,7 +41,7 @@ fn main() {
|
||||||
// contains a Deno.core object with several functions for interacting with it.
|
// contains a Deno.core object with several functions for interacting with it.
|
||||||
// You can find its definition in core.js.
|
// You can find its definition in core.js.
|
||||||
runtime
|
runtime
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
"<usage>",
|
"<usage>",
|
||||||
r#"
|
r#"
|
||||||
// Print helper function, calling Deno.core.print()
|
// Print helper function, calling Deno.core.print()
|
||||||
|
|
|
@ -165,7 +165,7 @@ fn main() {
|
||||||
js_runtime
|
js_runtime
|
||||||
.execute_script(
|
.execute_script(
|
||||||
"http_bench_json_ops.js",
|
"http_bench_json_ops.js",
|
||||||
include_str!("http_bench_json_ops.js"),
|
include_ascii_string!("http_bench_json_ops.js"),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
js_runtime.run_event_loop(false).await
|
js_runtime.run_event_loop(false).await
|
||||||
|
|
|
@ -31,6 +31,6 @@ fn main() {
|
||||||
extensions,
|
extensions,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
rt.execute_script("panik", "Deno.core.ops.op_panik()")
|
rt.execute_script_static("panik", "Deno.core.ops.op_panik()")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ fn main() {
|
||||||
let future = async move {
|
let future = async move {
|
||||||
// Schedule 10 tasks.
|
// Schedule 10 tasks.
|
||||||
js_runtime
|
js_runtime
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
"<usage>",
|
"<usage>",
|
||||||
r#"for (let i = 1; i <= 10; i++) Deno.core.ops.op_schedule_task(i);"#,
|
r#"for (let i = 1; i <= 10; i++) Deno.core.ops.op_schedule_task(i);"#,
|
||||||
)
|
)
|
||||||
|
|
|
@ -14,6 +14,7 @@ use anyhow::Error;
|
||||||
use deno_ast::MediaType;
|
use deno_ast::MediaType;
|
||||||
use deno_ast::ParseParams;
|
use deno_ast::ParseParams;
|
||||||
use deno_ast::SourceTextInfo;
|
use deno_ast::SourceTextInfo;
|
||||||
|
use deno_core::error::AnyError;
|
||||||
use deno_core::resolve_import;
|
use deno_core::resolve_import;
|
||||||
use deno_core::resolve_path;
|
use deno_core::resolve_path;
|
||||||
use deno_core::JsRuntime;
|
use deno_core::JsRuntime;
|
||||||
|
@ -41,11 +42,12 @@ impl ModuleLoader for TypescriptModuleLoader {
|
||||||
fn load(
|
fn load(
|
||||||
&self,
|
&self,
|
||||||
module_specifier: &ModuleSpecifier,
|
module_specifier: &ModuleSpecifier,
|
||||||
_maybe_referrer: Option<ModuleSpecifier>,
|
_maybe_referrer: Option<&ModuleSpecifier>,
|
||||||
_is_dyn_import: bool,
|
_is_dyn_import: bool,
|
||||||
) -> Pin<Box<ModuleSourceFuture>> {
|
) -> Pin<Box<ModuleSourceFuture>> {
|
||||||
let module_specifier = module_specifier.clone();
|
fn load(
|
||||||
async move {
|
module_specifier: &ModuleSpecifier,
|
||||||
|
) -> Result<ModuleSource, AnyError> {
|
||||||
let path = module_specifier
|
let path = module_specifier
|
||||||
.to_file_path()
|
.to_file_path()
|
||||||
.map_err(|_| anyhow!("Only file:// URLs are supported."))?;
|
.map_err(|_| anyhow!("Only file:// URLs are supported."))?;
|
||||||
|
@ -81,15 +83,14 @@ impl ModuleLoader for TypescriptModuleLoader {
|
||||||
} else {
|
} else {
|
||||||
code
|
code
|
||||||
};
|
};
|
||||||
let module = ModuleSource {
|
Ok(ModuleSource::new(
|
||||||
code: code.into(),
|
|
||||||
module_type,
|
module_type,
|
||||||
module_url_specified: module_specifier.to_string(),
|
code.into(),
|
||||||
module_url_found: module_specifier.to_string(),
|
module_specifier,
|
||||||
};
|
))
|
||||||
Ok(module)
|
|
||||||
}
|
}
|
||||||
.boxed_local()
|
|
||||||
|
futures::future::ready(load(module_specifier)).boxed_local()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,6 +62,6 @@ fn main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
runtime
|
runtime
|
||||||
.execute_script("<usage>", include_str!("wasm.js"))
|
.execute_script("<usage>", include_ascii_string!("wasm.js"))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ impl ExtensionFileSource {
|
||||||
self.specifier,
|
self.specifier,
|
||||||
Self::find_non_ascii(code)
|
Self::find_non_ascii(code)
|
||||||
);
|
);
|
||||||
Ok((*code).into())
|
Ok(ModuleCode::from_static(code))
|
||||||
}
|
}
|
||||||
ExtensionFileSourceCode::LoadedFromFsDuringSnapshot(path) => {
|
ExtensionFileSourceCode::LoadedFromFsDuringSnapshot(path) => {
|
||||||
let msg = || format!("Failed to read \"{}\"", path.display());
|
let msg = || format!("Failed to read \"{}\"", path.display());
|
||||||
|
|
243
core/fast_string.rs
Normal file
243
core/fast_string.rs
Normal file
|
@ -0,0 +1,243 @@
|
||||||
|
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
use std::borrow::Borrow;
|
||||||
|
use std::fmt::Debug;
|
||||||
|
use std::hash::Hash;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use url::Url;
|
||||||
|
use v8::NewStringType;
|
||||||
|
|
||||||
|
/// Module names and code can be sourced from strings or bytes that are either owned or borrowed. This enumeration allows us
|
||||||
|
/// to perform a minimal amount of cloning and format-shifting of the underlying data.
|
||||||
|
///
|
||||||
|
/// Note that any [`FastString`] created from a `'static` byte array or string must contain ASCII characters.
|
||||||
|
///
|
||||||
|
/// Examples of ways to construct a [`FastString`]:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use deno_core::{ascii_str, FastString};
|
||||||
|
///
|
||||||
|
/// let code: FastString = ascii_str!("a string");
|
||||||
|
/// let code: FastString = format!("a string").into();
|
||||||
|
/// ```
|
||||||
|
pub enum FastString {
|
||||||
|
/// Created from static data.
|
||||||
|
Static(&'static str),
|
||||||
|
|
||||||
|
/// Created from static data, known to contain only ASCII chars.
|
||||||
|
StaticAscii(&'static str),
|
||||||
|
|
||||||
|
/// An owned chunk of data. Note that we use `Box` rather than `Vec` to avoid the
|
||||||
|
/// storage overhead.
|
||||||
|
Owned(Box<str>),
|
||||||
|
|
||||||
|
// Scripts loaded from the `deno_graph` infrastructure.
|
||||||
|
Arc(Arc<str>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FastString {
|
||||||
|
/// Compile-time function to determine if a string is ASCII. Note that UTF-8 chars
|
||||||
|
/// longer than one byte have the high-bit set and thus, are not ASCII.
|
||||||
|
const fn is_ascii(s: &'static [u8]) -> bool {
|
||||||
|
let mut i = 0;
|
||||||
|
while i < s.len() {
|
||||||
|
if !s[i].is_ascii() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a [`FastString`] from a static string. The string may contain non-ASCII characters, and if
|
||||||
|
/// so, will take the slower path when used in v8.
|
||||||
|
pub const fn from_static(s: &'static str) -> Self {
|
||||||
|
if Self::is_ascii(s.as_bytes()) {
|
||||||
|
Self::StaticAscii(s)
|
||||||
|
} else {
|
||||||
|
Self::Static(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a [`FastString`] from a static string. If the string contains non-ASCII characters, the compiler
|
||||||
|
/// will abort.
|
||||||
|
pub const fn ensure_static_ascii(s: &'static str) -> Self {
|
||||||
|
if Self::is_ascii(s.as_bytes()) {
|
||||||
|
Self::StaticAscii(s)
|
||||||
|
} else {
|
||||||
|
panic!("This string contained non-ASCII characters and cannot be created with ensure_static_ascii")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a cheap copy of this [`FastString`], potentially transmuting it to a faster form. Note that this
|
||||||
|
/// is not a clone operation as it consumes the old [`FastString`].
|
||||||
|
pub fn into_cheap_copy(self) -> (Self, Self) {
|
||||||
|
match self {
|
||||||
|
Self::Static(s) => (Self::Static(s), Self::Static(s)),
|
||||||
|
Self::StaticAscii(s) => (Self::StaticAscii(s), Self::StaticAscii(s)),
|
||||||
|
Self::Arc(s) => (Self::Arc(s.clone()), Self::Arc(s)),
|
||||||
|
Self::Owned(s) => {
|
||||||
|
let s: Arc<str> = s.into();
|
||||||
|
(Self::Arc(s.clone()), Self::Arc(s))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn try_static_ascii(&self) -> Option<&'static [u8]> {
|
||||||
|
match self {
|
||||||
|
Self::StaticAscii(s) => Some(s.as_bytes()),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_bytes(&self) -> &[u8] {
|
||||||
|
// TODO(mmastrac): This can be const eventually (waiting for Arc const deref)
|
||||||
|
match self {
|
||||||
|
Self::Arc(s) => s.as_bytes(),
|
||||||
|
Self::Owned(s) => s.as_bytes(),
|
||||||
|
Self::Static(s) => s.as_bytes(),
|
||||||
|
Self::StaticAscii(s) => s.as_bytes(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_str(&self) -> &str {
|
||||||
|
// TODO(mmastrac): This can be const eventually (waiting for Arc const deref)
|
||||||
|
match self {
|
||||||
|
Self::Arc(s) => s,
|
||||||
|
Self::Owned(s) => s,
|
||||||
|
Self::Static(s) => s,
|
||||||
|
Self::StaticAscii(s) => s,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a v8 string from this [`FastString`]. If the string is static and contains only ASCII characters,
|
||||||
|
/// an external one-byte static is created.
|
||||||
|
pub fn v8<'a>(
|
||||||
|
&self,
|
||||||
|
scope: &mut v8::HandleScope<'a>,
|
||||||
|
) -> v8::Local<'a, v8::String> {
|
||||||
|
match self.try_static_ascii() {
|
||||||
|
Some(s) => v8::String::new_external_onebyte_static(scope, s).unwrap(),
|
||||||
|
None => {
|
||||||
|
v8::String::new_from_utf8(scope, self.as_bytes(), NewStringType::Normal)
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Truncates a [`FastString`] value, possibly re-allocating or memcpy'ing. May be slow.
|
||||||
|
pub fn truncate(&mut self, index: usize) {
|
||||||
|
match self {
|
||||||
|
Self::Static(b) => *self = Self::Static(&b[..index]),
|
||||||
|
Self::StaticAscii(b) => *self = Self::StaticAscii(&b[..index]),
|
||||||
|
Self::Owned(b) => *self = Self::Owned(b[..index].to_owned().into()),
|
||||||
|
// We can't do much if we have an Arc<str>, so we'll just take ownership of the truncated version
|
||||||
|
Self::Arc(s) => *self = s[..index].to_owned().into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hash for FastString {
|
||||||
|
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||||
|
self.as_str().hash(state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsRef<str> for FastString {
|
||||||
|
fn as_ref(&self) -> &str {
|
||||||
|
self.as_str()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Borrow<str> for FastString {
|
||||||
|
fn borrow(&self) -> &str {
|
||||||
|
self.as_str()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for FastString {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
Debug::fmt(self.as_str(), f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for FastString {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::StaticAscii("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for FastString {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.as_bytes() == other.as_bytes()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for FastString {}
|
||||||
|
|
||||||
|
/// [`FastString`] can be made cheaply from [`Url`] as we know it's owned and don't need to do an
|
||||||
|
/// ASCII check.
|
||||||
|
impl From<Url> for FastString {
|
||||||
|
fn from(value: Url) -> Self {
|
||||||
|
let s: String = value.into();
|
||||||
|
s.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// [`FastString`] can be made cheaply from [`String`] as we know it's owned and don't need to do an
|
||||||
|
/// ASCII check.
|
||||||
|
impl From<String> for FastString {
|
||||||
|
fn from(value: String) -> Self {
|
||||||
|
FastString::Owned(value.into_boxed_str())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// [`FastString`] can be made cheaply from [`Arc<str>`] as we know it's shared and don't need to do an
|
||||||
|
/// ASCII check.
|
||||||
|
impl From<Arc<str>> for FastString {
|
||||||
|
fn from(value: Arc<str>) -> Self {
|
||||||
|
FastString::Arc(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Include a fast string in the binary. This string is asserted at compile-time to be 7-bit ASCII for optimal
|
||||||
|
/// v8 performance.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! include_ascii_string {
|
||||||
|
($file:literal) => {
|
||||||
|
$crate::FastString::ensure_static_ascii(include_str!($file))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Include a fast string in the binary from a string literal. This string is asserted at compile-time to be
|
||||||
|
/// 7-bit ASCII for optimal v8 performance.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! ascii_str {
|
||||||
|
($str:literal) => {
|
||||||
|
$crate::FastString::ensure_static_ascii($str)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn truncate() {
|
||||||
|
let mut s = "123456".to_owned();
|
||||||
|
s.truncate(3);
|
||||||
|
|
||||||
|
let mut code: FastString = FastString::from_static("123456");
|
||||||
|
code.truncate(3);
|
||||||
|
assert_eq!(s, code.as_ref());
|
||||||
|
|
||||||
|
let mut code: FastString = "123456".to_owned().into();
|
||||||
|
code.truncate(3);
|
||||||
|
assert_eq!(s, code.as_ref());
|
||||||
|
|
||||||
|
let arc_str: Arc<str> = "123456".into();
|
||||||
|
let mut code: FastString = arc_str.into();
|
||||||
|
code.truncate(3);
|
||||||
|
assert_eq!(s, code.as_ref());
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,7 @@ mod bindings;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
mod error_codes;
|
mod error_codes;
|
||||||
mod extensions;
|
mod extensions;
|
||||||
|
mod fast_string;
|
||||||
mod flags;
|
mod flags;
|
||||||
mod gotham_state;
|
mod gotham_state;
|
||||||
mod inspector;
|
mod inspector;
|
||||||
|
@ -59,6 +60,7 @@ pub use crate::extensions::ExtensionFileSource;
|
||||||
pub use crate::extensions::ExtensionFileSourceCode;
|
pub use crate::extensions::ExtensionFileSourceCode;
|
||||||
pub use crate::extensions::OpDecl;
|
pub use crate::extensions::OpDecl;
|
||||||
pub use crate::extensions::OpMiddlewareFn;
|
pub use crate::extensions::OpMiddlewareFn;
|
||||||
|
pub use crate::fast_string::FastString;
|
||||||
pub use crate::flags::v8_set_flags;
|
pub use crate::flags::v8_set_flags;
|
||||||
pub use crate::inspector::InspectorMsg;
|
pub use crate::inspector::InspectorMsg;
|
||||||
pub use crate::inspector::InspectorMsgKind;
|
pub use crate::inspector::InspectorMsgKind;
|
||||||
|
|
712
core/modules.rs
712
core/modules.rs
File diff suppressed because it is too large
Load diff
323
core/runtime.rs
323
core/runtime.rs
|
@ -747,7 +747,6 @@ impl JsRuntime {
|
||||||
{
|
{
|
||||||
if let Some(js_files) = ext.get_js_sources() {
|
if let Some(js_files) = ext.get_js_sources() {
|
||||||
for file_source in js_files {
|
for file_source in js_files {
|
||||||
// TODO(@AaronO): use JsRuntime::execute_static() here to move src off heap
|
|
||||||
realm.execute_script(
|
realm.execute_script(
|
||||||
self.v8_isolate(),
|
self.v8_isolate(),
|
||||||
file_source.specifier,
|
file_source.specifier,
|
||||||
|
@ -914,16 +913,42 @@ impl JsRuntime {
|
||||||
/// The same `name` value can be used for multiple executions.
|
/// The same `name` value can be used for multiple executions.
|
||||||
///
|
///
|
||||||
/// `Error` can usually be downcast to `JsError`.
|
/// `Error` can usually be downcast to `JsError`.
|
||||||
pub fn execute_script<S: Into<ModuleCode>>(
|
pub fn execute_script(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
source_code: S,
|
source_code: ModuleCode,
|
||||||
) -> Result<v8::Global<v8::Value>, Error> {
|
) -> Result<v8::Global<v8::Value>, Error> {
|
||||||
self
|
self
|
||||||
.global_realm()
|
.global_realm()
|
||||||
.execute_script(self.v8_isolate(), name, source_code)
|
.execute_script(self.v8_isolate(), name, source_code)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Executes traditional JavaScript code (traditional = not ES modules).
|
||||||
|
///
|
||||||
|
/// The execution takes place on the current global context, so it is possible
|
||||||
|
/// to maintain local JS state and invoke this method multiple times.
|
||||||
|
///
|
||||||
|
/// `name` can be a filepath or any other string, but it is required to be 7-bit ASCII, eg.
|
||||||
|
///
|
||||||
|
/// - "/some/file/path.js"
|
||||||
|
/// - "<anon>"
|
||||||
|
/// - "[native code]"
|
||||||
|
///
|
||||||
|
/// The same `name` value can be used for multiple executions.
|
||||||
|
///
|
||||||
|
/// `Error` can usually be downcast to `JsError`.
|
||||||
|
pub fn execute_script_static(
|
||||||
|
&mut self,
|
||||||
|
name: &'static str,
|
||||||
|
source_code: &'static str,
|
||||||
|
) -> Result<v8::Global<v8::Value>, Error> {
|
||||||
|
self.global_realm().execute_script(
|
||||||
|
self.v8_isolate(),
|
||||||
|
name,
|
||||||
|
ModuleCode::from_static(source_code),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/// Takes a snapshot. The isolate should have been created with will_snapshot
|
/// Takes a snapshot. The isolate should have been created with will_snapshot
|
||||||
/// set to true.
|
/// set to true.
|
||||||
///
|
///
|
||||||
|
@ -1895,7 +1920,7 @@ impl JsRuntime {
|
||||||
let register_result = load.register_and_recurse(
|
let register_result = load.register_and_recurse(
|
||||||
&mut self.handle_scope(),
|
&mut self.handle_scope(),
|
||||||
&request,
|
&request,
|
||||||
&info,
|
info,
|
||||||
);
|
);
|
||||||
|
|
||||||
match register_result {
|
match register_result {
|
||||||
|
@ -2071,11 +2096,12 @@ impl JsRuntime {
|
||||||
) -> Result<ModuleId, Error> {
|
) -> Result<ModuleId, Error> {
|
||||||
let module_map_rc = Self::module_map(self.v8_isolate());
|
let module_map_rc = Self::module_map(self.v8_isolate());
|
||||||
if let Some(code) = code {
|
if let Some(code) = code {
|
||||||
|
let specifier = specifier.as_str().to_owned().into();
|
||||||
let scope = &mut self.handle_scope();
|
let scope = &mut self.handle_scope();
|
||||||
// true for main module
|
// true for main module
|
||||||
module_map_rc
|
module_map_rc
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.new_es_module(scope, true, specifier, &code, false)
|
.new_es_module(scope, true, specifier, code, false)
|
||||||
.map_err(|e| match e {
|
.map_err(|e| match e {
|
||||||
ModuleError::Exception(exception) => {
|
ModuleError::Exception(exception) => {
|
||||||
let exception = v8::Local::new(scope, exception);
|
let exception = v8::Local::new(scope, exception);
|
||||||
|
@ -2086,12 +2112,12 @@ impl JsRuntime {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut load =
|
let mut load =
|
||||||
ModuleMap::load_main(module_map_rc.clone(), specifier.as_str()).await?;
|
ModuleMap::load_main(module_map_rc.clone(), &specifier).await?;
|
||||||
|
|
||||||
while let Some(load_result) = load.next().await {
|
while let Some(load_result) = load.next().await {
|
||||||
let (request, info) = load_result?;
|
let (request, info) = load_result?;
|
||||||
let scope = &mut self.handle_scope();
|
let scope = &mut self.handle_scope();
|
||||||
load.register_and_recurse(scope, &request, &info).map_err(
|
load.register_and_recurse(scope, &request, info).map_err(
|
||||||
|e| match e {
|
|e| match e {
|
||||||
ModuleError::Exception(exception) => {
|
ModuleError::Exception(exception) => {
|
||||||
let exception = v8::Local::new(scope, exception);
|
let exception = v8::Local::new(scope, exception);
|
||||||
|
@ -2125,11 +2151,12 @@ impl JsRuntime {
|
||||||
) -> Result<ModuleId, Error> {
|
) -> Result<ModuleId, Error> {
|
||||||
let module_map_rc = Self::module_map(self.v8_isolate());
|
let module_map_rc = Self::module_map(self.v8_isolate());
|
||||||
if let Some(code) = code {
|
if let Some(code) = code {
|
||||||
|
let specifier = specifier.as_str().to_owned().into();
|
||||||
let scope = &mut self.handle_scope();
|
let scope = &mut self.handle_scope();
|
||||||
// false for side module (not main module)
|
// false for side module (not main module)
|
||||||
module_map_rc
|
module_map_rc
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.new_es_module(scope, false, specifier, &code, false)
|
.new_es_module(scope, false, specifier, code, false)
|
||||||
.map_err(|e| match e {
|
.map_err(|e| match e {
|
||||||
ModuleError::Exception(exception) => {
|
ModuleError::Exception(exception) => {
|
||||||
let exception = v8::Local::new(scope, exception);
|
let exception = v8::Local::new(scope, exception);
|
||||||
|
@ -2140,12 +2167,12 @@ impl JsRuntime {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut load =
|
let mut load =
|
||||||
ModuleMap::load_side(module_map_rc.clone(), specifier.as_str()).await?;
|
ModuleMap::load_side(module_map_rc.clone(), &specifier).await?;
|
||||||
|
|
||||||
while let Some(load_result) = load.next().await {
|
while let Some(load_result) = load.next().await {
|
||||||
let (request, info) = load_result?;
|
let (request, info) = load_result?;
|
||||||
let scope = &mut self.handle_scope();
|
let scope = &mut self.handle_scope();
|
||||||
load.register_and_recurse(scope, &request, &info).map_err(
|
load.register_and_recurse(scope, &request, info).map_err(
|
||||||
|e| match e {
|
|e| match e {
|
||||||
ModuleError::Exception(exception) => {
|
ModuleError::Exception(exception) => {
|
||||||
let exception = v8::Local::new(scope, exception);
|
let exception = v8::Local::new(scope, exception);
|
||||||
|
@ -2439,7 +2466,7 @@ impl JsRuntime {
|
||||||
/// .expect("Handle the error properly");
|
/// .expect("Handle the error properly");
|
||||||
/// let source_code = "var a = 0; a + 1";
|
/// let source_code = "var a = 0; a + 1";
|
||||||
/// let result = new_realm
|
/// let result = new_realm
|
||||||
/// .execute_script(runtime.v8_isolate(), "<anon>", source_code)
|
/// .execute_script_static(runtime.v8_isolate(), "<anon>", source_code)
|
||||||
/// .expect("Handle the error properly");
|
/// .expect("Handle the error properly");
|
||||||
/// # drop(result);
|
/// # drop(result);
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -2525,17 +2552,30 @@ impl JsRealm {
|
||||||
/// The same `name` value can be used for multiple executions.
|
/// The same `name` value can be used for multiple executions.
|
||||||
///
|
///
|
||||||
/// `Error` can usually be downcast to `JsError`.
|
/// `Error` can usually be downcast to `JsError`.
|
||||||
pub fn execute_script<S: Into<ModuleCode>>(
|
pub fn execute_script_static(
|
||||||
&self,
|
&self,
|
||||||
isolate: &mut v8::Isolate,
|
isolate: &mut v8::Isolate,
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
source_code: S,
|
source_code: &'static str,
|
||||||
) -> Result<v8::Global<v8::Value>, Error> {
|
) -> Result<v8::Global<v8::Value>, Error> {
|
||||||
// Manual monomorphization (TODO: replace w/momo)
|
self.execute_script(isolate, name, ModuleCode::from_static(source_code))
|
||||||
self.execute_script_inner(isolate, name, source_code.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_script_inner(
|
/// Executes traditional JavaScript code (traditional = not ES modules) in the
|
||||||
|
/// realm's context.
|
||||||
|
///
|
||||||
|
/// For info on the [`v8::Isolate`] parameter, check [`JsRealm#panics`].
|
||||||
|
///
|
||||||
|
/// The `name` parameter can be a filepath or any other string. E.g.:
|
||||||
|
///
|
||||||
|
/// - "/some/file/path.js"
|
||||||
|
/// - "<anon>"
|
||||||
|
/// - "[native code]"
|
||||||
|
///
|
||||||
|
/// The same `name` value can be used for multiple executions.
|
||||||
|
///
|
||||||
|
/// `Error` can usually be downcast to `JsError`.
|
||||||
|
pub fn execute_script(
|
||||||
&self,
|
&self,
|
||||||
isolate: &mut v8::Isolate,
|
isolate: &mut v8::Isolate,
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
|
@ -2687,8 +2727,10 @@ pub fn queue_async_op(
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub mod tests {
|
pub mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::ascii_str;
|
||||||
use crate::error::custom_error;
|
use crate::error::custom_error;
|
||||||
use crate::error::AnyError;
|
use crate::error::AnyError;
|
||||||
|
use crate::include_ascii_string;
|
||||||
use crate::modules::AssertedModuleType;
|
use crate::modules::AssertedModuleType;
|
||||||
use crate::modules::ModuleInfo;
|
use crate::modules::ModuleInfo;
|
||||||
use crate::modules::ModuleSource;
|
use crate::modules::ModuleSource;
|
||||||
|
@ -2787,7 +2829,7 @@ pub mod tests {
|
||||||
});
|
});
|
||||||
|
|
||||||
runtime
|
runtime
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
"setup.js",
|
"setup.js",
|
||||||
r#"
|
r#"
|
||||||
function assert(cond) {
|
function assert(cond) {
|
||||||
|
@ -2806,7 +2848,7 @@ pub mod tests {
|
||||||
fn test_ref_unref_ops() {
|
fn test_ref_unref_ops() {
|
||||||
let (mut runtime, _dispatch_count) = setup(Mode::AsyncDeferred);
|
let (mut runtime, _dispatch_count) = setup(Mode::AsyncDeferred);
|
||||||
runtime
|
runtime
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
"filename.js",
|
"filename.js",
|
||||||
r#"
|
r#"
|
||||||
|
|
||||||
|
@ -2824,7 +2866,7 @@ pub mod tests {
|
||||||
assert_eq!(realm.state(isolate).borrow().unrefed_ops.len(), 0);
|
assert_eq!(realm.state(isolate).borrow().unrefed_ops.len(), 0);
|
||||||
}
|
}
|
||||||
runtime
|
runtime
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
"filename.js",
|
"filename.js",
|
||||||
r#"
|
r#"
|
||||||
Deno.core.ops.op_unref_op(p1[promiseIdSymbol]);
|
Deno.core.ops.op_unref_op(p1[promiseIdSymbol]);
|
||||||
|
@ -2840,7 +2882,7 @@ pub mod tests {
|
||||||
assert_eq!(realm.state(isolate).borrow().unrefed_ops.len(), 2);
|
assert_eq!(realm.state(isolate).borrow().unrefed_ops.len(), 2);
|
||||||
}
|
}
|
||||||
runtime
|
runtime
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
"filename.js",
|
"filename.js",
|
||||||
r#"
|
r#"
|
||||||
Deno.core.ops.op_ref_op(p1[promiseIdSymbol]);
|
Deno.core.ops.op_ref_op(p1[promiseIdSymbol]);
|
||||||
|
@ -2861,7 +2903,7 @@ pub mod tests {
|
||||||
fn test_dispatch() {
|
fn test_dispatch() {
|
||||||
let (mut runtime, dispatch_count) = setup(Mode::Async);
|
let (mut runtime, dispatch_count) = setup(Mode::Async);
|
||||||
runtime
|
runtime
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
"filename.js",
|
"filename.js",
|
||||||
r#"
|
r#"
|
||||||
let control = 42;
|
let control = 42;
|
||||||
|
@ -2881,7 +2923,7 @@ pub mod tests {
|
||||||
fn test_op_async_promise_id() {
|
fn test_op_async_promise_id() {
|
||||||
let (mut runtime, _dispatch_count) = setup(Mode::Async);
|
let (mut runtime, _dispatch_count) = setup(Mode::Async);
|
||||||
runtime
|
runtime
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
"filename.js",
|
"filename.js",
|
||||||
r#"
|
r#"
|
||||||
|
|
||||||
|
@ -2898,7 +2940,7 @@ pub mod tests {
|
||||||
fn test_dispatch_no_zero_copy_buf() {
|
fn test_dispatch_no_zero_copy_buf() {
|
||||||
let (mut runtime, dispatch_count) = setup(Mode::AsyncZeroCopy(false));
|
let (mut runtime, dispatch_count) = setup(Mode::AsyncZeroCopy(false));
|
||||||
runtime
|
runtime
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
"filename.js",
|
"filename.js",
|
||||||
r#"
|
r#"
|
||||||
|
|
||||||
|
@ -2913,7 +2955,7 @@ pub mod tests {
|
||||||
fn test_dispatch_stack_zero_copy_bufs() {
|
fn test_dispatch_stack_zero_copy_bufs() {
|
||||||
let (mut runtime, dispatch_count) = setup(Mode::AsyncZeroCopy(true));
|
let (mut runtime, dispatch_count) = setup(Mode::AsyncZeroCopy(true));
|
||||||
runtime
|
runtime
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
"filename.js",
|
"filename.js",
|
||||||
r#"
|
r#"
|
||||||
|
|
||||||
|
@ -2928,13 +2970,16 @@ pub mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_execute_script_return_value() {
|
fn test_execute_script_return_value() {
|
||||||
let mut runtime = JsRuntime::new(Default::default());
|
let mut runtime = JsRuntime::new(Default::default());
|
||||||
let value_global = runtime.execute_script("a.js", "a = 1 + 2").unwrap();
|
let value_global =
|
||||||
|
runtime.execute_script_static("a.js", "a = 1 + 2").unwrap();
|
||||||
{
|
{
|
||||||
let scope = &mut runtime.handle_scope();
|
let scope = &mut runtime.handle_scope();
|
||||||
let value = value_global.open(scope);
|
let value = value_global.open(scope);
|
||||||
assert_eq!(value.integer_value(scope).unwrap(), 3);
|
assert_eq!(value.integer_value(scope).unwrap(), 3);
|
||||||
}
|
}
|
||||||
let value_global = runtime.execute_script("b.js", "b = 'foobar'").unwrap();
|
let value_global = runtime
|
||||||
|
.execute_script_static("b.js", "b = 'foobar'")
|
||||||
|
.unwrap();
|
||||||
{
|
{
|
||||||
let scope = &mut runtime.handle_scope();
|
let scope = &mut runtime.handle_scope();
|
||||||
let value = value_global.open(scope);
|
let value = value_global.open(scope);
|
||||||
|
@ -2951,7 +2996,7 @@ pub mod tests {
|
||||||
let mut runtime = JsRuntime::new(Default::default());
|
let mut runtime = JsRuntime::new(Default::default());
|
||||||
run_in_task(move |cx| {
|
run_in_task(move |cx| {
|
||||||
let value_global = runtime
|
let value_global = runtime
|
||||||
.execute_script("a.js", "Promise.resolve(1 + 2)")
|
.execute_script_static("a.js", "Promise.resolve(1 + 2)")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let v = runtime.poll_value(&value_global, cx);
|
let v = runtime.poll_value(&value_global, cx);
|
||||||
{
|
{
|
||||||
|
@ -2962,7 +3007,7 @@ pub mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
let value_global = runtime
|
let value_global = runtime
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
"a.js",
|
"a.js",
|
||||||
"Promise.resolve(new Promise(resolve => resolve(2 + 2)))",
|
"Promise.resolve(new Promise(resolve => resolve(2 + 2)))",
|
||||||
)
|
)
|
||||||
|
@ -2976,7 +3021,7 @@ pub mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
let value_global = runtime
|
let value_global = runtime
|
||||||
.execute_script("a.js", "Promise.reject(new Error('fail'))")
|
.execute_script_static("a.js", "Promise.reject(new Error('fail'))")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let v = runtime.poll_value(&value_global, cx);
|
let v = runtime.poll_value(&value_global, cx);
|
||||||
assert!(
|
assert!(
|
||||||
|
@ -2984,7 +3029,7 @@ pub mod tests {
|
||||||
);
|
);
|
||||||
|
|
||||||
let value_global = runtime
|
let value_global = runtime
|
||||||
.execute_script("a.js", "new Promise(resolve => {})")
|
.execute_script_static("a.js", "new Promise(resolve => {})")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let v = runtime.poll_value(&value_global, cx);
|
let v = runtime.poll_value(&value_global, cx);
|
||||||
matches!(v, Poll::Ready(Err(e)) if e.to_string() == "Promise resolution is still pending but the event loop has already resolved.");
|
matches!(v, Poll::Ready(Err(e)) if e.to_string() == "Promise resolution is still pending but the event loop has already resolved.");
|
||||||
|
@ -2995,7 +3040,7 @@ pub mod tests {
|
||||||
async fn test_resolve_value() {
|
async fn test_resolve_value() {
|
||||||
let mut runtime = JsRuntime::new(Default::default());
|
let mut runtime = JsRuntime::new(Default::default());
|
||||||
let value_global = runtime
|
let value_global = runtime
|
||||||
.execute_script("a.js", "Promise.resolve(1 + 2)")
|
.execute_script_static("a.js", "Promise.resolve(1 + 2)")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let result_global = runtime.resolve_value(value_global).await.unwrap();
|
let result_global = runtime.resolve_value(value_global).await.unwrap();
|
||||||
{
|
{
|
||||||
|
@ -3005,7 +3050,7 @@ pub mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
let value_global = runtime
|
let value_global = runtime
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
"a.js",
|
"a.js",
|
||||||
"Promise.resolve(new Promise(resolve => resolve(2 + 2)))",
|
"Promise.resolve(new Promise(resolve => resolve(2 + 2)))",
|
||||||
)
|
)
|
||||||
|
@ -3018,7 +3063,7 @@ pub mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
let value_global = runtime
|
let value_global = runtime
|
||||||
.execute_script("a.js", "Promise.reject(new Error('fail'))")
|
.execute_script_static("a.js", "Promise.reject(new Error('fail'))")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let err = runtime.resolve_value(value_global).await.unwrap_err();
|
let err = runtime.resolve_value(value_global).await.unwrap_err();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -3027,7 +3072,7 @@ pub mod tests {
|
||||||
);
|
);
|
||||||
|
|
||||||
let value_global = runtime
|
let value_global = runtime
|
||||||
.execute_script("a.js", "new Promise(resolve => {})")
|
.execute_script_static("a.js", "new Promise(resolve => {})")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let error_string = runtime
|
let error_string = runtime
|
||||||
.resolve_value(value_global)
|
.resolve_value(value_global)
|
||||||
|
@ -3046,7 +3091,7 @@ pub mod tests {
|
||||||
let v8_isolate_handle = runtime.v8_isolate().thread_safe_handle();
|
let v8_isolate_handle = runtime.v8_isolate().thread_safe_handle();
|
||||||
|
|
||||||
// Run an infinite loop in Webassemby code, which should be terminated.
|
// Run an infinite loop in Webassemby code, which should be terminated.
|
||||||
let promise = runtime.execute_script("infinite_wasm_loop.js",
|
let promise = runtime.execute_script_static("infinite_wasm_loop.js",
|
||||||
r#"
|
r#"
|
||||||
(async () => {
|
(async () => {
|
||||||
const wasmCode = new Uint8Array([
|
const wasmCode = new Uint8Array([
|
||||||
|
@ -3069,7 +3114,7 @@ pub mod tests {
|
||||||
assert!(ok);
|
assert!(ok);
|
||||||
});
|
});
|
||||||
let err = runtime
|
let err = runtime
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
"infinite_wasm_loop2.js",
|
"infinite_wasm_loop2.js",
|
||||||
"globalThis.wasmInstance.exports.infinite_loop();",
|
"globalThis.wasmInstance.exports.infinite_loop();",
|
||||||
)
|
)
|
||||||
|
@ -3082,7 +3127,7 @@ pub mod tests {
|
||||||
|
|
||||||
// Verify that the isolate usable again.
|
// Verify that the isolate usable again.
|
||||||
runtime
|
runtime
|
||||||
.execute_script("simple.js", "1 + 1")
|
.execute_script_static("simple.js", "1 + 1")
|
||||||
.expect("execution should be possible again");
|
.expect("execution should be possible again");
|
||||||
|
|
||||||
terminator_thread.join().unwrap();
|
terminator_thread.join().unwrap();
|
||||||
|
@ -3103,7 +3148,7 @@ pub mod tests {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Rn an infinite loop, which should be terminated.
|
// Rn an infinite loop, which should be terminated.
|
||||||
match isolate.execute_script("infinite_loop.js", "for(;;) {}") {
|
match isolate.execute_script_static("infinite_loop.js", "for(;;) {}") {
|
||||||
Ok(_) => panic!("execution should be terminated"),
|
Ok(_) => panic!("execution should be terminated"),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
assert_eq!(e.to_string(), "Uncaught Error: execution terminated")
|
assert_eq!(e.to_string(), "Uncaught Error: execution terminated")
|
||||||
|
@ -3117,7 +3162,7 @@ pub mod tests {
|
||||||
|
|
||||||
// Verify that the isolate usable again.
|
// Verify that the isolate usable again.
|
||||||
isolate
|
isolate
|
||||||
.execute_script("simple.js", "1 + 1")
|
.execute_script_static("simple.js", "1 + 1")
|
||||||
.expect("execution should be possible again");
|
.expect("execution should be possible again");
|
||||||
|
|
||||||
terminator_thread.join().unwrap();
|
terminator_thread.join().unwrap();
|
||||||
|
@ -3139,7 +3184,7 @@ pub mod tests {
|
||||||
fn syntax_error() {
|
fn syntax_error() {
|
||||||
let mut runtime = JsRuntime::new(Default::default());
|
let mut runtime = JsRuntime::new(Default::default());
|
||||||
let src = "hocuspocus(";
|
let src = "hocuspocus(";
|
||||||
let r = runtime.execute_script("i.js", src);
|
let r = runtime.execute_script_static("i.js", src);
|
||||||
let e = r.unwrap_err();
|
let e = r.unwrap_err();
|
||||||
let js_error = e.downcast::<JsError>().unwrap();
|
let js_error = e.downcast::<JsError>().unwrap();
|
||||||
let frame = js_error.frames.first().unwrap();
|
let frame = js_error.frames.first().unwrap();
|
||||||
|
@ -3154,7 +3199,7 @@ pub mod tests {
|
||||||
.execute_script(
|
.execute_script(
|
||||||
"encode_decode_test.js",
|
"encode_decode_test.js",
|
||||||
// Note: We make this to_owned because it contains non-ASCII chars
|
// Note: We make this to_owned because it contains non-ASCII chars
|
||||||
include_str!("encode_decode_test.js").to_owned(),
|
include_str!("encode_decode_test.js").to_owned().into(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
if let Poll::Ready(Err(_)) = runtime.poll_event_loop(cx, false) {
|
if let Poll::Ready(Err(_)) = runtime.poll_event_loop(cx, false) {
|
||||||
|
@ -3170,7 +3215,7 @@ pub mod tests {
|
||||||
runtime
|
runtime
|
||||||
.execute_script(
|
.execute_script(
|
||||||
"serialize_deserialize_test.js",
|
"serialize_deserialize_test.js",
|
||||||
include_str!("serialize_deserialize_test.js"),
|
include_ascii_string!("serialize_deserialize_test.js"),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
if let Poll::Ready(Err(_)) = runtime.poll_event_loop(cx, false) {
|
if let Poll::Ready(Err(_)) = runtime.poll_event_loop(cx, false) {
|
||||||
|
@ -3198,7 +3243,7 @@ pub mod tests {
|
||||||
});
|
});
|
||||||
run_in_task(move |cx| {
|
run_in_task(move |cx| {
|
||||||
runtime
|
runtime
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
"error_builder_test.js",
|
"error_builder_test.js",
|
||||||
include_str!("error_builder_test.js"),
|
include_str!("error_builder_test.js"),
|
||||||
)
|
)
|
||||||
|
@ -3216,7 +3261,7 @@ pub mod tests {
|
||||||
will_snapshot: true,
|
will_snapshot: true,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
runtime.execute_script("a.js", "a = 1 + 2").unwrap();
|
runtime.execute_script_static("a.js", "a = 1 + 2").unwrap();
|
||||||
runtime.snapshot()
|
runtime.snapshot()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3226,7 +3271,7 @@ pub mod tests {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
runtime2
|
runtime2
|
||||||
.execute_script("check.js", "if (a != 3) throw Error('x')")
|
.execute_script_static("check.js", "if (a != 3) throw Error('x')")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3237,7 +3282,9 @@ pub mod tests {
|
||||||
will_snapshot: true,
|
will_snapshot: true,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
runtime.execute_script("a.js", "let a = 1 + 2").unwrap();
|
runtime
|
||||||
|
.execute_script_static("a.js", "let a = 1 + 2")
|
||||||
|
.unwrap();
|
||||||
runtime.snapshot()
|
runtime.snapshot()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3250,9 +3297,9 @@ pub mod tests {
|
||||||
|
|
||||||
let startup_data = {
|
let startup_data = {
|
||||||
runtime
|
runtime
|
||||||
.execute_script("check_a.js", "if (a != 3) throw Error('x')")
|
.execute_script_static("check_a.js", "if (a != 3) throw Error('x')")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
runtime.execute_script("b.js", "b = 2 + 3").unwrap();
|
runtime.execute_script_static("b.js", "b = 2 + 3").unwrap();
|
||||||
runtime.snapshot()
|
runtime.snapshot()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3263,10 +3310,10 @@ pub mod tests {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
runtime
|
runtime
|
||||||
.execute_script("check_b.js", "if (b != 5) throw Error('x')")
|
.execute_script_static("check_b.js", "if (b != 5) throw Error('x')")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
runtime
|
runtime
|
||||||
.execute_script("check2.js", "if (!Deno.core) throw Error('x')")
|
.execute_script_static("check2.js", "if (!Deno.core) throw Error('x')")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3279,7 +3326,7 @@ pub mod tests {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
runtime
|
runtime
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
"a.js",
|
"a.js",
|
||||||
r#"
|
r#"
|
||||||
Deno.core.ops.op_set_macrotask_callback(() => {
|
Deno.core.ops.op_set_macrotask_callback(() => {
|
||||||
|
@ -3304,7 +3351,7 @@ pub mod tests {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
runtime2
|
runtime2
|
||||||
.execute_script("check.js", "if (a != 3) throw Error('x')")
|
.execute_script_static("check.js", "if (a != 3) throw Error('x')")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3315,7 +3362,7 @@ pub mod tests {
|
||||||
will_snapshot: true,
|
will_snapshot: true,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
runtime.execute_script("a.js", "a = 1 + 2").unwrap();
|
runtime.execute_script_static("a.js", "a = 1 + 2").unwrap();
|
||||||
let snap: &[u8] = &runtime.snapshot();
|
let snap: &[u8] = &runtime.snapshot();
|
||||||
Vec::from(snap).into_boxed_slice()
|
Vec::from(snap).into_boxed_slice()
|
||||||
};
|
};
|
||||||
|
@ -3326,7 +3373,7 @@ pub mod tests {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
runtime2
|
runtime2
|
||||||
.execute_script("check.js", "if (a != 3) throw Error('x')")
|
.execute_script_static("check.js", "if (a != 3) throw Error('x')")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3351,7 +3398,7 @@ pub mod tests {
|
||||||
fn load(
|
fn load(
|
||||||
&self,
|
&self,
|
||||||
_module_specifier: &ModuleSpecifier,
|
_module_specifier: &ModuleSpecifier,
|
||||||
_maybe_referrer: Option<ModuleSpecifier>,
|
_maybe_referrer: Option<&ModuleSpecifier>,
|
||||||
_is_dyn_import: bool,
|
_is_dyn_import: bool,
|
||||||
) -> Pin<Box<ModuleSourceFuture>> {
|
) -> Pin<Box<ModuleSourceFuture>> {
|
||||||
async { Err(generic_error("Module loading is not supported")) }
|
async { Err(generic_error("Module loading is not supported")) }
|
||||||
|
@ -3366,11 +3413,12 @@ pub mod tests {
|
||||||
});
|
});
|
||||||
|
|
||||||
let specifier = crate::resolve_url("file:///main.js").unwrap();
|
let specifier = crate::resolve_url("file:///main.js").unwrap();
|
||||||
let source_code = r#"
|
let source_code = ascii_str!(
|
||||||
|
r#"
|
||||||
export const a = "b";
|
export const a = "b";
|
||||||
export default 1 + 2;
|
export default 1 + 2;
|
||||||
"#
|
"#
|
||||||
.into();
|
);
|
||||||
|
|
||||||
let module_id = futures::executor::block_on(
|
let module_id = futures::executor::block_on(
|
||||||
runtime.load_main_module(&specifier, Some(source_code)),
|
runtime.load_main_module(&specifier, Some(source_code)),
|
||||||
|
@ -3435,7 +3483,7 @@ pub mod tests {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
let err = runtime
|
let err = runtime
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
"script name",
|
"script name",
|
||||||
r#"let s = ""; while(true) { s += "Hello"; }"#,
|
r#"let s = ""; while(true) { s += "Hello"; }"#,
|
||||||
)
|
)
|
||||||
|
@ -3488,7 +3536,7 @@ pub mod tests {
|
||||||
);
|
);
|
||||||
|
|
||||||
let err = runtime
|
let err = runtime
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
"script name",
|
"script name",
|
||||||
r#"let s = ""; while(true) { s += "Hello"; }"#,
|
r#"let s = ""; while(true) { s += "Hello"; }"#,
|
||||||
)
|
)
|
||||||
|
@ -3520,7 +3568,7 @@ pub mod tests {
|
||||||
fn load(
|
fn load(
|
||||||
&self,
|
&self,
|
||||||
_module_specifier: &ModuleSpecifier,
|
_module_specifier: &ModuleSpecifier,
|
||||||
_maybe_referrer: Option<ModuleSpecifier>,
|
_maybe_referrer: Option<&ModuleSpecifier>,
|
||||||
_is_dyn_import: bool,
|
_is_dyn_import: bool,
|
||||||
) -> Pin<Box<ModuleSourceFuture>> {
|
) -> Pin<Box<ModuleSourceFuture>> {
|
||||||
eprintln!("load() should not be called");
|
eprintln!("load() should not be called");
|
||||||
|
@ -3563,7 +3611,7 @@ pub mod tests {
|
||||||
ModuleInfo {
|
ModuleInfo {
|
||||||
id,
|
id,
|
||||||
main,
|
main,
|
||||||
name: specifier.to_string(),
|
name: specifier.into(),
|
||||||
requests: vec![crate::modules::ModuleRequest {
|
requests: vec![crate::modules::ModuleRequest {
|
||||||
specifier: format!("file:///{prev}.js"),
|
specifier: format!("file:///{prev}.js"),
|
||||||
asserted_module_type: AssertedModuleType::JavaScriptOrWasm,
|
asserted_module_type: AssertedModuleType::JavaScriptOrWasm,
|
||||||
|
@ -3577,7 +3625,13 @@ pub mod tests {
|
||||||
let module_map = module_map_rc.borrow();
|
let module_map = module_map_rc.borrow();
|
||||||
assert_eq!(module_map.handles.len(), modules.len());
|
assert_eq!(module_map.handles.len(), modules.len());
|
||||||
assert_eq!(module_map.info.len(), modules.len());
|
assert_eq!(module_map.info.len(), modules.len());
|
||||||
assert_eq!(module_map.by_name.len(), modules.len());
|
assert_eq!(
|
||||||
|
module_map.by_name(AssertedModuleType::Json).len()
|
||||||
|
+ module_map
|
||||||
|
.by_name(AssertedModuleType::JavaScriptOrWasm)
|
||||||
|
.len(),
|
||||||
|
modules.len()
|
||||||
|
);
|
||||||
|
|
||||||
assert_eq!(module_map.next_load_id, (modules.len() + 1) as ModuleLoadId);
|
assert_eq!(module_map.next_load_id, (modules.len() + 1) as ModuleLoadId);
|
||||||
|
|
||||||
|
@ -3586,8 +3640,8 @@ pub mod tests {
|
||||||
assert_eq!(module_map.info.get(info.id).unwrap(), info);
|
assert_eq!(module_map.info.get(info.id).unwrap(), info);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
module_map
|
module_map
|
||||||
.by_name
|
.by_name(AssertedModuleType::JavaScriptOrWasm)
|
||||||
.get(&(info.name.clone(), AssertedModuleType::JavaScriptOrWasm))
|
.get(&info.name)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
&SymbolicModule::Mod(info.id)
|
&SymbolicModule::Mod(info.id)
|
||||||
);
|
);
|
||||||
|
@ -3610,7 +3664,8 @@ pub mod tests {
|
||||||
});
|
});
|
||||||
|
|
||||||
let specifier = crate::resolve_url("file:///0.js").unwrap();
|
let specifier = crate::resolve_url("file:///0.js").unwrap();
|
||||||
let source_code = r#"export function f0() { return "hello world" }"#.into();
|
let source_code =
|
||||||
|
ascii_str!(r#"export function f0() { return "hello world" }"#);
|
||||||
let id = futures::executor::block_on(
|
let id = futures::executor::block_on(
|
||||||
runtime.load_side_module(&specifier, Some(source_code)),
|
runtime.load_side_module(&specifier, Some(source_code)),
|
||||||
)
|
)
|
||||||
|
@ -3624,7 +3679,7 @@ pub mod tests {
|
||||||
modules.push(ModuleInfo {
|
modules.push(ModuleInfo {
|
||||||
id,
|
id,
|
||||||
main: false,
|
main: false,
|
||||||
name: specifier.to_string(),
|
name: specifier.into(),
|
||||||
requests: vec![],
|
requests: vec![],
|
||||||
module_type: ModuleType::JavaScript,
|
module_type: ModuleType::JavaScript,
|
||||||
});
|
});
|
||||||
|
@ -3668,9 +3723,8 @@ pub mod tests {
|
||||||
let source_code = r#"(async () => {
|
let source_code = r#"(async () => {
|
||||||
const mod = await import("file:///400.js");
|
const mod = await import("file:///400.js");
|
||||||
return mod.f400() + " " + Deno.core.ops.op_test();
|
return mod.f400() + " " + Deno.core.ops.op_test();
|
||||||
})();"#
|
})();"#;
|
||||||
.to_string();
|
let val = runtime3.execute_script_static(".", source_code).unwrap();
|
||||||
let val = runtime3.execute_script(".", source_code).unwrap();
|
|
||||||
let val = futures::executor::block_on(runtime3.resolve_value(val)).unwrap();
|
let val = futures::executor::block_on(runtime3.resolve_value(val)).unwrap();
|
||||||
{
|
{
|
||||||
let scope = &mut runtime3.handle_scope();
|
let scope = &mut runtime3.handle_scope();
|
||||||
|
@ -3684,7 +3738,7 @@ pub mod tests {
|
||||||
fn test_error_without_stack() {
|
fn test_error_without_stack() {
|
||||||
let mut runtime = JsRuntime::new(RuntimeOptions::default());
|
let mut runtime = JsRuntime::new(RuntimeOptions::default());
|
||||||
// SyntaxError
|
// SyntaxError
|
||||||
let result = runtime.execute_script(
|
let result = runtime.execute_script_static(
|
||||||
"error_without_stack.js",
|
"error_without_stack.js",
|
||||||
r#"
|
r#"
|
||||||
function main() {
|
function main() {
|
||||||
|
@ -3701,7 +3755,7 @@ main();
|
||||||
#[test]
|
#[test]
|
||||||
fn test_error_stack() {
|
fn test_error_stack() {
|
||||||
let mut runtime = JsRuntime::new(RuntimeOptions::default());
|
let mut runtime = JsRuntime::new(RuntimeOptions::default());
|
||||||
let result = runtime.execute_script(
|
let result = runtime.execute_script_static(
|
||||||
"error_stack.js",
|
"error_stack.js",
|
||||||
r#"
|
r#"
|
||||||
function assert(cond) {
|
function assert(cond) {
|
||||||
|
@ -3727,7 +3781,7 @@ main();
|
||||||
let mut runtime = JsRuntime::new(RuntimeOptions::default());
|
let mut runtime = JsRuntime::new(RuntimeOptions::default());
|
||||||
run_in_task(move |cx| {
|
run_in_task(move |cx| {
|
||||||
runtime
|
runtime
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
"error_async_stack.js",
|
"error_async_stack.js",
|
||||||
r#"
|
r#"
|
||||||
(async () => {
|
(async () => {
|
||||||
|
@ -3781,7 +3835,7 @@ main();
|
||||||
|
|
||||||
run_in_task(move |cx| {
|
run_in_task(move |cx| {
|
||||||
runtime
|
runtime
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
"test_error_context_sync.js",
|
"test_error_context_sync.js",
|
||||||
r#"
|
r#"
|
||||||
let errMessage;
|
let errMessage;
|
||||||
|
@ -3798,7 +3852,7 @@ if (errMessage !== "higher-level sync error: original sync error") {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let promise = runtime
|
let promise = runtime
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
"test_error_context_async.js",
|
"test_error_context_async.js",
|
||||||
r#"
|
r#"
|
||||||
|
|
||||||
|
@ -3830,7 +3884,7 @@ if (errMessage !== "higher-level sync error: original sync error") {
|
||||||
let mut runtime = JsRuntime::new(RuntimeOptions::default());
|
let mut runtime = JsRuntime::new(RuntimeOptions::default());
|
||||||
run_in_task(move |cx| {
|
run_in_task(move |cx| {
|
||||||
runtime
|
runtime
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
"pump_message_loop.js",
|
"pump_message_loop.js",
|
||||||
r#"
|
r#"
|
||||||
function assertEquals(a, b) {
|
function assertEquals(a, b) {
|
||||||
|
@ -3860,12 +3914,15 @@ assertEquals(1, notify_return_value);
|
||||||
|
|
||||||
// noop script, will resolve promise from first script
|
// noop script, will resolve promise from first script
|
||||||
runtime
|
runtime
|
||||||
.execute_script("pump_message_loop2.js", r#"assertEquals(1, 1);"#)
|
.execute_script_static(
|
||||||
|
"pump_message_loop2.js",
|
||||||
|
r#"assertEquals(1, 1);"#,
|
||||||
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// check that promise from `Atomics.waitAsync` has been resolved
|
// check that promise from `Atomics.waitAsync` has been resolved
|
||||||
runtime
|
runtime
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
"pump_message_loop3.js",
|
"pump_message_loop3.js",
|
||||||
r#"assertEquals(globalThis.resolved, true);"#,
|
r#"assertEquals(globalThis.resolved, true);"#,
|
||||||
)
|
)
|
||||||
|
@ -3878,7 +3935,7 @@ assertEquals(1, notify_return_value);
|
||||||
let mut runtime = JsRuntime::new(RuntimeOptions::default());
|
let mut runtime = JsRuntime::new(RuntimeOptions::default());
|
||||||
// Call non-existent op so we get error from `core.js`
|
// Call non-existent op so we get error from `core.js`
|
||||||
let error = runtime
|
let error = runtime
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
"core_js_stack_frame.js",
|
"core_js_stack_frame.js",
|
||||||
"Deno.core.opAsync('non_existent');",
|
"Deno.core.opAsync('non_existent');",
|
||||||
)
|
)
|
||||||
|
@ -3895,7 +3952,7 @@ assertEquals(1, notify_return_value);
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let mut runtime = JsRuntime::new(options);
|
let mut runtime = JsRuntime::new(options);
|
||||||
runtime.execute_script("<none>", "").unwrap();
|
runtime.execute_script_static("<none>", "").unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[ignore] // TODO(@littledivy): Fast API ops when snapshot is not loaded.
|
#[ignore] // TODO(@littledivy): Fast API ops when snapshot is not loaded.
|
||||||
|
@ -3903,7 +3960,7 @@ assertEquals(1, notify_return_value);
|
||||||
fn test_is_proxy() {
|
fn test_is_proxy() {
|
||||||
let mut runtime = JsRuntime::new(RuntimeOptions::default());
|
let mut runtime = JsRuntime::new(RuntimeOptions::default());
|
||||||
let all_true: v8::Global<v8::Value> = runtime
|
let all_true: v8::Global<v8::Value> = runtime
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
"is_proxy.js",
|
"is_proxy.js",
|
||||||
r#"
|
r#"
|
||||||
(function () {
|
(function () {
|
||||||
|
@ -3951,7 +4008,7 @@ assertEquals(1, notify_return_value);
|
||||||
});
|
});
|
||||||
|
|
||||||
runtime
|
runtime
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
"op_async_borrow.js",
|
"op_async_borrow.js",
|
||||||
"Deno.core.opAsync(\"op_async_borrow\")",
|
"Deno.core.opAsync(\"op_async_borrow\")",
|
||||||
)
|
)
|
||||||
|
@ -3982,7 +4039,7 @@ assertEquals(1, notify_return_value);
|
||||||
});
|
});
|
||||||
|
|
||||||
runtime
|
runtime
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
"op_sync_serialize_object_with_numbers_as_keys.js",
|
"op_sync_serialize_object_with_numbers_as_keys.js",
|
||||||
r#"
|
r#"
|
||||||
Deno.core.ops.op_sync_serialize_object_with_numbers_as_keys({
|
Deno.core.ops.op_sync_serialize_object_with_numbers_as_keys({
|
||||||
|
@ -4024,7 +4081,7 @@ Deno.core.ops.op_sync_serialize_object_with_numbers_as_keys({
|
||||||
});
|
});
|
||||||
|
|
||||||
runtime
|
runtime
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
"op_async_serialize_object_with_numbers_as_keys.js",
|
"op_async_serialize_object_with_numbers_as_keys.js",
|
||||||
r#"
|
r#"
|
||||||
|
|
||||||
|
@ -4060,7 +4117,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
||||||
});
|
});
|
||||||
|
|
||||||
runtime
|
runtime
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
"macrotasks_and_nextticks.js",
|
"macrotasks_and_nextticks.js",
|
||||||
r#"
|
r#"
|
||||||
|
|
||||||
|
@ -4094,7 +4151,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
||||||
let mut runtime = JsRuntime::new(Default::default());
|
let mut runtime = JsRuntime::new(Default::default());
|
||||||
|
|
||||||
runtime
|
runtime
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
"multiple_macrotasks_and_nextticks.js",
|
"multiple_macrotasks_and_nextticks.js",
|
||||||
r#"
|
r#"
|
||||||
Deno.core.ops.op_set_macrotask_callback(() => { return true; });
|
Deno.core.ops.op_set_macrotask_callback(() => { return true; });
|
||||||
|
@ -4137,7 +4194,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
||||||
});
|
});
|
||||||
|
|
||||||
runtime
|
runtime
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
"has_tick_scheduled.js",
|
"has_tick_scheduled.js",
|
||||||
r#"
|
r#"
|
||||||
Deno.core.ops.op_set_macrotask_callback(() => {
|
Deno.core.ops.op_set_macrotask_callback(() => {
|
||||||
|
@ -4208,16 +4265,14 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
||||||
fn load(
|
fn load(
|
||||||
&self,
|
&self,
|
||||||
_module_specifier: &ModuleSpecifier,
|
_module_specifier: &ModuleSpecifier,
|
||||||
_maybe_referrer: Option<ModuleSpecifier>,
|
_maybe_referrer: Option<&ModuleSpecifier>,
|
||||||
_is_dyn_import: bool,
|
_is_dyn_import: bool,
|
||||||
) -> Pin<Box<ModuleSourceFuture>> {
|
) -> Pin<Box<ModuleSourceFuture>> {
|
||||||
async move {
|
async move {
|
||||||
Ok(ModuleSource {
|
Ok(ModuleSource::for_test(
|
||||||
code: b"console.log('hello world');".into(),
|
"console.log('hello world');",
|
||||||
module_url_specified: "file:///main.js".to_string(),
|
"file:///main.js",
|
||||||
module_url_found: "file:///main.js".to_string(),
|
))
|
||||||
module_type: ModuleType::JavaScript,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
.boxed_local()
|
.boxed_local()
|
||||||
}
|
}
|
||||||
|
@ -4230,7 +4285,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
||||||
});
|
});
|
||||||
|
|
||||||
let specifier = crate::resolve_url("file:///main.js").unwrap();
|
let specifier = crate::resolve_url("file:///main.js").unwrap();
|
||||||
let source_code = "Deno.core.print('hello\\n')".into();
|
let source_code = ascii_str!("Deno.core.print('hello\\n')");
|
||||||
|
|
||||||
let module_id = futures::executor::block_on(
|
let module_id = futures::executor::block_on(
|
||||||
runtime.load_main_module(&specifier, Some(source_code)),
|
runtime.load_main_module(&specifier, Some(source_code)),
|
||||||
|
@ -4264,7 +4319,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
||||||
});
|
});
|
||||||
|
|
||||||
runtime
|
runtime
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
"promise_reject_callback.js",
|
"promise_reject_callback.js",
|
||||||
r#"
|
r#"
|
||||||
// Note: |promise| is not the promise created below, it's a child.
|
// Note: |promise| is not the promise created below, it's a child.
|
||||||
|
@ -4287,7 +4342,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
||||||
assert_eq!(1, PROMISE_REJECT.load(Ordering::Relaxed));
|
assert_eq!(1, PROMISE_REJECT.load(Ordering::Relaxed));
|
||||||
|
|
||||||
runtime
|
runtime
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
"promise_reject_callback.js",
|
"promise_reject_callback.js",
|
||||||
r#"
|
r#"
|
||||||
{
|
{
|
||||||
|
@ -4332,7 +4387,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
||||||
}});
|
}});
|
||||||
Deno.core.opAsync("op_void_async").then(() => Promise.reject({number}));
|
Deno.core.opAsync("op_void_async").then(() => Promise.reject({number}));
|
||||||
"#
|
"#
|
||||||
)
|
).into()
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
@ -4341,7 +4396,11 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
||||||
|
|
||||||
for (realm, realm_name, number) in realm_expectations {
|
for (realm, realm_name, number) in realm_expectations {
|
||||||
let reject_value = realm
|
let reject_value = realm
|
||||||
.execute_script(runtime.v8_isolate(), "", "globalThis.rejectValue")
|
.execute_script_static(
|
||||||
|
runtime.v8_isolate(),
|
||||||
|
"",
|
||||||
|
"globalThis.rejectValue",
|
||||||
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let scope = &mut realm.handle_scope(runtime.v8_isolate());
|
let scope = &mut realm.handle_scope(runtime.v8_isolate());
|
||||||
let reject_value = v8::Local::new(scope, reject_value);
|
let reject_value = v8::Local::new(scope, reject_value);
|
||||||
|
@ -4382,24 +4441,17 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
||||||
fn load(
|
fn load(
|
||||||
&self,
|
&self,
|
||||||
_module_specifier: &ModuleSpecifier,
|
_module_specifier: &ModuleSpecifier,
|
||||||
_maybe_referrer: Option<ModuleSpecifier>,
|
_maybe_referrer: Option<&ModuleSpecifier>,
|
||||||
_is_dyn_import: bool,
|
_is_dyn_import: bool,
|
||||||
) -> Pin<Box<ModuleSourceFuture>> {
|
) -> Pin<Box<ModuleSourceFuture>> {
|
||||||
let source = r#"
|
let code = r#"
|
||||||
Deno.core.ops.op_set_promise_reject_callback((type, promise, reason) => {
|
Deno.core.ops.op_set_promise_reject_callback((type, promise, reason) => {
|
||||||
Deno.core.ops.op_promise_reject();
|
Deno.core.ops.op_promise_reject();
|
||||||
});
|
});
|
||||||
throw new Error('top level throw');
|
throw new Error('top level throw');
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
async move {
|
async move { Ok(ModuleSource::for_test(code, "file:///main.js")) }
|
||||||
Ok(ModuleSource {
|
|
||||||
code: source.into(),
|
|
||||||
module_url_specified: "file:///main.js".to_string(),
|
|
||||||
module_url_found: "file:///main.js".to_string(),
|
|
||||||
module_type: ModuleType::JavaScript,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
.boxed_local()
|
.boxed_local()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4434,7 +4486,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
assert!(runtime
|
assert!(runtime
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
"test_op_return_serde_v8_error.js",
|
"test_op_return_serde_v8_error.js",
|
||||||
"Deno.core.ops.op_err()"
|
"Deno.core.ops.op_err()"
|
||||||
)
|
)
|
||||||
|
@ -4459,7 +4511,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
let r = runtime
|
let r = runtime
|
||||||
.execute_script("test.js", "Deno.core.ops.op_add_4(1, 2, 3, 4)")
|
.execute_script_static("test.js", "Deno.core.ops.op_add_4(1, 2, 3, 4)")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let scope = &mut runtime.handle_scope();
|
let scope = &mut runtime.handle_scope();
|
||||||
assert_eq!(r.open(scope).integer_value(scope), Some(10));
|
assert_eq!(r.open(scope).integer_value(scope), Some(10));
|
||||||
|
@ -4482,7 +4534,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
let r = runtime
|
let r = runtime
|
||||||
.execute_script("test.js", "Deno.core.ops.op_foo()")
|
.execute_script_static("test.js", "Deno.core.ops.op_foo()")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let scope = &mut runtime.handle_scope();
|
let scope = &mut runtime.handle_scope();
|
||||||
assert!(r.open(scope).is_undefined());
|
assert!(r.open(scope).is_undefined());
|
||||||
|
@ -4511,7 +4563,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
||||||
});
|
});
|
||||||
|
|
||||||
runtime
|
runtime
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
"test.js",
|
"test.js",
|
||||||
r#"
|
r#"
|
||||||
const a1 = new Uint8Array([1,2,3]);
|
const a1 = new Uint8Array([1,2,3]);
|
||||||
|
@ -4579,7 +4631,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
runtime
|
runtime
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
"test.js",
|
"test.js",
|
||||||
r#"
|
r#"
|
||||||
if (Deno.core.ops.op_foo() !== 42) {
|
if (Deno.core.ops.op_foo() !== 42) {
|
||||||
|
@ -4607,9 +4659,9 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
||||||
assert_ne!(realm.context(), &main_context);
|
assert_ne!(realm.context(), &main_context);
|
||||||
assert_ne!(realm.global_object(runtime.v8_isolate()), main_global);
|
assert_ne!(realm.global_object(runtime.v8_isolate()), main_global);
|
||||||
|
|
||||||
let main_object = runtime.execute_script("", "Object").unwrap();
|
let main_object = runtime.execute_script_static("", "Object").unwrap();
|
||||||
let realm_object = realm
|
let realm_object = realm
|
||||||
.execute_script(runtime.v8_isolate(), "", "Object")
|
.execute_script_static(runtime.v8_isolate(), "", "Object")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_ne!(main_object, realm_object);
|
assert_ne!(main_object, realm_object);
|
||||||
}
|
}
|
||||||
|
@ -4628,7 +4680,11 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
||||||
});
|
});
|
||||||
let realm = runtime.create_realm().unwrap();
|
let realm = runtime.create_realm().unwrap();
|
||||||
let ret = realm
|
let ret = realm
|
||||||
.execute_script(runtime.v8_isolate(), "", "Deno.core.ops.op_test()")
|
.execute_script_static(
|
||||||
|
runtime.v8_isolate(),
|
||||||
|
"",
|
||||||
|
"Deno.core.ops.op_test()",
|
||||||
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let scope = &mut realm.handle_scope(runtime.v8_isolate());
|
let scope = &mut realm.handle_scope(runtime.v8_isolate());
|
||||||
|
@ -4665,7 +4721,11 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
||||||
});
|
});
|
||||||
let realm = runtime.create_realm().unwrap();
|
let realm = runtime.create_realm().unwrap();
|
||||||
let ret = realm
|
let ret = realm
|
||||||
.execute_script(runtime.v8_isolate(), "", "Deno.core.ops.op_test()")
|
.execute_script_static(
|
||||||
|
runtime.v8_isolate(),
|
||||||
|
"",
|
||||||
|
"Deno.core.ops.op_test()",
|
||||||
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let scope = &mut realm.handle_scope(runtime.v8_isolate());
|
let scope = &mut realm.handle_scope(runtime.v8_isolate());
|
||||||
|
@ -4701,7 +4761,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
||||||
// Test in both realms
|
// Test in both realms
|
||||||
for realm in [runtime.global_realm(), new_realm].into_iter() {
|
for realm in [runtime.global_realm(), new_realm].into_iter() {
|
||||||
let ret = realm
|
let ret = realm
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
runtime.v8_isolate(),
|
runtime.v8_isolate(),
|
||||||
"",
|
"",
|
||||||
r#"
|
r#"
|
||||||
|
@ -4753,7 +4813,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
||||||
// Test in both realms
|
// Test in both realms
|
||||||
for realm in [global_realm, new_realm].into_iter() {
|
for realm in [global_realm, new_realm].into_iter() {
|
||||||
let ret = realm
|
let ret = realm
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
runtime.v8_isolate(),
|
runtime.v8_isolate(),
|
||||||
"",
|
"",
|
||||||
r#"
|
r#"
|
||||||
|
@ -4806,7 +4866,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
||||||
let other_realm = runtime.create_realm().unwrap();
|
let other_realm = runtime.create_realm().unwrap();
|
||||||
|
|
||||||
main_realm
|
main_realm
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
runtime.v8_isolate(),
|
runtime.v8_isolate(),
|
||||||
"",
|
"",
|
||||||
r#"
|
r#"
|
||||||
|
@ -4816,7 +4876,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
other_realm
|
other_realm
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
runtime.v8_isolate(),
|
runtime.v8_isolate(),
|
||||||
"",
|
"",
|
||||||
r#"
|
r#"
|
||||||
|
@ -4828,7 +4888,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
||||||
assert!(matches!(runtime.poll_event_loop(cx, false), Poll::Pending));
|
assert!(matches!(runtime.poll_event_loop(cx, false), Poll::Pending));
|
||||||
|
|
||||||
main_realm
|
main_realm
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
runtime.v8_isolate(),
|
runtime.v8_isolate(),
|
||||||
"",
|
"",
|
||||||
r#"
|
r#"
|
||||||
|
@ -4840,7 +4900,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
||||||
assert!(matches!(runtime.poll_event_loop(cx, false), Poll::Pending));
|
assert!(matches!(runtime.poll_event_loop(cx, false), Poll::Pending));
|
||||||
|
|
||||||
other_realm
|
other_realm
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
runtime.v8_isolate(),
|
runtime.v8_isolate(),
|
||||||
"",
|
"",
|
||||||
r#"
|
r#"
|
||||||
|
@ -4861,7 +4921,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
||||||
// Verify that "array by copy" proposal is enabled (https://github.com/tc39/proposal-change-array-by-copy)
|
// Verify that "array by copy" proposal is enabled (https://github.com/tc39/proposal-change-array-by-copy)
|
||||||
let mut runtime = JsRuntime::new(Default::default());
|
let mut runtime = JsRuntime::new(Default::default());
|
||||||
assert!(runtime
|
assert!(runtime
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
"test_array_by_copy.js",
|
"test_array_by_copy.js",
|
||||||
"const a = [1, 2, 3];
|
"const a = [1, 2, 3];
|
||||||
const b = a.toReversed();
|
const b = a.toReversed();
|
||||||
|
@ -4880,7 +4940,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
||||||
// Verify that "resizable ArrayBuffer" is disabled
|
// Verify that "resizable ArrayBuffer" is disabled
|
||||||
let mut runtime = JsRuntime::new(Default::default());
|
let mut runtime = JsRuntime::new(Default::default());
|
||||||
runtime
|
runtime
|
||||||
.execute_script(
|
.execute_script_static(
|
||||||
"test_rab.js",
|
"test_rab.js",
|
||||||
r#"const a = new ArrayBuffer(100, {maxByteLength: 200});
|
r#"const a = new ArrayBuffer(100, {maxByteLength: 200});
|
||||||
if (a.byteLength !== 100) {
|
if (a.byteLength !== 100) {
|
||||||
|
@ -4916,23 +4976,16 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
||||||
fn load(
|
fn load(
|
||||||
&self,
|
&self,
|
||||||
_module_specifier: &ModuleSpecifier,
|
_module_specifier: &ModuleSpecifier,
|
||||||
_maybe_referrer: Option<ModuleSpecifier>,
|
_maybe_referrer: Option<&ModuleSpecifier>,
|
||||||
_is_dyn_import: bool,
|
_is_dyn_import: bool,
|
||||||
) -> Pin<Box<ModuleSourceFuture>> {
|
) -> Pin<Box<ModuleSourceFuture>> {
|
||||||
let source = r#"
|
let code = 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 "ext:".
|
// an error when specifier starts with "ext:".
|
||||||
import { core } from "ext:core.js";
|
import { core } from "ext:core.js";
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
async move {
|
async move { Ok(ModuleSource::for_test(code, "file:///main.js")) }
|
||||||
Ok(ModuleSource {
|
|
||||||
code: source.into(),
|
|
||||||
module_url_specified: "file:///main.js".to_string(),
|
|
||||||
module_url_found: "file:///main.js".to_string(),
|
|
||||||
module_type: ModuleType::JavaScript,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
.boxed_local()
|
.boxed_local()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -447,7 +447,7 @@ pub fn initialize_runtime(
|
||||||
argv0
|
argv0
|
||||||
);
|
);
|
||||||
|
|
||||||
js_runtime.execute_script(located_script_name!(), source_code)?;
|
js_runtime.execute_script(located_script_name!(), source_code.into())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -468,7 +468,8 @@ pub fn load_cjs_module(
|
||||||
main = main,
|
main = main,
|
||||||
module = escape_for_single_quote_string(module),
|
module = escape_for_single_quote_string(module),
|
||||||
inspect_brk = inspect_brk,
|
inspect_brk = inspect_brk,
|
||||||
);
|
)
|
||||||
|
.into();
|
||||||
|
|
||||||
js_runtime.execute_script(located_script_name!(), source_code)?;
|
js_runtime.execute_script(located_script_name!(), source_code)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -42,7 +42,7 @@ mod startup_snapshot {
|
||||||
|
|
||||||
let parsed = deno_ast::parse_module(ParseParams {
|
let parsed = deno_ast::parse_module(ParseParams {
|
||||||
specifier: file_source.specifier.to_string(),
|
specifier: file_source.specifier.to_string(),
|
||||||
text_info: SourceTextInfo::from_string(code.take_as_string()),
|
text_info: SourceTextInfo::from_string(code.as_str().to_owned()),
|
||||||
media_type,
|
media_type,
|
||||||
capture_tokens: false,
|
capture_tokens: false,
|
||||||
scope_analysis: false,
|
scope_analysis: false,
|
||||||
|
|
|
@ -9,6 +9,7 @@ use crate::BootstrapOptions;
|
||||||
use deno_broadcast_channel::InMemoryBroadcastChannel;
|
use deno_broadcast_channel::InMemoryBroadcastChannel;
|
||||||
use deno_cache::CreateCache;
|
use deno_cache::CreateCache;
|
||||||
use deno_cache::SqliteBackedCache;
|
use deno_cache::SqliteBackedCache;
|
||||||
|
use deno_core::ascii_str;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::error::JsError;
|
use deno_core::error::JsError;
|
||||||
use deno_core::futures::channel::mpsc;
|
use deno_core::futures::channel::mpsc;
|
||||||
|
@ -572,11 +573,13 @@ impl WebWorker {
|
||||||
// TODO(bartlomieju): this could be done using V8 API, without calling `execute_script`.
|
// TODO(bartlomieju): this could be done using V8 API, without calling `execute_script`.
|
||||||
// Save a reference to function that will start polling for messages
|
// Save a reference to function that will start polling for messages
|
||||||
// from a worker host; it will be called after the user code is loaded.
|
// from a worker host; it will be called after the user code is loaded.
|
||||||
let script = r#"
|
let script = ascii_str!(
|
||||||
|
r#"
|
||||||
const pollForMessages = globalThis.pollForMessages;
|
const pollForMessages = globalThis.pollForMessages;
|
||||||
delete globalThis.pollForMessages;
|
delete globalThis.pollForMessages;
|
||||||
pollForMessages
|
pollForMessages
|
||||||
"#;
|
"#
|
||||||
|
);
|
||||||
let poll_for_messages_fn = self
|
let poll_for_messages_fn = self
|
||||||
.js_runtime
|
.js_runtime
|
||||||
.execute_script(located_script_name!(), script)
|
.execute_script(located_script_name!(), script)
|
||||||
|
@ -585,10 +588,10 @@ impl WebWorker {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See [JsRuntime::execute_script](deno_core::JsRuntime::execute_script)
|
/// See [JsRuntime::execute_script](deno_core::JsRuntime::execute_script)
|
||||||
pub fn execute_script<S: Into<ModuleCode>>(
|
pub fn execute_script(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
source_code: S,
|
source_code: ModuleCode,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
self.js_runtime.execute_script(name, source_code)?;
|
self.js_runtime.execute_script(name, source_code)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -777,7 +780,7 @@ pub fn run_web_worker(
|
||||||
|
|
||||||
// Execute provided source code immediately
|
// Execute provided source code immediately
|
||||||
let result = if let Some(source_code) = maybe_source_code.take() {
|
let result = if let Some(source_code) = maybe_source_code.take() {
|
||||||
let r = worker.execute_script(located_script_name!(), source_code);
|
let r = worker.execute_script(located_script_name!(), source_code.into());
|
||||||
worker.start_polling_for_messages();
|
worker.start_polling_for_messages();
|
||||||
r
|
r
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -11,6 +11,7 @@ use std::task::Poll;
|
||||||
use deno_broadcast_channel::InMemoryBroadcastChannel;
|
use deno_broadcast_channel::InMemoryBroadcastChannel;
|
||||||
use deno_cache::CreateCache;
|
use deno_cache::CreateCache;
|
||||||
use deno_cache::SqliteBackedCache;
|
use deno_cache::SqliteBackedCache;
|
||||||
|
use deno_core::ascii_str;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::error::JsError;
|
use deno_core::error::JsError;
|
||||||
use deno_core::futures::Future;
|
use deno_core::futures::Future;
|
||||||
|
@ -370,10 +371,10 @@ impl MainWorker {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See [JsRuntime::execute_script](deno_core::JsRuntime::execute_script)
|
/// See [JsRuntime::execute_script](deno_core::JsRuntime::execute_script)
|
||||||
pub fn execute_script<S: Into<ModuleCode>>(
|
pub fn execute_script(
|
||||||
&mut self,
|
&mut self,
|
||||||
script_name: &'static str,
|
script_name: &'static str,
|
||||||
source_code: S,
|
source_code: ModuleCode,
|
||||||
) -> Result<v8::Global<v8::Value>, AnyError> {
|
) -> Result<v8::Global<v8::Value>, AnyError> {
|
||||||
self.js_runtime.execute_script(script_name, source_code)
|
self.js_runtime.execute_script(script_name, source_code)
|
||||||
}
|
}
|
||||||
|
@ -510,12 +511,12 @@ impl MainWorker {
|
||||||
&mut self,
|
&mut self,
|
||||||
script_name: &'static str,
|
script_name: &'static str,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
self.execute_script(
|
self.js_runtime.execute_script(
|
||||||
script_name,
|
script_name,
|
||||||
// NOTE(@bartlomieju): not using `globalThis` here, because user might delete
|
// NOTE(@bartlomieju): not using `globalThis` here, because user might delete
|
||||||
// it. Instead we're using global `dispatchEvent` function which will
|
// it. Instead we're using global `dispatchEvent` function which will
|
||||||
// used a saved reference to global scope.
|
// used a saved reference to global scope.
|
||||||
"dispatchEvent(new Event('load'))",
|
ascii_str!("dispatchEvent(new Event('load'))"),
|
||||||
)?;
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -527,12 +528,12 @@ impl MainWorker {
|
||||||
&mut self,
|
&mut self,
|
||||||
script_name: &'static str,
|
script_name: &'static str,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
self.execute_script(
|
self.js_runtime.execute_script(
|
||||||
script_name,
|
script_name,
|
||||||
// NOTE(@bartlomieju): not using `globalThis` here, because user might delete
|
// NOTE(@bartlomieju): not using `globalThis` here, because user might delete
|
||||||
// it. Instead we're using global `dispatchEvent` function which will
|
// it. Instead we're using global `dispatchEvent` function which will
|
||||||
// used a saved reference to global scope.
|
// used a saved reference to global scope.
|
||||||
"dispatchEvent(new Event('unload'))",
|
ascii_str!("dispatchEvent(new Event('unload'))"),
|
||||||
)?;
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -549,7 +550,9 @@ impl MainWorker {
|
||||||
// NOTE(@bartlomieju): not using `globalThis` here, because user might delete
|
// NOTE(@bartlomieju): not using `globalThis` here, because user might delete
|
||||||
// it. Instead we're using global `dispatchEvent` function which will
|
// it. Instead we're using global `dispatchEvent` function which will
|
||||||
// used a saved reference to global scope.
|
// used a saved reference to global scope.
|
||||||
"dispatchEvent(new Event('beforeunload', { cancelable: true }));",
|
ascii_str!(
|
||||||
|
"dispatchEvent(new Event('beforeunload', { cancelable: true }));"
|
||||||
|
),
|
||||||
)?;
|
)?;
|
||||||
let local_value = value.open(&mut self.js_runtime.handle_scope());
|
let local_value = value.open(&mut self.js_runtime.handle_scope());
|
||||||
Ok(local_value.is_false())
|
Ok(local_value.is_false())
|
||||||
|
|
Loading…
Reference in a new issue