diff --git a/src/node_url_pattern.cc b/src/node_url_pattern.cc index bc007db47daca6..b0836cebd7441f 100644 --- a/src/node_url_pattern.cc +++ b/src/node_url_pattern.cc @@ -409,22 +409,28 @@ std::optional URLPattern::URLPatternInit::FromJsObject( } MaybeLocal URLPattern::URLPatternComponentResult::ToJSObject( - Environment* env, const ada::url_pattern_component_result& result) { + Environment* env, + const ada::url_pattern_component_result& result, + const std::vector& ordered_group_names) { auto isolate = env->isolate(); auto context = env->context(); LocalVector group_names(isolate); LocalVector group_values(isolate); group_names.reserve(result.groups.size()); group_values.reserve(result.groups.size()); - for (const auto& [group_key, group_value] : result.groups) { + for (const auto& group_key : ordered_group_names) { + const auto group = result.groups.find(group_key); + if (group == result.groups.end()) { + continue; + } Local key; if (!ToV8Value(context, group_key).ToLocal(&key)) { return {}; } group_names.push_back(key.As()); Local value; - if (group_value) { - if (!ToV8Value(env->context(), *group_value).ToLocal(&value)) { + if (group->second) { + if (!ToV8Value(env->context(), *group->second).ToLocal(&value)) { return {}; } } else { @@ -457,7 +463,9 @@ MaybeLocal URLPattern::URLPatternComponentResult::ToJSObject( } MaybeLocal URLPattern::URLPatternResult::ToJSValue( - Environment* env, const ada::url_pattern_result& result) { + Environment* env, + const ada::url_pattern_result& result, + const ada::url_pattern& url_pattern) { auto isolate = env->isolate(); auto tmpl = env->urlpatternresult_template(); @@ -479,8 +487,10 @@ MaybeLocal URLPattern::URLPatternResult::ToJSValue( size_t index = 0; MaybeLocal vals[] = { - URLPatternComponentResult::ToJSObject(env, result.hash), - URLPatternComponentResult::ToJSObject(env, result.hostname), + URLPatternComponentResult::ToJSObject( + env, result.hash, url_pattern.hash_component.group_name_list), + URLPatternComponentResult::ToJSObject( + env, result.hostname, url_pattern.hostname_component.group_name_list), Array::New(env->context(), result.inputs.size(), [&index, &inputs = result.inputs, env]() { @@ -495,12 +505,20 @@ MaybeLocal URLPattern::URLPatternResult::ToJSValue( return URLPatternInit::ToJsObject(env, init); } }), - URLPatternComponentResult::ToJSObject(env, result.password), - URLPatternComponentResult::ToJSObject(env, result.pathname), - URLPatternComponentResult::ToJSObject(env, result.port), - URLPatternComponentResult::ToJSObject(env, result.protocol), - URLPatternComponentResult::ToJSObject(env, result.search), - URLPatternComponentResult::ToJSObject(env, result.username)}; + URLPatternComponentResult::ToJSObject( + env, result.password, url_pattern.password_component.group_name_list), + URLPatternComponentResult::ToJSObject( + env, result.pathname, url_pattern.pathname_component.group_name_list), + URLPatternComponentResult::ToJSObject( + env, result.port, url_pattern.port_component.group_name_list), + URLPatternComponentResult::ToJSObject( + env, result.protocol, url_pattern.protocol_component.group_name_list), + URLPatternComponentResult::ToJSObject( + env, result.search, url_pattern.search_component.group_name_list), + URLPatternComponentResult::ToJSObject( + env, + result.username, + url_pattern.username_component.group_name_list)}; return NewDictionaryInstanceNullProto(env->context(), tmpl, vals); } @@ -552,7 +570,7 @@ MaybeLocal URLPattern::Exec(Environment* env, std::optional& baseURL) { if (auto result = url_pattern_.exec(input, baseURL ? &*baseURL : nullptr)) { if (result->has_value()) { - return URLPatternResult::ToJSValue(env, result->value()); + return URLPatternResult::ToJSValue(env, result->value(), url_pattern_); } return Null(env->isolate()); } diff --git a/src/node_url_pattern.h b/src/node_url_pattern.h index 48f3956cb74458..02e61c6241a28e 100644 --- a/src/node_url_pattern.h +++ b/src/node_url_pattern.h @@ -10,7 +10,9 @@ #include #include +#include #include +#include namespace node::url_pattern { @@ -81,13 +83,17 @@ class URLPattern : public BaseObject { class URLPatternResult { public: static v8::MaybeLocal ToJSValue( - Environment* env, const ada::url_pattern_result& result); + Environment* env, + const ada::url_pattern_result& result, + const ada::url_pattern& url_pattern); }; class URLPatternComponentResult { public: static v8::MaybeLocal ToJSObject( - Environment* env, const ada::url_pattern_component_result& result); + Environment* env, + const ada::url_pattern_component_result& result, + const std::vector& ordered_group_names); }; private: diff --git a/test/parallel/test-urlpattern.js b/test/parallel/test-urlpattern.js index 42bdd114f43d18..638bba916e39c4 100644 --- a/test/parallel/test-urlpattern.js +++ b/test/parallel/test-urlpattern.js @@ -50,3 +50,14 @@ assert.throws(() => { assert.strictEqual(result.pathname.input, '/test'); assert.strictEqual(result.pathname.groups.value, 'test'); } + +{ + const result = new URLPattern({ pathname: '/:one/:two/:three' }) + .exec('https://example.com/a/b/c'); + + assert.deepStrictEqual(Object.entries(result.pathname.groups), [ + ['one', 'a'], + ['two', 'b'], + ['three', 'c'], + ]); +}