diff options
author | Divy Srivastava <dj.srivastava23@gmail.com> | 2022-11-11 06:37:18 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-11 20:07:18 +0530 |
commit | 38f0b41e7d16db24c1ba7c7cc7b536f4d7e169e9 (patch) | |
tree | c8688f12f5808bd78f03c9c3ad2d078e974aa185 /ext/web/lib.rs | |
parent | 5b9620df7ac655449abd2cce5292bd4669b1f211 (diff) |
perf(web): optimize single pass utf8 decoding (#16593)
- [x] Avoid copying buffers.
https://encoding.spec.whatwg.org/#dom-textdecoder-decode
> Implementations are strongly encouraged to use an implementation
strategy that avoids this copy. When doing so they will have to make
sure that changes to input do not affect future calls to
[decode()](https://encoding.spec.whatwg.org/#dom-textdecoder-decode).
- [x] Special op to avoid string label deserialization and parsing.
(Ideally we should map labels to integers in JS)
- [x] Avoid webidl `Object.assign` when options is undefined.
Diffstat (limited to 'ext/web/lib.rs')
-rw-r--r-- | ext/web/lib.rs | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/ext/web/lib.rs b/ext/web/lib.rs index 588a3adfd..f799f02e7 100644 --- a/ext/web/lib.rs +++ b/ext/web/lib.rs @@ -91,6 +91,7 @@ pub fn init<P: TimersPermission + 'static>( op_base64_btoa::decl(), op_encoding_normalize_label::decl(), op_encoding_decode_single::decl(), + op_encoding_decode_utf8::decl(), op_encoding_new_decoder::decl(), op_encoding_decode::decl(), op_encoding_encode_into::decl(), @@ -179,6 +180,39 @@ fn op_encoding_normalize_label(label: String) -> Result<String, AnyError> { Ok(encoding.name().to_lowercase()) } +#[op(v8)] +fn op_encoding_decode_utf8<'a>( + scope: &mut v8::HandleScope<'a>, + zero_copy: &[u8], + ignore_bom: bool, +) -> Result<serde_v8::Value<'a>, AnyError> { + let buf = &zero_copy; + + let buf = if !ignore_bom + && buf.len() >= 3 + && buf[0] == 0xef + && buf[1] == 0xbb + && buf[2] == 0xbf + { + &buf[3..] + } else { + buf + }; + + // If `String::new_from_utf8()` returns `None`, this means that the + // length of the decoded string would be longer than what V8 can + // handle. In this case we return `RangeError`. + // + // For more details see: + // - https://encoding.spec.whatwg.org/#dom-textdecoder-decode + // - https://github.com/denoland/deno/issues/6649 + // - https://github.com/v8/v8/blob/d68fb4733e39525f9ff0a9222107c02c28096e2a/include/v8.h#L3277-L3278 + match v8::String::new_from_utf8(scope, buf, v8::NewStringType::Normal) { + Some(text) => Ok(serde_v8::from_v8(scope, text.into())?), + None => Err(type_error("buffer exceeds maximum length")), + } +} + #[op] fn op_encoding_decode_single( data: &[u8], |