script: Implement TextEncoder::encodeInto() (#33360)

* Implement TextEncoder::encodeInto()

Signed-off-by: webbeef <me@webbeef.org>

* Update components/script/dom/textencoder.rs

Signed-off-by: Martin Robinson <mrobinson@igalia.com>

* Update components/script/dom/textencoder.rs

Signed-off-by: Martin Robinson <mrobinson@igalia.com>

---------

Signed-off-by: webbeef <me@webbeef.org>
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
webbeef 2024-09-09 07:40:12 -07:00 committed by GitHub
parent 52a447b1e3
commit a3a86d5913
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 66 additions and 280 deletions

View file

@ -5,12 +5,16 @@
use std::ptr;
use dom_struct::dom_struct;
use js::gc::CustomAutoRooterGuard;
use js::jsapi::JSObject;
use js::rust::HandleObject;
use js::typedarray;
use js::typedarray::Uint8Array;
use crate::dom::bindings::buffer_source::create_buffer_source;
use crate::dom::bindings::codegen::Bindings::TextEncoderBinding::TextEncoderMethods;
use crate::dom::bindings::codegen::Bindings::TextEncoderBinding::{
TextEncoderEncodeIntoResult, TextEncoderMethods,
};
use crate::dom::bindings::error::Fallible;
use crate::dom::bindings::reflector::{reflect_dom_object_with_proto, Reflector};
use crate::dom::bindings::root::DomRoot;
@ -43,7 +47,7 @@ impl TextEncoder {
)
}
// https://encoding.spec.whatwg.org/#dom-textencoder
/// <https://encoding.spec.whatwg.org/#dom-textencoder>
#[allow(non_snake_case)]
pub fn Constructor(
global: &GlobalScope,
@ -55,12 +59,12 @@ impl TextEncoder {
}
impl TextEncoderMethods for TextEncoder {
// https://encoding.spec.whatwg.org/#dom-textencoder-encoding
/// <https://encoding.spec.whatwg.org/#dom-textencoder-encoding>
fn Encoding(&self) -> DOMString {
DOMString::from("utf-8")
}
// https://encoding.spec.whatwg.org/#dom-textencoder-encode
/// <https://encoding.spec.whatwg.org/#dom-textencoder-encode>
fn Encode(&self, cx: JSContext, input: USVString) -> Uint8Array {
let encoded = input.0.as_bytes();
@ -68,4 +72,55 @@ impl TextEncoderMethods for TextEncoder {
create_buffer_source(cx, encoded, js_object.handle_mut())
.expect("Converting input to uint8 array should never fail")
}
/// <https://encoding.spec.whatwg.org/#dom-textencoder-encodeinto>
#[allow(unsafe_code)]
fn EncodeInto(
&self,
source: USVString,
mut destination: CustomAutoRooterGuard<typedarray::Uint8Array>,
) -> TextEncoderEncodeIntoResult {
let available = destination.len();
// Bail out if the destination has no space available.
if available == 0 {
return TextEncoderEncodeIntoResult {
read: Some(0),
written: Some(0),
};
}
let mut read = 0;
let mut written = 0;
let dest = unsafe { destination.as_mut_slice() };
// Step 3, 4, 5, 6
// Turn the source into a queue of scalar values.
// Iterate over the source values.
for result in source.0.chars() {
let utf8_len = result.len_utf8();
if available - written >= utf8_len {
// Step 6.4.1
// If destinations byte length written is greater than or equal to the number of bytes in result
read += if result > '\u{FFFF}' { 2 } else { 1 };
// Write the bytes in result into destination, with startingOffset set to written.
let target = &mut dest[written..written + utf8_len];
result.encode_utf8(target);
// Increment written by the number of bytes in result.
written += utf8_len;
} else {
// Step 6.4.2
// Bail out when destination buffer is full.
break;
}
}
TextEncoderEncodeIntoResult {
read: Some(read),
written: Some(written as _),
}
}
}

View file

@ -3,10 +3,17 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
/* https://encoding.spec.whatwg.org/#interface-textencoder */
dictionary TextEncoderEncodeIntoResult {
unsigned long long read;
unsigned long long written;
};
[Exposed=(Window,Worker)]
interface TextEncoder {
[Throws] constructor();
readonly attribute DOMString encoding;
[NewObject]
Uint8Array encode(optional USVString input = "");
TextEncoderEncodeIntoResult encodeInto(USVString source, [AllowShared] Uint8Array destination);
};