summaryrefslogtreecommitdiff
path: root/ext/node
diff options
context:
space:
mode:
authorsnek <snek@deno.com>2024-07-31 16:22:34 -0700
committerGitHub <noreply@github.com>2024-07-31 23:22:34 +0000
commitf57745fe2106a4d26dd2209e1b2cacb2d6430245 (patch)
treef3ea0c476940b296ec3cc507adca05088ed947be /ext/node
parentfbcd250bc8ffb3b577afca7131d1d37f55eb47a2 (diff)
feat: upgrade V8 to 12.8 (#24693)
- upgrade to v8 12.8 - optimizes DataView bigint methods - fixes global interceptors - includes CPED methods for ALS - fix global resolution - makes global resolution consistent using host_defined_options. originally a separate patch but due to the global interceptor bug it needs to be included in this pr for all tests to pass.
Diffstat (limited to 'ext/node')
-rw-r--r--ext/node/global.rs95
-rw-r--r--ext/node/lib.rs21
-rw-r--r--ext/node/ops/vm_internal.rs40
-rw-r--r--ext/node/polyfills/01_require.js30
4 files changed, 93 insertions, 93 deletions
diff --git a/ext/node/global.rs b/ext/node/global.rs
index 618e68494..2434a64fd 100644
--- a/ext/node/global.rs
+++ b/ext/node/global.rs
@@ -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
@@ -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();
@@ -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>,
}
@@ -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
@@ -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,
};
@@ -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
@@ -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;
};
@@ -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;
@@ -338,26 +301,18 @@ 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
}
@@ -365,7 +320,7 @@ 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;
@@ -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;
@@ -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);
@@ -451,7 +406,7 @@ pub fn enumerator<'s>(
return;
};
- rv.set(array.into());
+ rv.set(array);
}
pub fn definer<'s>(
@@ -459,7 +414,7 @@ pub fn definer<'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;
diff --git a/ext/node/lib.rs b/ext/node/lib.rs
index 987d52520..a4a757996 100644
--- a/ext/node/lib.rs
+++ b/ext/node/lib.rs
@@ -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 {
@@ -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| {
@@ -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 {
@@ -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()
+}
diff --git a/ext/node/ops/vm_internal.rs b/ext/node/ops/vm_internal.rs
index a9c13a582..ca3cac41f 100644
--- a/ext/node/ops/vm_internal.rs
+++ b/ext/node/ops/vm_internal.rs
@@ -1,5 +1,6 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+use crate::create_host_defined_options;
use deno_core::error::type_error;
use deno_core::error::AnyError;
use deno_core::v8;
@@ -19,7 +20,22 @@ impl ContextifyScript {
scope: &mut v8::HandleScope,
source_str: v8::Local<v8::String>,
) -> Result<Self, AnyError> {
- let source = v8::script_compiler::Source::new(source_str, None);
+ let resource_name = v8::undefined(scope);
+ let host_defined_options = create_host_defined_options(scope);
+ let origin = v8::ScriptOrigin::new(
+ scope,
+ resource_name.into(),
+ 0,
+ 0,
+ false,
+ 0,
+ None,
+ false,
+ false,
+ false,
+ Some(host_defined_options),
+ );
+ let source = v8::script_compiler::Source::new(source_str, Some(&origin));
let unbound_script = v8::script_compiler::compile_unbound_script(
scope,
@@ -260,7 +276,7 @@ pub fn init_global_template<'a>(
thread_local! {
pub static GETTER_MAP_FN: v8::NamedPropertyGetterCallback<'static> = property_getter.map_fn_to();
pub static SETTER_MAP_FN: v8::NamedPropertySetterCallback<'static> = property_setter.map_fn_to();
- pub static DELETER_MAP_FN: v8::NamedPropertyGetterCallback<'static> = property_deleter.map_fn_to();
+ pub static DELETER_MAP_FN: v8::NamedPropertyDeleterCallback<'static> = property_deleter.map_fn_to();
pub static ENUMERATOR_MAP_FN: v8::NamedPropertyEnumeratorCallback<'static> = property_enumerator.map_fn_to();
pub static DEFINER_MAP_FN: v8::NamedPropertyDefinerCallback<'static> = property_definer.map_fn_to();
pub static DESCRIPTOR_MAP_FN: v8::NamedPropertyGetterCallback<'static> = property_descriptor.map_fn_to();
@@ -269,7 +285,7 @@ thread_local! {
thread_local! {
pub static INDEXED_GETTER_MAP_FN: v8::IndexedPropertyGetterCallback<'static> = indexed_property_getter.map_fn_to();
pub static INDEXED_SETTER_MAP_FN: v8::IndexedPropertySetterCallback<'static> = indexed_property_setter.map_fn_to();
- pub static INDEXED_DELETER_MAP_FN: v8::IndexedPropertyGetterCallback<'static> = indexed_property_deleter.map_fn_to();
+ pub static INDEXED_DELETER_MAP_FN: v8::IndexedPropertyDeleterCallback<'static> = indexed_property_deleter.map_fn_to();
pub static INDEXED_DEFINER_MAP_FN: v8::IndexedPropertyDefinerCallback<'static> = indexed_property_definer.map_fn_to();
pub static INDEXED_DESCRIPTOR_MAP_FN: v8::IndexedPropertyGetterCallback<'static> = indexed_property_descriptor.map_fn_to();
}
@@ -362,7 +378,7 @@ fn property_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 {
let Some(ctx) = ContextifyContext::get(scope, args.this()) else {
return v8::Intercepted::No;
@@ -441,7 +457,7 @@ fn property_setter<'s>(
.has_own_property(scope, set_key.into())
.unwrap_or(false)
{
- rv.set(value);
+ rv.set_bool(true);
return v8::Intercepted::Yes;
}
}
@@ -455,7 +471,7 @@ fn property_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 {
let Some(ctx) = ContextifyContext::get(scope, args.this()) else {
return v8::Intercepted::No;
@@ -475,7 +491,7 @@ fn property_deleter<'s>(
fn property_enumerator<'s>(
scope: &mut v8::HandleScope<'s>,
args: v8::PropertyCallbackArguments<'s>,
- mut rv: v8::ReturnValue,
+ mut rv: v8::ReturnValue<v8::Array>,
) {
let Some(ctx) = ContextifyContext::get(scope, args.this()) else {
return;
@@ -490,7 +506,7 @@ fn property_enumerator<'s>(
return;
};
- rv.set(properties.into());
+ rv.set(properties);
}
fn property_definer<'s>(
@@ -498,7 +514,7 @@ fn property_definer<'s>(
key: v8::Local<'s, v8::Name>,
desc: &v8::PropertyDescriptor,
args: v8::PropertyCallbackArguments<'s>,
- _: v8::ReturnValue,
+ _: v8::ReturnValue<()>,
) -> v8::Intercepted {
let Some(ctx) = ContextifyContext::get(scope, args.this()) else {
return v8::Intercepted::No;
@@ -622,7 +638,7 @@ fn indexed_property_setter<'s>(
index: u32,
value: v8::Local<'s, v8::Value>,
args: v8::PropertyCallbackArguments<'s>,
- rv: v8::ReturnValue,
+ rv: v8::ReturnValue<()>,
) -> v8::Intercepted {
let key = uint32_to_name(scope, index);
property_setter(scope, key, value, args, rv)
@@ -632,7 +648,7 @@ fn indexed_property_deleter<'s>(
scope: &mut v8::HandleScope<'s>,
index: u32,
args: v8::PropertyCallbackArguments<'s>,
- mut rv: v8::ReturnValue,
+ mut rv: v8::ReturnValue<v8::Boolean>,
) -> v8::Intercepted {
let Some(ctx) = ContextifyContext::get(scope, args.this()) else {
return v8::Intercepted::No;
@@ -656,7 +672,7 @@ fn indexed_property_definer<'s>(
index: u32,
descriptor: &v8::PropertyDescriptor,
args: v8::PropertyCallbackArguments<'s>,
- rv: v8::ReturnValue,
+ rv: v8::ReturnValue<()>,
) -> v8::Intercepted {
let key = uint32_to_name(scope, index);
property_definer(scope, key, descriptor, args, rv)
diff --git a/ext/node/polyfills/01_require.js b/ext/node/polyfills/01_require.js
index 94d6e90e0..f71e009ba 100644
--- a/ext/node/polyfills/01_require.js
+++ b/ext/node/polyfills/01_require.js
@@ -976,9 +976,14 @@ function wrapSafe(
filename,
content,
cjsModuleInstance,
+ format,
) {
const wrapper = Module.wrap(content);
- const [f, err] = core.evalContext(wrapper, `file://${filename}`);
+ const [f, err] = core.evalContext(
+ wrapper,
+ url.pathToFileURL(filename).toString(),
+ [format !== "module"],
+ );
if (err) {
if (process.mainModule === cjsModuleInstance) {
enrichCJSError(err.thrown);
@@ -995,8 +1000,16 @@ function wrapSafe(
return f;
}
-Module.prototype._compile = function (content, filename) {
- const compiledWrapper = wrapSafe(filename, content, this);
+Module.prototype._compile = function (content, filename, format) {
+ const compiledWrapper = wrapSafe(filename, content, this, format);
+
+ if (format === "module") {
+ // TODO(https://github.com/denoland/deno/issues/24822): implement require esm
+ throw createRequireEsmError(
+ filename,
+ moduleParentCache.get(module)?.filename,
+ );
+ }
const dirname = pathDirname(filename);
const require = makeRequireFunction(this);
@@ -1053,17 +1066,24 @@ Module.prototype._compile = function (content, filename) {
Module._extensions[".js"] = function (module, filename) {
const content = op_require_read_file(filename);
+ let format;
if (StringPrototypeEndsWith(filename, ".js")) {
const pkg = op_require_read_closest_package_json(filename);
- if (pkg && pkg.typ === "module") {
+ if (pkg?.typ === "module") {
+ // TODO(https://github.com/denoland/deno/issues/24822): implement require esm
+ format = "module";
throw createRequireEsmError(
filename,
moduleParentCache.get(module)?.filename,
);
+ } else if (pkg?.type === "commonjs") {
+ format = "commonjs";
}
+ } else if (StringPrototypeEndsWith(filename, ".cjs")) {
+ format = "commonjs";
}
- module._compile(content, filename);
+ module._compile(content, filename, format);
};
function createRequireEsmError(filename, parent) {