#[op2]
Expand description
A macro designed to provide an extremely fast V8->Rust interface layer.
op2
#[op2]
is the in-progress replacement for #[op]
.
Strings
String
s in Rust are always UTF-8. String
s in v8, however, are either
two-byte UTF-16 or one-byte Latin-1. One-byte Latin-1 strings are not
byte-compatible with UTF-8, as characters with the index 128-255 require two
bytes to encode in UTF-8.
Because of this, String
s in op
s always require a copy (at least) to ensure
that we are not incorrectly passing Latin-1 data to methods that expect a UTF-8
string. At this time there is no way to avoid this copy, though the op
code
does attempt to avoid any allocations where possible by making use of a stack
buffer.
async
calls
Asynchronous calls are supported in two forms:
async fn op_xyz(/* ... */) -> X {}
and
fn op_xyz(/* ... */) -> impl Future<Output = X> {}
These are desugared to a function that adds a hidden promise_id
argument, and
returns Option<X>
instead. Deno will eagerly poll the op, and if it is
immediately ready, the function will return Some(X)
. If the op is not ready,
the function will return None
and the future will be handled by Deno’s pending
op system.
fn op_xyz(promise_id: i32, /* ... */) -> Option<X> {}
Parameters
Rust | Fastcall | v8 | |
---|---|---|---|
| ✅ | Bool | |
| ✅ | Uint32, Int32, Number, BigInt | |
| ✅ | Uint32, Int32, Number, BigInt | |
| ✅ | Uint32, Int32, Number, BigInt | |
| ✅ | Uint32, Int32, Number, BigInt | |
| ✅ | Uint32, Int32, Number, BigInt | |
| ✅ | Uint32, Int32, Number, BigInt | |
| ✅ | Uint32, Int32, Number, BigInt | SMI is internally represented as a signed integer, but unsigned `#[smi]` types will be bit-converted to unsigned values for the Rust call. JavaScript code will continue to see signed integers. |
| ✅ | Uint32, Int32, Number, BigInt | |
| ✅ | Uint32, Int32, Number, BigInt | |
| ✅ | Uint32, Int32, Number, BigInt | |
| ✅ | Uint32, Int32, Number, BigInt | |
| ✅ | Uint32, Int32, Number, BigInt | |
| ✅ | Uint32, Int32, Number, BigInt | |
| ✅ | String | Fastcall available only if string is Latin-1. Will always create an allocated, UTF-8 copy of the String data. |
| ✅ | String | Fastcall available only if string is Latin-1. Will create an owned `String` copy of the String data if it doesn't fit on the stack. Will never allocate in a fastcall, but will copy Latin-1 -> UTF-8. |
| ✅ | String | Fastcall available only if string is Latin-1. Will create a `Cow::Owned` copy of the String data if it doesn't fit on the stack. Will always be `Cow::Borrowed` in a fastcall, but will copy Latin-1 -> UTF-8. |
| ✅ | String | Fastest `String`-type method. If the string is not Latin-1, will throw a TypeError. |
| ✅ | any | |
| ✅ | String | |
| ✅ | Object | |
| ✅ | Function | |
| ✅ | ... | |
| ✅ | any | |
| ✅ | String | |
| ✅ | Object | |
| ✅ | Function | |
| ✅ | ... | |
| any | ⚠️ Slower than `v8::Local`. | |
| String | ⚠️ Slower than `v8::Local`. | |
| Object | ⚠️ Slower than `v8::Local`. | |
| Function | ⚠️ Slower than `v8::Local`. | |
| ... | ⚠️ Slower than `v8::Local`. | |
| any | ⚠️ May be slow. | |
| any | ⚠️ May be slow. | |
| ✅ | ArrayBuffer, ArrayBufferView (resizable=true,false) | ⚠️ JS may modify the contents of the slice if V8 is called re-entrantly. |
| ✅ | ArrayBuffer, ArrayBufferView (resizable=true,false) | ⚠️ JS may modify the contents of the slice if V8 is called re-entrantly. |
| ✅ | ArrayBuffer, ArrayBufferView (resizable=true,false) | ⚠️ JS may modify the contents of the slice if V8 is called re-entrantly. Because of how V8 treats empty arrays in fastcalls, they will always be passed as null. |
| ✅ | ArrayBuffer, ArrayBufferView (resizable=true,false) | ⚠️ JS may modify the contents of the slice if V8 is called re-entrantly. Because of how V8 treats empty arrays in fastcalls, they will always be passed as null. |
| ✅ | ArrayBuffer (resizable=true,false) | ⚠️ JS may modify the contents of the slice if V8 is called re-entrantly. |
| ✅ | ArrayBuffer (resizable=true,false) | ⚠️ JS may modify the contents of the slice if V8 is called re-entrantly. |
| ✅ | ArrayBuffer (resizable=true,false) | ⚠️ JS may modify the contents of the slice if V8 is called re-entrantly. Because of how V8 treats empty arrays in fastcalls, they will always be passed as null. |
| ✅ | ArrayBuffer (resizable=true,false) | ⚠️ JS may modify the contents of the slice if V8 is called re-entrantly. Because of how V8 treats empty arrays in fastcalls, they will always be passed as null. |
| ✅ | ArrayBuffer (resizable=true,false) | Safe, but forces a copy. |
| ✅ | ArrayBuffer (resizable=true,false) | Safe, but forces a copy. |
| ✅ | ArrayBuffer (resizable=true,false) | Safe, but forces a copy. |
| ✅ | UInt8Array (resizable=true,false) | ⚠️ JS may modify the contents of the slice if V8 is called re-entrantly. |
| ✅ | UInt8Array (resizable=true,false) | ⚠️ JS may modify the contents of the slice if V8 is called re-entrantly. |
| ✅ | UInt8Array (resizable=true,false) | ⚠️ JS may modify the contents of the slice if V8 is called re-entrantly. Because of how V8 treats empty arrays in fastcalls, they will always be passed as null. |
| ✅ | UInt8Array (resizable=true,false) | ⚠️ JS may modify the contents of the slice if V8 is called re-entrantly. Because of how V8 treats empty arrays in fastcalls, they will always be passed as null. |
| ✅ | UInt8Array (resizable=true,false) | Safe, but forces a copy. |
| ✅ | UInt8Array (resizable=true,false) | Safe, but forces a copy. |
| ✅ | UInt8Array (resizable=true,false) | Safe, but forces a copy. |
| ✅ | UInt32Array (resizable=true,false) | ⚠️ JS may modify the contents of the slice if V8 is called re-entrantly. |
| ✅ | UInt32Array (resizable=true,false) | ⚠️ JS may modify the contents of the slice if V8 is called re-entrantly. |
| ✅ | UInt32Array (resizable=true,false) | Safe, but forces a copy. |
| ✅ | UInt32Array (resizable=true,false) | Safe, but forces a copy. |
| ArrayBuffer, ArrayBufferView (resizable=false) | ⚠️ JS may modify the contents of slices obtained from buffer. | |
| ArrayBuffer, ArrayBufferView (resizable=true,false) | Safe. | |
| ✅ | External | |
| ✅ | External | |
| ✅ | ||
| ✅ | ||
| ✅ | ||
| ✅ | Extracts an object from `OpState`. | |
| ✅ | Extracts an object from `OpState`. | |
| ✅ | Only usable in `deno_core`. | |
| ✅ | Only usable in `deno_core`. | |
| ✅ | Only usable in `deno_core`. |
Return Values
Rust | Fastcall | Async | v8 | |
---|---|---|---|---|
| ✅ | |||
| ✅ | |||
| ✅ | |||
| ✅ | |||
| ✅ | |||
| ✅ | |||
| ✅ | |||
| ✅ | SMI is internally represented as a signed integer, but unsigned `#[smi]` types will be bit-converted to unsigned values for the Rust call. JavaScript code will continue to see signed integers. | ||
| ||||
| ||||
| ||||
| ||||
| ✅ | Result must fit within `Number.MIN_SAFE_INTEGER` and `Number.MAX_SAFE_INTEGER` | ||
| ✅ | Result must fit within `Number.MIN_SAFE_INTEGER` and `Number.MAX_SAFE_INTEGER` | ||
| ✅ | Result must fit within `Number.MIN_SAFE_INTEGER` and `Number.MAX_SAFE_INTEGER` | ||
| ✅ | Result must fit within `Number.MIN_SAFE_INTEGER` and `Number.MAX_SAFE_INTEGER` | ||
| ✅ | |||
| ✅ | |||
| ||||
| ||||
| ||||
| ||||
| ||||
| ||||
| ||||
| ||||
| ||||
| ||||
| ||||
| ||||
| ||||
| ✅ | |||
| ✅ | |||
| ||||
| ||||
| ||||
| ||||
| ||||
| ||||
| ||||
| ||||
| ||||
| ||||
| ||||
|