Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: upgrade V8 to 12.8 #24693

Merged
merged 3 commits into from
Jul 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ repository = "https://github.com/denoland/deno"

[workspace.dependencies]
deno_ast = { version = "=0.41.2", features = ["transpiling"] }
deno_core = { version = "0.299.0" }
deno_core = { version = "0.300.0" }

deno_bench_util = { version = "0.158.0", path = "./bench_util" }
deno_lockfile = "0.20.0"
Expand Down
15 changes: 14 additions & 1 deletion cli/module_loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ use crate::util::text_encoding::code_without_source_map;
use crate::util::text_encoding::source_map_from_code;
use crate::worker::ModuleLoaderAndSourceMapGetter;
use crate::worker::ModuleLoaderFactory;

use deno_ast::MediaType;
use deno_core::anyhow::anyhow;
use deno_core::anyhow::bail;
Expand Down Expand Up @@ -64,6 +63,7 @@ use deno_graph::Module;
use deno_graph::ModuleGraph;
use deno_graph::Resolution;
use deno_runtime::code_cache;
use deno_runtime::deno_node::create_host_defined_options;
use deno_runtime::deno_permissions::PermissionsContainer;
use deno_semver::npm::NpmPackageReqReference;
use node_resolver::NodeResolutionMode;
Expand Down Expand Up @@ -725,6 +725,19 @@ impl<TGraphContainer: ModuleGraphContainer> ModuleLoader
Ok(specifier)
}

fn get_host_defined_options<'s>(
&self,
scope: &mut deno_core::v8::HandleScope<'s>,
name: &str,
) -> Option<deno_core::v8::Local<'s, deno_core::v8::Data>> {
let name = deno_core::ModuleSpecifier::parse(name).ok()?;
if self.0.shared.node_resolver.in_npm_package(&name) {
Some(create_host_defined_options(scope))
} else {
None
}
}

fn load(
&self,
specifier: &ModuleSpecifier,
Expand Down
14 changes: 14 additions & 0 deletions cli/standalone/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use deno_core::ResolutionKind;
use deno_npm::npm_rc::ResolvedNpmRc;
use deno_package_json::PackageJsonDepValue;
use deno_runtime::deno_fs;
use deno_runtime::deno_node::create_host_defined_options;
use deno_runtime::deno_node::NodeResolver;
use deno_runtime::deno_permissions::Permissions;
use deno_runtime::deno_permissions::PermissionsContainer;
Expand Down Expand Up @@ -267,6 +268,19 @@ impl ModuleLoader for EmbeddedModuleLoader {
}
}

fn get_host_defined_options<'s>(
&self,
scope: &mut deno_core::v8::HandleScope<'s>,
name: &str,
) -> Option<deno_core::v8::Local<'s, deno_core::v8::Data>> {
let name = deno_core::ModuleSpecifier::parse(name).ok()?;
if self.shared.node_resolver.in_npm_package(&name) {
Some(create_host_defined_options(scope))
} else {
None
}
}

fn load(
&self,
original_specifier: &ModuleSpecifier,
Expand Down
95 changes: 25 additions & 70 deletions ext/node/global.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.

use std::mem::MaybeUninit;

use deno_core::v8;
use deno_core::v8::GetPropertyNamesArgs;
use deno_core::v8::MapFnTo;

use crate::NodeResolverRc;

// NOTE(bartlomieju): somehow calling `.map_fn_to()` multiple times on a function
// returns two different pointers. That shouldn't be the case as `.map_fn_to()`
// creates a thin wrapper that is a pure function. @piscisaureus suggests it
Expand All @@ -17,8 +13,8 @@ use crate::NodeResolverRc;
thread_local! {
pub static GETTER_MAP_FN: v8::NamedPropertyGetterCallback<'static> = getter.map_fn_to();
pub static SETTER_MAP_FN: v8::NamedPropertySetterCallback<'static> = setter.map_fn_to();
pub static QUERY_MAP_FN: v8::NamedPropertyGetterCallback<'static> = query.map_fn_to();
pub static DELETER_MAP_FN: v8::NamedPropertyGetterCallback<'static> = deleter.map_fn_to();
pub static QUERY_MAP_FN: v8::NamedPropertyQueryCallback<'static> = query.map_fn_to();
pub static DELETER_MAP_FN: v8::NamedPropertyDeleterCallback<'static> = deleter.map_fn_to();
pub static ENUMERATOR_MAP_FN: v8::NamedPropertyEnumeratorCallback<'static> = enumerator.map_fn_to();
pub static DEFINER_MAP_FN: v8::NamedPropertyDefinerCallback<'static> = definer.map_fn_to();
pub static DESCRIPTOR_MAP_FN: v8::NamedPropertyGetterCallback<'static> = descriptor.map_fn_to();
Expand Down Expand Up @@ -93,8 +89,6 @@ enum Mode {
}

struct GlobalsStorage {
reflect_get: v8::Global<v8::Function>,
reflect_set: v8::Global<v8::Function>,
deno_globals: v8::Global<v8::Object>,
node_globals: v8::Global<v8::Object>,
}
Expand Down Expand Up @@ -154,27 +148,6 @@ pub fn global_object_middleware<'s>(
.unwrap();
assert_ne!(global, object_prototype);

// Get the Reflect object
let reflect_key =
v8::String::new_external_onebyte_static(scope, b"Reflect").unwrap();
let reflect = global
.get(scope, reflect_key.into())
.unwrap()
.to_object(scope)
.unwrap();

// Get the Reflect.get function.
let get_key = v8::String::new_external_onebyte_static(scope, b"get").unwrap();
let reflect_get = reflect.get(scope, get_key.into()).unwrap();
let reflect_get_fn: v8::Local<v8::Function> = reflect_get.try_into().unwrap();
let reflect_get = v8::Global::new(scope, reflect_get_fn);

// Get the Reflect.set function.
let set_key = v8::String::new_external_onebyte_static(scope, b"set").unwrap();
let reflect_set = reflect.get(scope, set_key.into()).unwrap();
let reflect_set_fn: v8::Local<v8::Function> = reflect_set.try_into().unwrap();
let reflect_set = v8::Global::new(scope, reflect_set_fn);

// globalThis.__bootstrap.ext_node_denoGlobals and
// globalThis.__bootstrap.ext_node_nodeGlobals are the objects that contain
// the Deno and Node specific globals respectively. If they do not yet exist
Expand Down Expand Up @@ -231,8 +204,6 @@ pub fn global_object_middleware<'s>(

// Create the storage struct and store it in a context slot.
let storage = GlobalsStorage {
reflect_get,
reflect_set,
deno_globals,
node_globals,
};
Expand Down Expand Up @@ -264,19 +235,19 @@ fn is_managed_key(
}

fn current_mode(scope: &mut v8::HandleScope) -> Mode {
let Some(v8_string) =
v8::StackTrace::current_script_name_or_source_url(scope)
let Some(host_defined_options) = scope.get_current_host_defined_options()
else {
return Mode::Deno;
};
let op_state = deno_core::JsRuntime::op_state_from(scope);
let op_state = op_state.borrow();
let Some(node_resolver) = op_state.try_borrow::<NodeResolverRc>() else {
return Mode::Deno;
// SAFETY: host defined options must always be a PrimitiveArray in current V8.
let host_defined_options = unsafe {
v8::Local::<v8::PrimitiveArray>::cast_unchecked(host_defined_options)
};
let mut buffer = [MaybeUninit::uninit(); 2048];
let str = v8_string.to_rust_cow_lossy(scope, &mut buffer);
if str.starts_with("node:") || node_resolver.in_npm_package_with_cache(str) {
if host_defined_options.length() < 1 {
return Mode::Deno;
}
let is_node = host_defined_options.get(scope, 0).is_true();
if is_node {
Mode::Node
} else {
Mode::Deno
Expand All @@ -297,25 +268,17 @@ pub fn getter<'s>(
let mode = current_mode(scope);

let context = scope.get_current_context();
let (reflect_get, inner) = {
let inner = {
let storage = context.get_slot::<GlobalsStorage>(scope).unwrap();
let reflect_get = storage.reflect_get.clone();
let inner = storage.inner_for_mode(mode);
(reflect_get, inner)
storage.inner_for_mode(mode)
};
let reflect_get = v8::Local::new(scope, reflect_get);
let inner = v8::Local::new(scope, inner);

if !inner.has_own_property(scope, key).unwrap_or(false) {
return v8::Intercepted::No;
}

let undefined = v8::undefined(scope);
let Some(value) = reflect_get.call(
scope,
undefined.into(),
&[inner.into(), key.into(), this.into()],
) else {
let Some(value) = inner.get_with_receiver(scope, key.into(), this) else {
return v8::Intercepted::No;
};

Expand All @@ -328,7 +291,7 @@ pub fn setter<'s>(
key: v8::Local<'s, v8::Name>,
value: v8::Local<'s, v8::Value>,
args: v8::PropertyCallbackArguments<'s>,
mut rv: v8::ReturnValue,
mut rv: v8::ReturnValue<()>,
) -> v8::Intercepted {
if !is_managed_key(scope, key) {
return v8::Intercepted::No;
Expand All @@ -338,34 +301,26 @@ pub fn setter<'s>(
let mode = current_mode(scope);

let context = scope.get_current_context();
let (reflect_set, inner) = {
let inner = {
let storage = context.get_slot::<GlobalsStorage>(scope).unwrap();
let reflect_set = storage.reflect_set.clone();
let inner = storage.inner_for_mode(mode);
(reflect_set, inner)
storage.inner_for_mode(mode)
};
let reflect_set = v8::Local::new(scope, reflect_set);
let inner = v8::Local::new(scope, inner);

let undefined = v8::undefined(scope);

let Some(success) = reflect_set.call(
scope,
undefined.into(),
&[inner.into(), key.into(), value, this.into()],
) else {
let Some(success) = inner.set_with_receiver(scope, key.into(), value, this)
else {
return v8::Intercepted::No;
};

rv.set(success);
rv.set_bool(success);
v8::Intercepted::Yes
}

pub fn query<'s>(
scope: &mut v8::HandleScope<'s>,
key: v8::Local<'s, v8::Name>,
_args: v8::PropertyCallbackArguments<'s>,
mut rv: v8::ReturnValue,
mut rv: v8::ReturnValue<v8::Integer>,
) -> v8::Intercepted {
if !is_managed_key(scope, key) {
return v8::Intercepted::No;
Expand Down Expand Up @@ -396,7 +351,7 @@ pub fn deleter<'s>(
scope: &mut v8::HandleScope<'s>,
key: v8::Local<'s, v8::Name>,
args: v8::PropertyCallbackArguments<'s>,
mut rv: v8::ReturnValue,
mut rv: v8::ReturnValue<v8::Boolean>,
) -> v8::Intercepted {
if !is_managed_key(scope, key) {
return v8::Intercepted::No;
Expand Down Expand Up @@ -429,7 +384,7 @@ pub fn deleter<'s>(
pub fn enumerator<'s>(
scope: &mut v8::HandleScope<'s>,
_args: v8::PropertyCallbackArguments<'s>,
mut rv: v8::ReturnValue,
mut rv: v8::ReturnValue<v8::Array>,
) {
let mode = current_mode(scope);

Expand All @@ -451,15 +406,15 @@ pub fn enumerator<'s>(
return;
};

rv.set(array.into());
rv.set(array);
}

pub fn definer<'s>(
scope: &mut v8::HandleScope<'s>,
key: v8::Local<'s, v8::Name>,
descriptor: &v8::PropertyDescriptor,
args: v8::PropertyCallbackArguments<'s>,
_rv: v8::ReturnValue,
_rv: v8::ReturnValue<()>,
) -> v8::Intercepted {
if !is_managed_key(scope, key) {
return v8::Intercepted::No;
Expand Down
21 changes: 15 additions & 6 deletions ext/node/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -655,8 +655,8 @@ deno_core::extension!(deno_node,
});
vm::DELETER_MAP_FN.with(|deleter| {
external_references.push(ExternalReference {
named_getter: *deleter,
},);
named_deleter: *deleter,
});
});
vm::ENUMERATOR_MAP_FN.with(|enumerator| {
external_references.push(ExternalReference {
Expand Down Expand Up @@ -686,7 +686,7 @@ deno_core::extension!(deno_node,
});
vm::INDEXED_DELETER_MAP_FN.with(|deleter| {
external_references.push(ExternalReference {
indexed_getter: *deleter,
indexed_deleter: *deleter,
});
});
vm::INDEXED_DEFINER_MAP_FN.with(|definer| {
Expand All @@ -712,13 +712,13 @@ deno_core::extension!(deno_node,
});
global::QUERY_MAP_FN.with(|query| {
external_references.push(ExternalReference {
named_getter: *query,
named_query: *query,
});
});
global::DELETER_MAP_FN.with(|deleter| {
external_references.push(ExternalReference {
named_getter: *deleter,
},);
named_deleter: *deleter,
});
});
global::ENUMERATOR_MAP_FN.with(|enumerator| {
external_references.push(ExternalReference {
Expand Down Expand Up @@ -842,3 +842,12 @@ impl<'a> deno_package_json::fs::DenoPkgJsonFs for DenoPkgJsonFsAdapter<'a> {
.map_err(|err| err.into_io_error())
}
}

pub fn create_host_defined_options<'s>(
scope: &mut v8::HandleScope<'s>,
) -> v8::Local<'s, v8::Data> {
let host_defined_options = v8::PrimitiveArray::new(scope, 1);
let value = v8::Boolean::new(scope, true);
host_defined_options.set(scope, 0, value.into());
host_defined_options.into()
}
Loading