mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-09-18 15:32:22 +00:00
LibJS: Implement Uint8Array.prototype.toHex
This commit is contained in:
parent
b97f9f2c55
commit
c69d6fab8f
Notes:
github-actions[bot]
2024-09-03 15:46:57 +00:00
Author: https://github.com/trflynn89
Commit: c69d6fab8f
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/1258
Reviewed-by: https://github.com/awesomekling
4 changed files with 88 additions and 0 deletions
|
@ -533,6 +533,7 @@ namespace JS {
|
||||||
P(toExponential) \
|
P(toExponential) \
|
||||||
P(toFixed) \
|
P(toFixed) \
|
||||||
P(toGMTString) \
|
P(toGMTString) \
|
||||||
|
P(toHex) \
|
||||||
P(toInstant) \
|
P(toInstant) \
|
||||||
P(toISOString) \
|
P(toISOString) \
|
||||||
P(toJSON) \
|
P(toJSON) \
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <AK/Base64.h>
|
#include <AK/Base64.h>
|
||||||
|
#include <AK/StringBuilder.h>
|
||||||
#include <LibJS/Runtime/Temporal/AbstractOperations.h>
|
#include <LibJS/Runtime/Temporal/AbstractOperations.h>
|
||||||
#include <LibJS/Runtime/TypedArray.h>
|
#include <LibJS/Runtime/TypedArray.h>
|
||||||
#include <LibJS/Runtime/Uint8Array.h>
|
#include <LibJS/Runtime/Uint8Array.h>
|
||||||
|
@ -19,6 +20,7 @@ void Uint8ArrayPrototypeHelpers::initialize(Realm& realm, Object& prototype)
|
||||||
|
|
||||||
static constexpr u8 attr = Attribute::Writable | Attribute::Configurable;
|
static constexpr u8 attr = Attribute::Writable | Attribute::Configurable;
|
||||||
prototype.define_native_function(realm, vm.names.toBase64, to_base64, 0, attr);
|
prototype.define_native_function(realm, vm.names.toBase64, to_base64, 0, attr);
|
||||||
|
prototype.define_native_function(realm, vm.names.toHex, to_hex, 0, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ThrowCompletionOr<Alphabet> parse_alphabet(VM& vm, Object& options)
|
static ThrowCompletionOr<Alphabet> parse_alphabet(VM& vm, Object& options)
|
||||||
|
@ -85,6 +87,31 @@ JS_DEFINE_NATIVE_FUNCTION(Uint8ArrayPrototypeHelpers::to_base64)
|
||||||
return PrimitiveString::create(vm, move(out_ascii));
|
return PrimitiveString::create(vm, move(out_ascii));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 2 Uint8Array.prototype.toHex ( ), https://tc39.es/proposal-arraybuffer-base64/spec/#sec-uint8array.prototype.tobase64
|
||||||
|
JS_DEFINE_NATIVE_FUNCTION(Uint8ArrayPrototypeHelpers::to_hex)
|
||||||
|
{
|
||||||
|
// 1. Let O be the this value.
|
||||||
|
// 2. Perform ? ValidateUint8Array(O).
|
||||||
|
auto typed_array = TRY(validate_uint8_array(vm));
|
||||||
|
|
||||||
|
// 3. Let toEncode be ? GetUint8ArrayBytes(O).
|
||||||
|
auto to_encode = TRY(get_uint8_array_bytes(vm, typed_array));
|
||||||
|
|
||||||
|
// 4. Let out be the empty String.
|
||||||
|
StringBuilder out;
|
||||||
|
|
||||||
|
// 5. For each byte byte of toEncode, do
|
||||||
|
for (auto byte : to_encode.bytes()) {
|
||||||
|
// a. Let hex be Number::toString(𝔽(byte), 16).
|
||||||
|
// b. Set hex to StringPad(hex, 2, "0", START).
|
||||||
|
// c. Set out to the string-concatenation of out and hex.
|
||||||
|
out.appendff("{:02x}", byte);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. Return out.
|
||||||
|
return PrimitiveString::create(vm, MUST(out.to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
// 7 ValidateUint8Array ( ta ), https://tc39.es/proposal-arraybuffer-base64/spec/#sec-validateuint8array
|
// 7 ValidateUint8Array ( ta ), https://tc39.es/proposal-arraybuffer-base64/spec/#sec-validateuint8array
|
||||||
ThrowCompletionOr<NonnullGCPtr<TypedArrayBase>> validate_uint8_array(VM& vm)
|
ThrowCompletionOr<NonnullGCPtr<TypedArrayBase>> validate_uint8_array(VM& vm)
|
||||||
{
|
{
|
||||||
|
|
|
@ -17,6 +17,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
JS_DECLARE_NATIVE_FUNCTION(to_base64);
|
JS_DECLARE_NATIVE_FUNCTION(to_base64);
|
||||||
|
JS_DECLARE_NATIVE_FUNCTION(to_hex);
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class Alphabet {
|
enum class Alphabet {
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
describe("errors", () => {
|
||||||
|
test("called on non-Uint8Array object", () => {
|
||||||
|
expect(() => {
|
||||||
|
Uint8Array.prototype.toHex.call(1);
|
||||||
|
}).toThrowWithMessage(TypeError, "Not an object of type Uint8Array");
|
||||||
|
|
||||||
|
expect(() => {
|
||||||
|
Uint8Array.prototype.toHex.call(new Uint16Array());
|
||||||
|
}).toThrowWithMessage(TypeError, "Not an object of type Uint8Array");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("detached ArrayBuffer", () => {
|
||||||
|
let arrayBuffer = new ArrayBuffer(5, { maxByteLength: 10 });
|
||||||
|
let typedArray = new Uint8Array(arrayBuffer, Uint8Array.BYTES_PER_ELEMENT, 1);
|
||||||
|
detachArrayBuffer(arrayBuffer);
|
||||||
|
|
||||||
|
expect(() => {
|
||||||
|
typedArray.toHex();
|
||||||
|
}).toThrowWithMessage(
|
||||||
|
TypeError,
|
||||||
|
"TypedArray contains a property which references a value at an index not contained within its buffer's bounds"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("ArrayBuffer out of bounds", () => {
|
||||||
|
let arrayBuffer = new ArrayBuffer(Uint8Array.BYTES_PER_ELEMENT * 2, {
|
||||||
|
maxByteLength: Uint8Array.BYTES_PER_ELEMENT * 4,
|
||||||
|
});
|
||||||
|
|
||||||
|
let typedArray = new Uint8Array(arrayBuffer, Uint8Array.BYTES_PER_ELEMENT, 1);
|
||||||
|
arrayBuffer.resize(Uint8Array.BYTES_PER_ELEMENT);
|
||||||
|
|
||||||
|
expect(() => {
|
||||||
|
typedArray.toHex();
|
||||||
|
}).toThrowWithMessage(
|
||||||
|
TypeError,
|
||||||
|
"TypedArray contains a property which references a value at an index not contained within its buffer's bounds"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("correct behavior", () => {
|
||||||
|
test("length is 0", () => {
|
||||||
|
expect(Uint8Array.prototype.toHex).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
const encodeEqual = (input, expected) => {
|
||||||
|
const encoded = toUTF8Bytes(input).toHex();
|
||||||
|
expect(encoded).toBe(expected);
|
||||||
|
};
|
||||||
|
|
||||||
|
test("basic functionality", () => {
|
||||||
|
encodeEqual("", "");
|
||||||
|
encodeEqual("a", "61");
|
||||||
|
encodeEqual("abcdef012345", "616263646566303132333435");
|
||||||
|
encodeEqual("🤓", "f09fa493");
|
||||||
|
encodeEqual("🤓foo🖖", "f09fa493666f6ff09f9696");
|
||||||
|
});
|
||||||
|
});
|
Loading…
Add table
Add a link
Reference in a new issue