|
24 | 24 | #include "node_blob.h" |
25 | 25 | #include "node_errors.h" |
26 | 26 | #include "node_external_reference.h" |
| 27 | +#include "node_i18n.h" |
27 | 28 | #include "node_internals.h" |
28 | 29 |
|
29 | 30 | #include "env-inl.h" |
@@ -565,6 +566,54 @@ void StringSlice(const FunctionCallbackInfo<Value>& args) { |
565 | 566 | args.GetReturnValue().Set(ret); |
566 | 567 | } |
567 | 568 |
|
| 569 | +// Convert the input into an encoded string |
| 570 | +void DecodeUTF8(const FunctionCallbackInfo<Value>& args) { |
| 571 | + Environment* env = Environment::GetCurrent(args); // list, flags |
| 572 | + |
| 573 | + if (!(args[0]->IsArrayBuffer() || args[0]->IsSharedArrayBuffer() || |
| 574 | + args[0]->IsArrayBufferView())) { |
| 575 | + return node::THROW_ERR_INVALID_ARG_TYPE( |
| 576 | + env->isolate(), |
| 577 | + "The \"list\" argument must be an instance of SharedArrayBuffer, " |
| 578 | + "ArrayBuffer or ArrayBufferView."); |
| 579 | + } |
| 580 | + |
| 581 | + ArrayBufferViewContents<char> buffer(args[0]); |
| 582 | + |
| 583 | + CHECK(args[1]->IsBoolean()); |
| 584 | + bool ignore_bom = args[1]->BooleanValue(env->isolate()); |
| 585 | + |
| 586 | + const char* data = buffer.data(); |
| 587 | + auto beginning = 0; |
| 588 | + auto length = buffer.length(); |
| 589 | + |
| 590 | + if (buffer.length() == 0) return args.GetReturnValue().SetEmptyString(); |
| 591 | + |
| 592 | + if (!ignore_bom) { |
| 593 | + char bom[] = "\xEF\xBB\xBF"; |
| 594 | + |
| 595 | + if (strncmp(data, bom, 0) == 0 && strncmp(data, bom, 1) == 0 && |
| 596 | + strncmp(data, bom, 2) == 0) { |
| 597 | + beginning += 3; |
| 598 | + length -= 3; |
| 599 | + } |
| 600 | + } |
| 601 | + |
| 602 | + auto output = data + beginning; |
| 603 | + |
| 604 | + Local<Value> error; |
| 605 | + MaybeLocal<Value> maybe_ret = |
| 606 | + StringBytes::Encode(env->isolate(), output, length, UTF8, &error); |
| 607 | + Local<Value> ret; |
| 608 | + |
| 609 | + if (!maybe_ret.ToLocal(&ret)) { |
| 610 | + CHECK(!error.IsEmpty()); |
| 611 | + env->isolate()->ThrowException(error); |
| 612 | + return; |
| 613 | + } |
| 614 | + |
| 615 | + args.GetReturnValue().Set(ret); |
| 616 | +} |
568 | 617 |
|
569 | 618 | // bytesCopied = copy(buffer, target[, targetStart][, sourceStart][, sourceEnd]) |
570 | 619 | void Copy(const FunctionCallbackInfo<Value> &args) { |
@@ -1282,6 +1331,7 @@ void Initialize(Local<Object> target, |
1282 | 1331 |
|
1283 | 1332 | SetMethod(context, target, "setBufferPrototype", SetBufferPrototype); |
1284 | 1333 | SetMethodNoSideEffect(context, target, "createFromString", CreateFromString); |
| 1334 | + SetMethodNoSideEffect(context, target, "decodeUTF8", DecodeUTF8); |
1285 | 1335 |
|
1286 | 1336 | SetMethodNoSideEffect(context, target, "byteLengthUtf8", ByteLengthUtf8); |
1287 | 1337 | SetMethod(context, target, "copy", Copy); |
@@ -1339,6 +1389,7 @@ void Initialize(Local<Object> target, |
1339 | 1389 | void RegisterExternalReferences(ExternalReferenceRegistry* registry) { |
1340 | 1390 | registry->Register(SetBufferPrototype); |
1341 | 1391 | registry->Register(CreateFromString); |
| 1392 | + registry->Register(DecodeUTF8); |
1342 | 1393 |
|
1343 | 1394 | registry->Register(ByteLengthUtf8); |
1344 | 1395 | registry->Register(Copy); |
|
0 commit comments