diff --git a/lib/internal/util.js b/lib/internal/util.js index ba98a41e406cfe..a3706062564d7b 100644 --- a/lib/internal/util.js +++ b/lib/internal/util.js @@ -28,10 +28,6 @@ const { SymbolFor, } = primordials; -const { - toUSVString: _toUSVString, -} = internalBinding('url'); - const { hideStackFrames, codes: { @@ -47,7 +43,8 @@ const { setHiddenValue, arrow_message_private_symbol: kArrowMessagePrivateSymbolIndex, decorated_private_symbol: kDecoratedPrivateSymbolIndex, - sleep: _sleep + sleep: _sleep, + toUSVString: _toUSVString, } = internalBinding('util'); const { isNativeError } = internalBinding('types'); diff --git a/src/node_url.cc b/src/node_url.cc index d78cb7a3e1ceb0..14522fccb079ab 100644 --- a/src/node_url.cc +++ b/src/node_url.cc @@ -52,9 +52,6 @@ namespace { // https://url.spec.whatwg.org/#eof-code-point constexpr char kEOL = -1; -// Used in ToUSVString(). -constexpr char16_t kUnicodeReplacementCharacter = 0xFFFD; - // https://url.spec.whatwg.org/#concept-host class URLHost { public: @@ -160,14 +157,6 @@ enum url_error_cb_args { #undef XX }; -#define CHAR_TEST(bits, name, expr) \ - template \ - bool name(const T ch) { \ - static_assert(sizeof(ch) >= (bits) / 8, \ - "Character must be wider than " #bits " bits"); \ - return (expr); \ - } - #define TWO_CHAR_STRING_TEST(bits, name, expr) \ template \ bool name(const T ch1, const T ch2) { \ @@ -225,19 +214,8 @@ TWO_CHAR_STRING_TEST(8, IsWindowsDriveLetter, TWO_CHAR_STRING_TEST(8, IsNormalizedWindowsDriveLetter, (IsASCIIAlpha(ch1) && ch2 == ':')) -// If a UTF-16 character is a low/trailing surrogate. -CHAR_TEST(16, IsUnicodeTrail, (ch & 0xFC00) == 0xDC00) - -// If a UTF-16 character is a surrogate. -CHAR_TEST(16, IsUnicodeSurrogate, (ch & 0xF800) == 0xD800) - -// If a UTF-16 surrogate is a low/trailing one. -CHAR_TEST(16, IsUnicodeSurrogateTrail, (ch & 0x400) != 0) - -#undef CHAR_TEST #undef TWO_CHAR_STRING_TEST - bool BitAt(const uint8_t a[], const uint8_t i) { return !!(a[i >> 3] & (1 << (i & 7))); } @@ -1736,40 +1714,6 @@ void EncodeAuthSet(const FunctionCallbackInfo& args) { String::NewFromUtf8(env->isolate(), output.c_str()).ToLocalChecked()); } -void ToUSVString(const FunctionCallbackInfo& args) { - Environment* env = Environment::GetCurrent(args); - CHECK_GE(args.Length(), 2); - CHECK(args[0]->IsString()); - CHECK(args[1]->IsNumber()); - - TwoByteValue value(env->isolate(), args[0]); - - int64_t start = args[1]->IntegerValue(env->context()).FromJust(); - CHECK_GE(start, 0); - - for (size_t i = start; i < value.length(); i++) { - char16_t c = value[i]; - if (!IsUnicodeSurrogate(c)) { - continue; - } else if (IsUnicodeSurrogateTrail(c) || i == value.length() - 1) { - value[i] = kUnicodeReplacementCharacter; - } else { - char16_t d = value[i + 1]; - if (IsUnicodeTrail(d)) { - i++; - } else { - value[i] = kUnicodeReplacementCharacter; - } - } - } - - args.GetReturnValue().Set( - String::NewFromTwoByte(env->isolate(), - *value, - NewStringType::kNormal, - value.length()).ToLocalChecked()); -} - void DomainToASCII(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); CHECK_GE(args.Length(), 1); @@ -1820,7 +1764,6 @@ void Initialize(Local target, Environment* env = Environment::GetCurrent(context); env->SetMethod(target, "parse", Parse); env->SetMethodNoSideEffect(target, "encodeAuth", EncodeAuthSet); - env->SetMethodNoSideEffect(target, "toUSVString", ToUSVString); env->SetMethodNoSideEffect(target, "domainToASCII", DomainToASCII); env->SetMethodNoSideEffect(target, "domainToUnicode", DomainToUnicode); env->SetMethod(target, "setURLConstructor", SetURLConstructor); @@ -1838,7 +1781,6 @@ void Initialize(Local target, void RegisterExternalReferences(ExternalReferenceRegistry* registry) { registry->Register(Parse); registry->Register(EncodeAuthSet); - registry->Register(ToUSVString); registry->Register(DomainToASCII); registry->Register(DomainToUnicode); registry->Register(SetURLConstructor); diff --git a/src/node_util.cc b/src/node_util.cc index cc03ec0aba602a..2db45bd1fb40af 100644 --- a/src/node_util.cc +++ b/src/node_util.cc @@ -35,6 +35,18 @@ using v8::String; using v8::Uint32; using v8::Value; +// Used in ToUSVString(). +constexpr char16_t kUnicodeReplacementCharacter = 0xFFFD; + +// If a UTF-16 character is a low/trailing surrogate. +CHAR_TEST(16, IsUnicodeTrail, (ch & 0xFC00) == 0xDC00) + +// If a UTF-16 character is a surrogate. +CHAR_TEST(16, IsUnicodeSurrogate, (ch & 0xF800) == 0xD800) + +// If a UTF-16 surrogate is a low/trailing one. +CHAR_TEST(16, IsUnicodeSurrogateTrail, (ch & 0x400) != 0) + static void GetOwnNonIndexProperties( const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); @@ -282,6 +294,40 @@ static void IsConstructor(const FunctionCallbackInfo& args) { args.GetReturnValue().Set(args[0].As()->IsConstructor()); } +static void ToUSVString(const FunctionCallbackInfo& args) { + Environment* env = Environment::GetCurrent(args); + CHECK_GE(args.Length(), 2); + CHECK(args[0]->IsString()); + CHECK(args[1]->IsNumber()); + + TwoByteValue value(env->isolate(), args[0]); + + int64_t start = args[1]->IntegerValue(env->context()).FromJust(); + CHECK_GE(start, 0); + + for (size_t i = start; i < value.length(); i++) { + char16_t c = value[i]; + if (!IsUnicodeSurrogate(c)) { + continue; + } else if (IsUnicodeSurrogateTrail(c) || i == value.length() - 1) { + value[i] = kUnicodeReplacementCharacter; + } else { + char16_t d = value[i + 1]; + if (IsUnicodeTrail(d)) { + i++; + } else { + value[i] = kUnicodeReplacementCharacter; + } + } + } + + args.GetReturnValue().Set( + String::NewFromTwoByte(env->isolate(), + *value, + v8::NewStringType::kNormal, + value.length()).ToLocalChecked()); +} + void RegisterExternalReferences(ExternalReferenceRegistry* registry) { registry->Register(GetHiddenValue); registry->Register(SetHiddenValue); @@ -299,6 +345,7 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) { registry->Register(WeakReference::DecRef); registry->Register(GuessHandleType); registry->Register(IsConstructor); + registry->Register(ToUSVString); } void Initialize(Local target, @@ -370,6 +417,8 @@ void Initialize(Local target, env->SetConstructorFunction(target, "WeakReference", weak_ref); env->SetMethod(target, "guessHandleType", GuessHandleType); + + env->SetMethodNoSideEffect(target, "toUSVString", ToUSVString); } } // namespace util diff --git a/src/util-inl.h b/src/util-inl.h index 517da707170586..b860c7008a340a 100644 --- a/src/util-inl.h +++ b/src/util-inl.h @@ -64,6 +64,14 @@ (((x) & 0x00000000000000FFull) << 56) #endif +#define CHAR_TEST(bits, name, expr) \ + template \ + bool name(const T ch) { \ + static_assert(sizeof(ch) >= (bits) / 8, \ + "Character must be wider than " #bits " bits"); \ + return (expr); \ + } + namespace node { template