11cb0ef41Sopenharmony_ci#include "node_url.h"
21cb0ef41Sopenharmony_ci#include "ada.h"
31cb0ef41Sopenharmony_ci#include "base_object-inl.h"
41cb0ef41Sopenharmony_ci#include "node_errors.h"
51cb0ef41Sopenharmony_ci#include "node_external_reference.h"
61cb0ef41Sopenharmony_ci#include "node_i18n.h"
71cb0ef41Sopenharmony_ci#include "util-inl.h"
81cb0ef41Sopenharmony_ci#include "v8.h"
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci#include <cstdint>
111cb0ef41Sopenharmony_ci#include <cstdio>
121cb0ef41Sopenharmony_ci#include <numeric>
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_cinamespace node {
151cb0ef41Sopenharmony_cinamespace url {
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_ciusing v8::Context;
181cb0ef41Sopenharmony_ciusing v8::FunctionCallbackInfo;
191cb0ef41Sopenharmony_ciusing v8::HandleScope;
201cb0ef41Sopenharmony_ciusing v8::Isolate;
211cb0ef41Sopenharmony_ciusing v8::Local;
221cb0ef41Sopenharmony_ciusing v8::NewStringType;
231cb0ef41Sopenharmony_ciusing v8::Object;
241cb0ef41Sopenharmony_ciusing v8::String;
251cb0ef41Sopenharmony_ciusing v8::Value;
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_civoid BindingData::MemoryInfo(MemoryTracker* tracker) const {
281cb0ef41Sopenharmony_ci  tracker->TrackField("url_components_buffer", url_components_buffer_);
291cb0ef41Sopenharmony_ci}
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_ciBindingData::BindingData(Realm* realm, v8::Local<v8::Object> object)
321cb0ef41Sopenharmony_ci    : SnapshotableObject(realm, object, type_int),
331cb0ef41Sopenharmony_ci      url_components_buffer_(realm->isolate(), kURLComponentsLength) {
341cb0ef41Sopenharmony_ci  object
351cb0ef41Sopenharmony_ci      ->Set(realm->context(),
361cb0ef41Sopenharmony_ci            FIXED_ONE_BYTE_STRING(realm->isolate(), "urlComponents"),
371cb0ef41Sopenharmony_ci            url_components_buffer_.GetJSArray())
381cb0ef41Sopenharmony_ci      .Check();
391cb0ef41Sopenharmony_ci}
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_cibool BindingData::PrepareForSerialization(v8::Local<v8::Context> context,
421cb0ef41Sopenharmony_ci                                          v8::SnapshotCreator* creator) {
431cb0ef41Sopenharmony_ci  // We'll just re-initialize the buffers in the constructor since their
441cb0ef41Sopenharmony_ci  // contents can be thrown away once consumed in the previous call.
451cb0ef41Sopenharmony_ci  url_components_buffer_.Release();
461cb0ef41Sopenharmony_ci  // Return true because we need to maintain the reference to the binding from
471cb0ef41Sopenharmony_ci  // JS land.
481cb0ef41Sopenharmony_ci  return true;
491cb0ef41Sopenharmony_ci}
501cb0ef41Sopenharmony_ci
511cb0ef41Sopenharmony_ciInternalFieldInfoBase* BindingData::Serialize(int index) {
521cb0ef41Sopenharmony_ci  DCHECK_EQ(index, BaseObject::kEmbedderType);
531cb0ef41Sopenharmony_ci  InternalFieldInfo* info =
541cb0ef41Sopenharmony_ci      InternalFieldInfoBase::New<InternalFieldInfo>(type());
551cb0ef41Sopenharmony_ci  return info;
561cb0ef41Sopenharmony_ci}
571cb0ef41Sopenharmony_ci
581cb0ef41Sopenharmony_civoid BindingData::Deserialize(v8::Local<v8::Context> context,
591cb0ef41Sopenharmony_ci                              v8::Local<v8::Object> holder,
601cb0ef41Sopenharmony_ci                              int index,
611cb0ef41Sopenharmony_ci                              InternalFieldInfoBase* info) {
621cb0ef41Sopenharmony_ci  DCHECK_EQ(index, BaseObject::kEmbedderType);
631cb0ef41Sopenharmony_ci  v8::HandleScope scope(context->GetIsolate());
641cb0ef41Sopenharmony_ci  Realm* realm = Realm::GetCurrent(context);
651cb0ef41Sopenharmony_ci  BindingData* binding = realm->AddBindingData<BindingData>(context, holder);
661cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(binding);
671cb0ef41Sopenharmony_ci}
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_civoid BindingData::DomainToASCII(const FunctionCallbackInfo<Value>& args) {
701cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
711cb0ef41Sopenharmony_ci  CHECK_GE(args.Length(), 1);
721cb0ef41Sopenharmony_ci  CHECK(args[0]->IsString());
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ci  std::string input = Utf8Value(env->isolate(), args[0]).ToString();
751cb0ef41Sopenharmony_ci  if (input.empty()) {
761cb0ef41Sopenharmony_ci    return args.GetReturnValue().Set(FIXED_ONE_BYTE_STRING(env->isolate(), ""));
771cb0ef41Sopenharmony_ci  }
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ci  // It is important to have an initial value that contains a special scheme.
801cb0ef41Sopenharmony_ci  // Since it will change the implementation of `set_hostname` according to URL
811cb0ef41Sopenharmony_ci  // spec.
821cb0ef41Sopenharmony_ci  auto out = ada::parse<ada::url>("ws://x");
831cb0ef41Sopenharmony_ci  DCHECK(out);
841cb0ef41Sopenharmony_ci  if (!out->set_hostname(input)) {
851cb0ef41Sopenharmony_ci    return args.GetReturnValue().Set(FIXED_ONE_BYTE_STRING(env->isolate(), ""));
861cb0ef41Sopenharmony_ci  }
871cb0ef41Sopenharmony_ci  std::string host = out->get_hostname();
881cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(
891cb0ef41Sopenharmony_ci      String::NewFromUtf8(env->isolate(), host.c_str()).ToLocalChecked());
901cb0ef41Sopenharmony_ci}
911cb0ef41Sopenharmony_ci
921cb0ef41Sopenharmony_civoid BindingData::DomainToUnicode(const FunctionCallbackInfo<Value>& args) {
931cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
941cb0ef41Sopenharmony_ci  CHECK_GE(args.Length(), 1);
951cb0ef41Sopenharmony_ci  CHECK(args[0]->IsString());
961cb0ef41Sopenharmony_ci
971cb0ef41Sopenharmony_ci  std::string input = Utf8Value(env->isolate(), args[0]).ToString();
981cb0ef41Sopenharmony_ci  if (input.empty()) {
991cb0ef41Sopenharmony_ci    return args.GetReturnValue().Set(
1001cb0ef41Sopenharmony_ci        String::NewFromUtf8(env->isolate(), "").ToLocalChecked());
1011cb0ef41Sopenharmony_ci  }
1021cb0ef41Sopenharmony_ci
1031cb0ef41Sopenharmony_ci  // It is important to have an initial value that contains a special scheme.
1041cb0ef41Sopenharmony_ci  // Since it will change the implementation of `set_hostname` according to URL
1051cb0ef41Sopenharmony_ci  // spec.
1061cb0ef41Sopenharmony_ci  auto out = ada::parse<ada::url>("ws://x");
1071cb0ef41Sopenharmony_ci  DCHECK(out);
1081cb0ef41Sopenharmony_ci  if (!out->set_hostname(input)) {
1091cb0ef41Sopenharmony_ci    return args.GetReturnValue().Set(
1101cb0ef41Sopenharmony_ci        String::NewFromUtf8(env->isolate(), "").ToLocalChecked());
1111cb0ef41Sopenharmony_ci  }
1121cb0ef41Sopenharmony_ci  std::string result = ada::unicode::to_unicode(out->get_hostname());
1131cb0ef41Sopenharmony_ci
1141cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(String::NewFromUtf8(env->isolate(),
1151cb0ef41Sopenharmony_ci                                                result.c_str(),
1161cb0ef41Sopenharmony_ci                                                NewStringType::kNormal,
1171cb0ef41Sopenharmony_ci                                                result.length())
1181cb0ef41Sopenharmony_ci                                .ToLocalChecked());
1191cb0ef41Sopenharmony_ci}
1201cb0ef41Sopenharmony_ci
1211cb0ef41Sopenharmony_ci// TODO(@anonrig): Add V8 Fast API for CanParse method
1221cb0ef41Sopenharmony_civoid BindingData::CanParse(const FunctionCallbackInfo<Value>& args) {
1231cb0ef41Sopenharmony_ci  CHECK_GE(args.Length(), 1);
1241cb0ef41Sopenharmony_ci  CHECK(args[0]->IsString());  // input
1251cb0ef41Sopenharmony_ci  // args[1] // base url
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
1281cb0ef41Sopenharmony_ci  HandleScope handle_scope(env->isolate());
1291cb0ef41Sopenharmony_ci  Context::Scope context_scope(env->context());
1301cb0ef41Sopenharmony_ci
1311cb0ef41Sopenharmony_ci  Utf8Value input(env->isolate(), args[0]);
1321cb0ef41Sopenharmony_ci  ada::result<ada::url_aggregator> base;
1331cb0ef41Sopenharmony_ci  ada::url_aggregator* base_pointer = nullptr;
1341cb0ef41Sopenharmony_ci  if (args[1]->IsString()) {
1351cb0ef41Sopenharmony_ci    base = ada::parse<ada::url_aggregator>(
1361cb0ef41Sopenharmony_ci        Utf8Value(env->isolate(), args[1]).ToString());
1371cb0ef41Sopenharmony_ci    if (!base) {
1381cb0ef41Sopenharmony_ci      return args.GetReturnValue().Set(false);
1391cb0ef41Sopenharmony_ci    }
1401cb0ef41Sopenharmony_ci    base_pointer = &base.value();
1411cb0ef41Sopenharmony_ci  }
1421cb0ef41Sopenharmony_ci  auto out =
1431cb0ef41Sopenharmony_ci      ada::parse<ada::url_aggregator>(input.ToStringView(), base_pointer);
1441cb0ef41Sopenharmony_ci
1451cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(out.has_value());
1461cb0ef41Sopenharmony_ci}
1471cb0ef41Sopenharmony_ci
1481cb0ef41Sopenharmony_civoid BindingData::Format(const FunctionCallbackInfo<Value>& args) {
1491cb0ef41Sopenharmony_ci  CHECK_GT(args.Length(), 4);
1501cb0ef41Sopenharmony_ci  CHECK(args[0]->IsString());  // url href
1511cb0ef41Sopenharmony_ci
1521cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
1531cb0ef41Sopenharmony_ci  Isolate* isolate = env->isolate();
1541cb0ef41Sopenharmony_ci
1551cb0ef41Sopenharmony_ci  Utf8Value href(isolate, args[0].As<String>());
1561cb0ef41Sopenharmony_ci  const bool hash = args[1]->IsTrue();
1571cb0ef41Sopenharmony_ci  const bool unicode = args[2]->IsTrue();
1581cb0ef41Sopenharmony_ci  const bool search = args[3]->IsTrue();
1591cb0ef41Sopenharmony_ci  const bool auth = args[4]->IsTrue();
1601cb0ef41Sopenharmony_ci
1611cb0ef41Sopenharmony_ci  // ada::url provides a faster alternative to ada::url_aggregator if we
1621cb0ef41Sopenharmony_ci  // directly want to manipulate the url components without using the respective
1631cb0ef41Sopenharmony_ci  // setters. therefore we are using ada::url here.
1641cb0ef41Sopenharmony_ci  auto out = ada::parse<ada::url>(href.ToStringView());
1651cb0ef41Sopenharmony_ci  CHECK(out);
1661cb0ef41Sopenharmony_ci
1671cb0ef41Sopenharmony_ci  if (!hash) {
1681cb0ef41Sopenharmony_ci    out->hash = std::nullopt;
1691cb0ef41Sopenharmony_ci  }
1701cb0ef41Sopenharmony_ci
1711cb0ef41Sopenharmony_ci  if (unicode && out->has_hostname()) {
1721cb0ef41Sopenharmony_ci    out->host = ada::idna::to_unicode(out->get_hostname());
1731cb0ef41Sopenharmony_ci  }
1741cb0ef41Sopenharmony_ci
1751cb0ef41Sopenharmony_ci  if (!search) {
1761cb0ef41Sopenharmony_ci    out->query = std::nullopt;
1771cb0ef41Sopenharmony_ci  }
1781cb0ef41Sopenharmony_ci
1791cb0ef41Sopenharmony_ci  if (!auth) {
1801cb0ef41Sopenharmony_ci    out->username = "";
1811cb0ef41Sopenharmony_ci    out->password = "";
1821cb0ef41Sopenharmony_ci  }
1831cb0ef41Sopenharmony_ci
1841cb0ef41Sopenharmony_ci  std::string result = out->get_href();
1851cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(String::NewFromUtf8(env->isolate(),
1861cb0ef41Sopenharmony_ci                                                result.data(),
1871cb0ef41Sopenharmony_ci                                                NewStringType::kNormal,
1881cb0ef41Sopenharmony_ci                                                result.length())
1891cb0ef41Sopenharmony_ci                                .ToLocalChecked());
1901cb0ef41Sopenharmony_ci}
1911cb0ef41Sopenharmony_ci
1921cb0ef41Sopenharmony_civoid BindingData::Parse(const FunctionCallbackInfo<Value>& args) {
1931cb0ef41Sopenharmony_ci  CHECK_GE(args.Length(), 1);
1941cb0ef41Sopenharmony_ci  CHECK(args[0]->IsString());  // input
1951cb0ef41Sopenharmony_ci  // args[1] // base url
1961cb0ef41Sopenharmony_ci
1971cb0ef41Sopenharmony_ci  BindingData* binding_data = Realm::GetBindingData<BindingData>(args);
1981cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
1991cb0ef41Sopenharmony_ci  HandleScope handle_scope(env->isolate());
2001cb0ef41Sopenharmony_ci  Context::Scope context_scope(env->context());
2011cb0ef41Sopenharmony_ci
2021cb0ef41Sopenharmony_ci  Utf8Value input(env->isolate(), args[0]);
2031cb0ef41Sopenharmony_ci  ada::result<ada::url_aggregator> base;
2041cb0ef41Sopenharmony_ci  ada::url_aggregator* base_pointer = nullptr;
2051cb0ef41Sopenharmony_ci  if (args[1]->IsString()) {
2061cb0ef41Sopenharmony_ci    base = ada::parse<ada::url_aggregator>(
2071cb0ef41Sopenharmony_ci        Utf8Value(env->isolate(), args[1]).ToString());
2081cb0ef41Sopenharmony_ci    if (!base) {
2091cb0ef41Sopenharmony_ci      return args.GetReturnValue().Set(false);
2101cb0ef41Sopenharmony_ci    }
2111cb0ef41Sopenharmony_ci    base_pointer = &base.value();
2121cb0ef41Sopenharmony_ci  }
2131cb0ef41Sopenharmony_ci  auto out =
2141cb0ef41Sopenharmony_ci      ada::parse<ada::url_aggregator>(input.ToStringView(), base_pointer);
2151cb0ef41Sopenharmony_ci
2161cb0ef41Sopenharmony_ci  if (!out) {
2171cb0ef41Sopenharmony_ci    return args.GetReturnValue().Set(false);
2181cb0ef41Sopenharmony_ci  }
2191cb0ef41Sopenharmony_ci
2201cb0ef41Sopenharmony_ci  binding_data->UpdateComponents(out->get_components(), out->type);
2211cb0ef41Sopenharmony_ci
2221cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(
2231cb0ef41Sopenharmony_ci      ToV8Value(env->context(), out->get_href(), env->isolate())
2241cb0ef41Sopenharmony_ci          .ToLocalChecked());
2251cb0ef41Sopenharmony_ci}
2261cb0ef41Sopenharmony_ci
2271cb0ef41Sopenharmony_civoid BindingData::Update(const FunctionCallbackInfo<Value>& args) {
2281cb0ef41Sopenharmony_ci  CHECK(args[0]->IsString());    // href
2291cb0ef41Sopenharmony_ci  CHECK(args[1]->IsNumber());    // action type
2301cb0ef41Sopenharmony_ci  CHECK(args[2]->IsString());    // new value
2311cb0ef41Sopenharmony_ci
2321cb0ef41Sopenharmony_ci  BindingData* binding_data = Realm::GetBindingData<BindingData>(args);
2331cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
2341cb0ef41Sopenharmony_ci  Isolate* isolate = env->isolate();
2351cb0ef41Sopenharmony_ci
2361cb0ef41Sopenharmony_ci  enum url_update_action action = static_cast<enum url_update_action>(
2371cb0ef41Sopenharmony_ci      args[1]->Uint32Value(env->context()).FromJust());
2381cb0ef41Sopenharmony_ci  Utf8Value input(isolate, args[0].As<String>());
2391cb0ef41Sopenharmony_ci  Utf8Value new_value(isolate, args[2].As<String>());
2401cb0ef41Sopenharmony_ci
2411cb0ef41Sopenharmony_ci  std::string_view new_value_view = new_value.ToStringView();
2421cb0ef41Sopenharmony_ci  auto out = ada::parse<ada::url_aggregator>(input.ToStringView());
2431cb0ef41Sopenharmony_ci  CHECK(out);
2441cb0ef41Sopenharmony_ci
2451cb0ef41Sopenharmony_ci  bool result{true};
2461cb0ef41Sopenharmony_ci
2471cb0ef41Sopenharmony_ci  switch (action) {
2481cb0ef41Sopenharmony_ci    case kPathname: {
2491cb0ef41Sopenharmony_ci      result = out->set_pathname(new_value_view);
2501cb0ef41Sopenharmony_ci      break;
2511cb0ef41Sopenharmony_ci    }
2521cb0ef41Sopenharmony_ci    case kHash: {
2531cb0ef41Sopenharmony_ci      out->set_hash(new_value_view);
2541cb0ef41Sopenharmony_ci      break;
2551cb0ef41Sopenharmony_ci    }
2561cb0ef41Sopenharmony_ci    case kHost: {
2571cb0ef41Sopenharmony_ci      result = out->set_host(new_value_view);
2581cb0ef41Sopenharmony_ci      break;
2591cb0ef41Sopenharmony_ci    }
2601cb0ef41Sopenharmony_ci    case kHostname: {
2611cb0ef41Sopenharmony_ci      result = out->set_hostname(new_value_view);
2621cb0ef41Sopenharmony_ci      break;
2631cb0ef41Sopenharmony_ci    }
2641cb0ef41Sopenharmony_ci    case kHref: {
2651cb0ef41Sopenharmony_ci      result = out->set_href(new_value_view);
2661cb0ef41Sopenharmony_ci      break;
2671cb0ef41Sopenharmony_ci    }
2681cb0ef41Sopenharmony_ci    case kPassword: {
2691cb0ef41Sopenharmony_ci      result = out->set_password(new_value_view);
2701cb0ef41Sopenharmony_ci      break;
2711cb0ef41Sopenharmony_ci    }
2721cb0ef41Sopenharmony_ci    case kPort: {
2731cb0ef41Sopenharmony_ci      result = out->set_port(new_value_view);
2741cb0ef41Sopenharmony_ci      break;
2751cb0ef41Sopenharmony_ci    }
2761cb0ef41Sopenharmony_ci    case kProtocol: {
2771cb0ef41Sopenharmony_ci      result = out->set_protocol(new_value_view);
2781cb0ef41Sopenharmony_ci      break;
2791cb0ef41Sopenharmony_ci    }
2801cb0ef41Sopenharmony_ci    case kSearch: {
2811cb0ef41Sopenharmony_ci      out->set_search(new_value_view);
2821cb0ef41Sopenharmony_ci      break;
2831cb0ef41Sopenharmony_ci    }
2841cb0ef41Sopenharmony_ci    case kUsername: {
2851cb0ef41Sopenharmony_ci      result = out->set_username(new_value_view);
2861cb0ef41Sopenharmony_ci      break;
2871cb0ef41Sopenharmony_ci    }
2881cb0ef41Sopenharmony_ci    default:
2891cb0ef41Sopenharmony_ci      UNREACHABLE("Unsupported URL update action");
2901cb0ef41Sopenharmony_ci  }
2911cb0ef41Sopenharmony_ci
2921cb0ef41Sopenharmony_ci  if (!result) {
2931cb0ef41Sopenharmony_ci    return args.GetReturnValue().Set(false);
2941cb0ef41Sopenharmony_ci  }
2951cb0ef41Sopenharmony_ci
2961cb0ef41Sopenharmony_ci  binding_data->UpdateComponents(out->get_components(), out->type);
2971cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(
2981cb0ef41Sopenharmony_ci      ToV8Value(env->context(), out->get_href(), env->isolate())
2991cb0ef41Sopenharmony_ci          .ToLocalChecked());
3001cb0ef41Sopenharmony_ci}
3011cb0ef41Sopenharmony_ci
3021cb0ef41Sopenharmony_civoid BindingData::ToASCII(const v8::FunctionCallbackInfo<v8::Value>& args) {
3031cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
3041cb0ef41Sopenharmony_ci  CHECK_GE(args.Length(), 1);
3051cb0ef41Sopenharmony_ci  CHECK(args[0]->IsString());
3061cb0ef41Sopenharmony_ci
3071cb0ef41Sopenharmony_ci  Utf8Value input(env->isolate(), args[0]);
3081cb0ef41Sopenharmony_ci  auto out = ada::idna::to_ascii(input.ToStringView());
3091cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(
3101cb0ef41Sopenharmony_ci      String::NewFromUtf8(env->isolate(), out.c_str()).ToLocalChecked());
3111cb0ef41Sopenharmony_ci}
3121cb0ef41Sopenharmony_ci
3131cb0ef41Sopenharmony_civoid BindingData::ToUnicode(const v8::FunctionCallbackInfo<v8::Value>& args) {
3141cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
3151cb0ef41Sopenharmony_ci  CHECK_GE(args.Length(), 1);
3161cb0ef41Sopenharmony_ci  CHECK(args[0]->IsString());
3171cb0ef41Sopenharmony_ci
3181cb0ef41Sopenharmony_ci  Utf8Value input(env->isolate(), args[0]);
3191cb0ef41Sopenharmony_ci  auto out = ada::idna::to_unicode(input.ToStringView());
3201cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(
3211cb0ef41Sopenharmony_ci      String::NewFromUtf8(env->isolate(), out.c_str()).ToLocalChecked());
3221cb0ef41Sopenharmony_ci}
3231cb0ef41Sopenharmony_ci
3241cb0ef41Sopenharmony_civoid BindingData::UpdateComponents(const ada::url_components& components,
3251cb0ef41Sopenharmony_ci                                   const ada::scheme::type type) {
3261cb0ef41Sopenharmony_ci  url_components_buffer_[0] = components.protocol_end;
3271cb0ef41Sopenharmony_ci  url_components_buffer_[1] = components.username_end;
3281cb0ef41Sopenharmony_ci  url_components_buffer_[2] = components.host_start;
3291cb0ef41Sopenharmony_ci  url_components_buffer_[3] = components.host_end;
3301cb0ef41Sopenharmony_ci  url_components_buffer_[4] = components.port;
3311cb0ef41Sopenharmony_ci  url_components_buffer_[5] = components.pathname_start;
3321cb0ef41Sopenharmony_ci  url_components_buffer_[6] = components.search_start;
3331cb0ef41Sopenharmony_ci  url_components_buffer_[7] = components.hash_start;
3341cb0ef41Sopenharmony_ci  url_components_buffer_[8] = type;
3351cb0ef41Sopenharmony_ci  static_assert(kURLComponentsLength == 9,
3361cb0ef41Sopenharmony_ci                "kURLComponentsLength should be up-to-date");
3371cb0ef41Sopenharmony_ci}
3381cb0ef41Sopenharmony_ci
3391cb0ef41Sopenharmony_civoid BindingData::Initialize(Local<Object> target,
3401cb0ef41Sopenharmony_ci                             Local<Value> unused,
3411cb0ef41Sopenharmony_ci                             Local<Context> context,
3421cb0ef41Sopenharmony_ci                             void* priv) {
3431cb0ef41Sopenharmony_ci  Realm* realm = Realm::GetCurrent(context);
3441cb0ef41Sopenharmony_ci  BindingData* const binding_data =
3451cb0ef41Sopenharmony_ci      realm->AddBindingData<BindingData>(context, target);
3461cb0ef41Sopenharmony_ci  if (binding_data == nullptr) return;
3471cb0ef41Sopenharmony_ci
3481cb0ef41Sopenharmony_ci  SetMethodNoSideEffect(context, target, "toASCII", ToASCII);
3491cb0ef41Sopenharmony_ci  SetMethodNoSideEffect(context, target, "toUnicode", ToUnicode);
3501cb0ef41Sopenharmony_ci  SetMethodNoSideEffect(context, target, "domainToASCII", DomainToASCII);
3511cb0ef41Sopenharmony_ci  SetMethodNoSideEffect(context, target, "domainToUnicode", DomainToUnicode);
3521cb0ef41Sopenharmony_ci  SetMethodNoSideEffect(context, target, "canParse", CanParse);
3531cb0ef41Sopenharmony_ci  SetMethodNoSideEffect(context, target, "format", Format);
3541cb0ef41Sopenharmony_ci  SetMethod(context, target, "parse", Parse);
3551cb0ef41Sopenharmony_ci  SetMethod(context, target, "update", Update);
3561cb0ef41Sopenharmony_ci}
3571cb0ef41Sopenharmony_ci
3581cb0ef41Sopenharmony_civoid BindingData::RegisterExternalReferences(
3591cb0ef41Sopenharmony_ci    ExternalReferenceRegistry* registry) {
3601cb0ef41Sopenharmony_ci  registry->Register(ToASCII);
3611cb0ef41Sopenharmony_ci  registry->Register(ToUnicode);
3621cb0ef41Sopenharmony_ci  registry->Register(DomainToASCII);
3631cb0ef41Sopenharmony_ci  registry->Register(DomainToUnicode);
3641cb0ef41Sopenharmony_ci  registry->Register(CanParse);
3651cb0ef41Sopenharmony_ci  registry->Register(Format);
3661cb0ef41Sopenharmony_ci  registry->Register(Parse);
3671cb0ef41Sopenharmony_ci  registry->Register(Update);
3681cb0ef41Sopenharmony_ci}
3691cb0ef41Sopenharmony_ci
3701cb0ef41Sopenharmony_cistd::string FromFilePath(const std::string_view file_path) {
3711cb0ef41Sopenharmony_ci  std::string escaped_file_path;
3721cb0ef41Sopenharmony_ci  for (size_t i = 0; i < file_path.length(); ++i) {
3731cb0ef41Sopenharmony_ci    escaped_file_path += file_path[i];
3741cb0ef41Sopenharmony_ci    if (file_path[i] == '%') escaped_file_path += "25";
3751cb0ef41Sopenharmony_ci  }
3761cb0ef41Sopenharmony_ci
3771cb0ef41Sopenharmony_ci  return ada::href_from_file(escaped_file_path);
3781cb0ef41Sopenharmony_ci}
3791cb0ef41Sopenharmony_ci
3801cb0ef41Sopenharmony_ci}  // namespace url
3811cb0ef41Sopenharmony_ci
3821cb0ef41Sopenharmony_ci}  // namespace node
3831cb0ef41Sopenharmony_ci
3841cb0ef41Sopenharmony_ciNODE_BINDING_CONTEXT_AWARE_INTERNAL(url, node::url::BindingData::Initialize)
3851cb0ef41Sopenharmony_ciNODE_BINDING_EXTERNAL_REFERENCE(
3861cb0ef41Sopenharmony_ci    url, node::url::BindingData::RegisterExternalReferences)
387