mirror of
https://github.com/denoland/deno.git
synced 2024-11-24 15:19:26 -05: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
27 changed files with 817 additions and 641 deletions
|
@ -117,6 +117,6 @@ pub fn bench_js_async_with(
|
|||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ mod tests {
|
|||
..Default::default()
|
||||
});
|
||||
js_runtime
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
"<anon>",
|
||||
r#"
|
||||
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_src = format!("globalThis.serverInit({init_config});");
|
||||
|
||||
runtime.execute_script(located_script_name!(), init_src)?;
|
||||
runtime.execute_script(located_script_name!(), init_src.into())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -3493,7 +3493,7 @@ pub fn request(
|
|||
};
|
||||
let mark = performance.mark("request", Some(request_params.clone()));
|
||||
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 mut op_state = op_state.borrow_mut();
|
||||
|
|
|
@ -78,7 +78,7 @@ impl CliModuleLoader {
|
|||
fn load_prepared_module(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
maybe_referrer: Option<ModuleSpecifier>,
|
||||
maybe_referrer: Option<&ModuleSpecifier>,
|
||||
) -> Result<ModuleCodeSource, AnyError> {
|
||||
if specifier.scheme() == "node" {
|
||||
unreachable!(); // Node built-in modules should be handled internally.
|
||||
|
@ -92,7 +92,7 @@ impl CliModuleLoader {
|
|||
specifier,
|
||||
..
|
||||
})) => Ok(ModuleCodeSource {
|
||||
code: source.into(),
|
||||
code: source.clone().into(),
|
||||
found_url: specifier.clone(),
|
||||
media_type: *media_type,
|
||||
}),
|
||||
|
@ -107,7 +107,7 @@ impl CliModuleLoader {
|
|||
| MediaType::Unknown
|
||||
| MediaType::Cjs
|
||||
| MediaType::Mjs
|
||||
| MediaType::Json => source.into(),
|
||||
| MediaType::Json => source.clone().into(),
|
||||
MediaType::Dts | MediaType::Dcts | MediaType::Dmts => {
|
||||
Default::default()
|
||||
}
|
||||
|
@ -154,7 +154,7 @@ impl CliModuleLoader {
|
|||
fn load_sync(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
maybe_referrer: Option<ModuleSpecifier>,
|
||||
maybe_referrer: Option<&ModuleSpecifier>,
|
||||
is_dynamic: bool,
|
||||
) -> Result<ModuleSource, AnyError> {
|
||||
let code_source = if self.ps.npm_resolver.in_npm_package(specifier) {
|
||||
|
@ -210,15 +210,15 @@ impl CliModuleLoader {
|
|||
// because we don't need it
|
||||
code_without_source_map(code_source.code)
|
||||
};
|
||||
Ok(ModuleSource {
|
||||
code,
|
||||
module_url_specified: specifier.to_string(),
|
||||
module_url_found: code_source.found_url.to_string(),
|
||||
module_type: match code_source.media_type {
|
||||
Ok(ModuleSource::new_with_redirect(
|
||||
match code_source.media_type {
|
||||
MediaType::Json => ModuleType::Json,
|
||||
_ => ModuleType::JavaScript,
|
||||
},
|
||||
})
|
||||
code,
|
||||
specifier,
|
||||
&code_source.found_url,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -240,7 +240,7 @@ impl ModuleLoader for CliModuleLoader {
|
|||
fn load(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
maybe_referrer: Option<ModuleSpecifier>,
|
||||
maybe_referrer: Option<&ModuleSpecifier>,
|
||||
is_dynamic: bool,
|
||||
) -> Pin<Box<deno_core::ModuleSourceFuture>> {
|
||||
// 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::ModuleLoader;
|
||||
use deno_core::ModuleSpecifier;
|
||||
use deno_core::ModuleType;
|
||||
use deno_core::ResolutionKind;
|
||||
use deno_graph::source::Resolver;
|
||||
use deno_runtime::fmt_errors::format_js_error;
|
||||
|
@ -165,7 +166,7 @@ impl ModuleLoader for EmbeddedModuleLoader {
|
|||
fn load(
|
||||
&self,
|
||||
module_specifier: &ModuleSpecifier,
|
||||
_maybe_referrer: Option<ModuleSpecifier>,
|
||||
_maybe_referrer: Option<&ModuleSpecifier>,
|
||||
_is_dynamic: bool,
|
||||
) -> Pin<Box<deno_core::ModuleSourceFuture>> {
|
||||
let is_data_uri = get_source_from_data_url(module_specifier).ok();
|
||||
|
@ -173,33 +174,33 @@ impl ModuleLoader for EmbeddedModuleLoader {
|
|||
.eszip
|
||||
.get_module(module_specifier.as_str())
|
||||
.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();
|
||||
|
||||
async move {
|
||||
if let Some((source, _)) = is_data_uri {
|
||||
return Ok(deno_core::ModuleSource {
|
||||
code: source.into(),
|
||||
module_type: deno_core::ModuleType::JavaScript,
|
||||
module_url_specified: module_specifier.to_string(),
|
||||
module_url_found: module_specifier.to_string(),
|
||||
});
|
||||
return Ok(deno_core::ModuleSource::new(
|
||||
deno_core::ModuleType::JavaScript,
|
||||
source.into(),
|
||||
&module_specifier,
|
||||
));
|
||||
}
|
||||
|
||||
let module = module?;
|
||||
let code = module.source().await;
|
||||
let code = std::str::from_utf8(&code)
|
||||
.map_err(|_| type_error("Module source is not utf-8"))?
|
||||
.to_owned();
|
||||
.to_owned()
|
||||
.into();
|
||||
|
||||
Ok(deno_core::ModuleSource {
|
||||
code: code.into(),
|
||||
module_type: match module.kind {
|
||||
eszip::ModuleKind::JavaScript => deno_core::ModuleType::JavaScript,
|
||||
eszip::ModuleKind::Json => deno_core::ModuleType::Json,
|
||||
Ok(deno_core::ModuleSource::new(
|
||||
match module.kind {
|
||||
eszip::ModuleKind::JavaScript => ModuleType::JavaScript,
|
||||
eszip::ModuleKind::Json => ModuleType::Json,
|
||||
},
|
||||
module_url_specified: module_specifier.to_string(),
|
||||
module_url_found: module_specifier.to_string(),
|
||||
})
|
||||
code,
|
||||
&module_specifier,
|
||||
))
|
||||
}
|
||||
.boxed_local()
|
||||
}
|
||||
|
|
|
@ -691,7 +691,7 @@ pub async fn cover_files(
|
|||
| MediaType::Unknown
|
||||
| MediaType::Cjs
|
||||
| MediaType::Mjs
|
||||
| MediaType::Json => file.source.into(),
|
||||
| MediaType::Json => file.source.clone().into(),
|
||||
MediaType::Dts | MediaType::Dmts | MediaType::Dcts => Default::default(),
|
||||
MediaType::TypeScript
|
||||
| MediaType::Jsx
|
||||
|
@ -718,7 +718,7 @@ pub async fn cover_files(
|
|||
let source_map = source_map_from_code(&transpiled_code);
|
||||
let coverage_report = generate_coverage_report(
|
||||
&script_coverage,
|
||||
transpiled_code.take_as_string(),
|
||||
transpiled_code.as_str().to_owned(),
|
||||
&source_map,
|
||||
&out_mode,
|
||||
);
|
||||
|
|
|
@ -13,6 +13,7 @@ use crate::util::path::mapped_specifier_for_tsc;
|
|||
use deno_ast::MediaType;
|
||||
use deno_core::anyhow::anyhow;
|
||||
use deno_core::anyhow::Context;
|
||||
use deno_core::ascii_str;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::located_script_name;
|
||||
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()],
|
||||
..Default::default()
|
||||
});
|
||||
let global =
|
||||
runtime.execute_script("get_assets.js", "globalThis.getAssets()")?;
|
||||
let global = runtime
|
||||
.execute_script("get_assets.js", ascii_str!("globalThis.getAssets()"))?;
|
||||
let scope = &mut runtime.handle_scope();
|
||||
let local = deno_core::v8::Local::new(scope, global);
|
||||
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!({
|
||||
"config": request.config,
|
||||
"debug": request.debug,
|
||||
"rootNames": root_names,
|
||||
"localOnly": request.check_mode == TypeCheckMode::Local,
|
||||
});
|
||||
let request_str = request_value.to_string();
|
||||
let exec_source = format!("globalThis.exec({request_str})");
|
||||
let exec_source = format!("globalThis.exec({request_value})").into();
|
||||
|
||||
let mut runtime = JsRuntime::new(RuntimeOptions {
|
||||
startup_snapshot: Some(compiler_snapshot()),
|
||||
|
@ -974,7 +974,7 @@ mod tests {
|
|||
..Default::default()
|
||||
});
|
||||
js_runtime
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
"<anon>",
|
||||
r#"
|
||||
if (!(startup)) {
|
||||
|
|
|
@ -160,7 +160,9 @@ mod tests {
|
|||
|
||||
fn run_test(input: &'static str, output: &'static str) {
|
||||
assert_eq!(
|
||||
code_without_source_map(input.into()).take_as_string(),
|
||||
code_without_source_map(ModuleCode::from_static(input))
|
||||
.as_str()
|
||||
.to_owned(),
|
||||
output
|
||||
);
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ use std::rc::Rc;
|
|||
use std::sync::Arc;
|
||||
|
||||
use deno_ast::ModuleSpecifier;
|
||||
use deno_core::ascii_str;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::futures::task::LocalFutureObj;
|
||||
use deno_core::futures::FutureExt;
|
||||
|
@ -184,7 +185,7 @@ impl CliMainWorker {
|
|||
// Enable op call tracing in core to enable better debugging of op sanitizer
|
||||
// failures.
|
||||
if self.ps.options.trace_ops() {
|
||||
self.worker.js_runtime.execute_script(
|
||||
self.worker.js_runtime.execute_script_static(
|
||||
located_script_name!(),
|
||||
"Deno[Deno.internal].core.enableOpCallTracing();",
|
||||
)?;
|
||||
|
@ -231,7 +232,7 @@ impl CliMainWorker {
|
|||
|
||||
self.worker.execute_script(
|
||||
located_script_name!(),
|
||||
"Deno[Deno.internal].core.enableOpCallTracing();",
|
||||
ascii_str!("Deno[Deno.internal].core.enableOpCallTracing();"),
|
||||
)?;
|
||||
|
||||
if mode != TestMode::Documentation {
|
||||
|
|
|
@ -345,7 +345,7 @@ pub extern "C" fn host_initialize_import_meta_object_callback(
|
|||
.expect("Module not found");
|
||||
|
||||
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());
|
||||
|
||||
let main_key =
|
||||
|
@ -616,7 +616,7 @@ pub fn module_resolve_callback<'s>(
|
|||
let referrer_info = module_map
|
||||
.get_info(&referrer_global)
|
||||
.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);
|
||||
|
||||
|
@ -628,7 +628,7 @@ pub fn module_resolve_callback<'s>(
|
|||
let maybe_module = module_map.resolve_callback(
|
||||
scope,
|
||||
&specifier_str,
|
||||
&referrer_name,
|
||||
referrer_name,
|
||||
assertions,
|
||||
);
|
||||
if let Some(module) = maybe_module {
|
||||
|
|
|
@ -22,6 +22,6 @@ fn main() {
|
|||
|
||||
// Deno.core.print() will now be a NOP
|
||||
runtime
|
||||
.execute_script("<usage>", r#"Deno.core.print("I'm broken")"#)
|
||||
.execute_script_static("<usage>", r#"Deno.core.print("I'm broken")"#)
|
||||
.unwrap();
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ fn eval(
|
|||
context: &mut JsRuntime,
|
||||
code: &'static str,
|
||||
) -> Result<serde_json::Value, String> {
|
||||
let res = context.execute_script("<anon>", code);
|
||||
let res = context.execute_script_static("<anon>", code);
|
||||
match res {
|
||||
Ok(global) => {
|
||||
let scope = &mut context.handle_scope();
|
||||
|
|
|
@ -41,7 +41,7 @@ fn main() {
|
|||
// contains a Deno.core object with several functions for interacting with it.
|
||||
// You can find its definition in core.js.
|
||||
runtime
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
"<usage>",
|
||||
r#"
|
||||
// Print helper function, calling Deno.core.print()
|
||||
|
|
|
@ -165,7 +165,7 @@ fn main() {
|
|||
js_runtime
|
||||
.execute_script(
|
||||
"http_bench_json_ops.js",
|
||||
include_str!("http_bench_json_ops.js"),
|
||||
include_ascii_string!("http_bench_json_ops.js"),
|
||||
)
|
||||
.unwrap();
|
||||
js_runtime.run_event_loop(false).await
|
||||
|
|
|
@ -31,6 +31,6 @@ fn main() {
|
|||
extensions,
|
||||
..Default::default()
|
||||
});
|
||||
rt.execute_script("panik", "Deno.core.ops.op_panik()")
|
||||
rt.execute_script_static("panik", "Deno.core.ops.op_panik()")
|
||||
.unwrap();
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ fn main() {
|
|||
let future = async move {
|
||||
// Schedule 10 tasks.
|
||||
js_runtime
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
"<usage>",
|
||||
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::ParseParams;
|
||||
use deno_ast::SourceTextInfo;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::resolve_import;
|
||||
use deno_core::resolve_path;
|
||||
use deno_core::JsRuntime;
|
||||
|
@ -41,11 +42,12 @@ impl ModuleLoader for TypescriptModuleLoader {
|
|||
fn load(
|
||||
&self,
|
||||
module_specifier: &ModuleSpecifier,
|
||||
_maybe_referrer: Option<ModuleSpecifier>,
|
||||
_maybe_referrer: Option<&ModuleSpecifier>,
|
||||
_is_dyn_import: bool,
|
||||
) -> Pin<Box<ModuleSourceFuture>> {
|
||||
let module_specifier = module_specifier.clone();
|
||||
async move {
|
||||
fn load(
|
||||
module_specifier: &ModuleSpecifier,
|
||||
) -> Result<ModuleSource, AnyError> {
|
||||
let path = module_specifier
|
||||
.to_file_path()
|
||||
.map_err(|_| anyhow!("Only file:// URLs are supported."))?;
|
||||
|
@ -81,15 +83,14 @@ impl ModuleLoader for TypescriptModuleLoader {
|
|||
} else {
|
||||
code
|
||||
};
|
||||
let module = ModuleSource {
|
||||
code: code.into(),
|
||||
Ok(ModuleSource::new(
|
||||
module_type,
|
||||
module_url_specified: module_specifier.to_string(),
|
||||
module_url_found: module_specifier.to_string(),
|
||||
};
|
||||
Ok(module)
|
||||
code.into(),
|
||||
module_specifier,
|
||||
))
|
||||
}
|
||||
.boxed_local()
|
||||
|
||||
futures::future::ready(load(module_specifier)).boxed_local()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -62,6 +62,6 @@ fn main() {
|
|||
});
|
||||
|
||||
runtime
|
||||
.execute_script("<usage>", include_str!("wasm.js"))
|
||||
.execute_script("<usage>", include_ascii_string!("wasm.js"))
|
||||
.unwrap();
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ impl ExtensionFileSource {
|
|||
self.specifier,
|
||||
Self::find_non_ascii(code)
|
||||
);
|
||||
Ok((*code).into())
|
||||
Ok(ModuleCode::from_static(code))
|
||||
}
|
||||
ExtensionFileSourceCode::LoadedFromFsDuringSnapshot(path) => {
|
||||
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;
|
||||
mod error_codes;
|
||||
mod extensions;
|
||||
mod fast_string;
|
||||
mod flags;
|
||||
mod gotham_state;
|
||||
mod inspector;
|
||||
|
@ -59,6 +60,7 @@ pub use crate::extensions::ExtensionFileSource;
|
|||
pub use crate::extensions::ExtensionFileSourceCode;
|
||||
pub use crate::extensions::OpDecl;
|
||||
pub use crate::extensions::OpMiddlewareFn;
|
||||
pub use crate::fast_string::FastString;
|
||||
pub use crate::flags::v8_set_flags;
|
||||
pub use crate::inspector::InspectorMsg;
|
||||
pub use crate::inspector::InspectorMsgKind;
|
||||
|
|
716
core/modules.rs
716
core/modules.rs
File diff suppressed because it is too large
Load diff
327
core/runtime.rs
327
core/runtime.rs
|
@ -747,7 +747,6 @@ impl JsRuntime {
|
|||
{
|
||||
if let Some(js_files) = ext.get_js_sources() {
|
||||
for file_source in js_files {
|
||||
// TODO(@AaronO): use JsRuntime::execute_static() here to move src off heap
|
||||
realm.execute_script(
|
||||
self.v8_isolate(),
|
||||
file_source.specifier,
|
||||
|
@ -914,16 +913,42 @@ impl JsRuntime {
|
|||
/// The same `name` value can be used for multiple executions.
|
||||
///
|
||||
/// `Error` can usually be downcast to `JsError`.
|
||||
pub fn execute_script<S: Into<ModuleCode>>(
|
||||
pub fn execute_script(
|
||||
&mut self,
|
||||
name: &'static str,
|
||||
source_code: S,
|
||||
source_code: ModuleCode,
|
||||
) -> Result<v8::Global<v8::Value>, Error> {
|
||||
self
|
||||
.global_realm()
|
||||
.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
|
||||
/// set to true.
|
||||
///
|
||||
|
@ -1895,7 +1920,7 @@ impl JsRuntime {
|
|||
let register_result = load.register_and_recurse(
|
||||
&mut self.handle_scope(),
|
||||
&request,
|
||||
&info,
|
||||
info,
|
||||
);
|
||||
|
||||
match register_result {
|
||||
|
@ -2071,11 +2096,12 @@ impl JsRuntime {
|
|||
) -> Result<ModuleId, Error> {
|
||||
let module_map_rc = Self::module_map(self.v8_isolate());
|
||||
if let Some(code) = code {
|
||||
let specifier = specifier.as_str().to_owned().into();
|
||||
let scope = &mut self.handle_scope();
|
||||
// true for main module
|
||||
module_map_rc
|
||||
.borrow_mut()
|
||||
.new_es_module(scope, true, specifier, &code, false)
|
||||
.new_es_module(scope, true, specifier, code, false)
|
||||
.map_err(|e| match e {
|
||||
ModuleError::Exception(exception) => {
|
||||
let exception = v8::Local::new(scope, exception);
|
||||
|
@ -2086,12 +2112,12 @@ impl JsRuntime {
|
|||
}
|
||||
|
||||
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 {
|
||||
let (request, info) = load_result?;
|
||||
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 {
|
||||
ModuleError::Exception(exception) => {
|
||||
let exception = v8::Local::new(scope, exception);
|
||||
|
@ -2125,11 +2151,12 @@ impl JsRuntime {
|
|||
) -> Result<ModuleId, Error> {
|
||||
let module_map_rc = Self::module_map(self.v8_isolate());
|
||||
if let Some(code) = code {
|
||||
let specifier = specifier.as_str().to_owned().into();
|
||||
let scope = &mut self.handle_scope();
|
||||
// false for side module (not main module)
|
||||
module_map_rc
|
||||
.borrow_mut()
|
||||
.new_es_module(scope, false, specifier, &code, false)
|
||||
.new_es_module(scope, false, specifier, code, false)
|
||||
.map_err(|e| match e {
|
||||
ModuleError::Exception(exception) => {
|
||||
let exception = v8::Local::new(scope, exception);
|
||||
|
@ -2140,12 +2167,12 @@ impl JsRuntime {
|
|||
}
|
||||
|
||||
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 {
|
||||
let (request, info) = load_result?;
|
||||
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 {
|
||||
ModuleError::Exception(exception) => {
|
||||
let exception = v8::Local::new(scope, exception);
|
||||
|
@ -2439,7 +2466,7 @@ impl JsRuntime {
|
|||
/// .expect("Handle the error properly");
|
||||
/// let source_code = "var a = 0; a + 1";
|
||||
/// 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");
|
||||
/// # drop(result);
|
||||
/// ```
|
||||
|
@ -2525,17 +2552,30 @@ impl JsRealm {
|
|||
/// The same `name` value can be used for multiple executions.
|
||||
///
|
||||
/// `Error` can usually be downcast to `JsError`.
|
||||
pub fn execute_script<S: Into<ModuleCode>>(
|
||||
pub fn execute_script_static(
|
||||
&self,
|
||||
isolate: &mut v8::Isolate,
|
||||
name: &'static str,
|
||||
source_code: S,
|
||||
source_code: &'static str,
|
||||
) -> Result<v8::Global<v8::Value>, Error> {
|
||||
// Manual monomorphization (TODO: replace w/momo)
|
||||
self.execute_script_inner(isolate, name, source_code.into())
|
||||
self.execute_script(isolate, name, ModuleCode::from_static(source_code))
|
||||
}
|
||||
|
||||
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,
|
||||
isolate: &mut v8::Isolate,
|
||||
name: &'static str,
|
||||
|
@ -2687,8 +2727,10 @@ pub fn queue_async_op(
|
|||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use super::*;
|
||||
use crate::ascii_str;
|
||||
use crate::error::custom_error;
|
||||
use crate::error::AnyError;
|
||||
use crate::include_ascii_string;
|
||||
use crate::modules::AssertedModuleType;
|
||||
use crate::modules::ModuleInfo;
|
||||
use crate::modules::ModuleSource;
|
||||
|
@ -2787,7 +2829,7 @@ pub mod tests {
|
|||
});
|
||||
|
||||
runtime
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
"setup.js",
|
||||
r#"
|
||||
function assert(cond) {
|
||||
|
@ -2806,7 +2848,7 @@ pub mod tests {
|
|||
fn test_ref_unref_ops() {
|
||||
let (mut runtime, _dispatch_count) = setup(Mode::AsyncDeferred);
|
||||
runtime
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
"filename.js",
|
||||
r#"
|
||||
|
||||
|
@ -2824,7 +2866,7 @@ pub mod tests {
|
|||
assert_eq!(realm.state(isolate).borrow().unrefed_ops.len(), 0);
|
||||
}
|
||||
runtime
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
"filename.js",
|
||||
r#"
|
||||
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);
|
||||
}
|
||||
runtime
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
"filename.js",
|
||||
r#"
|
||||
Deno.core.ops.op_ref_op(p1[promiseIdSymbol]);
|
||||
|
@ -2861,7 +2903,7 @@ pub mod tests {
|
|||
fn test_dispatch() {
|
||||
let (mut runtime, dispatch_count) = setup(Mode::Async);
|
||||
runtime
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
"filename.js",
|
||||
r#"
|
||||
let control = 42;
|
||||
|
@ -2881,7 +2923,7 @@ pub mod tests {
|
|||
fn test_op_async_promise_id() {
|
||||
let (mut runtime, _dispatch_count) = setup(Mode::Async);
|
||||
runtime
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
"filename.js",
|
||||
r#"
|
||||
|
||||
|
@ -2898,7 +2940,7 @@ pub mod tests {
|
|||
fn test_dispatch_no_zero_copy_buf() {
|
||||
let (mut runtime, dispatch_count) = setup(Mode::AsyncZeroCopy(false));
|
||||
runtime
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
"filename.js",
|
||||
r#"
|
||||
|
||||
|
@ -2913,7 +2955,7 @@ pub mod tests {
|
|||
fn test_dispatch_stack_zero_copy_bufs() {
|
||||
let (mut runtime, dispatch_count) = setup(Mode::AsyncZeroCopy(true));
|
||||
runtime
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
"filename.js",
|
||||
r#"
|
||||
|
||||
|
@ -2928,13 +2970,16 @@ pub mod tests {
|
|||
#[test]
|
||||
fn test_execute_script_return_value() {
|
||||
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 value = value_global.open(scope);
|
||||
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 value = value_global.open(scope);
|
||||
|
@ -2951,7 +2996,7 @@ pub mod tests {
|
|||
let mut runtime = JsRuntime::new(Default::default());
|
||||
run_in_task(move |cx| {
|
||||
let value_global = runtime
|
||||
.execute_script("a.js", "Promise.resolve(1 + 2)")
|
||||
.execute_script_static("a.js", "Promise.resolve(1 + 2)")
|
||||
.unwrap();
|
||||
let v = runtime.poll_value(&value_global, cx);
|
||||
{
|
||||
|
@ -2962,7 +3007,7 @@ pub mod tests {
|
|||
}
|
||||
|
||||
let value_global = runtime
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
"a.js",
|
||||
"Promise.resolve(new Promise(resolve => resolve(2 + 2)))",
|
||||
)
|
||||
|
@ -2976,7 +3021,7 @@ pub mod tests {
|
|||
}
|
||||
|
||||
let value_global = runtime
|
||||
.execute_script("a.js", "Promise.reject(new Error('fail'))")
|
||||
.execute_script_static("a.js", "Promise.reject(new Error('fail'))")
|
||||
.unwrap();
|
||||
let v = runtime.poll_value(&value_global, cx);
|
||||
assert!(
|
||||
|
@ -2984,7 +3029,7 @@ pub mod tests {
|
|||
);
|
||||
|
||||
let value_global = runtime
|
||||
.execute_script("a.js", "new Promise(resolve => {})")
|
||||
.execute_script_static("a.js", "new Promise(resolve => {})")
|
||||
.unwrap();
|
||||
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.");
|
||||
|
@ -2995,7 +3040,7 @@ pub mod tests {
|
|||
async fn test_resolve_value() {
|
||||
let mut runtime = JsRuntime::new(Default::default());
|
||||
let value_global = runtime
|
||||
.execute_script("a.js", "Promise.resolve(1 + 2)")
|
||||
.execute_script_static("a.js", "Promise.resolve(1 + 2)")
|
||||
.unwrap();
|
||||
let result_global = runtime.resolve_value(value_global).await.unwrap();
|
||||
{
|
||||
|
@ -3005,7 +3050,7 @@ pub mod tests {
|
|||
}
|
||||
|
||||
let value_global = runtime
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
"a.js",
|
||||
"Promise.resolve(new Promise(resolve => resolve(2 + 2)))",
|
||||
)
|
||||
|
@ -3018,7 +3063,7 @@ pub mod tests {
|
|||
}
|
||||
|
||||
let value_global = runtime
|
||||
.execute_script("a.js", "Promise.reject(new Error('fail'))")
|
||||
.execute_script_static("a.js", "Promise.reject(new Error('fail'))")
|
||||
.unwrap();
|
||||
let err = runtime.resolve_value(value_global).await.unwrap_err();
|
||||
assert_eq!(
|
||||
|
@ -3027,7 +3072,7 @@ pub mod tests {
|
|||
);
|
||||
|
||||
let value_global = runtime
|
||||
.execute_script("a.js", "new Promise(resolve => {})")
|
||||
.execute_script_static("a.js", "new Promise(resolve => {})")
|
||||
.unwrap();
|
||||
let error_string = runtime
|
||||
.resolve_value(value_global)
|
||||
|
@ -3046,7 +3091,7 @@ pub mod tests {
|
|||
let v8_isolate_handle = runtime.v8_isolate().thread_safe_handle();
|
||||
|
||||
// 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#"
|
||||
(async () => {
|
||||
const wasmCode = new Uint8Array([
|
||||
|
@ -3069,7 +3114,7 @@ pub mod tests {
|
|||
assert!(ok);
|
||||
});
|
||||
let err = runtime
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
"infinite_wasm_loop2.js",
|
||||
"globalThis.wasmInstance.exports.infinite_loop();",
|
||||
)
|
||||
|
@ -3082,7 +3127,7 @@ pub mod tests {
|
|||
|
||||
// Verify that the isolate usable again.
|
||||
runtime
|
||||
.execute_script("simple.js", "1 + 1")
|
||||
.execute_script_static("simple.js", "1 + 1")
|
||||
.expect("execution should be possible again");
|
||||
|
||||
terminator_thread.join().unwrap();
|
||||
|
@ -3103,7 +3148,7 @@ pub mod tests {
|
|||
});
|
||||
|
||||
// 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"),
|
||||
Err(e) => {
|
||||
assert_eq!(e.to_string(), "Uncaught Error: execution terminated")
|
||||
|
@ -3117,7 +3162,7 @@ pub mod tests {
|
|||
|
||||
// Verify that the isolate usable again.
|
||||
isolate
|
||||
.execute_script("simple.js", "1 + 1")
|
||||
.execute_script_static("simple.js", "1 + 1")
|
||||
.expect("execution should be possible again");
|
||||
|
||||
terminator_thread.join().unwrap();
|
||||
|
@ -3139,7 +3184,7 @@ pub mod tests {
|
|||
fn syntax_error() {
|
||||
let mut runtime = JsRuntime::new(Default::default());
|
||||
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 js_error = e.downcast::<JsError>().unwrap();
|
||||
let frame = js_error.frames.first().unwrap();
|
||||
|
@ -3154,7 +3199,7 @@ pub mod tests {
|
|||
.execute_script(
|
||||
"encode_decode_test.js",
|
||||
// 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();
|
||||
if let Poll::Ready(Err(_)) = runtime.poll_event_loop(cx, false) {
|
||||
|
@ -3170,7 +3215,7 @@ pub mod tests {
|
|||
runtime
|
||||
.execute_script(
|
||||
"serialize_deserialize_test.js",
|
||||
include_str!("serialize_deserialize_test.js"),
|
||||
include_ascii_string!("serialize_deserialize_test.js"),
|
||||
)
|
||||
.unwrap();
|
||||
if let Poll::Ready(Err(_)) = runtime.poll_event_loop(cx, false) {
|
||||
|
@ -3198,7 +3243,7 @@ pub mod tests {
|
|||
});
|
||||
run_in_task(move |cx| {
|
||||
runtime
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
"error_builder_test.js",
|
||||
include_str!("error_builder_test.js"),
|
||||
)
|
||||
|
@ -3216,7 +3261,7 @@ pub mod tests {
|
|||
will_snapshot: true,
|
||||
..Default::default()
|
||||
});
|
||||
runtime.execute_script("a.js", "a = 1 + 2").unwrap();
|
||||
runtime.execute_script_static("a.js", "a = 1 + 2").unwrap();
|
||||
runtime.snapshot()
|
||||
};
|
||||
|
||||
|
@ -3226,7 +3271,7 @@ pub mod tests {
|
|||
..Default::default()
|
||||
});
|
||||
runtime2
|
||||
.execute_script("check.js", "if (a != 3) throw Error('x')")
|
||||
.execute_script_static("check.js", "if (a != 3) throw Error('x')")
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
|
@ -3237,7 +3282,9 @@ pub mod tests {
|
|||
will_snapshot: true,
|
||||
..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()
|
||||
};
|
||||
|
||||
|
@ -3250,9 +3297,9 @@ pub mod tests {
|
|||
|
||||
let startup_data = {
|
||||
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();
|
||||
runtime.execute_script("b.js", "b = 2 + 3").unwrap();
|
||||
runtime.execute_script_static("b.js", "b = 2 + 3").unwrap();
|
||||
runtime.snapshot()
|
||||
};
|
||||
|
||||
|
@ -3263,10 +3310,10 @@ pub mod tests {
|
|||
..Default::default()
|
||||
});
|
||||
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();
|
||||
runtime
|
||||
.execute_script("check2.js", "if (!Deno.core) throw Error('x')")
|
||||
.execute_script_static("check2.js", "if (!Deno.core) throw Error('x')")
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
@ -3279,7 +3326,7 @@ pub mod tests {
|
|||
..Default::default()
|
||||
});
|
||||
runtime
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
"a.js",
|
||||
r#"
|
||||
Deno.core.ops.op_set_macrotask_callback(() => {
|
||||
|
@ -3304,7 +3351,7 @@ pub mod tests {
|
|||
..Default::default()
|
||||
});
|
||||
runtime2
|
||||
.execute_script("check.js", "if (a != 3) throw Error('x')")
|
||||
.execute_script_static("check.js", "if (a != 3) throw Error('x')")
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
|
@ -3315,7 +3362,7 @@ pub mod tests {
|
|||
will_snapshot: true,
|
||||
..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();
|
||||
Vec::from(snap).into_boxed_slice()
|
||||
};
|
||||
|
@ -3326,7 +3373,7 @@ pub mod tests {
|
|||
..Default::default()
|
||||
});
|
||||
runtime2
|
||||
.execute_script("check.js", "if (a != 3) throw Error('x')")
|
||||
.execute_script_static("check.js", "if (a != 3) throw Error('x')")
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
|
@ -3351,7 +3398,7 @@ pub mod tests {
|
|||
fn load(
|
||||
&self,
|
||||
_module_specifier: &ModuleSpecifier,
|
||||
_maybe_referrer: Option<ModuleSpecifier>,
|
||||
_maybe_referrer: Option<&ModuleSpecifier>,
|
||||
_is_dyn_import: bool,
|
||||
) -> Pin<Box<ModuleSourceFuture>> {
|
||||
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 source_code = r#"
|
||||
let source_code = ascii_str!(
|
||||
r#"
|
||||
export const a = "b";
|
||||
export default 1 + 2;
|
||||
"#
|
||||
.into();
|
||||
);
|
||||
|
||||
let module_id = futures::executor::block_on(
|
||||
runtime.load_main_module(&specifier, Some(source_code)),
|
||||
|
@ -3435,7 +3483,7 @@ pub mod tests {
|
|||
},
|
||||
);
|
||||
let err = runtime
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
"script name",
|
||||
r#"let s = ""; while(true) { s += "Hello"; }"#,
|
||||
)
|
||||
|
@ -3488,7 +3536,7 @@ pub mod tests {
|
|||
);
|
||||
|
||||
let err = runtime
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
"script name",
|
||||
r#"let s = ""; while(true) { s += "Hello"; }"#,
|
||||
)
|
||||
|
@ -3520,7 +3568,7 @@ pub mod tests {
|
|||
fn load(
|
||||
&self,
|
||||
_module_specifier: &ModuleSpecifier,
|
||||
_maybe_referrer: Option<ModuleSpecifier>,
|
||||
_maybe_referrer: Option<&ModuleSpecifier>,
|
||||
_is_dyn_import: bool,
|
||||
) -> Pin<Box<ModuleSourceFuture>> {
|
||||
eprintln!("load() should not be called");
|
||||
|
@ -3563,7 +3611,7 @@ pub mod tests {
|
|||
ModuleInfo {
|
||||
id,
|
||||
main,
|
||||
name: specifier.to_string(),
|
||||
name: specifier.into(),
|
||||
requests: vec![crate::modules::ModuleRequest {
|
||||
specifier: format!("file:///{prev}.js"),
|
||||
asserted_module_type: AssertedModuleType::JavaScriptOrWasm,
|
||||
|
@ -3577,7 +3625,13 @@ pub mod tests {
|
|||
let module_map = module_map_rc.borrow();
|
||||
assert_eq!(module_map.handles.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);
|
||||
|
||||
|
@ -3586,8 +3640,8 @@ pub mod tests {
|
|||
assert_eq!(module_map.info.get(info.id).unwrap(), info);
|
||||
assert_eq!(
|
||||
module_map
|
||||
.by_name
|
||||
.get(&(info.name.clone(), AssertedModuleType::JavaScriptOrWasm))
|
||||
.by_name(AssertedModuleType::JavaScriptOrWasm)
|
||||
.get(&info.name)
|
||||
.unwrap(),
|
||||
&SymbolicModule::Mod(info.id)
|
||||
);
|
||||
|
@ -3610,7 +3664,8 @@ pub mod tests {
|
|||
});
|
||||
|
||||
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(
|
||||
runtime.load_side_module(&specifier, Some(source_code)),
|
||||
)
|
||||
|
@ -3624,7 +3679,7 @@ pub mod tests {
|
|||
modules.push(ModuleInfo {
|
||||
id,
|
||||
main: false,
|
||||
name: specifier.to_string(),
|
||||
name: specifier.into(),
|
||||
requests: vec![],
|
||||
module_type: ModuleType::JavaScript,
|
||||
});
|
||||
|
@ -3668,9 +3723,8 @@ pub mod tests {
|
|||
let source_code = r#"(async () => {
|
||||
const mod = await import("file:///400.js");
|
||||
return mod.f400() + " " + Deno.core.ops.op_test();
|
||||
})();"#
|
||||
.to_string();
|
||||
let val = runtime3.execute_script(".", source_code).unwrap();
|
||||
})();"#;
|
||||
let val = runtime3.execute_script_static(".", source_code).unwrap();
|
||||
let val = futures::executor::block_on(runtime3.resolve_value(val)).unwrap();
|
||||
{
|
||||
let scope = &mut runtime3.handle_scope();
|
||||
|
@ -3684,7 +3738,7 @@ pub mod tests {
|
|||
fn test_error_without_stack() {
|
||||
let mut runtime = JsRuntime::new(RuntimeOptions::default());
|
||||
// SyntaxError
|
||||
let result = runtime.execute_script(
|
||||
let result = runtime.execute_script_static(
|
||||
"error_without_stack.js",
|
||||
r#"
|
||||
function main() {
|
||||
|
@ -3701,7 +3755,7 @@ main();
|
|||
#[test]
|
||||
fn test_error_stack() {
|
||||
let mut runtime = JsRuntime::new(RuntimeOptions::default());
|
||||
let result = runtime.execute_script(
|
||||
let result = runtime.execute_script_static(
|
||||
"error_stack.js",
|
||||
r#"
|
||||
function assert(cond) {
|
||||
|
@ -3727,7 +3781,7 @@ main();
|
|||
let mut runtime = JsRuntime::new(RuntimeOptions::default());
|
||||
run_in_task(move |cx| {
|
||||
runtime
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
"error_async_stack.js",
|
||||
r#"
|
||||
(async () => {
|
||||
|
@ -3781,7 +3835,7 @@ main();
|
|||
|
||||
run_in_task(move |cx| {
|
||||
runtime
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
"test_error_context_sync.js",
|
||||
r#"
|
||||
let errMessage;
|
||||
|
@ -3798,7 +3852,7 @@ if (errMessage !== "higher-level sync error: original sync error") {
|
|||
.unwrap();
|
||||
|
||||
let promise = runtime
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
"test_error_context_async.js",
|
||||
r#"
|
||||
|
||||
|
@ -3830,7 +3884,7 @@ if (errMessage !== "higher-level sync error: original sync error") {
|
|||
let mut runtime = JsRuntime::new(RuntimeOptions::default());
|
||||
run_in_task(move |cx| {
|
||||
runtime
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
"pump_message_loop.js",
|
||||
r#"
|
||||
function assertEquals(a, b) {
|
||||
|
@ -3860,12 +3914,15 @@ assertEquals(1, notify_return_value);
|
|||
|
||||
// noop script, will resolve promise from first script
|
||||
runtime
|
||||
.execute_script("pump_message_loop2.js", r#"assertEquals(1, 1);"#)
|
||||
.execute_script_static(
|
||||
"pump_message_loop2.js",
|
||||
r#"assertEquals(1, 1);"#,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// check that promise from `Atomics.waitAsync` has been resolved
|
||||
runtime
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
"pump_message_loop3.js",
|
||||
r#"assertEquals(globalThis.resolved, true);"#,
|
||||
)
|
||||
|
@ -3878,7 +3935,7 @@ assertEquals(1, notify_return_value);
|
|||
let mut runtime = JsRuntime::new(RuntimeOptions::default());
|
||||
// Call non-existent op so we get error from `core.js`
|
||||
let error = runtime
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
"core_js_stack_frame.js",
|
||||
"Deno.core.opAsync('non_existent');",
|
||||
)
|
||||
|
@ -3895,7 +3952,7 @@ assertEquals(1, notify_return_value);
|
|||
..Default::default()
|
||||
};
|
||||
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.
|
||||
|
@ -3903,7 +3960,7 @@ assertEquals(1, notify_return_value);
|
|||
fn test_is_proxy() {
|
||||
let mut runtime = JsRuntime::new(RuntimeOptions::default());
|
||||
let all_true: v8::Global<v8::Value> = runtime
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
"is_proxy.js",
|
||||
r#"
|
||||
(function () {
|
||||
|
@ -3951,7 +4008,7 @@ assertEquals(1, notify_return_value);
|
|||
});
|
||||
|
||||
runtime
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
"op_async_borrow.js",
|
||||
"Deno.core.opAsync(\"op_async_borrow\")",
|
||||
)
|
||||
|
@ -3982,7 +4039,7 @@ assertEquals(1, notify_return_value);
|
|||
});
|
||||
|
||||
runtime
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
"op_sync_serialize_object_with_numbers_as_keys.js",
|
||||
r#"
|
||||
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
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
"op_async_serialize_object_with_numbers_as_keys.js",
|
||||
r#"
|
||||
|
||||
|
@ -4060,7 +4117,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
|||
});
|
||||
|
||||
runtime
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
"macrotasks_and_nextticks.js",
|
||||
r#"
|
||||
|
||||
|
@ -4094,7 +4151,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
|||
let mut runtime = JsRuntime::new(Default::default());
|
||||
|
||||
runtime
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
"multiple_macrotasks_and_nextticks.js",
|
||||
r#"
|
||||
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
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
"has_tick_scheduled.js",
|
||||
r#"
|
||||
Deno.core.ops.op_set_macrotask_callback(() => {
|
||||
|
@ -4208,16 +4265,14 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
|||
fn load(
|
||||
&self,
|
||||
_module_specifier: &ModuleSpecifier,
|
||||
_maybe_referrer: Option<ModuleSpecifier>,
|
||||
_maybe_referrer: Option<&ModuleSpecifier>,
|
||||
_is_dyn_import: bool,
|
||||
) -> Pin<Box<ModuleSourceFuture>> {
|
||||
async move {
|
||||
Ok(ModuleSource {
|
||||
code: b"console.log('hello world');".into(),
|
||||
module_url_specified: "file:///main.js".to_string(),
|
||||
module_url_found: "file:///main.js".to_string(),
|
||||
module_type: ModuleType::JavaScript,
|
||||
})
|
||||
Ok(ModuleSource::for_test(
|
||||
"console.log('hello world');",
|
||||
"file:///main.js",
|
||||
))
|
||||
}
|
||||
.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 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(
|
||||
runtime.load_main_module(&specifier, Some(source_code)),
|
||||
|
@ -4264,7 +4319,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
|||
});
|
||||
|
||||
runtime
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
"promise_reject_callback.js",
|
||||
r#"
|
||||
// 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));
|
||||
|
||||
runtime
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
"promise_reject_callback.js",
|
||||
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}));
|
||||
"#
|
||||
)
|
||||
).into()
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
@ -4341,7 +4396,11 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
|||
|
||||
for (realm, realm_name, number) in realm_expectations {
|
||||
let reject_value = realm
|
||||
.execute_script(runtime.v8_isolate(), "", "globalThis.rejectValue")
|
||||
.execute_script_static(
|
||||
runtime.v8_isolate(),
|
||||
"",
|
||||
"globalThis.rejectValue",
|
||||
)
|
||||
.unwrap();
|
||||
let scope = &mut realm.handle_scope(runtime.v8_isolate());
|
||||
let reject_value = v8::Local::new(scope, reject_value);
|
||||
|
@ -4382,25 +4441,18 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
|||
fn load(
|
||||
&self,
|
||||
_module_specifier: &ModuleSpecifier,
|
||||
_maybe_referrer: Option<ModuleSpecifier>,
|
||||
_maybe_referrer: Option<&ModuleSpecifier>,
|
||||
_is_dyn_import: bool,
|
||||
) -> Pin<Box<ModuleSourceFuture>> {
|
||||
let source = r#"
|
||||
let code = r#"
|
||||
Deno.core.ops.op_set_promise_reject_callback((type, promise, reason) => {
|
||||
Deno.core.ops.op_promise_reject();
|
||||
});
|
||||
throw new Error('top level throw');
|
||||
"#;
|
||||
|
||||
async move {
|
||||
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()
|
||||
async move { Ok(ModuleSource::for_test(code, "file:///main.js")) }
|
||||
.boxed_local()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4434,7 +4486,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
|||
..Default::default()
|
||||
});
|
||||
assert!(runtime
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
"test_op_return_serde_v8_error.js",
|
||||
"Deno.core.ops.op_err()"
|
||||
)
|
||||
|
@ -4459,7 +4511,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
|||
..Default::default()
|
||||
});
|
||||
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();
|
||||
let scope = &mut runtime.handle_scope();
|
||||
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()
|
||||
});
|
||||
let r = runtime
|
||||
.execute_script("test.js", "Deno.core.ops.op_foo()")
|
||||
.execute_script_static("test.js", "Deno.core.ops.op_foo()")
|
||||
.unwrap();
|
||||
let scope = &mut runtime.handle_scope();
|
||||
assert!(r.open(scope).is_undefined());
|
||||
|
@ -4511,7 +4563,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
|||
});
|
||||
|
||||
runtime
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
"test.js",
|
||||
r#"
|
||||
const a1 = new Uint8Array([1,2,3]);
|
||||
|
@ -4579,7 +4631,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
|||
..Default::default()
|
||||
});
|
||||
runtime
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
"test.js",
|
||||
r#"
|
||||
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.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
|
||||
.execute_script(runtime.v8_isolate(), "", "Object")
|
||||
.execute_script_static(runtime.v8_isolate(), "", "Object")
|
||||
.unwrap();
|
||||
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 ret = realm
|
||||
.execute_script(runtime.v8_isolate(), "", "Deno.core.ops.op_test()")
|
||||
.execute_script_static(
|
||||
runtime.v8_isolate(),
|
||||
"",
|
||||
"Deno.core.ops.op_test()",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
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 ret = realm
|
||||
.execute_script(runtime.v8_isolate(), "", "Deno.core.ops.op_test()")
|
||||
.execute_script_static(
|
||||
runtime.v8_isolate(),
|
||||
"",
|
||||
"Deno.core.ops.op_test()",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
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
|
||||
for realm in [runtime.global_realm(), new_realm].into_iter() {
|
||||
let ret = realm
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
runtime.v8_isolate(),
|
||||
"",
|
||||
r#"
|
||||
|
@ -4753,7 +4813,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
|||
// Test in both realms
|
||||
for realm in [global_realm, new_realm].into_iter() {
|
||||
let ret = realm
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
runtime.v8_isolate(),
|
||||
"",
|
||||
r#"
|
||||
|
@ -4806,7 +4866,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
|||
let other_realm = runtime.create_realm().unwrap();
|
||||
|
||||
main_realm
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
runtime.v8_isolate(),
|
||||
"",
|
||||
r#"
|
||||
|
@ -4816,7 +4876,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
|||
)
|
||||
.unwrap();
|
||||
other_realm
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
runtime.v8_isolate(),
|
||||
"",
|
||||
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));
|
||||
|
||||
main_realm
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
runtime.v8_isolate(),
|
||||
"",
|
||||
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));
|
||||
|
||||
other_realm
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
runtime.v8_isolate(),
|
||||
"",
|
||||
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)
|
||||
let mut runtime = JsRuntime::new(Default::default());
|
||||
assert!(runtime
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
"test_array_by_copy.js",
|
||||
"const a = [1, 2, 3];
|
||||
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
|
||||
let mut runtime = JsRuntime::new(Default::default());
|
||||
runtime
|
||||
.execute_script(
|
||||
.execute_script_static(
|
||||
"test_rab.js",
|
||||
r#"const a = new ArrayBuffer(100, {maxByteLength: 200});
|
||||
if (a.byteLength !== 100) {
|
||||
|
@ -4916,24 +4976,17 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
|
|||
fn load(
|
||||
&self,
|
||||
_module_specifier: &ModuleSpecifier,
|
||||
_maybe_referrer: Option<ModuleSpecifier>,
|
||||
_maybe_referrer: Option<&ModuleSpecifier>,
|
||||
_is_dyn_import: bool,
|
||||
) -> Pin<Box<ModuleSourceFuture>> {
|
||||
let source = r#"
|
||||
let code = r#"
|
||||
// This module doesn't really exist, just verifying that we'll get
|
||||
// an error when specifier starts with "ext:".
|
||||
import { core } from "ext:core.js";
|
||||
"#;
|
||||
|
||||
async move {
|
||||
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()
|
||||
async move { Ok(ModuleSource::for_test(code, "file:///main.js")) }
|
||||
.boxed_local()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -447,7 +447,7 @@ pub fn initialize_runtime(
|
|||
argv0
|
||||
);
|
||||
|
||||
js_runtime.execute_script(located_script_name!(), source_code)?;
|
||||
js_runtime.execute_script(located_script_name!(), source_code.into())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -468,7 +468,8 @@ pub fn load_cjs_module(
|
|||
main = main,
|
||||
module = escape_for_single_quote_string(module),
|
||||
inspect_brk = inspect_brk,
|
||||
);
|
||||
)
|
||||
.into();
|
||||
|
||||
js_runtime.execute_script(located_script_name!(), source_code)?;
|
||||
Ok(())
|
||||
|
|
|
@ -42,7 +42,7 @@ mod startup_snapshot {
|
|||
|
||||
let parsed = deno_ast::parse_module(ParseParams {
|
||||
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,
|
||||
capture_tokens: false,
|
||||
scope_analysis: false,
|
||||
|
|
|
@ -9,6 +9,7 @@ use crate::BootstrapOptions;
|
|||
use deno_broadcast_channel::InMemoryBroadcastChannel;
|
||||
use deno_cache::CreateCache;
|
||||
use deno_cache::SqliteBackedCache;
|
||||
use deno_core::ascii_str;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::error::JsError;
|
||||
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`.
|
||||
// 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.
|
||||
let script = r#"
|
||||
let script = ascii_str!(
|
||||
r#"
|
||||
const pollForMessages = globalThis.pollForMessages;
|
||||
delete globalThis.pollForMessages;
|
||||
pollForMessages
|
||||
"#;
|
||||
"#
|
||||
);
|
||||
let poll_for_messages_fn = self
|
||||
.js_runtime
|
||||
.execute_script(located_script_name!(), script)
|
||||
|
@ -585,10 +588,10 @@ impl WebWorker {
|
|||
}
|
||||
|
||||
/// See [JsRuntime::execute_script](deno_core::JsRuntime::execute_script)
|
||||
pub fn execute_script<S: Into<ModuleCode>>(
|
||||
pub fn execute_script(
|
||||
&mut self,
|
||||
name: &'static str,
|
||||
source_code: S,
|
||||
source_code: ModuleCode,
|
||||
) -> Result<(), AnyError> {
|
||||
self.js_runtime.execute_script(name, source_code)?;
|
||||
Ok(())
|
||||
|
@ -777,7 +780,7 @@ pub fn run_web_worker(
|
|||
|
||||
// Execute provided source code immediately
|
||||
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();
|
||||
r
|
||||
} else {
|
||||
|
|
|
@ -11,6 +11,7 @@ use std::task::Poll;
|
|||
use deno_broadcast_channel::InMemoryBroadcastChannel;
|
||||
use deno_cache::CreateCache;
|
||||
use deno_cache::SqliteBackedCache;
|
||||
use deno_core::ascii_str;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::error::JsError;
|
||||
use deno_core::futures::Future;
|
||||
|
@ -370,10 +371,10 @@ impl MainWorker {
|
|||
}
|
||||
|
||||
/// See [JsRuntime::execute_script](deno_core::JsRuntime::execute_script)
|
||||
pub fn execute_script<S: Into<ModuleCode>>(
|
||||
pub fn execute_script(
|
||||
&mut self,
|
||||
script_name: &'static str,
|
||||
source_code: S,
|
||||
source_code: ModuleCode,
|
||||
) -> Result<v8::Global<v8::Value>, AnyError> {
|
||||
self.js_runtime.execute_script(script_name, source_code)
|
||||
}
|
||||
|
@ -510,12 +511,12 @@ impl MainWorker {
|
|||
&mut self,
|
||||
script_name: &'static str,
|
||||
) -> Result<(), AnyError> {
|
||||
self.execute_script(
|
||||
self.js_runtime.execute_script(
|
||||
script_name,
|
||||
// NOTE(@bartlomieju): not using `globalThis` here, because user might delete
|
||||
// it. Instead we're using global `dispatchEvent` function which will
|
||||
// used a saved reference to global scope.
|
||||
"dispatchEvent(new Event('load'))",
|
||||
ascii_str!("dispatchEvent(new Event('load'))"),
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -527,12 +528,12 @@ impl MainWorker {
|
|||
&mut self,
|
||||
script_name: &'static str,
|
||||
) -> Result<(), AnyError> {
|
||||
self.execute_script(
|
||||
self.js_runtime.execute_script(
|
||||
script_name,
|
||||
// NOTE(@bartlomieju): not using `globalThis` here, because user might delete
|
||||
// it. Instead we're using global `dispatchEvent` function which will
|
||||
// used a saved reference to global scope.
|
||||
"dispatchEvent(new Event('unload'))",
|
||||
ascii_str!("dispatchEvent(new Event('unload'))"),
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -549,7 +550,9 @@ impl MainWorker {
|
|||
// NOTE(@bartlomieju): not using `globalThis` here, because user might delete
|
||||
// it. Instead we're using global `dispatchEvent` function which will
|
||||
// used a saved reference to global scope.
|
||||
"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());
|
||||
Ok(local_value.is_false())
|
||||
|
|
Loading…
Reference in a new issue