| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 3b305f2 commit f8910e3
3 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -165,6 +165,10 @@ void URLPattern::New(const FunctionCallbackInfo<Value>& args) { | |||
| 165 | 165 | input = input_buffer.ToString(); | |
| 166 | 166 | } else if (args[0]->IsObject()) { | |
| 167 | 167 | init = URLPatternInit::FromJsObject(env, args[0].As<Object>()); | |
| 168 | + // If init does not have a value here, the implication is that an | ||
| 169 | + // error was thrown. Let's allow that to be handled now by returning | ||
| 170 | + // early. If we don't, the error thrown will be swallowed. | ||
| 171 | + if (!init) return; | ||
| 168 | 172 | } else { | |
| 169 | 173 | THROW_ERR_INVALID_ARG_TYPE(env, "Input must be an object or a string"); | |
| 170 | 174 | return; | |
@@ -180,7 +184,9 @@ void URLPattern::New(const FunctionCallbackInfo<Value>& args) { | |||
| 180 | 184 | CHECK(!options.has_value()); | |
| 181 | 185 | options = URLPatternOptions::FromJsObject(env, args[1].As<Object>()); | |
| 182 | 186 | if (!options) { | |
| 183 | - THROW_ERR_INVALID_ARG_TYPE(env, "options.ignoreCase must be a boolean"); | ||
| 187 | + // If options does not have a value, we assume an error was | ||
| 188 | + // thrown and scheduled on the isolate. Return early to | ||
| 189 | + // propagate it. | ||
| 184 | 190 | return; | |
| 185 | 191 | } | |
| 186 | 192 | } else { | |
@@ -197,7 +203,9 @@ void URLPattern::New(const FunctionCallbackInfo<Value>& args) { | |||
| 197 | 203 | CHECK(!options.has_value()); | |
| 198 | 204 | options = URLPatternOptions::FromJsObject(env, args[2].As<Object>()); | |
| 199 | 205 | if (!options) { | |
| 200 | - THROW_ERR_INVALID_ARG_TYPE(env, "options.ignoreCase must be a boolean"); | ||
| 206 | + // If options does not have a value, we assume an error was | ||
| 207 | + // thrown and scheduled on the isolate. Return early to | ||
| 208 | + // propagate it. | ||
| 201 | 209 | return; | |
| 202 | 210 | } | |
| 203 | 211 | } | |
@@ -234,73 +242,29 @@ MaybeLocal<Value> URLPattern::URLPatternInit::ToJsObject( | |||
| 234 | 242 | auto isolate = env->isolate(); | |
| 235 | 243 | auto context = env->context(); | |
| 236 | 244 | auto result = Object::New(isolate); | |
| 237 | - if (init.protocol) { | ||
| 238 | - Local<Value> protocol; | ||
| 239 | - if (!ToV8Value(context, *init.protocol).ToLocal(&protocol) || | ||
| 240 | - result->Set(context, env->protocol_string(), protocol).IsNothing()) { | ||
| 241 | - return {}; | ||
| 242 | - } | ||
| 243 | - } | ||
| 244 | - if (init.username) { | ||
| 245 | - Local<Value> username; | ||
| 246 | - if (!ToV8Value(context, *init.username).ToLocal(&username) || | ||
| 247 | - result->Set(context, env->username_string(), username).IsNothing()) { | ||
| 248 | - return {}; | ||
| 249 | - } | ||
| 250 | - } | ||
| 251 | - if (init.password) { | ||
| 252 | - Local<Value> password; | ||
| 253 | - if (!ToV8Value(context, *init.password).ToLocal(&password) || | ||
| 254 | - result->Set(context, env->password_string(), password).IsNothing()) { | ||
| 255 | - return {}; | ||
| 256 | - } | ||
| 257 | - } | ||
| 258 | - if (init.hostname) { | ||
| 259 | - Local<Value> hostname; | ||
| 260 | - if (!ToV8Value(context, *init.hostname).ToLocal(&hostname) || | ||
| 261 | - result->Set(context, env->hostname_string(), hostname).IsNothing()) { | ||
| 262 | - return {}; | ||
| 263 | - } | ||
| 264 | - } | ||
| 265 | - if (init.port) { | ||
| 266 | - Local<Value> port; | ||
| 267 | - if (!ToV8Value(context, *init.port).ToLocal(&port) || | ||
| 268 | - result->Set(context, env->port_string(), port).IsNothing()) { | ||
| 269 | - return {}; | ||
| 270 | - } | ||
| 271 | - } | ||
| 272 | - if (init.pathname) { | ||
| 273 | - Local<Value> pathname; | ||
| 274 | - if (!ToV8Value(context, *init.pathname).ToLocal(&pathname) || | ||
| 275 | - result->Set(context, env->pathname_string(), pathname).IsNothing()) { | ||
| 276 | - return {}; | ||
| 277 | - } | ||
| 278 | - } | ||
| 279 | - if (init.search) { | ||
| 280 | - Local<Value> search; | ||
| 281 | - if (!ToV8Value(context, *init.search).ToLocal(&search) || | ||
| 282 | - result->Set(context, env->search_string(), search).IsNothing()) { | ||
| 283 | - return {}; | ||
| 284 | - } | ||
| 285 | - } | ||
| 286 | - if (init.hash) { | ||
| 287 | - Local<Value> hash; | ||
| 288 | - if (!ToV8Value(context, *init.hash).ToLocal(&hash) || | ||
| 289 | - result->Set(context, env->hash_string(), hash).IsNothing()) { | ||
| 290 | - return {}; | ||
| 291 | - } | ||
| 292 | - } | ||
| 293 | - if (init.base_url) { | ||
| 294 | - Local<Value> base_url; | ||
| 295 | - if (!ToV8Value(context, *init.base_url).ToLocal(&base_url) || | ||
| 296 | - result->Set(context, env->base_url_string(), base_url).IsNothing()) { | ||
| 297 | - return {}; | ||
| 298 | - } | ||
| 245 | + | ||
| 246 | + const auto trySet = [&](auto name, const std::optional<std::string>& val) { | ||
| 247 | + if (!val) return true; | ||
| 248 | + Local<Value> temp; | ||
| 249 | + return ToV8Value(context, *val).ToLocal(&temp) && | ||
| 250 | + result->Set(context, name, temp).IsJust(); | ||
| 251 | + }; | ||
| 252 | + | ||
| 253 | + if (!trySet(env->protocol_string(), init.protocol) || | ||
| 254 | + !trySet(env->username_string(), init.username) || | ||
| 255 | + !trySet(env->password_string(), init.password) || | ||
| 256 | + !trySet(env->hostname_string(), init.hostname) || | ||
| 257 | + !trySet(env->port_string(), init.port) || | ||
| 258 | + !trySet(env->pathname_string(), init.pathname) || | ||
| 259 | + !trySet(env->search_string(), init.search) || | ||
| 260 | + !trySet(env->hash_string(), init.hash) || | ||
| 261 | + !trySet(env->base_url_string(), init.base_url)) { | ||
| 262 | + return {}; | ||
| 299 | 263 | } | |
| 300 | 264 | return result; | |
| 301 | 265 | } | |
| 302 | 266 | ||
| 303 | - ada::url_pattern_init URLPattern::URLPatternInit::FromJsObject( | ||
| 267 | + std::optional<ada::url_pattern_init> URLPattern::URLPatternInit::FromJsObject( | ||
| 304 | 268 | Environment* env, Local<Object> obj) { | |
| 305 | 269 | ada::url_pattern_init init{}; | |
| 306 | 270 | Local<String> components[] = { | |
@@ -344,6 +308,10 @@ ada::url_pattern_init URLPattern::URLPatternInit::FromJsObject( | |||
| 344 | 308 | Utf8Value utf8_value(isolate, value); | |
| 345 | 309 | set_parameter(key.ToStringView(), utf8_value.ToStringView()); | |
| 346 | 310 | } | |
| 311 | + } else { | ||
| 312 | + // If ToLocal failed then we assume an error occurred, | ||
| 313 | + // bail out early to propagate the error. | ||
| 314 | + return std::nullopt; | ||
| 347 | 315 | } | |
| 348 | 316 | } | |
| 349 | 317 | return init; | |
@@ -355,12 +323,8 @@ MaybeLocal<Object> URLPattern::URLPatternComponentResult::ToJSObject( | |||
| 355 | 323 | auto context = env->context(); | |
| 356 | 324 | auto parsed_group = Object::New(isolate); | |
| 357 | 325 | for (const auto& [group_key, group_value] : result.groups) { | |
| 358 | - Local<String> key; | ||
| 359 | - if (!String::NewFromUtf8(isolate, | ||
| 360 | - group_key.c_str(), | ||
| 361 | - NewStringType::kNormal, | ||
| 362 | - group_key.size()) | ||
| 363 | - .ToLocal(&key)) { | ||
| 326 | + Local<Value> key; | ||
| 327 | + if (!ToV8Value(context, group_key).ToLocal(&key)) { | ||
| 364 | 328 | return {}; | |
| 365 | 329 | } | |
| 366 | 330 | Local<Value> value; | |
@@ -371,7 +335,9 @@ MaybeLocal<Object> URLPattern::URLPatternComponentResult::ToJSObject( | |||
| 371 | 335 | } else { | |
| 372 | 336 | value = Undefined(isolate); | |
| 373 | 337 | } | |
| 374 | - USE(parsed_group->Set(context, key, value)); | ||
| 338 | + if (parsed_group->Set(context, key, value).IsNothing()) { | ||
| 339 | + return {}; | ||
| 340 | + } | ||
| 375 | 341 | } | |
| 376 | 342 | Local<Value> input; | |
| 377 | 343 | if (!ToV8Value(env->context(), result.input).ToLocal(&input)) { | |
@@ -418,34 +384,20 @@ MaybeLocal<Value> URLPattern::URLPatternResult::ToJSValue( | |||
| 418 | 384 | LocalVector<Value> values(isolate, arraysize(names)); | |
| 419 | 385 | values[0] = Array::New(isolate, inputs.data(), inputs.size()); | |
| 420 | 386 | if (!URLPatternComponentResult::ToJSObject(env, result.protocol) | |
| 421 | - .ToLocal(&values[1])) { | ||
| 422 | - return {}; | ||
| 423 | - } | ||
| 424 | - if (!URLPatternComponentResult::ToJSObject(env, result.username) | ||
| 425 | - .ToLocal(&values[2])) { | ||
| 426 | - return {}; | ||
| 427 | - } | ||
| 428 | - if (!URLPatternComponentResult::ToJSObject(env, result.password) | ||
| 429 | - .ToLocal(&values[3])) { | ||
| 430 | - return {}; | ||
| 431 | - } | ||
| 432 | - if (!URLPatternComponentResult::ToJSObject(env, result.hostname) | ||
| 433 | - .ToLocal(&values[4])) { | ||
| 434 | - return {}; | ||
| 435 | - } | ||
| 436 | - if (!URLPatternComponentResult::ToJSObject(env, result.port) | ||
| 437 | - .ToLocal(&values[5])) { | ||
| 438 | - return {}; | ||
| 439 | - } | ||
| 440 | - if (!URLPatternComponentResult::ToJSObject(env, result.pathname) | ||
| 441 | - .ToLocal(&values[6])) { | ||
| 442 | - return {}; | ||
| 443 | - } | ||
| 444 | - if (!URLPatternComponentResult::ToJSObject(env, result.search) | ||
| 445 | - .ToLocal(&values[7])) { | ||
| 446 | - return {}; | ||
| 447 | - } | ||
| 448 | - if (!URLPatternComponentResult::ToJSObject(env, result.hash) | ||
| 387 | + .ToLocal(&values[1]) || | ||
| 388 | + !URLPatternComponentResult::ToJSObject(env, result.username) | ||
| 389 | + .ToLocal(&values[2]) || | ||
| 390 | + !URLPatternComponentResult::ToJSObject(env, result.password) | ||
| 391 | + .ToLocal(&values[3]) || | ||
| 392 | + !URLPatternComponentResult::ToJSObject(env, result.hostname) | ||
| 393 | + .ToLocal(&values[4]) || | ||
| 394 | + !URLPatternComponentResult::ToJSObject(env, result.port) | ||
| 395 | + .ToLocal(&values[5]) || | ||
| 396 | + !URLPatternComponentResult::ToJSObject(env, result.pathname) | ||
| 397 | + .ToLocal(&values[6]) || | ||
| 398 | + !URLPatternComponentResult::ToJSObject(env, result.search) | ||
| 399 | + .ToLocal(&values[7]) || | ||
| 400 | + !URLPatternComponentResult::ToJSObject(env, result.hash) | ||
| 449 | 401 | .ToLocal(&values[8])) { | |
| 450 | 402 | return {}; | |
| 451 | 403 | } | |
@@ -461,9 +413,15 @@ URLPattern::URLPatternOptions::FromJsObject(Environment* env, | |||
| 461 | 413 | if (obj->Get(env->context(), env->ignore_case_string()) | |
| 462 | 414 | .ToLocal(&ignore_case)) { | |
| 463 | 415 | if (!ignore_case->IsBoolean()) { | |
| 416 | + THROW_ERR_INVALID_ARG_TYPE(env, "options.ignoreCase must be a boolean"); | ||
| 464 | 417 | return std::nullopt; | |
| 465 | 418 | } | |
| 466 | 419 | options.ignore_case = ignore_case->IsTrue(); | |
| 420 | + } else { | ||
| 421 | + // If ToLocal returns false, the assumption is that getting the | ||
| 422 | + // ignore_case_string threw an error, let's propagate that now | ||
| 423 | + // by returning std::nullopt. | ||
| 424 | + return std::nullopt; | ||
| 467 | 425 | } | |
| 468 | 426 | return options; | |
| 469 | 427 | } | |
@@ -553,7 +511,9 @@ void URLPattern::Exec(const FunctionCallbackInfo<Value>& args) { | |||
| 553 | 511 | input_base = input_value.ToString(); | |
| 554 | 512 | input = std::string_view(input_base); | |
| 555 | 513 | } else if (args[0]->IsObject()) { | |
| 556 | - input = URLPatternInit::FromJsObject(env, args[0].As<Object>()); | ||
| 514 | + auto maybeInput = URLPatternInit::FromJsObject(env, args[0].As<Object>()); | ||
| 515 | + if (!maybeInput.has_value()) return; | ||
| 516 | + input = std::move(*maybeInput); | ||
| 557 | 517 | } else { | |
| 558 | 518 | THROW_ERR_INVALID_ARG_TYPE( | |
| 559 | 519 | env, "URLPattern input needs to be a string or an object"); | |
@@ -594,7 +554,9 @@ void URLPattern::Test(const FunctionCallbackInfo<Value>& args) { | |||
| 594 | 554 | input_base = input_value.ToString(); | |
| 595 | 555 | input = std::string_view(input_base); | |
| 596 | 556 | } else if (args[0]->IsObject()) { | |
| 597 | - input = URLPatternInit::FromJsObject(env, args[0].As<Object>()); | ||
| 557 | + auto maybeInput = URLPatternInit::FromJsObject(env, args[0].As<Object>()); | ||
| 558 | + if (!maybeInput.has_value()) return; | ||
| 559 | + input = std::move(*maybeInput); | ||
| 598 | 560 | } else { | |
| 599 | 561 | THROW_ERR_INVALID_ARG_TYPE( | |
| 600 | 562 | env, "URLPattern input needs to be a string or an object"); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -59,8 +59,8 @@ class URLPattern : public BaseObject { | |||
| 59 | 59 | ||
| 60 | 60 | class URLPatternInit { | |
| 61 | 61 | public: | |
| 62 | - static ada::url_pattern_init FromJsObject(Environment* env, | ||
| 63 | - v8::Local<v8::Object> obj); | ||
| 62 | + static std::optional<ada::url_pattern_init> FromJsObject( | ||
| 63 | + Environment* env, v8::Local<v8::Object> obj); | ||
| 64 | 64 | static v8::MaybeLocal<v8::Value> ToJsObject( | |
| 65 | 65 | Environment* env, const ada::url_pattern_init& init); | |
| 66 | 66 | }; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,28 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + | ||
| 3 | + require('../common'); | ||
| 4 | + | ||
| 5 | + const { throws } = require('assert'); | ||
| 6 | + const { URLPattern } = require('url'); | ||
| 7 | + | ||
| 8 | + // Verify that if an error is thrown while accessing any of the | ||
| 9 | + // init options, the error is appropriately propagated. | ||
| 10 | + throws(() => { | ||
| 11 | + new URLPattern({ | ||
| 12 | + get protocol() { | ||
| 13 | + throw new Error('boom'); | ||
| 14 | + } | ||
| 15 | + }); | ||
| 16 | + }, { | ||
| 17 | + message: 'boom', | ||
| 18 | + }); | ||
| 19 | + | ||
| 20 | + // Verify that if an error is thrown while accessing the ignoreCase | ||
| 21 | + // option, the error is appropriately propagated. | ||
| 22 | + throws(() => { | ||
| 23 | + new URLPattern({}, { get ignoreCase() { | ||
| 24 | + throw new Error('boom'); | ||
| 25 | + } }); | ||
| 26 | + }, { | ||
| 27 | + message: 'boom' | ||
| 28 | + }); | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments