1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-21 15:04:11 -05:00

perf(core): preserve ops between snapshots (#18080)

This commit changes the build process in a way that preserves already
registered ops in the snapshot. This allows us to skip creating hundreds of
"v8::String" on each startup, but sadly there is still some op registration
going on startup (however we're registering 49 ops instead of >200 ops). 

This situation could be further improved, by moving some of the ops 
from "runtime/" to a separate extension crates.

---------

Co-authored-by: Divy Srivastava <dj.srivastava23@gmail.com>
This commit is contained in:
Bartek Iwańczuk 2023-03-18 07:51:21 -04:00 committed by GitHub
parent 9bfa8dc90c
commit 4b6305f4f2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
54 changed files with 278 additions and 125 deletions

View file

@ -5,7 +5,6 @@ use std::path::PathBuf;
use deno_core::snapshot_util::*; use deno_core::snapshot_util::*;
use deno_core::Extension; use deno_core::Extension;
use deno_core::ExtensionBuilder;
use deno_core::ExtensionFileSource; use deno_core::ExtensionFileSource;
use deno_core::ExtensionFileSourceCode; use deno_core::ExtensionFileSourceCode;
use deno_runtime::deno_cache::SqliteBackedCache; use deno_runtime::deno_cache::SqliteBackedCache;
@ -318,7 +317,7 @@ deno_core::extension!(
dir "js", dir "js",
"40_testing.js" "40_testing.js"
], ],
customizer = |ext: &mut ExtensionBuilder| { customizer = |ext: &mut deno_core::ExtensionBuilder| {
ext.esm(vec![ExtensionFileSource { ext.esm(vec![ExtensionFileSource {
specifier: "runtime/js/99_main.js".to_string(), specifier: "runtime/js/99_main.js".to_string(),
code: ExtensionFileSourceCode::LoadedFromFsDuringSnapshot( code: ExtensionFileSourceCode::LoadedFromFsDuringSnapshot(

View file

@ -2843,6 +2843,9 @@ deno_core::extension!(deno_tsc,
options.performance, options.performance,
)); ));
}, },
customizer = |ext: &mut deno_core::ExtensionBuilder| {
ext.force_op_registration();
},
); );
/// Instruct a language server runtime to start the language server and provide /// Instruct a language server runtime to start the language server and provide

View file

@ -38,6 +38,9 @@ deno_core::extension!(deno_bench,
state.put(options.sender); state.put(options.sender);
state.put(options.filter); state.put(options.filter);
}, },
customizer = |ext: &mut deno_core::ExtensionBuilder| {
ext.force_op_registration();
},
); );
#[derive(Clone)] #[derive(Clone)]

View file

@ -21,6 +21,9 @@ deno_core::extension!(deno_cli,
state = |state, options| { state = |state, options| {
state.put(options.ps); state.put(options.ps);
}, },
customizer = |ext: &mut deno_core::ExtensionBuilder| {
ext.force_op_registration();
},
); );
#[op] #[op]

View file

@ -44,6 +44,9 @@ deno_core::extension!(deno_test,
state.put(options.fail_fast_tracker); state.put(options.fail_fast_tracker);
state.put(options.filter); state.put(options.filter);
}, },
customizer = |ext: &mut deno_core::ExtensionBuilder| {
ext.force_op_registration();
},
); );
#[derive(Clone)] #[derive(Clone)]

View file

@ -114,7 +114,13 @@ pub fn get_types_declaration_file_text(unstable: bool) -> String {
} }
fn get_asset_texts_from_new_runtime() -> Result<Vec<AssetText>, AnyError> { fn get_asset_texts_from_new_runtime() -> Result<Vec<AssetText>, AnyError> {
deno_core::extension!(deno_cli_tsc, ops_fn = deno_ops,); deno_core::extension!(
deno_cli_tsc,
ops_fn = deno_ops,
customizer = |ext: &mut deno_core::ExtensionBuilder| {
ext.force_op_registration();
},
);
// the assets are stored within the typescript isolate, so take them out of there // the assets are stored within the typescript isolate, so take them out of there
let mut runtime = JsRuntime::new(RuntimeOptions { let mut runtime = JsRuntime::new(RuntimeOptions {
@ -846,6 +852,9 @@ pub fn exec(request: Request) -> Result<Response, AnyError> {
.unwrap(), .unwrap(),
)); ));
}, },
customizer = |ext: &mut deno_core::ExtensionBuilder| {
ext.force_op_registration();
},
); );
let startup_source = "globalThis.startup({ legacyFlag: false })"; let startup_source = "globalThis.startup({ legacyFlag: false })";

View file

@ -19,24 +19,22 @@ use crate::snapshot_util::SnapshotOptions;
use crate::JsRealm; use crate::JsRealm;
use crate::JsRuntime; use crate::JsRuntime;
pub(crate) fn external_references( pub(crate) fn external_references(ops: &[OpCtx]) -> v8::ExternalReferences {
ops: &[OpCtx], // Overallocate a bit, it's better than having to resize the vector.
snapshot_options: SnapshotOptions, let mut references = Vec::with_capacity(4 + ops.len() * 4);
) -> v8::ExternalReferences {
let mut references = vec![ references.push(v8::ExternalReference {
v8::ExternalReference {
function: call_console.map_fn_to(), function: call_console.map_fn_to(),
}, });
v8::ExternalReference { references.push(v8::ExternalReference {
function: import_meta_resolve.map_fn_to(), function: import_meta_resolve.map_fn_to(),
}, });
v8::ExternalReference { references.push(v8::ExternalReference {
function: catch_dynamic_import_promise_error.map_fn_to(), function: catch_dynamic_import_promise_error.map_fn_to(),
}, });
v8::ExternalReference { references.push(v8::ExternalReference {
function: empty_fn.map_fn_to(), function: empty_fn.map_fn_to(),
}, });
];
for ctx in ops { for ctx in ops {
let ctx_ptr = ctx as *const OpCtx as _; let ctx_ptr = ctx as *const OpCtx as _;
@ -44,12 +42,13 @@ pub(crate) fn external_references(
references.push(v8::ExternalReference { references.push(v8::ExternalReference {
function: ctx.decl.v8_fn_ptr, function: ctx.decl.v8_fn_ptr,
}); });
if !snapshot_options.will_snapshot() {
if let Some(fast_fn) = &ctx.decl.fast_fn { if let Some(fast_fn) = &ctx.decl.fast_fn {
references.push(v8::ExternalReference { references.push(v8::ExternalReference {
pointer: fast_fn.function() as _, pointer: fast_fn.function() as _,
}); });
} references.push(v8::ExternalReference {
pointer: ctx.fast_fn_c_info.unwrap().as_ptr() as _,
});
} }
} }
@ -114,9 +113,9 @@ pub(crate) fn initialize_context<'s>(
v8::String::new_external_onebyte_static(scope, b"core").unwrap(); v8::String::new_external_onebyte_static(scope, b"core").unwrap();
let ops_str = v8::String::new_external_onebyte_static(scope, b"ops").unwrap(); let ops_str = v8::String::new_external_onebyte_static(scope, b"ops").unwrap();
let ops_obj = if snapshot_options.loaded() {
// Snapshot already registered `Deno.core.ops` but // Snapshot already registered `Deno.core.ops` but
// extensions may provide ops that aren't part of the snapshot. // extensions may provide ops that aren't part of the snapshot.
if snapshot_options.loaded() {
// Grab the Deno.core.ops object & init it // Grab the Deno.core.ops object & init it
let deno_obj: v8::Local<v8::Object> = global let deno_obj: v8::Local<v8::Object> = global
.get(scope, deno_str.into()) .get(scope, deno_str.into())
@ -133,13 +132,9 @@ pub(crate) fn initialize_context<'s>(
.expect("Deno.core.ops to exist") .expect("Deno.core.ops to exist")
.try_into() .try_into()
.unwrap(); .unwrap();
for ctx in op_ctxs { ops_obj
add_op_to_deno_core_ops(scope, ops_obj, ctx, snapshot_options); } else {
} // globalThis.Deno = { core: { } };
return context;
}
// global.Deno = { core: { } };
let deno_obj = v8::Object::new(scope); let deno_obj = v8::Object::new(scope);
global.set(scope, deno_str.into(), deno_obj.into()); global.set(scope, deno_str.into(), deno_obj.into());
@ -159,8 +154,36 @@ pub(crate) fn initialize_context<'s>(
// Bind functions to Deno.core.ops.* // Bind functions to Deno.core.ops.*
let ops_obj = v8::Object::new(scope); let ops_obj = v8::Object::new(scope);
core_obj.set(scope, ops_str.into(), ops_obj.into()); core_obj.set(scope, ops_str.into(), ops_obj.into());
for ctx in op_ctxs { ops_obj
add_op_to_deno_core_ops(scope, ops_obj, ctx, snapshot_options); };
if matches!(snapshot_options, SnapshotOptions::Load) {
// Only register ops that have `force_registration` flag set to true,
// the remaining ones should already be in the snapshot.
for op_ctx in op_ctxs
.iter()
.filter(|op_ctx| op_ctx.decl.force_registration)
{
add_op_to_deno_core_ops(scope, ops_obj, op_ctx);
}
} else if matches!(snapshot_options, SnapshotOptions::CreateFromExisting) {
// Register all ops, probing for which ones are already registered.
for op_ctx in op_ctxs {
let key = v8::String::new_external_onebyte_static(
scope,
op_ctx.decl.name.as_bytes(),
)
.unwrap();
if ops_obj.get(scope, key.into()).is_some() {
continue;
}
add_op_to_deno_core_ops(scope, ops_obj, op_ctx);
}
} else {
// In other cases register all ops unconditionally.
for op_ctx in op_ctxs {
add_op_to_deno_core_ops(scope, ops_obj, op_ctx);
}
} }
context context
@ -183,7 +206,6 @@ fn add_op_to_deno_core_ops(
scope: &mut v8::HandleScope<'_>, scope: &mut v8::HandleScope<'_>,
obj: v8::Local<v8::Object>, obj: v8::Local<v8::Object>,
op_ctx: &OpCtx, op_ctx: &OpCtx,
snapshot_options: SnapshotOptions,
) { ) {
let op_ctx_ptr = op_ctx as *const OpCtx as *const c_void; let op_ctx_ptr = op_ctx as *const OpCtx as *const c_void;
let key = let key =
@ -193,24 +215,14 @@ fn add_op_to_deno_core_ops(
let builder = v8::FunctionTemplate::builder_raw(op_ctx.decl.v8_fn_ptr) let builder = v8::FunctionTemplate::builder_raw(op_ctx.decl.v8_fn_ptr)
.data(external.into()); .data(external.into());
// TODO(bartlomieju): this should be cleaned up once we update Fast Calls API let templ = if let Some(fast_function) = &op_ctx.decl.fast_fn {
// If this is a fast op, we don't want it to be in the snapshot. builder.build_fast(
// Only initialize once snapshot is loaded. scope,
let maybe_fast_fn = &**fast_function,
if op_ctx.decl.fast_fn.is_some() && snapshot_options.loaded() { Some(op_ctx.fast_fn_c_info.unwrap().as_ptr()),
&op_ctx.decl.fast_fn None,
} else { None,
&None )
};
let templ = if let Some(fast_function) = maybe_fast_fn {
// Don't initialize fast ops when snapshotting, the external references count mismatch.
if !snapshot_options.will_snapshot() {
// TODO(@littledivy): Support fast api overloads in ops.
builder.build_fast(scope, &**fast_function, None, None, None)
} else {
builder.build(scope)
}
} else { } else {
builder.build(scope) builder.build(scope)
}; };

View file

@ -53,6 +53,7 @@ pub struct OpDecl {
pub is_unstable: bool, pub is_unstable: bool,
pub is_v8: bool, pub is_v8: bool,
pub fast_fn: Option<Box<dyn FastFunction>>, pub fast_fn: Option<Box<dyn FastFunction>>,
pub force_registration: bool,
} }
impl OpDecl { impl OpDecl {
@ -240,6 +241,7 @@ macro_rules! extension {
#[inline(always)] #[inline(always)]
#[allow(unused_variables)] #[allow(unused_variables)]
#[allow(clippy::redundant_closure_call)]
fn with_customizer(ext: &mut $crate::ExtensionBuilder) { fn with_customizer(ext: &mut $crate::ExtensionBuilder) {
$( ($customizer_fn)(ext); )? $( ($customizer_fn)(ext); )?
} }
@ -325,6 +327,7 @@ pub struct Extension {
enabled: bool, enabled: bool,
name: &'static str, name: &'static str,
deps: Option<&'static [&'static str]>, deps: Option<&'static [&'static str]>,
force_op_registration: bool,
} }
// Note: this used to be a trait, but we "downgraded" it to a single concrete type // Note: this used to be a trait, but we "downgraded" it to a single concrete type
@ -394,6 +397,7 @@ impl Extension {
let mut ops = self.ops.take()?; let mut ops = self.ops.take()?;
for op in ops.iter_mut() { for op in ops.iter_mut() {
op.enabled = self.enabled && op.enabled; op.enabled = self.enabled && op.enabled;
op.force_registration = self.force_op_registration;
} }
Some(ops) Some(ops)
} }
@ -447,6 +451,7 @@ pub struct ExtensionBuilder {
event_loop_middleware: Option<Box<OpEventLoopFn>>, event_loop_middleware: Option<Box<OpEventLoopFn>>,
name: &'static str, name: &'static str,
deps: &'static [&'static str], deps: &'static [&'static str],
force_op_registration: bool,
} }
impl ExtensionBuilder { impl ExtensionBuilder {
@ -511,6 +516,15 @@ impl ExtensionBuilder {
self self
} }
/// Mark that ops from this extension should be added to `Deno.core.ops`
/// unconditionally. This is useful is some ops are not available
/// during snapshotting, as ops are not registered by default when a
/// `JsRuntime` is created with an existing snapshot.
pub fn force_op_registration(&mut self) -> &mut Self {
self.force_op_registration = true;
self
}
/// Consume the [`ExtensionBuilder`] and return an [`Extension`]. /// Consume the [`ExtensionBuilder`] and return an [`Extension`].
pub fn take(self) -> Extension { pub fn take(self) -> Extension {
let js_files = Some(self.js); let js_files = Some(self.js);
@ -528,6 +542,7 @@ impl ExtensionBuilder {
initialized: false, initialized: false,
enabled: true, enabled: true,
name: self.name, name: self.name,
force_op_registration: self.force_op_registration,
deps, deps,
} }
} }
@ -549,6 +564,7 @@ impl ExtensionBuilder {
enabled: true, enabled: true,
name: self.name, name: self.name,
deps, deps,
force_op_registration: self.force_op_registration,
} }
} }
} }

View file

@ -19,10 +19,13 @@ use std::cell::RefCell;
use std::ops::Deref; use std::ops::Deref;
use std::ops::DerefMut; use std::ops::DerefMut;
use std::pin::Pin; use std::pin::Pin;
use std::ptr::NonNull;
use std::rc::Rc; use std::rc::Rc;
use std::rc::Weak; use std::rc::Weak;
use std::task::Context; use std::task::Context;
use std::task::Poll; use std::task::Poll;
use v8::fast_api::CFunctionInfo;
use v8::fast_api::CTypeInfo;
/// Wrapper around a Future, which causes that Future to be polled immediately. /// Wrapper around a Future, which causes that Future to be polled immediately.
/// ///
@ -155,11 +158,45 @@ pub struct OpCtx {
pub id: OpId, pub id: OpId,
pub state: Rc<RefCell<OpState>>, pub state: Rc<RefCell<OpState>>,
pub decl: Rc<OpDecl>, pub decl: Rc<OpDecl>,
pub fast_fn_c_info: Option<NonNull<v8::fast_api::CFunctionInfo>>,
pub runtime_state: Weak<RefCell<JsRuntimeState>>, pub runtime_state: Weak<RefCell<JsRuntimeState>>,
// Index of the current realm into `JsRuntimeState::known_realms`. // Index of the current realm into `JsRuntimeState::known_realms`.
pub realm_idx: RealmIdx, pub realm_idx: RealmIdx,
} }
impl OpCtx {
pub fn new(
id: OpId,
realm_idx: RealmIdx,
decl: Rc<OpDecl>,
state: Rc<RefCell<OpState>>,
runtime_state: Weak<RefCell<JsRuntimeState>>,
) -> Self {
let mut fast_fn_c_info = None;
if let Some(fast_fn) = &decl.fast_fn {
let args = CTypeInfo::new_from_slice(fast_fn.args());
let ret = CTypeInfo::new(fast_fn.return_type());
// SAFETY: all arguments are coming from the trait and they have
// static lifetime
let c_fn = unsafe {
CFunctionInfo::new(args.as_ptr(), fast_fn.args().len(), ret.as_ptr())
};
fast_fn_c_info = Some(c_fn);
}
OpCtx {
id,
state,
runtime_state,
decl,
realm_idx,
fast_fn_c_info,
}
}
}
/// Maintains the resources and ops inside a JS runtime. /// Maintains the resources and ops inside a JS runtime.
pub struct OpState { pub struct OpState {
pub resource_table: ResourceTable, pub resource_table: ResourceTable,

View file

@ -319,6 +319,7 @@ impl JsRuntime {
DENO_INIT.call_once(move || v8_init(v8_platform, options.will_snapshot)); DENO_INIT.call_once(move || v8_init(v8_platform, options.will_snapshot));
// Add builtins extension // Add builtins extension
// TODO(bartlomieju): remove this in favor of `SnapshotOptions`.
let has_startup_snapshot = options.startup_snapshot.is_some(); let has_startup_snapshot = options.startup_snapshot.is_some();
if !has_startup_snapshot { if !has_startup_snapshot {
options options
@ -375,12 +376,8 @@ impl JsRuntime {
let op_ctxs = ops let op_ctxs = ops
.into_iter() .into_iter()
.enumerate() .enumerate()
.map(|(id, decl)| OpCtx { .map(|(id, decl)| {
id, OpCtx::new(id, 0, Rc::new(decl), op_state.clone(), weak.clone())
state: op_state.clone(),
runtime_state: weak.clone(),
decl: Rc::new(decl),
realm_idx: 0,
}) })
.collect::<Vec<_>>() .collect::<Vec<_>>()
.into_boxed_slice(); .into_boxed_slice();
@ -389,7 +386,7 @@ impl JsRuntime {
options.startup_snapshot.is_some(), options.startup_snapshot.is_some(),
options.will_snapshot, options.will_snapshot,
); );
let refs = bindings::external_references(&op_ctxs, snapshot_options); let refs = bindings::external_references(&op_ctxs);
// V8 takes ownership of external_references. // V8 takes ownership of external_references.
let refs: &'static v8::ExternalReferences = Box::leak(Box::new(refs)); let refs: &'static v8::ExternalReferences = Box::leak(Box::new(refs));
let global_context; let global_context;
@ -398,7 +395,7 @@ impl JsRuntime {
let (mut isolate, snapshot_options) = if snapshot_options.will_snapshot() { let (mut isolate, snapshot_options) = if snapshot_options.will_snapshot() {
let snapshot_creator = let snapshot_creator =
snapshot_util::create_snapshot_creator(refs, options.startup_snapshot); snapshot_util::create_snapshot_creator(refs, options.startup_snapshot);
eprintln!("create snapshot {:#?}", snapshot_options);
let mut isolate = JsRuntime::setup_isolate(snapshot_creator); let mut isolate = JsRuntime::setup_isolate(snapshot_creator);
{ {
let scope = &mut v8::HandleScope::new(&mut isolate); let scope = &mut v8::HandleScope::new(&mut isolate);
@ -460,6 +457,7 @@ impl JsRuntime {
isolate_ptr.write(isolate); isolate_ptr.write(isolate);
isolate_ptr.read() isolate_ptr.read()
}; };
global_context.open(&mut isolate).set_slot( global_context.open(&mut isolate).set_slot(
&mut isolate, &mut isolate,
Rc::new(RefCell::new(ContextState { Rc::new(RefCell::new(ContextState {
@ -620,12 +618,14 @@ impl JsRuntime {
.borrow() .borrow()
.op_ctxs .op_ctxs
.iter() .iter()
.map(|op_ctx| OpCtx { .map(|op_ctx| {
id: op_ctx.id, OpCtx::new(
state: op_ctx.state.clone(), op_ctx.id,
decl: op_ctx.decl.clone(),
runtime_state: op_ctx.runtime_state.clone(),
realm_idx, realm_idx,
op_ctx.decl.clone(),
op_ctx.state.clone(),
op_ctx.runtime_state.clone(),
)
}) })
.collect(); .collect();
@ -927,18 +927,6 @@ impl JsRuntime {
/// ///
/// `Error` can usually be downcast to `JsError`. /// `Error` can usually be downcast to `JsError`.
pub fn snapshot(mut self) -> v8::StartupData { pub fn snapshot(mut self) -> v8::StartupData {
// Nuke Deno.core.ops.* to avoid ExternalReference snapshotting issues
// TODO(@AaronO): make ops stable across snapshots
{
let scope = &mut self.handle_scope();
let o = Self::eval::<v8::Object>(scope, "Deno.core.ops").unwrap();
let names = o.get_own_property_names(scope, Default::default()).unwrap();
for i in 0..names.length() {
let key = names.get_index(scope, i).unwrap();
o.delete(scope, key);
}
}
self.state.borrow_mut().inspector.take(); self.state.borrow_mut().inspector.take();
// Serialize the module map and store its data in the snapshot. // Serialize the module map and store its data in the snapshot.
@ -3556,10 +3544,18 @@ pub mod tests {
} }
} }
#[op]
fn op_test() -> Result<String, Error> {
Ok(String::from("test"))
}
let loader = Rc::new(ModsLoader::default()); let loader = Rc::new(ModsLoader::default());
let mut runtime = JsRuntime::new(RuntimeOptions { let mut runtime = JsRuntime::new(RuntimeOptions {
module_loader: Some(loader.clone()), module_loader: Some(loader.clone()),
will_snapshot: true, will_snapshot: true,
extensions: vec![Extension::builder("text_ext")
.ops(vec![op_test::decl()])
.build()],
..Default::default() ..Default::default()
}); });
@ -3594,6 +3590,9 @@ pub mod tests {
module_loader: Some(loader.clone()), module_loader: Some(loader.clone()),
will_snapshot: true, will_snapshot: true,
startup_snapshot: Some(Snapshot::JustCreated(snapshot)), startup_snapshot: Some(Snapshot::JustCreated(snapshot)),
extensions: vec![Extension::builder("text_ext")
.ops(vec![op_test::decl()])
.build()],
..Default::default() ..Default::default()
}); });
@ -3609,6 +3608,9 @@ pub mod tests {
let mut runtime3 = JsRuntime::new(RuntimeOptions { let mut runtime3 = JsRuntime::new(RuntimeOptions {
module_loader: Some(loader), module_loader: Some(loader),
startup_snapshot: Some(Snapshot::JustCreated(snapshot2)), startup_snapshot: Some(Snapshot::JustCreated(snapshot2)),
extensions: vec![Extension::builder("text_ext")
.ops(vec![op_test::decl()])
.build()],
..Default::default() ..Default::default()
}); });
@ -3616,7 +3618,7 @@ pub mod tests {
let source_code = r#"(async () => { let source_code = r#"(async () => {
const mod = await import("file:///400.js"); const mod = await import("file:///400.js");
return mod.f400(); return mod.f400() + " " + Deno.core.ops.op_test();
})();"# })();"#
.to_string(); .to_string();
let val = runtime3.execute_script(".", &source_code).unwrap(); let val = runtime3.execute_script(".", &source_code).unwrap();
@ -3625,7 +3627,7 @@ pub mod tests {
let scope = &mut runtime3.handle_scope(); let scope = &mut runtime3.handle_scope();
let value = v8::Local::new(scope, val); let value = v8::Local::new(scope, val);
let str_ = value.to_string(scope).unwrap().to_rust_string_lossy(scope); let str_ = value.to_string(scope).unwrap().to_rust_string_lossy(scope);
assert_eq!(str_, "hello world"); assert_eq!(str_, "hello world test");
} }
} }
@ -4600,7 +4602,13 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
Ok(String::from("Test")) Ok(String::from("Test"))
} }
deno_core::extension!(test_ext, ops = [op_test]); deno_core::extension!(
test_ext,
ops = [op_test],
customizer = |ext: &mut deno_core::ExtensionBuilder| {
ext.force_op_registration();
},
);
let mut runtime = JsRuntime::new(RuntimeOptions { let mut runtime = JsRuntime::new(RuntimeOptions {
startup_snapshot: Some(Snapshot::Boxed(snapshot)), startup_snapshot: Some(Snapshot::Boxed(snapshot)),
extensions: vec![test_ext::init_ops()], extensions: vec![test_ext::init_ops()],

View file

@ -121,7 +121,7 @@ fn data_error_to_panic(err: v8::DataError) -> ! {
} }
} }
#[derive(Copy, Clone, PartialEq, Eq)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub(crate) enum SnapshotOptions { pub(crate) enum SnapshotOptions {
Load, Load,
CreateFromExisting, CreateFromExisting,

View file

@ -38,10 +38,10 @@ export function CSI(strings, ...args) {
} }
CSI.kEscape = kEscape; CSI.kEscape = kEscape;
CSI.kClearToLineBeginning = CSI`1K`; CSI.kClearToLineBeginning = `${kEscape}[1K`;
CSI.kClearToLineEnd = CSI`0K`; CSI.kClearToLineEnd = `${kEscape}[0K`;
CSI.kClearLine = CSI`2K`; CSI.kClearLine = `${kEscape}[2K`;
CSI.kClearScreenDown = CSI`0J`; CSI.kClearScreenDown = `${kEscape}[0J`;
// TODO(BridgeAR): Treat combined characters as single character, i.e, // TODO(BridgeAR): Treat combined characters as single character, i.e,
// 'a\u0301' and '\u0301a' (both have the same visual output). // 'a\u0301' and '\u0301a' (both have the same visual output).

View file

@ -145,6 +145,7 @@ impl Op {
is_async: #is_async, is_async: #is_async,
is_unstable: #is_unstable, is_unstable: #is_unstable,
is_v8: #is_v8, is_v8: #is_v8,
force_registration: false,
} }
} }
@ -201,6 +202,7 @@ impl Op {
is_async: #is_async, is_async: #is_async,
is_unstable: #is_unstable, is_unstable: #is_unstable,
is_v8: #is_v8, is_v8: #is_v8,
force_registration: false,
} }
} }

View file

@ -26,6 +26,7 @@ impl op_void_async {
is_async: true, is_async: true,
is_unstable: false, is_unstable: false,
is_v8: false, is_v8: false,
force_registration: false,
} }
} }
#[inline] #[inline]

View file

@ -26,6 +26,7 @@ impl op_async_result {
is_async: true, is_async: true,
is_unstable: false, is_unstable: false,
is_v8: false, is_v8: false,
force_registration: false,
} }
} }
#[inline] #[inline]

View file

@ -26,6 +26,7 @@ impl op_fallback {
is_async: false, is_async: false,
is_unstable: false, is_unstable: false,
is_v8: false, is_v8: false,
force_registration: false,
} }
} }
#[inline] #[inline]

View file

@ -26,6 +26,7 @@ impl op_cow_str {
is_async: false, is_async: false,
is_unstable: false, is_unstable: false,
is_v8: false, is_v8: false,
force_registration: false,
} }
} }
#[inline] #[inline]

View file

@ -26,6 +26,7 @@ impl op_f64_buf {
is_async: false, is_async: false,
is_unstable: false, is_unstable: false,
is_v8: false, is_v8: false,
force_registration: false,
} }
} }
#[inline] #[inline]

View file

@ -22,6 +22,7 @@ impl op_sync_serialize_object_with_numbers_as_keys {
is_async: false, is_async: false,
is_unstable: false, is_unstable: false,
is_v8: false, is_v8: false,
force_registration: false,
} }
} }
#[inline] #[inline]

View file

@ -22,6 +22,7 @@ impl send_stdin {
is_async: true, is_async: true,
is_unstable: false, is_unstable: false,
is_v8: false, is_v8: false,
force_registration: false,
} }
} }
#[inline] #[inline]

View file

@ -22,6 +22,7 @@ impl send_stdin {
is_async: true, is_async: true,
is_unstable: false, is_unstable: false,
is_v8: false, is_v8: false,
force_registration: false,
} }
} }
#[inline] #[inline]

View file

@ -22,6 +22,7 @@ impl op_blob_revoke_object_url {
is_async: false, is_async: false,
is_unstable: false, is_unstable: false,
is_v8: false, is_v8: false,
force_registration: false,
} }
} }
#[inline] #[inline]

View file

@ -26,6 +26,7 @@ impl op_ffi_ptr_value {
is_async: false, is_async: false,
is_unstable: false, is_unstable: false,
is_v8: false, is_v8: false,
force_registration: false,
} }
} }
#[inline] #[inline]

View file

@ -22,6 +22,7 @@ impl op_print {
is_async: false, is_async: false,
is_unstable: false, is_unstable: false,
is_v8: false, is_v8: false,
force_registration: false,
} }
} }
#[inline] #[inline]

View file

@ -26,6 +26,7 @@ impl op_set_exit_code {
is_async: false, is_async: false,
is_unstable: false, is_unstable: false,
is_v8: false, is_v8: false,
force_registration: false,
} }
} }
#[inline] #[inline]

View file

@ -26,6 +26,7 @@ impl foo {
is_async: false, is_async: false,
is_unstable: false, is_unstable: false,
is_v8: false, is_v8: false,
force_registration: false,
} }
} }
#[inline] #[inline]

View file

@ -32,6 +32,7 @@ impl op_foo {
is_async: false, is_async: false,
is_unstable: false, is_unstable: false,
is_v8: false, is_v8: false,
force_registration: false,
} }
} }
#[inline] #[inline]

View file

@ -26,6 +26,7 @@ impl foo {
is_async: false, is_async: false,
is_unstable: false, is_unstable: false,
is_v8: false, is_v8: false,
force_registration: false,
} }
} }
#[inline] #[inline]

View file

@ -26,6 +26,7 @@ impl op_listen {
is_async: false, is_async: false,
is_unstable: false, is_unstable: false,
is_v8: false, is_v8: false,
force_registration: false,
} }
} }
#[inline] #[inline]

View file

@ -32,6 +32,7 @@ impl op_now {
is_async: false, is_async: false,
is_unstable: false, is_unstable: false,
is_v8: false, is_v8: false,
force_registration: false,
} }
} }
#[inline] #[inline]

View file

@ -26,6 +26,7 @@ impl op_add_4 {
is_async: false, is_async: false,
is_unstable: false, is_unstable: false,
is_v8: false, is_v8: false,
force_registration: false,
} }
} }
#[inline] #[inline]

View file

@ -22,6 +22,7 @@ impl op_try_close {
is_async: false, is_async: false,
is_unstable: false, is_unstable: false,
is_v8: false, is_v8: false,
force_registration: false,
} }
} }
#[inline] #[inline]

View file

@ -26,6 +26,7 @@ impl op_string_length {
is_async: false, is_async: false,
is_unstable: false, is_unstable: false,
is_v8: false, is_v8: false,
force_registration: false,
} }
} }
#[inline] #[inline]

View file

@ -22,6 +22,7 @@ impl op_read_sync {
is_async: false, is_async: false,
is_unstable: false, is_unstable: false,
is_v8: false, is_v8: false,
force_registration: false,
} }
} }
#[inline] #[inline]

View file

@ -32,6 +32,7 @@ impl op_ffi_ptr_of {
is_async: false, is_async: false,
is_unstable: false, is_unstable: false,
is_v8: false, is_v8: false,
force_registration: false,
} }
} }
#[inline] #[inline]

View file

@ -26,6 +26,7 @@ impl op_is_proxy {
is_async: false, is_async: false,
is_unstable: false, is_unstable: false,
is_v8: false, is_v8: false,
force_registration: false,
} }
} }
#[inline] #[inline]

View file

@ -26,6 +26,7 @@ impl op_string_length {
is_async: false, is_async: false,
is_unstable: false, is_unstable: false,
is_v8: false, is_v8: false,
force_registration: false,
} }
} }
#[inline] #[inline]

View file

@ -22,6 +22,7 @@ impl op_string_length {
is_async: false, is_async: false,
is_unstable: false, is_unstable: false,
is_v8: false, is_v8: false,
force_registration: false,
} }
} }
#[inline] #[inline]

View file

@ -22,6 +22,7 @@ impl op_bench_now {
is_async: false, is_async: false,
is_unstable: false, is_unstable: false,
is_v8: false, is_v8: false,
force_registration: false,
} }
} }
#[inline] #[inline]

View file

@ -26,6 +26,7 @@ impl op_import_spki_x25519 {
is_async: false, is_async: false,
is_unstable: false, is_unstable: false,
is_v8: false, is_v8: false,
force_registration: false,
} }
} }
#[inline] #[inline]

View file

@ -26,6 +26,7 @@ impl op_unit_result {
is_async: false, is_async: false,
is_unstable: false, is_unstable: false,
is_v8: false, is_v8: false,
force_registration: false,
} }
} }
#[inline] #[inline]

View file

@ -26,6 +26,7 @@ impl op_set_nodelay {
is_async: false, is_async: false,
is_unstable: false, is_unstable: false,
is_v8: false, is_v8: false,
force_registration: false,
} }
} }
#[inline] #[inline]

View file

@ -26,6 +26,7 @@ impl op_unit {
is_async: false, is_async: false,
is_unstable: false, is_unstable: false,
is_v8: false, is_v8: false,
force_registration: false,
} }
} }
#[inline] #[inline]

View file

@ -26,6 +26,7 @@ impl op_wasm {
is_async: false, is_async: false,
is_unstable: false, is_unstable: false,
is_v8: false, is_v8: false,
force_registration: false,
} }
} }
#[inline] #[inline]

View file

@ -30,7 +30,10 @@ use tokio::sync::mpsc;
deno_core::extension!( deno_core::extension!(
deno_fs_events, deno_fs_events,
ops = [op_fs_events_open, op_fs_events_poll] ops = [op_fs_events_open, op_fs_events_poll],
customizer = |ext: &mut deno_core::ExtensionBuilder| {
ext.force_op_registration();
},
); );
struct FsEventsResource { struct FsEventsResource {

View file

@ -30,6 +30,9 @@ use tokio::net::UnixStream;
deno_core::extension!( deno_core::extension!(
deno_http_runtime, deno_http_runtime,
ops = [op_http_start, op_http_upgrade, op_flash_upgrade_http], ops = [op_http_start, op_http_upgrade, op_flash_upgrade_http],
customizer = |ext: &mut deno_core::ExtensionBuilder| {
ext.force_op_registration();
},
); );
#[op] #[op]

View file

@ -48,23 +48,23 @@ deno_core::extension!(
state = |state, options| { state = |state, options| {
state.put::<ExitCode>(options.exit_code); state.put::<ExitCode>(options.exit_code);
}, },
customizer = |ext: &mut deno_core::ExtensionBuilder| {
ext.force_op_registration();
}
); );
deno_core::extension!( deno_core::extension!(
deno_os_worker, deno_os_worker,
ops_fn = deno_ops, ops_fn = deno_ops,
middleware = |op| match op.name { middleware = |op| match op.name {
"op_exit" => noop_op::decl(), "op_exit" | "op_set_exit_code" => op.disable(),
"op_set_exit_code" => noop_op::decl(),
_ => op, _ => op,
}, },
customizer = |ext: &mut deno_core::ExtensionBuilder| {
ext.force_op_registration();
}
); );
#[op]
fn noop_op() -> Result<(), AnyError> {
Ok(())
}
#[op] #[op]
fn op_exec_path(state: &mut OpState) -> Result<String, AnyError> { fn op_exec_path(state: &mut OpState) -> Result<String, AnyError> {
let current_exe = env::current_exe().unwrap(); let current_exe = env::current_exe().unwrap();

View file

@ -17,7 +17,10 @@ deno_core::extension!(
op_query_permission, op_query_permission,
op_revoke_permission, op_revoke_permission,
op_request_permission, op_request_permission,
] ],
customizer = |ext: &mut deno_core::ExtensionBuilder| {
ext.force_op_registration();
},
); );
#[derive(Deserialize)] #[derive(Deserialize)]

View file

@ -107,7 +107,10 @@ deno_core::extension!(
deprecated::op_run, deprecated::op_run,
deprecated::op_run_status, deprecated::op_run_status,
deprecated::op_kill, deprecated::op_kill,
] ],
customizer = |ext: &mut deno_core::ExtensionBuilder| {
ext.force_op_registration();
},
); );
struct ChildResource(tokio::process::Child); struct ChildResource(tokio::process::Child);

View file

@ -12,7 +12,10 @@ deno_core::extension!(
options = { main_module: ModuleSpecifier }, options = { main_module: ModuleSpecifier },
state = |state, options| { state = |state, options| {
state.put::<ModuleSpecifier>(options.main_module); state.put::<ModuleSpecifier>(options.main_module);
} },
customizer = |ext: &mut deno_core::ExtensionBuilder| {
ext.force_op_registration();
},
); );
#[op] #[op]

View file

@ -31,7 +31,10 @@ use tokio::signal::windows::CtrlC;
deno_core::extension!( deno_core::extension!(
deno_signal, deno_signal,
ops = [op_signal_bind, op_signal_unbind, op_signal_poll] ops = [op_signal_bind, op_signal_unbind, op_signal_poll],
customizer = |ext: &mut deno_core::ExtensionBuilder| {
ext.force_op_registration();
},
); );
#[cfg(unix)] #[cfg(unix)]

View file

@ -34,7 +34,10 @@ fn get_windows_handle(
deno_core::extension!( deno_core::extension!(
deno_tty, deno_tty,
ops = [op_stdin_set_raw, op_isatty, op_console_size] ops = [op_stdin_set_raw, op_isatty, op_console_size],
customizer = |ext: &mut deno_core::ExtensionBuilder| {
ext.force_op_registration();
},
); );
// ref: <https://learn.microsoft.com/en-us/windows/console/setconsolemode> // ref: <https://learn.microsoft.com/en-us/windows/console/setconsolemode>

View file

@ -24,7 +24,10 @@ deno_core::extension!(
op_worker_close, op_worker_close,
op_worker_get_type, op_worker_get_type,
op_worker_sync_fetch, op_worker_sync_fetch,
] ],
customizer = |ext: &mut deno_core::ExtensionBuilder| {
ext.force_op_registration();
},
); );
#[op] #[op]

View file

@ -118,7 +118,10 @@ deno_core::extension!(
let format_js_error_fn_holder = let format_js_error_fn_holder =
FormatJsErrorFnHolder(options.format_js_error_fn); FormatJsErrorFnHolder(options.format_js_error_fn);
state.put::<FormatJsErrorFnHolder>(format_js_error_fn_holder); state.put::<FormatJsErrorFnHolder>(format_js_error_fn_holder);
} },
customizer = |ext: &mut deno_core::ExtensionBuilder| {
ext.force_op_registration();
},
); );
#[derive(Deserialize)] #[derive(Deserialize)]