Skip to content

Commit ebc6a1c

Browse files
committed
feat: add UTF-8 string coercion utility for URL parsing in macOS
1 parent cd12261 commit ebc6a1c

1 file changed

Lines changed: 63 additions & 85 deletions

File tree

  • NativeScript/runtime/modules/url

NativeScript/runtime/modules/url/URL.cpp

Lines changed: 63 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,33 @@ using namespace ada;
77
using namespace nativescript;
88

99
namespace {
10+
struct CoercedUtf8String {
11+
std::vector<char> storage;
12+
size_t length = 0;
13+
14+
std::string_view view() const { return {storage.data(), length}; }
15+
};
16+
17+
bool CoerceToUtf8String(napi_env env, napi_value value,
18+
CoercedUtf8String& out) {
19+
NAPI_PREAMBLE
20+
napi_value coerced;
21+
NAPI_GUARD(napi_coerce_to_string(env, value, &coerced)) { return false; }
22+
23+
NAPI_GUARD(
24+
napi_get_value_string_utf8(env, coerced, nullptr, 0, &out.length)) {
25+
return false;
26+
}
27+
28+
out.storage.resize(out.length + 1);
29+
NAPI_GUARD(napi_get_value_string_utf8(env, coerced, out.storage.data(),
30+
out.storage.size(), nullptr)) {
31+
return false;
32+
}
33+
34+
return true;
35+
}
36+
1037
URL* GetInstance(napi_env env, napi_callback_info info) {
1138
NAPI_PREAMBLE
1239
napi_value jsThis;
@@ -51,23 +78,15 @@ napi_value SetUrlProperty(napi_env env, napi_callback_info info,
5178

5279
if (argc < 1) return nullptr;
5380

54-
size_t str_size;
55-
NAPI_GUARD(napi_get_value_string_utf8(env, argv[0], nullptr, 0, &str_size)) {
56-
return nullptr;
57-
}
81+
CoercedUtf8String value;
82+
if (!CoerceToUtf8String(env, argv[0], value)) return nullptr;
5883

59-
std::vector<char> buffer(str_size + 1);
60-
NAPI_GUARD(napi_get_value_string_utf8(env, argv[0], buffer.data(),
61-
str_size + 1, nullptr)) {
62-
return nullptr;
63-
}
64-
65-
(instance->GetURL()->*setter)(buffer.data());
84+
(instance->GetURL()->*setter)(value.view());
6685
return napi_util::get_true(env);
6786
}
6887
} // namespace
6988

70-
URL::URL(url_aggregator url) : url_(url) {}
89+
URL::URL(url_aggregator url) : url_(std::move(url)) {}
7190

7291
url_aggregator* URL::GetURL() { return &url_; }
7392

@@ -126,7 +145,8 @@ napi_value URL::GetSearchParams(napi_env env, napi_callback_info info) {
126145

127146
// Create URLSearchParams from the search string
128147
url_search_params params(search_string);
129-
URLSearchParams* searchParams = new URLSearchParams(params, instance->GetURL());
148+
URLSearchParams* searchParams =
149+
new URLSearchParams(params, instance->GetURL());
130150

131151
// Get the URLSearchParams constructor
132152
napi_value global;
@@ -229,60 +249,31 @@ napi_value URL::New(napi_env env, napi_callback_info info) {
229249
return nullptr;
230250
}
231251

232-
size_t str_size;
233-
NAPI_GUARD(napi_get_value_string_utf8(env, argv[0], nullptr, 0, &str_size)) {
234-
return nullptr;
235-
}
236-
237-
std::vector<char> url_buffer(str_size + 1);
238-
NAPI_GUARD(napi_get_value_string_utf8(env, argv[0], url_buffer.data(),
239-
str_size + 1, nullptr)) {
240-
return nullptr;
241-
}
252+
CoercedUtf8String url_input;
253+
if (!CoerceToUtf8String(env, argv[0], url_input)) return nullptr;
242254

243-
url_aggregator url;
244-
std::string_view url_string_view(url_buffer.data(), url_buffer.size());
255+
auto parse_result =
256+
ada::parse<ada::url_aggregator>(url_input.view(), nullptr);
245257

246-
if (argc > 1) {
247-
// Handle base URL
248-
size_t base_str_size;
249-
NAPI_GUARD(
250-
napi_get_value_string_utf8(env, argv[1], nullptr, 0, &base_str_size)) {
251-
return nullptr;
252-
}
258+
// If the input is not absolute, retry with the provided base if available.
259+
if (!parse_result && argc > 1) {
260+
CoercedUtf8String base_input;
261+
if (!CoerceToUtf8String(env, argv[1], base_input)) return nullptr;
253262

254-
std::vector<char> base_buffer(base_str_size + 1);
255-
NAPI_GUARD(napi_get_value_string_utf8(env, argv[1], base_buffer.data(),
256-
base_str_size + 1, nullptr)) {
257-
return nullptr;
263+
auto base_result =
264+
ada::parse<ada::url_aggregator>(base_input.view(), nullptr);
265+
if (base_result) {
266+
parse_result = ada::parse<ada::url_aggregator>(url_input.view(),
267+
&base_result.value());
258268
}
269+
}
259270

260-
std::string_view base_string_view(base_buffer.data(), base_buffer.size());
261-
262-
if (!can_parse(url_string_view, &base_string_view)) {
263-
napi_throw_type_error(env, nullptr, "Invalid URL");
264-
return nullptr;
265-
}
266-
267-
auto base_url = ada::parse<ada::url_aggregator>(base_string_view, nullptr);
268-
auto result =
269-
ada::parse<ada::url_aggregator>(url_string_view, &base_url.value());
270-
271-
if (!result) {
272-
napi_throw_type_error(env, nullptr, "Invalid URL");
273-
return nullptr;
274-
}
275-
url = result.value();
276-
} else {
277-
auto result = ada::parse<ada::url_aggregator>(url_string_view, nullptr);
278-
if (!result) {
279-
napi_throw_type_error(env, nullptr, "Invalid URL");
280-
return nullptr;
281-
}
282-
url = result.value();
271+
if (!parse_result) {
272+
napi_throw_type_error(env, nullptr, "Invalid URL");
273+
return nullptr;
283274
}
284275

285-
URL* urlImpl = new URL(url);
276+
URL* urlImpl = new URL(std::move(parse_result.value()));
286277
napi_wrap(env, jsThis, urlImpl, URL::Destructor, urlImpl, nullptr);
287278

288279
return jsThis;
@@ -298,35 +289,22 @@ napi_value URL::CanParse(napi_env env, napi_callback_info info) {
298289
return nullptr;
299290
}
300291

301-
size_t str_size;
302-
NAPI_GUARD(napi_get_value_string_utf8(env, argv[0], nullptr, 0, &str_size)) {
303-
return nullptr;
304-
}
292+
CoercedUtf8String input;
293+
if (!CoerceToUtf8String(env, argv[0], input)) return nullptr;
305294

306-
std::vector<char> buffer(str_size + 1);
307-
NAPI_GUARD(napi_get_value_string_utf8(env, argv[0], buffer.data(),
308-
str_size + 1, nullptr)) {
309-
return nullptr;
310-
}
295+
bool result =
296+
static_cast<bool>(ada::parse<ada::url_aggregator>(input.view(), nullptr));
311297

312-
bool result;
313-
if (argc > 1) {
314-
size_t base_str_size;
315-
NAPI_GUARD(
316-
napi_get_value_string_utf8(env, argv[1], nullptr, 0, &base_str_size)) {
317-
return nullptr;
318-
}
298+
if (!result && argc > 1) {
299+
CoercedUtf8String base_input;
300+
if (!CoerceToUtf8String(env, argv[1], base_input)) return nullptr;
319301

320-
std::vector<char> base_buffer(base_str_size + 1);
321-
NAPI_GUARD(napi_get_value_string_utf8(env, argv[1], base_buffer.data(),
322-
base_str_size + 1, nullptr)) {
323-
return nullptr;
302+
auto base_result =
303+
ada::parse<ada::url_aggregator>(base_input.view(), nullptr);
304+
if (base_result) {
305+
result = static_cast<bool>(
306+
ada::parse<ada::url_aggregator>(input.view(), &base_result.value()));
324307
}
325-
326-
std::string_view base_string_view(base_buffer.data());
327-
result = can_parse(buffer.data(), &base_string_view);
328-
} else {
329-
result = can_parse(buffer.data(), nullptr);
330308
}
331309

332310
napi_value returnValue;

0 commit comments

Comments
 (0)