@@ -61,6 +61,7 @@ using v8::FunctionTemplate; |
61 | 61 | using v8::Global; |
62 | 62 | using v8::Isolate; |
63 | 63 | using v8::Local; |
| 64 | +using v8::LocalVector; |
64 | 65 | using v8::MaybeLocal; |
65 | 66 | using v8::Name; |
66 | 67 | using v8::NewStringType; |
@@ -284,27 +285,56 @@ MaybeLocal<Value> URLPattern::URLPatternInit::ToJsObject( |
284 | 285 | Environment* env, const ada::url_pattern_init& init) { |
285 | 286 | auto isolate = env->isolate(); |
286 | 287 | auto context = env->context(); |
287 | | - auto result = Object::New(isolate); |
288 | 288 |
|
289 | | - const auto trySet = [&](auto name, const std::optional<std::string>& val) { |
290 | | - if (!val) return true; |
291 | | - Local<Value> temp; |
292 | | - return ToV8Value(context, *val).ToLocal(&temp) && |
293 | | - result->Set(context, name, temp).IsJust(); |
| 289 | + auto tmpl = env->urlpatterninit_template(); |
| 290 | + if (tmpl.IsEmpty()) { |
| 291 | + static constexpr std::string_view namesVec[] = { |
| 292 | + "protocol", |
| 293 | + "username", |
| 294 | + "password", |
| 295 | + "hostname", |
| 296 | + "port", |
| 297 | + "pathname", |
| 298 | + "search", |
| 299 | + "hash", |
| 300 | + "baseURL", |
| 301 | + }; |
| 302 | + tmpl = DictionaryTemplate::New(isolate, namesVec); |
| 303 | + env->set_urlpatterninit_template(tmpl); |
| 304 | + } |
| 305 | + |
| 306 | + MaybeLocal<Value> values[] = { |
| 307 | + Undefined(isolate), // protocol |
| 308 | + Undefined(isolate), // username |
| 309 | + Undefined(isolate), // password |
| 310 | + Undefined(isolate), // hostname |
| 311 | + Undefined(isolate), // port |
| 312 | + Undefined(isolate), // pathname |
| 313 | + Undefined(isolate), // search |
| 314 | + Undefined(isolate), // hash |
| 315 | + Undefined(isolate), // baseURL |
| 316 | + }; |
| 317 | + |
| 318 | + int idx = 0; |
| 319 | + Local<Value> temp; |
| 320 | + const auto trySet = [&](const std::optional<std::string>& val) { |
| 321 | + if (val.has_value()) { |
| 322 | + if (!ToV8Value(context, *val).ToLocal(&temp)) { |
| 323 | + return false; |
| 324 | + } |
| 325 | + values[idx] = temp; |
| 326 | + } |
| 327 | + idx++; |
| 328 | + return true; |
294 | 329 | }; |
295 | 330 |
|
296 | | - if (!trySet(env->protocol_string(), init.protocol) || |
297 | | - !trySet(env->username_string(), init.username) || |
298 | | - !trySet(env->password_string(), init.password) || |
299 | | - !trySet(env->hostname_string(), init.hostname) || |
300 | | - !trySet(env->port_string(), init.port) || |
301 | | - !trySet(env->pathname_string(), init.pathname) || |
302 | | - !trySet(env->search_string(), init.search) || |
303 | | - !trySet(env->hash_string(), init.hash) || |
304 | | - !trySet(env->base_url_string(), init.base_url)) { |
| 331 | + if (!trySet(init.protocol) || !trySet(init.username) || |
| 332 | + !trySet(init.password) || !trySet(init.hostname) || !trySet(init.port) || |
| 333 | + !trySet(init.pathname) || !trySet(init.search) || !trySet(init.hash) || |
| 334 | + !trySet(init.base_url)) { |
305 | 335 | return {}; |
306 | 336 | } |
307 | | - return result; |
| 337 | + return NewDictionaryInstance(env->context(), tmpl, values); |
308 | 338 | } |
309 | 339 |
|
310 | 340 | std::optional<ada::url_pattern_init> URLPattern::URLPatternInit::FromJsObject( |
@@ -364,12 +394,16 @@ MaybeLocal<Object> URLPattern::URLPatternComponentResult::ToJSObject( |
364 | 394 | Environment* env, const ada::url_pattern_component_result& result) { |
365 | 395 | auto isolate = env->isolate(); |
366 | 396 | auto context = env->context(); |
367 | | - auto parsed_group = Object::New(isolate); |
| 397 | + LocalVector<Name> group_names(isolate); |
| 398 | + LocalVector<Value> group_values(isolate); |
| 399 | + group_names.reserve(result.groups.size()); |
| 400 | + group_values.reserve(result.groups.size()); |
368 | 401 | for (const auto& [group_key, group_value] : result.groups) { |
369 | 402 | Local<Value> key; |
370 | 403 | if (!ToV8Value(context, group_key).ToLocal(&key)) { |
371 | 404 | return {}; |
372 | 405 | } |
| 406 | + group_names.push_back(key.As<Name>()); |
373 | 407 | Local<Value> value; |
374 | 408 | if (group_value) { |
375 | 409 | if (!ToV8Value(env->context(), *group_value).ToLocal(&value)) { |
@@ -378,19 +412,30 @@ MaybeLocal<Object> URLPattern::URLPatternComponentResult::ToJSObject( |
378 | 412 | } else { |
379 | 413 | value = Undefined(isolate); |
380 | 414 | } |
381 | | - if (parsed_group->Set(context, key, value).IsNothing()) { |
382 | | - return {}; |
383 | | - } |
| 415 | + group_values.push_back(value); |
384 | 416 | } |
| 417 | + auto parsed_group = Object::New(isolate, |
| 418 | + Object::New(isolate), |
| 419 | + group_names.data(), |
| 420 | + group_values.data(), |
| 421 | + group_names.size()); |
| 422 | + |
385 | 423 | Local<Value> input; |
386 | 424 | if (!ToV8Value(env->context(), result.input).ToLocal(&input)) { |
387 | 425 | return {}; |
388 | 426 | } |
389 | | - Local<Name> names[] = {env->input_string(), env->groups_string()}; |
390 | | - Local<Value> values[] = {input, parsed_group}; |
391 | | - DCHECK_EQ(arraysize(names), arraysize(values)); |
392 | | - return Object::New( |
393 | | - isolate, Object::New(isolate), names, values, arraysize(names)); |
| 427 | + |
| 428 | + auto tmpl = env->urlpatterncomponentresult_template(); |
| 429 | + if (tmpl.IsEmpty()) { |
| 430 | + static constexpr std::string_view namesVec[] = { |
| 431 | + "input", |
| 432 | + "groups", |
| 433 | + }; |
| 434 | + tmpl = DictionaryTemplate::New(isolate, namesVec); |
| 435 | + env->set_urlpatterncomponentresult_template(tmpl); |
| 436 | + } |
| 437 | + MaybeLocal<Value> values[] = {input, parsed_group}; |
| 438 | + return NewDictionaryInstance(env->context(), tmpl, values); |
394 | 439 | } |
395 | 440 |
|
396 | 441 | MaybeLocal<Value> URLPattern::URLPatternResult::ToJSValue( |
|