| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 6201cfe commit 9473c5f
4 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -6,26 +6,42 @@ const bench = common.createBenchmark(main, { | |||
| 6 | 6 | encoding: ['utf-8', 'windows-1252', 'iso-8859-3'], | |
| 7 | 7 | ignoreBOM: [0, 1], | |
| 8 | 8 | fatal: [0, 1], | |
| 9 | + type: ['SharedArrayBuffer', 'ArrayBuffer', 'Buffer'], | ||
| 10 | + content: ['ascii', 'one-byte-string', 'two-byte-string'], | ||
| 9 | 11 | len: [256, 1024 * 16, 1024 * 128], | |
| 10 | 12 | n: [1e3], | |
| 11 | - type: ['SharedArrayBuffer', 'ArrayBuffer', 'Buffer'], | ||
| 12 | 13 | }); | |
| 13 | 14 | ||
| 14 | - function main({ encoding, len, n, ignoreBOM, type, fatal }) { | ||
| 15 | + function buildContent(content, len) { | ||
| 16 | + let base; | ||
| 17 | + switch (content) { | ||
| 18 | + case 'ascii': base = 'a'; break; | ||
| 19 | + case 'one-byte-string': base = '\xff'; break; | ||
| 20 | + case 'two-byte-string': base = 'ğ'; break; | ||
| 21 | + } | ||
| 22 | + const unitBytes = Buffer.byteLength(base, 'utf8'); | ||
| 23 | + const copies = Math.max(1, Math.floor(len / unitBytes)); | ||
| 24 | + return Buffer.from(base.repeat(copies)); | ||
| 25 | + } | ||
| 26 | + | ||
| 27 | + function main({ encoding, len, n, ignoreBOM, type, fatal, content }) { | ||
| 15 | 28 | const decoder = new TextDecoder(encoding, { ignoreBOM, fatal }); | |
| 29 | + const seed = buildContent(content, len); | ||
| 16 | 30 | let buf; | |
| 17 | 31 | ||
| 18 | 32 | switch (type) { | |
| 19 | 33 | case 'SharedArrayBuffer': { | |
| 20 | - buf = new SharedArrayBuffer(len); | ||
| 34 | + buf = new SharedArrayBuffer(seed.length); | ||
| 35 | + new Uint8Array(buf).set(seed); | ||
| 21 | 36 | break; | |
| 22 | 37 | } | |
| 23 | 38 | case 'ArrayBuffer': { | |
| 24 | - buf = new ArrayBuffer(len); | ||
| 39 | + buf = new ArrayBuffer(seed.length); | ||
| 40 | + new Uint8Array(buf).set(seed); | ||
| 25 | 41 | break; | |
| 26 | 42 | } | |
| 27 | 43 | case 'Buffer': { | |
| 28 | - buf = Buffer.allocUnsafe(len); | ||
| 44 | + buf = seed; | ||
| 29 | 45 | break; | |
| 30 | 46 | } | |
| 31 | 47 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -193,14 +193,15 @@ void BindingData::DecodeUTF8(const FunctionCallbackInfo<Value>& args) { | |||
| 193 | 193 | return node::THROW_ERR_ENCODING_INVALID_ENCODED_DATA( | |
| 194 | 194 | env->isolate(), "The encoded data was not valid for encoding utf-8"); | |
| 195 | 195 | } | |
| 196 | - | ||
| 197 | - // TODO(chalker): save on utf8 validity recheck in StringBytes::Encode() | ||
| 198 | 196 | } | |
| 199 | 197 | ||
| 200 | 198 | if (length == 0) return args.GetReturnValue().SetEmptyString(); | |
| 201 | 199 | ||
| 202 | 200 | Local<Value> ret; | |
| 203 | - if (StringBytes::Encode(env->isolate(), data, length, UTF8).ToLocal(&ret)) { | ||
| 201 | + v8::MaybeLocal<Value> encoded = | ||
| 202 | + has_fatal ? StringBytes::EncodeValidUtf8(env->isolate(), data, length) | ||
| 203 | + : StringBytes::Encode(env->isolate(), data, length, UTF8); | ||
| 204 | + if (encoded.ToLocal(&ret)) { | ||
| 204 | 205 | args.GetReturnValue().Set(ret); | |
| 205 | 206 | } | |
| 206 | 207 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -671,6 +671,40 @@ MaybeLocal<Value> StringBytes::Encode(Isolate* isolate, | |||
| 671 | 671 | } | |
| 672 | 672 | } | |
| 673 | 673 | ||
| 674 | + MaybeLocal<Value> StringBytes::EncodeValidUtf8(Isolate* isolate, | ||
| 675 | + const char* buf, | ||
| 676 | + size_t buflen) { | ||
| 677 | + CHECK_BUFLEN_IN_RANGE(buflen); | ||
| 678 | + if (!buflen) return String::Empty(isolate); | ||
| 679 | + buflen = keep_buflen_in_range(buflen); | ||
| 680 | + | ||
| 681 | + // ASCII fast path | ||
| 682 | + if (!simdutf::validate_ascii_with_errors(buf, buflen).error) { | ||
| 683 | + return ExternOneByteString::NewFromCopy(isolate, buf, buflen); | ||
| 684 | + } | ||
| 685 | + | ||
| 686 | + if (buflen >= 32) { | ||
| 687 | + size_t u16size = simdutf::utf16_length_from_utf8(buf, buflen); | ||
| 688 | + if (u16size > static_cast<size_t>(v8::String::kMaxLength)) { | ||
| 689 | + isolate->ThrowException(ERR_STRING_TOO_LONG(isolate)); | ||
| 690 | + return MaybeLocal<Value>(); | ||
| 691 | + } | ||
| 692 | + return EncodeTwoByteString( | ||
| 693 | + isolate, u16size, [buf, buflen, u16size](uint16_t* dst) { | ||
| 694 | + size_t written = simdutf::convert_valid_utf8_to_utf16( | ||
| 695 | + buf, buflen, reinterpret_cast<char16_t*>(dst)); | ||
| 696 | + CHECK_EQ(written, u16size); | ||
| 697 | + }); | ||
| 698 | + } | ||
| 699 | + | ||
| 700 | + Local<String> str; | ||
| 701 | + if (!String::NewFromUtf8(isolate, buf, v8::NewStringType::kNormal, buflen) | ||
| 702 | + .ToLocal(&str)) { | ||
| 703 | + isolate->ThrowException(node::ERR_STRING_TOO_LONG(isolate)); | ||
| 704 | + } | ||
| 705 | + return str; | ||
| 706 | + } | ||
| 707 | + | ||
| 674 | 708 | MaybeLocal<Value> StringBytes::Encode(Isolate* isolate, | |
| 675 | 709 | const uint16_t* buf, | |
| 676 | 710 | size_t buflen) { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -83,6 +83,11 @@ class StringBytes { | |||
| 83 | 83 | size_t buflen, | |
| 84 | 84 | enum encoding encoding); | |
| 85 | 85 | ||
| 86 | + // Like Encode(..., UTF8) but does not re-validate. Input must be valid UTF-8. | ||
| 87 | + static v8::MaybeLocal<v8::Value> EncodeValidUtf8(v8::Isolate* isolate, | ||
| 88 | + const char* buf, | ||
| 89 | + size_t buflen); | ||
| 90 | + | ||
| 86 | 91 | // Warning: This reverses endianness on BE platforms, even though the | |
| 87 | 92 | // signature using uint16_t implies that it should not. | |
| 88 | 93 | // However, the brokenness is already public API and can't therefore | |
| Back | FazBrowse Home | New Git URL |
0 commit comments