util: add fast path for Latin1 decoding · nodejs/node@374eb41
1+#include "encoding_binding.h"
2+#include "env-inl.h"
3+#include "gtest/gtest.h"
4+#include "node_test_fixture.h"
5+#include "v8.h"
6+7+namespace node {
8+namespace encoding_binding {
9+10+bool RunDecodeLatin1(Environment* env,
11+ Local<Value> args[],
12+bool ignore_bom,
13+bool has_fatal,
14+ Local<Value>* result) {
15+ Isolate* isolate = env->isolate();
16+ TryCatch try_catch(isolate);
17+18+ Local<Boolean> ignoreBOMValue = Boolean::New(isolate, ignore_bom);
19+ Local<Boolean> fatalValue = Boolean::New(isolate, has_fatal);
20+21+ Local<Value> updatedArgs[] = {args[0], ignoreBOMValue, fatalValue};
22+23+BindingData::DecodeLatin1(FunctionCallbackInfo<Value>(updatedArgs));
24+25+if (try_catch.HasCaught()) {
26+return false;
27+ }
28+29+ *result = try_catch.Exception();
30+return true;
31+}
32+33+class EncodingBindingTest : public NodeTestFixture {};
34+35+TEST_F(EncodingBindingTest, DecodeLatin1_ValidInput) {
36+ Environment* env = CreateEnvironment();
37+ Isolate* isolate = env->isolate();
38+ HandleScope handle_scope(isolate);
39+40+const uint8_t latin1_data[] = {0xC1, 0xE9, 0xF3};
41+ Local<ArrayBuffer> ab = ArrayBuffer::New(isolate, sizeof(latin1_data));
42+memcpy(ab->GetBackingStore()->Data(), latin1_data, sizeof(latin1_data));
43+44+ Local<Uint8Array> array = Uint8Array::New(ab, 0, sizeof(latin1_data));
45+ Local<Value> args[] = {array};
46+47+ Local<Value> result;
48+EXPECT_TRUE(RunDecodeLatin1(env, args, false, false, &result));
49+50+ String::Utf8Value utf8_result(isolate, result);
51+EXPECT_STREQ(*utf8_result, "Áéó");
52+}
53+54+TEST_F(EncodingBindingTest, DecodeLatin1_EmptyInput) {
55+ Environment* env = CreateEnvironment();
56+ Isolate* isolate = env->isolate();
57+ HandleScope handle_scope(isolate);
58+59+ Local<ArrayBuffer> ab = ArrayBuffer::New(isolate, 0);
60+ Local<Uint8Array> array = Uint8Array::New(ab, 0, 0);
61+ Local<Value> args[] = {array};
62+63+ Local<Value> result;
64+EXPECT_TRUE(RunDecodeLatin1(env, args, false, false, &result));
65+66+ String::Utf8Value utf8_result(isolate, result);
67+EXPECT_STREQ(*utf8_result, "");
68+}
69+70+TEST_F(EncodingBindingTest, DecodeLatin1_InvalidInput) {
71+ Environment* env = CreateEnvironment();
72+ Isolate* isolate = env->isolate();
73+ HandleScope handle_scope(isolate);
74+75+ Local<Value> args[] = {String::NewFromUtf8Literal(isolate, "Invalid input")};
76+77+ Local<Value> result;
78+EXPECT_FALSE(RunDecodeLatin1(env, args, false, false, &result));
79+}
80+81+TEST_F(EncodingBindingTest, DecodeLatin1_IgnoreBOM) {
82+ Environment* env = CreateEnvironment();
83+ Isolate* isolate = env->isolate();
84+ HandleScope handle_scope(isolate);
85+86+const uint8_t latin1_data[] = {0xFE, 0xFF, 0xC1, 0xE9, 0xF3};
87+ Local<ArrayBuffer> ab = ArrayBuffer::New(isolate, sizeof(latin1_data));
88+memcpy(ab->GetBackingStore()->Data(), latin1_data, sizeof(latin1_data));
89+90+ Local<Uint8Array> array = Uint8Array::New(ab, 0, sizeof(latin1_data));
91+ Local<Value> args[] = {array};
92+93+ Local<Value> result;
94+EXPECT_TRUE(RunDecodeLatin1(env, args, true, false, &result));
95+96+ String::Utf8Value utf8_result(isolate, result);
97+EXPECT_STREQ(*utf8_result, "Áéó");
98+}
99+100+TEST_F(EncodingBindingTest, DecodeLatin1_FatalInvalidInput) {
101+ Environment* env = CreateEnvironment();
102+ Isolate* isolate = env->isolate();
103+ HandleScope handle_scope(isolate);
104+105+const uint8_t invalid_data[] = {0xFF, 0xFF, 0xFF};
106+ Local<ArrayBuffer> ab = ArrayBuffer::New(isolate, sizeof(invalid_data));
107+memcpy(ab->GetBackingStore()->Data(), invalid_data, sizeof(invalid_data));
108+109+ Local<Uint8Array> array = Uint8Array::New(ab, 0, sizeof(invalid_data));
110+ Local<Value> args[] = {array};
111+112+ Local<Value> result;
113+EXPECT_FALSE(RunDecodeLatin1(env, args, false, true, &result));
114+}
115+116+TEST_F(EncodingBindingTest, DecodeLatin1_IgnoreBOMAndFatal) {
117+ Environment* env = CreateEnvironment();
118+ Isolate* isolate = env->isolate();
119+ HandleScope handle_scope(isolate);
120+121+const uint8_t latin1_data[] = {0xFE, 0xFF, 0xC1, 0xE9, 0xF3};
122+ Local<ArrayBuffer> ab = ArrayBuffer::New(isolate, sizeof(latin1_data));
123+memcpy(ab->GetBackingStore()->Data(), latin1_data, sizeof(latin1_data));
124+125+ Local<Uint8Array> array = Uint8Array::New(ab, 0, sizeof(latin1_data));
126+ Local<Value> args[] = {array};
127+128+ Local<Value> result;
129+EXPECT_TRUE(RunDecodeLatin1(env, args, true, true, &result));
130+131+ String::Utf8Value utf8_result(isolate, result);
132+EXPECT_STREQ(*utf8_result, "Áéó");
133+}
134+135+TEST_F(EncodingBindingTest, DecodeLatin1_BOMPresent) {
136+ Environment* env = CreateEnvironment();
137+ Isolate* isolate = env->isolate();
138+ HandleScope handle_scope(isolate);
139+140+const uint8_t latin1_data[] = {0xFF, 0xC1, 0xE9, 0xF3};
141+ Local<ArrayBuffer> ab = ArrayBuffer::New(isolate, sizeof(latin1_data));
142+memcpy(ab->GetBackingStore()->Data(), latin1_data, sizeof(latin1_data));
143+144+ Local<Uint8Array> array = Uint8Array::New(ab, 0, sizeof(latin1_data));
145+ Local<Value> args[] = {array};
146+147+ Local<Value> result;
148+EXPECT_TRUE(RunDecodeLatin1(env, args, true, false, &result));
149+150+ String::Utf8Value utf8_result(isolate, result);
151+EXPECT_STREQ(*utf8_result, "Áéó");
152+}
153+154+} // namespace encoding_binding
155+} // namespace node