diff --git a/Libraries/LibJS/Forward.h b/Libraries/LibJS/Forward.h index 936c2a89dc6..407743e9b0b 100644 --- a/Libraries/LibJS/Forward.h +++ b/Libraries/LibJS/Forward.h @@ -61,6 +61,7 @@ #define JS_ENUMERATE_ERROR_SUBCLASSES \ __JS_ENUMERATE(EvalError, eval_error, EvalErrorPrototype, EvalErrorConstructor) \ __JS_ENUMERATE(InternalError, internal_error, InternalErrorPrototype, InternalErrorConstructor) \ + __JS_ENUMERATE(InvalidCharacterError, invalid_character_error, InvalidCharacterErrorPrototype, InvalidCharacterErrorConstructor) \ __JS_ENUMERATE(RangeError, range_error, RangeErrorPrototype, RangeErrorConstructor) \ __JS_ENUMERATE(ReferenceError, reference_error, ReferenceErrorPrototype, ReferenceErrorConstructor) \ __JS_ENUMERATE(SyntaxError, syntax_error, SyntaxErrorPrototype, SyntaxErrorConstructor) \ diff --git a/Libraries/LibJS/Runtime/ErrorTypes.h b/Libraries/LibJS/Runtime/ErrorTypes.h index 4d19d24d3ef..9851a5f0911 100644 --- a/Libraries/LibJS/Runtime/ErrorTypes.h +++ b/Libraries/LibJS/Runtime/ErrorTypes.h @@ -152,6 +152,7 @@ M(ToObjectNullOrUndef, "ToObject on null or undefined") \ M(UnknownIdentifier, "'%s' is not defined") \ /* LibWeb bindings */ \ + M(NotAByteString, "Argument to %s() must be a byte string") \ M(BadArgCountOne, "%s() needs one argument") \ M(BadArgCountAtLeastOne, "%s() needs at least one argument") \ M(BadArgCountMany, "%s() needs %s arguments") diff --git a/Libraries/LibWeb/Bindings/WindowObject.cpp b/Libraries/LibWeb/Bindings/WindowObject.cpp index bcce2b7e482..cf33529f830 100644 --- a/Libraries/LibWeb/Bindings/WindowObject.cpp +++ b/Libraries/LibWeb/Bindings/WindowObject.cpp @@ -28,11 +28,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -251,9 +253,10 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::atob) auto string = interpreter.argument(0).to_string(interpreter); if (interpreter.exception()) return {}; - // FIXME: This should convert string from a byte string to LibJS's internal string encoding (UTF-8). auto decoded = decode_base64(StringView(string)); - return JS::js_string(interpreter, String::copy(decoded)); + + // decode_base64() returns a byte string. LibJS uses UTF-8 for strings. Use Latin1Decoder to convert bytes 128-255 to UTF-8. + return JS::js_string(interpreter, TextCodec::decoder_for("iso-8859-1")->to_utf8(decoded)); } JS_DEFINE_NATIVE_FUNCTION(WindowObject::btoa) @@ -266,8 +269,16 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::btoa) auto string = interpreter.argument(0).to_string(interpreter); if (interpreter.exception()) return {}; - // FIXME: This should convert string to a non-UTF-8 byte string first. - auto encoded = encode_base64(ByteBuffer::wrap(string.characters(), string.length())); + + Vector byte_string; + byte_string.ensure_capacity(string.length()); + for (u32 codepoint : Utf8View(string)) { + if (codepoint > 0xff) + return interpreter.throw_exception(JS::ErrorType::NotAByteString, "btoa"); + byte_string.append(codepoint); + } + + auto encoded = encode_base64(ByteBuffer::wrap(byte_string.data(), byte_string.size())); return JS::js_string(interpreter, move(encoded)); }