summaryrefslogtreecommitdiff
path: root/core/runtime.rs
diff options
context:
space:
mode:
Diffstat (limited to 'core/runtime.rs')
-rw-r--r--core/runtime.rs99
1 files changed, 59 insertions, 40 deletions
diff --git a/core/runtime.rs b/core/runtime.rs
index 7b6dfba92..f9f2e5523 100644
--- a/core/runtime.rs
+++ b/core/runtime.rs
@@ -9,6 +9,7 @@ use crate::extensions::OpEventLoopFn;
use crate::inspector::JsRuntimeInspector;
use crate::module_specifier::ModuleSpecifier;
use crate::modules::ExtModuleLoaderCb;
+use crate::modules::ModuleCode;
use crate::modules::ModuleError;
use crate::modules::ModuleId;
use crate::modules::ModuleLoadId;
@@ -50,6 +51,8 @@ use std::sync::Mutex;
use std::sync::Once;
use std::task::Context;
use std::task::Poll;
+use v8::HandleScope;
+use v8::Local;
use v8::OwnedIsolate;
type PendingOpFuture = OpCall<(RealmIdx, PromiseId, OpId, OpResult)>;
@@ -748,7 +751,7 @@ impl JsRuntime {
realm.execute_script(
self.v8_isolate(),
file_source.specifier,
- &file_source.code.load()?,
+ file_source.code.load()?,
)?;
}
}
@@ -902,7 +905,7 @@ impl JsRuntime {
/// 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, eg.
+ /// `name` can be a filepath or any other string, but it is required to be 7-bit ASCII, eg.
///
/// - "/some/file/path.js"
/// - "<anon>"
@@ -911,10 +914,10 @@ impl JsRuntime {
/// The same `name` value can be used for multiple executions.
///
/// `Error` can usually be downcast to `JsError`.
- pub fn execute_script(
+ pub fn execute_script<S: Into<ModuleCode>>(
&mut self,
- name: &str,
- source_code: &str,
+ name: &'static str,
+ source_code: S,
) -> Result<v8::Global<v8::Value>, Error> {
self
.global_realm()
@@ -2056,21 +2059,15 @@ impl JsRuntime {
pub async fn load_main_module(
&mut self,
specifier: &ModuleSpecifier,
- code: Option<String>,
+ code: Option<ModuleCode>,
) -> Result<ModuleId, Error> {
let module_map_rc = Self::module_map(self.v8_isolate());
if let Some(code) = code {
let scope = &mut self.handle_scope();
+ // true for main module
module_map_rc
.borrow_mut()
- .new_es_module(
- scope,
- // main module
- true,
- specifier.as_str(),
- code.as_bytes(),
- false,
- )
+ .new_es_module(scope, true, specifier, &code, false)
.map_err(|e| match e {
ModuleError::Exception(exception) => {
let exception = v8::Local::new(scope, exception);
@@ -2116,21 +2113,15 @@ impl JsRuntime {
pub async fn load_side_module(
&mut self,
specifier: &ModuleSpecifier,
- code: Option<String>,
+ code: Option<ModuleCode>,
) -> Result<ModuleId, Error> {
let module_map_rc = Self::module_map(self.v8_isolate());
if let Some(code) = code {
let scope = &mut self.handle_scope();
+ // false for side module (not main module)
module_map_rc
.borrow_mut()
- .new_es_module(
- scope,
- // not main module
- false,
- specifier.as_str(),
- code.as_bytes(),
- false,
- )
+ .new_es_module(scope, false, specifier, &code, false)
.map_err(|e| match e {
ModuleError::Exception(exception) => {
let exception = v8::Local::new(scope, exception);
@@ -2476,6 +2467,21 @@ impl JsRealm {
self.0.open(scope).global(scope)
}
+ fn string_from_code<'a>(
+ scope: &mut HandleScope<'a>,
+ code: &ModuleCode,
+ ) -> Option<Local<'a, v8::String>> {
+ if let Some(code) = code.try_static_ascii() {
+ v8::String::new_external_onebyte_static(scope, code)
+ } else {
+ v8::String::new_from_utf8(
+ scope,
+ code.as_bytes(),
+ v8::NewStringType::Normal,
+ )
+ }
+ }
+
/// Executes traditional JavaScript code (traditional = not ES modules) in the
/// realm's context.
///
@@ -2488,16 +2494,28 @@ impl JsRealm {
/// The same `name` value can be used for multiple executions.
///
/// `Error` can usually be downcast to `JsError`.
- pub fn execute_script(
+ pub fn execute_script<S: Into<ModuleCode>>(
&self,
isolate: &mut v8::Isolate,
- name: &str,
- source_code: &str,
+ name: &'static str,
+ source_code: S,
+ ) -> Result<v8::Global<v8::Value>, Error> {
+ // Manual monomorphization (TODO: replace w/momo)
+ self.execute_script_inner(isolate, name, source_code.into())
+ }
+
+ fn execute_script_inner(
+ &self,
+ isolate: &mut v8::Isolate,
+ name: &'static str,
+ source_code: ModuleCode,
) -> Result<v8::Global<v8::Value>, Error> {
let scope = &mut self.handle_scope(isolate);
- let source = v8::String::new(scope, source_code).unwrap();
- let name = v8::String::new(scope, name).unwrap();
+ let source = Self::string_from_code(scope, &source_code).unwrap();
+ assert!(name.is_ascii());
+ let name =
+ v8::String::new_external_onebyte_static(scope, name.as_bytes()).unwrap();
let origin = bindings::script_origin(scope, name);
let tc_scope = &mut v8::TryCatch::new(scope);
@@ -3104,7 +3122,8 @@ pub mod tests {
runtime
.execute_script(
"encode_decode_test.js",
- include_str!("encode_decode_test.js"),
+ // Note: We make this to_owned because it contains non-ASCII chars
+ include_str!("encode_decode_test.js").to_owned(),
)
.unwrap();
if let Poll::Ready(Err(_)) = runtime.poll_event_loop(cx, false) {
@@ -3320,7 +3339,7 @@ pub mod tests {
export const a = "b";
export default 1 + 2;
"#
- .to_string();
+ .into();
let module_id = futures::executor::block_on(
runtime.load_main_module(&specifier, Some(source_code)),
@@ -3490,7 +3509,8 @@ pub mod tests {
import {{ f{prev} }} from "file:///{prev}.js";
export function f{i}() {{ return f{prev}() }}
"#
- );
+ )
+ .into();
let id = if main {
futures::executor::block_on(
@@ -3559,8 +3579,7 @@ pub mod tests {
});
let specifier = crate::resolve_url("file:///0.js").unwrap();
- let source_code =
- r#"export function f0() { return "hello world" }"#.to_string();
+ let source_code = r#"export function f0() { return "hello world" }"#.into();
let id = futures::executor::block_on(
runtime.load_side_module(&specifier, Some(source_code)),
)
@@ -3620,7 +3639,7 @@ pub mod tests {
return mod.f400() + " " + Deno.core.ops.op_test();
})();"#
.to_string();
- let val = runtime3.execute_script(".", &source_code).unwrap();
+ let val = runtime3.execute_script(".", source_code).unwrap();
let val = futures::executor::block_on(runtime3.resolve_value(val)).unwrap();
{
let scope = &mut runtime3.handle_scope();
@@ -4163,7 +4182,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
) -> Pin<Box<ModuleSourceFuture>> {
async move {
Ok(ModuleSource {
- code: b"console.log('hello world');".to_vec().into_boxed_slice(),
+ 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,
@@ -4180,7 +4199,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')".to_string();
+ let source_code = "Deno.core.print('hello\\n')".into();
let module_id = futures::executor::block_on(
runtime.load_main_module(&specifier, Some(source_code)),
@@ -4273,7 +4292,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
.execute_script(
runtime.v8_isolate(),
"",
- &format!(
+ format!(
r#"
globalThis.rejectValue = undefined;
@@ -4282,7 +4301,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
}});
Deno.core.opAsync("op_void_async").then(() => Promise.reject({number}));
"#
- ),
+ )
)
.unwrap();
}
@@ -4344,7 +4363,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
async move {
Ok(ModuleSource {
- code: source.as_bytes().to_vec().into_boxed_slice(),
+ code: source.into(),
module_url_specified: "file:///main.js".to_string(),
module_url_found: "file:///main.js".to_string(),
module_type: ModuleType::JavaScript,
@@ -4858,7 +4877,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
async move {
Ok(ModuleSource {
- code: source.as_bytes().to_vec().into_boxed_slice(),
+ code: source.into(),
module_url_specified: "file:///main.js".to_string(),
module_url_found: "file:///main.js".to_string(),
module_type: ModuleType::JavaScript,