@@ -409,22 +409,30 @@ std::optional<ada::url_pattern_init> URLPattern::URLPatternInit::FromJsObject(
409409}
410410
411411MaybeLocal<Object> URLPattern::URLPatternComponentResult::ToJSObject (
412- Environment* env, const ada::url_pattern_component_result& result) {
412+ Environment* env,
413+ const ada::url_pattern_component_result& result,
414+ const std::vector<std::string>& ordered_group_names) {
413415 auto isolate = env->isolate ();
414416 auto context = env->context ();
415- LocalVector<Name> group_names (isolate);
417+ LocalVector<Name> js_group_names (isolate);
416418 LocalVector<Value> group_values (isolate);
417- group_names .reserve (result.groups .size ());
419+ js_group_names .reserve (result.groups .size ());
418420 group_values.reserve (result.groups .size ());
419- for (const auto & [group_key, group_value] : result.groups ) {
421+ // The result uses an unordered map, so follow the component's group name
422+ // list to preserve capture declaration order.
423+ for (const auto & group_key : ordered_group_names) {
424+ const auto group = result.groups .find (group_key);
425+ if (group == result.groups .end ()) {
426+ continue ;
427+ }
420428 Local<Value> key;
421429 if (!ToV8Value (context, group_key).ToLocal (&key)) {
422430 return {};
423431 }
424- group_names .push_back (key.As <Name>());
432+ js_group_names .push_back (key.As <Name>());
425433 Local<Value> value;
426- if (group_value ) {
427- if (!ToV8Value (env->context (), *group_value ).ToLocal (&value)) {
434+ if (group-> second ) {
435+ if (!ToV8Value (env->context (), *group-> second ).ToLocal (&value)) {
428436 return {};
429437 }
430438 } else {
@@ -434,9 +442,9 @@ MaybeLocal<Object> URLPattern::URLPatternComponentResult::ToJSObject(
434442 }
435443 auto parsed_group = Object::New (isolate,
436444 Object::New (isolate),
437- group_names .data (),
445+ js_group_names .data (),
438446 group_values.data (),
439- group_names .size ());
447+ js_group_names .size ());
440448
441449 Local<Value> input;
442450 if (!ToV8Value (env->context (), result.input ).ToLocal (&input)) {
@@ -457,7 +465,9 @@ MaybeLocal<Object> URLPattern::URLPatternComponentResult::ToJSObject(
457465}
458466
459467MaybeLocal<Value> URLPattern::URLPatternResult::ToJSValue (
460- Environment* env, const ada::url_pattern_result& result) {
468+ Environment* env,
469+ const ada::url_pattern_result& result,
470+ const ada::url_pattern<URLPatternRegexProvider>& url_pattern) {
461471 auto isolate = env->isolate ();
462472
463473 auto tmpl = env->urlpatternresult_template ();
@@ -479,8 +489,10 @@ MaybeLocal<Value> URLPattern::URLPatternResult::ToJSValue(
479489
480490 size_t index = 0 ;
481491 MaybeLocal<Value> vals[] = {
482- URLPatternComponentResult::ToJSObject (env, result.hash ),
483- URLPatternComponentResult::ToJSObject (env, result.hostname ),
492+ URLPatternComponentResult::ToJSObject (
493+ env, result.hash , url_pattern.hash_component .group_name_list ),
494+ URLPatternComponentResult::ToJSObject (
495+ env, result.hostname , url_pattern.hostname_component .group_name_list ),
484496 Array::New (env->context (),
485497 result.inputs .size (),
486498 [&index, &inputs = result.inputs , env]() {
@@ -495,12 +507,20 @@ MaybeLocal<Value> URLPattern::URLPatternResult::ToJSValue(
495507 return URLPatternInit::ToJsObject (env, init);
496508 }
497509 }),
498- URLPatternComponentResult::ToJSObject (env, result.password ),
499- URLPatternComponentResult::ToJSObject (env, result.pathname ),
500- URLPatternComponentResult::ToJSObject (env, result.port ),
501- URLPatternComponentResult::ToJSObject (env, result.protocol ),
502- URLPatternComponentResult::ToJSObject (env, result.search ),
503- URLPatternComponentResult::ToJSObject (env, result.username )};
510+ URLPatternComponentResult::ToJSObject (
511+ env, result.password , url_pattern.password_component .group_name_list ),
512+ URLPatternComponentResult::ToJSObject (
513+ env, result.pathname , url_pattern.pathname_component .group_name_list ),
514+ URLPatternComponentResult::ToJSObject (
515+ env, result.port , url_pattern.port_component .group_name_list ),
516+ URLPatternComponentResult::ToJSObject (
517+ env, result.protocol , url_pattern.protocol_component .group_name_list ),
518+ URLPatternComponentResult::ToJSObject (
519+ env, result.search , url_pattern.search_component .group_name_list ),
520+ URLPatternComponentResult::ToJSObject (
521+ env,
522+ result.username ,
523+ url_pattern.username_component .group_name_list )};
504524 return NewDictionaryInstanceNullProto (env->context (), tmpl, vals);
505525}
506526
@@ -552,7 +572,7 @@ MaybeLocal<Value> URLPattern::Exec(Environment* env,
552572 std::optional<std::string_view>& baseURL) {
553573 if (auto result = url_pattern_.exec (input, baseURL ? &*baseURL : nullptr )) {
554574 if (result->has_value ()) {
555- return URLPatternResult::ToJSValue (env, result->value ());
575+ return URLPatternResult::ToJSValue (env, result->value (), url_pattern_ );
556576 }
557577 return Null (env->isolate ());
558578 }
0 commit comments