From bbb348aa33b56e15f376e8e7ee7b71bd5badd936 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Thu, 14 Sep 2023 08:29:44 +0200 Subject: [PATCH] refactor: rewrite ext/node to op2 (#20489) --- ext/node/lib.rs | 18 +-- ext/node/ops/crypto/mod.rs | 288 ++++++++++++++++++++---------------- ext/node/ops/idna.rs | 22 +-- ext/node/ops/zlib/brotli.rs | 32 ++-- ext/node/ops/zlib/mod.rs | 25 +++- 5 files changed, 221 insertions(+), 164 deletions(-) diff --git a/ext/node/lib.rs b/ext/node/lib.rs index c1bb882759..c01785b954 100644 --- a/ext/node/lib.rs +++ b/ext/node/lib.rs @@ -7,8 +7,7 @@ use std::rc::Rc; use deno_core::error::AnyError; use deno_core::located_script_name; -use deno_core::op; -use deno_core::serde_v8; +use deno_core::op2; use deno_core::url::Url; #[allow(unused_imports)] use deno_core::v8; @@ -129,19 +128,20 @@ pub static NODE_ENV_VAR_ALLOWLIST: Lazy> = Lazy::new(|| { set }); -#[op] +#[op2] +#[string] fn op_node_build_os() -> String { env!("TARGET").split('-').nth(2).unwrap().to_string() } -#[op(fast)] -fn op_is_any_arraybuffer(value: serde_v8::Value) -> bool { - value.v8_value.is_array_buffer() || value.v8_value.is_shared_array_buffer() +#[op2(fast)] +fn op_is_any_arraybuffer(value: &v8::Value) -> bool { + value.is_array_buffer() || value.is_shared_array_buffer() } -#[op(fast)] -fn op_node_is_promise_rejected(value: serde_v8::Value) -> bool { - let Ok(promise) = v8::Local::::try_from(value.v8_value) else { +#[op2(fast)] +fn op_node_is_promise_rejected(value: v8::Local) -> bool { + let Ok(promise) = v8::Local::::try_from(value) else { return false; }; diff --git a/ext/node/ops/crypto/mod.rs b/ext/node/ops/crypto/mod.rs index ce2ff0ebc0..324b4ea05d 100644 --- a/ext/node/ops/crypto/mod.rs +++ b/ext/node/ops/crypto/mod.rs @@ -3,6 +3,7 @@ use deno_core::error::generic_error; use deno_core::error::type_error; use deno_core::error::AnyError; use deno_core::op; +use deno_core::op2; use deno_core::serde_v8; use deno_core::unsync::spawn_blocking; use deno_core::JsBuffer; @@ -78,8 +79,12 @@ pub fn op_node_check_prime_bytes_async( }) } -#[op(fast)] -pub fn op_node_create_hash(state: &mut OpState, algorithm: &str) -> u32 { +#[op2(fast)] +#[smi] +pub fn op_node_create_hash( + state: &mut OpState, + #[string] algorithm: &str, +) -> u32 { state .resource_table .add(match digest::Context::new(algorithm) { @@ -88,13 +93,18 @@ pub fn op_node_create_hash(state: &mut OpState, algorithm: &str) -> u32 { }) } -#[op(fast)] +#[op2] +#[serde] pub fn op_node_get_hashes() -> Vec<&'static str> { digest::Hash::get_hashes() } -#[op(fast)] -pub fn op_node_hash_update(state: &mut OpState, rid: u32, data: &[u8]) -> bool { +#[op2(fast)] +pub fn op_node_hash_update( + state: &mut OpState, + #[smi] rid: u32, + #[buffer] data: &[u8], +) -> bool { let context = match state.resource_table.get::(rid) { Ok(context) => context, _ => return false, @@ -103,11 +113,11 @@ pub fn op_node_hash_update(state: &mut OpState, rid: u32, data: &[u8]) -> bool { true } -#[op(fast)] +#[op2(fast)] pub fn op_node_hash_update_str( state: &mut OpState, - rid: u32, - data: &str, + #[smi] rid: u32, + #[string] data: &str, ) -> bool { let context = match state.resource_table.get::(rid) { Ok(context) => context, @@ -117,10 +127,11 @@ pub fn op_node_hash_update_str( true } -#[op] +#[op2] +#[serde] pub fn op_node_hash_digest( state: &mut OpState, - rid: ResourceId, + #[smi] rid: ResourceId, ) -> Result { let context = state.resource_table.take::(rid)?; let context = Rc::try_unwrap(context) @@ -128,10 +139,11 @@ pub fn op_node_hash_digest( Ok(context.digest()?.into()) } -#[op] +#[op2] +#[string] pub fn op_node_hash_digest_hex( state: &mut OpState, - rid: ResourceId, + #[smi] rid: ResourceId, ) -> Result { let context = state.resource_table.take::(rid)?; let context = Rc::try_unwrap(context) @@ -140,20 +152,22 @@ pub fn op_node_hash_digest_hex( Ok(hex::encode(digest)) } -#[op] +#[op2(fast)] +#[smi] pub fn op_node_hash_clone( state: &mut OpState, - rid: ResourceId, + #[smi] rid: ResourceId, ) -> Result { let context = state.resource_table.get::(rid)?; Ok(state.resource_table.add(context.as_ref().clone())) } -#[op] +#[op2] +#[serde] pub fn op_node_private_encrypt( - key: StringOrBuffer, - msg: StringOrBuffer, - padding: u32, + #[serde] key: StringOrBuffer, + #[serde] msg: StringOrBuffer, + #[smi] padding: u32, ) -> Result { let key = RsaPrivateKey::from_pkcs8_pem((&key).try_into()?)?; @@ -173,11 +187,12 @@ pub fn op_node_private_encrypt( } } -#[op] +#[op2] +#[serde] pub fn op_node_private_decrypt( - key: StringOrBuffer, - msg: StringOrBuffer, - padding: u32, + #[serde] key: StringOrBuffer, + #[serde] msg: StringOrBuffer, + #[smi] padding: u32, ) -> Result { let key = RsaPrivateKey::from_pkcs8_pem((&key).try_into()?)?; @@ -196,11 +211,12 @@ pub fn op_node_private_decrypt( } } -#[op] +#[op2] +#[serde] pub fn op_node_public_encrypt( - key: StringOrBuffer, - msg: StringOrBuffer, - padding: u32, + #[serde] key: StringOrBuffer, + #[serde] msg: StringOrBuffer, + #[smi] padding: u32, ) -> Result { let key = RsaPublicKey::from_public_key_pem((&key).try_into()?)?; @@ -220,12 +236,13 @@ pub fn op_node_public_encrypt( } } -#[op(fast)] +#[op2(fast)] +#[smi] pub fn op_node_create_cipheriv( state: &mut OpState, - algorithm: &str, - key: &[u8], - iv: &[u8], + #[string] algorithm: &str, + #[buffer] key: &[u8], + #[buffer] iv: &[u8], ) -> u32 { state.resource_table.add( match cipher::CipherContext::new(algorithm, key, iv) { @@ -235,11 +252,11 @@ pub fn op_node_create_cipheriv( ) } -#[op(fast)] +#[op2(fast)] pub fn op_node_cipheriv_set_aad( state: &mut OpState, - rid: u32, - aad: &[u8], + #[smi] rid: u32, + #[buffer] aad: &[u8], ) -> bool { let context = match state.resource_table.get::(rid) { Ok(context) => context, @@ -249,12 +266,12 @@ pub fn op_node_cipheriv_set_aad( true } -#[op(fast)] +#[op2(fast)] pub fn op_node_cipheriv_encrypt( state: &mut OpState, - rid: u32, - input: &[u8], - output: &mut [u8], + #[smi] rid: u32, + #[buffer] input: &[u8], + #[buffer] output: &mut [u8], ) -> bool { let context = match state.resource_table.get::(rid) { Ok(context) => context, @@ -264,12 +281,13 @@ pub fn op_node_cipheriv_encrypt( true } -#[op] +#[op2] +#[serde] pub fn op_node_cipheriv_final( state: &mut OpState, - rid: u32, - input: &[u8], - output: &mut [u8], + #[smi] rid: u32, + #[buffer] input: &[u8], + #[buffer] output: &mut [u8], ) -> Result>, AnyError> { let context = state.resource_table.take::(rid)?; let context = Rc::try_unwrap(context) @@ -277,12 +295,13 @@ pub fn op_node_cipheriv_final( context.r#final(input, output) } -#[op(fast)] +#[op2(fast)] +#[smi] pub fn op_node_create_decipheriv( state: &mut OpState, - algorithm: &str, - key: &[u8], - iv: &[u8], + #[string] algorithm: &str, + #[buffer] key: &[u8], + #[buffer] iv: &[u8], ) -> u32 { state.resource_table.add( match cipher::DecipherContext::new(algorithm, key, iv) { @@ -292,11 +311,11 @@ pub fn op_node_create_decipheriv( ) } -#[op(fast)] +#[op2(fast)] pub fn op_node_decipheriv_set_aad( state: &mut OpState, - rid: u32, - aad: &[u8], + #[smi] rid: u32, + #[buffer] aad: &[u8], ) -> bool { let context = match state.resource_table.get::(rid) { Ok(context) => context, @@ -306,12 +325,12 @@ pub fn op_node_decipheriv_set_aad( true } -#[op(fast)] +#[op2(fast)] pub fn op_node_decipheriv_decrypt( state: &mut OpState, - rid: u32, - input: &[u8], - output: &mut [u8], + #[smi] rid: u32, + #[buffer] input: &[u8], + #[buffer] output: &mut [u8], ) -> bool { let context = match state.resource_table.get::(rid) { Ok(context) => context, @@ -321,13 +340,13 @@ pub fn op_node_decipheriv_decrypt( true } -#[op] +#[op2(fast)] pub fn op_node_decipheriv_final( state: &mut OpState, - rid: u32, - input: &[u8], - output: &mut [u8], - auth_tag: &[u8], + #[smi] rid: u32, + #[buffer] input: &[u8], + #[buffer] output: &mut [u8], + #[buffer] auth_tag: &[u8], ) -> Result<(), AnyError> { let context = state.resource_table.take::(rid)?; let context = Rc::try_unwrap(context) @@ -335,13 +354,14 @@ pub fn op_node_decipheriv_final( context.r#final(input, output, auth_tag) } -#[op] +#[op2] +#[serde] pub fn op_node_sign( - digest: &[u8], - digest_type: &str, - key: StringOrBuffer, - key_type: &str, - key_format: &str, + #[buffer] digest: &[u8], + #[string] digest_type: &str, + #[serde] key: StringOrBuffer, + #[string] key_type: &str, + #[string] key_format: &str, ) -> Result { match key_type { "rsa" => { @@ -393,14 +413,14 @@ pub fn op_node_sign( } } -#[op] -fn op_node_verify( - digest: &[u8], - digest_type: &str, - key: StringOrBuffer, - key_type: &str, - key_format: &str, - signature: &[u8], +#[op2] +pub fn op_node_verify( + #[buffer] digest: &[u8], + #[string] digest_type: &str, + #[serde] key: StringOrBuffer, + #[string] key_type: &str, + #[string] key_format: &str, + #[buffer] signature: &[u8], ) -> Result { match key_type { "rsa" => { @@ -473,13 +493,13 @@ fn pbkdf2_sync( Ok(()) } -#[op] +#[op2] pub fn op_node_pbkdf2( - password: StringOrBuffer, - salt: StringOrBuffer, - iterations: u32, - digest: &str, - derived_key: &mut [u8], + #[serde] password: StringOrBuffer, + #[serde] salt: StringOrBuffer, + #[smi] iterations: u32, + #[string] digest: &str, + #[buffer] derived_key: &mut [u8], ) -> bool { pbkdf2_sync(&password, &salt, iterations, digest, derived_key).is_ok() } @@ -500,13 +520,14 @@ pub async fn op_node_pbkdf2_async( .await? } -#[op] -pub fn op_node_generate_secret(buf: &mut [u8]) { +#[op2(fast)] +pub fn op_node_generate_secret(#[buffer] buf: &mut [u8]) { rand::thread_rng().fill(buf); } -#[op] -pub async fn op_node_generate_secret_async(len: i32) -> ToJsBuffer { +#[op2(async)] +#[serde] +pub async fn op_node_generate_secret_async(#[smi] len: i32) -> ToJsBuffer { spawn_blocking(move || { let mut buf = vec![0u8; len as usize]; rand::thread_rng().fill(&mut buf[..]); @@ -546,13 +567,13 @@ fn hkdf_sync( Ok(()) } -#[op] +#[op2(fast)] pub fn op_node_hkdf( - hash: &str, - ikm: &[u8], - salt: &[u8], - info: &[u8], - okm: &mut [u8], + #[string] hash: &str, + #[buffer] ikm: &[u8], + #[buffer] salt: &[u8], + #[buffer] info: &[u8], + #[buffer] okm: &mut [u8], ) -> Result<(), AnyError> { hkdf_sync(hash, ikm, salt, info, okm) } @@ -690,16 +711,18 @@ fn ec_generate( Ok((pkcs8.as_ref().to_vec().into(), public_key.into())) } -#[op] +#[op2] +#[serde] pub fn op_node_ec_generate( - named_curve: &str, + #[string] named_curve: &str, ) -> Result<(ToJsBuffer, ToJsBuffer), AnyError> { ec_generate(named_curve) } -#[op] +#[op2(async)] +#[serde] pub async fn op_node_ec_generate_async( - named_curve: String, + #[string] named_curve: String, ) -> Result<(ToJsBuffer, ToJsBuffer), AnyError> { spawn_blocking(move || ec_generate(&named_curve)).await? } @@ -719,13 +742,15 @@ fn ed25519_generate() -> Result<(ToJsBuffer, ToJsBuffer), AnyError> { Ok((seed.into(), public_key.into())) } -#[op] +#[op2] +#[serde] pub fn op_node_ed25519_generate() -> Result<(ToJsBuffer, ToJsBuffer), AnyError> { ed25519_generate() } -#[op] +#[op2(async)] +#[serde] pub async fn op_node_ed25519_generate_async( ) -> Result<(ToJsBuffer, ToJsBuffer), AnyError> { spawn_blocking(ed25519_generate).await? @@ -754,12 +779,14 @@ fn x25519_generate() -> Result<(ToJsBuffer, ToJsBuffer), AnyError> { Ok((pkey_copy.into(), pubkey.to_vec().into())) } -#[op] +#[op2] +#[serde] pub fn op_node_x25519_generate() -> Result<(ToJsBuffer, ToJsBuffer), AnyError> { x25519_generate() } -#[op] +#[op2(async)] +#[serde] pub async fn op_node_x25519_generate_async( ) -> Result<(ToJsBuffer, ToJsBuffer), AnyError> { spawn_blocking(x25519_generate).await? @@ -784,16 +811,18 @@ fn dh_generate_group( )) } -#[op] +#[op2] +#[serde] pub fn op_node_dh_generate_group( - group_name: &str, + #[string] group_name: &str, ) -> Result<(ToJsBuffer, ToJsBuffer), AnyError> { dh_generate_group(group_name) } -#[op] +#[op2(async)] +#[serde] pub async fn op_node_dh_generate_group_async( - group_name: String, + #[string] group_name: String, ) -> Result<(ToJsBuffer, ToJsBuffer), AnyError> { spawn_blocking(move || dh_generate_group(&group_name)).await? } @@ -833,11 +862,12 @@ pub fn op_node_dh_generate2( dh_generate(Some(prime).as_deref(), prime_len, generator) } -#[op] +#[op2] +#[serde] pub fn op_node_dh_compute_secret( - prime: JsBuffer, - private_key: JsBuffer, - their_public_key: JsBuffer, + #[buffer] prime: JsBuffer, + #[buffer] private_key: JsBuffer, + #[buffer] their_public_key: JsBuffer, ) -> Result { let pubkey: BigUint = BigUint::from_bytes_be(their_public_key.as_ref()); let privkey: BigUint = BigUint::from_bytes_be(private_key.as_ref()); @@ -857,8 +887,12 @@ pub async fn op_node_dh_generate_async( .await? } -#[op] -pub fn op_node_random_int(min: i32, max: i32) -> Result { +#[op2(fast)] +#[smi] +pub fn op_node_random_int( + #[smi] min: i32, + #[smi] max: i32, +) -> Result { let mut rng = rand::thread_rng(); // Uniform distribution is required to avoid Modulo Bias // https://en.wikipedia.org/wiki/Fisher–Yates_shuffle#Modulo_bias @@ -920,15 +954,16 @@ pub fn op_node_scrypt_sync( ) } -#[op] +#[op2(async)] +#[serde] pub async fn op_node_scrypt_async( - password: StringOrBuffer, - salt: StringOrBuffer, - keylen: u32, - cost: u32, - block_size: u32, - parallelization: u32, - maxmem: u32, + #[serde] password: StringOrBuffer, + #[serde] salt: StringOrBuffer, + #[smi] keylen: u32, + #[smi] cost: u32, + #[smi] block_size: u32, + #[smi] parallelization: u32, + #[smi] maxmem: u32, ) -> Result { spawn_blocking(move || { let mut output_buffer = vec![0u8; keylen as usize]; @@ -953,11 +988,12 @@ pub async fn op_node_scrypt_async( .await? } -#[op] +#[op2(fast)] +#[smi] pub fn op_node_ecdh_generate_keys( - curve: &str, - pubbuf: &mut [u8], - privbuf: &mut [u8], + #[string] curve: &str, + #[buffer] pubbuf: &mut [u8], + #[buffer] privbuf: &mut [u8], ) -> Result { let mut rng = rand::thread_rng(); match curve { @@ -994,12 +1030,12 @@ pub fn op_node_ecdh_generate_keys( } } -#[op] +#[op2] pub fn op_node_ecdh_compute_secret( - curve: &str, - this_priv: Option, - their_pub: &mut [u8], - secret: &mut [u8], + #[string] curve: &str, + #[buffer] this_priv: Option, + #[buffer] their_pub: &mut [u8], + #[buffer] secret: &mut [u8], ) -> Result<(), AnyError> { match curve { "secp256k1" => { @@ -1067,11 +1103,11 @@ pub fn op_node_ecdh_compute_secret( } } -#[op] +#[op2(fast)] pub fn op_node_ecdh_compute_public_key( - curve: &str, - privkey: &[u8], - pubkey: &mut [u8], + #[string] curve: &str, + #[buffer] privkey: &[u8], + #[buffer] pubkey: &mut [u8], ) -> Result<(), AnyError> { match curve { "secp256k1" => { diff --git a/ext/node/ops/idna.rs b/ext/node/ops/idna.rs index 8f7cfe34ab..988468297a 100644 --- a/ext/node/ops/idna.rs +++ b/ext/node/ops/idna.rs @@ -1,26 +1,30 @@ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. use deno_core::error::AnyError; -use deno_core::op; +use deno_core::op2; -#[op] +#[op2] +#[string] pub fn op_node_idna_domain_to_ascii( - domain: String, + #[string] domain: String, ) -> Result { Ok(idna::domain_to_ascii(&domain)?) } -#[op] -pub fn op_node_idna_domain_to_unicode(domain: String) -> String { +#[op2] +#[string] +pub fn op_node_idna_domain_to_unicode(#[string] domain: String) -> String { idna::domain_to_unicode(&domain).0 } -#[op] -pub fn op_node_idna_punycode_decode(domain: String) -> String { +#[op2] +#[string] +pub fn op_node_idna_punycode_decode(#[string] domain: String) -> String { idna::punycode::decode_to_string(&domain).unwrap_or_default() } -#[op] -pub fn op_node_idna_punycode_encode(domain: String) -> String { +#[op2] +#[string] +pub fn op_node_idna_punycode_encode(#[string] domain: String) -> String { idna::punycode::encode_str(&domain).unwrap_or_default() } diff --git a/ext/node/ops/zlib/brotli.rs b/ext/node/ops/zlib/brotli.rs index b4d9709702..a5c0f0f922 100644 --- a/ext/node/ops/zlib/brotli.rs +++ b/ext/node/ops/zlib/brotli.rs @@ -8,6 +8,7 @@ use brotli::Decompressor; use deno_core::error::type_error; use deno_core::error::AnyError; use deno_core::op; +use deno_core::op2; use deno_core::JsBuffer; use deno_core::OpState; use deno_core::Resource; @@ -71,12 +72,13 @@ fn max_compressed_size(input_size: usize) -> usize { } } -#[op] +#[op2(async)] +#[serde] pub async fn op_brotli_compress_async( - input: JsBuffer, - quality: i32, - lgwin: i32, - mode: u32, + #[buffer] input: JsBuffer, + #[smi] quality: i32, + #[smi] lgwin: i32, + #[smi] mode: u32, ) -> Result { tokio::task::spawn_blocking(move || { let in_buffer = input.as_ptr(); @@ -123,10 +125,11 @@ impl Drop for BrotliCompressCtx { } } -#[op] +#[op2] +#[smi] pub fn op_create_brotli_compress( state: &mut OpState, - params: Vec<(u8, i32)>, + #[serde] params: Vec<(u8, i32)>, ) -> u32 { let inst = // SAFETY: Creates a brotli encoder instance for default allocators. @@ -222,14 +225,18 @@ fn brotli_decompress(buffer: &[u8]) -> Result { Ok(output.into()) } -#[op] -pub fn op_brotli_decompress(buffer: &[u8]) -> Result { +#[op2] +#[serde] +pub fn op_brotli_decompress( + #[buffer] buffer: &[u8], +) -> Result { brotli_decompress(buffer) } -#[op] +#[op2(async)] +#[serde] pub async fn op_brotli_decompress_async( - buffer: JsBuffer, + #[buffer] buffer: JsBuffer, ) -> Result { tokio::task::spawn_blocking(move || brotli_decompress(&buffer)).await? } @@ -247,7 +254,8 @@ impl Drop for BrotliDecompressCtx { } } -#[op] +#[op2(fast)] +#[smi] pub fn op_create_brotli_decompress(state: &mut OpState) -> u32 { let inst = // SAFETY: TODO(littledivy) diff --git a/ext/node/ops/zlib/mod.rs b/ext/node/ops/zlib/mod.rs index 105666b06b..0964bf0509 100644 --- a/ext/node/ops/zlib/mod.rs +++ b/ext/node/ops/zlib/mod.rs @@ -4,6 +4,7 @@ use deno_core::error::bad_resource_id; use deno_core::error::type_error; use deno_core::error::AnyError; use deno_core::op; +use deno_core::op2; use deno_core::OpState; use libz_sys::*; use std::borrow::Cow; @@ -252,8 +253,12 @@ impl deno_core::Resource for Zlib { } } -#[op] -pub fn op_zlib_new(state: &mut OpState, mode: i32) -> Result { +#[op2(fast)] +#[smi] +pub fn op_zlib_new( + state: &mut OpState, + #[smi] mode: i32, +) -> Result { let mode = Mode::try_from(mode)?; let inner = ZlibInner { @@ -266,8 +271,11 @@ pub fn op_zlib_new(state: &mut OpState, mode: i32) -> Result { })) } -#[op] -pub fn op_zlib_close(state: &mut OpState, handle: u32) -> Result<(), AnyError> { +#[op2(fast)] +pub fn op_zlib_close( + state: &mut OpState, + #[smi] handle: u32, +) -> Result<(), AnyError> { let resource = zlib(state, handle)?; let mut zlib = resource.inner.borrow_mut(); @@ -382,10 +390,11 @@ pub fn op_zlib_init( Ok(zlib.err) } -#[op] +#[op2(fast)] +#[smi] pub fn op_zlib_reset( state: &mut OpState, - handle: u32, + #[smi] handle: u32, ) -> Result { let resource = zlib(state, handle)?; @@ -395,10 +404,10 @@ pub fn op_zlib_reset( Ok(zlib.err) } -#[op] +#[op2(fast)] pub fn op_zlib_close_if_pending( state: &mut OpState, - handle: u32, + #[smi] handle: u32, ) -> Result<(), AnyError> { let resource = zlib(state, handle)?; let pending_close = {