|
| 1 | +<!DOCTYPE html> |
| 2 | +<metacharset="utf-8"> |
| 3 | +<title>URLPattern regexp groups work without a script context (detached frame)</title> |
| 4 | +<scriptsrc="/resources/testharness.js"></script> |
| 5 | +<scriptsrc="/resources/testharnessreport.js"></script> |
| 6 | +<body> |
| 7 | +<script> |
| 8 | +// These tests exercise URLPattern objects whose associated document/global |
| 9 | +// object has gone away (the owning frame is detached). This means URLPattern |
| 10 | +// is being used without a valid JavaScript context. |
| 11 | +functionwithDetachedPatternConstructor(t){ |
| 12 | +returnnewPromise(resolve=>{ |
| 13 | +constframe=document.createElement("iframe"); |
| 14 | +frame.srcdoc=""; |
| 15 | +frame.onload=()=>{ |
| 16 | +constFrameURLPattern=frame.contentWindow.URLPattern; |
| 17 | +frame.remove(); |
| 18 | +resolve(FrameURLPattern); |
| 19 | +}; |
| 20 | +document.body.appendChild(frame); |
| 21 | +t.add_cleanup(()=>frame.remove()); |
| 22 | +}); |
| 23 | +} |
| 24 | + |
| 25 | +promise_test(asynct=>{ |
| 26 | +constFrameURLPattern=awaitwithDetachedPatternConstructor(t); |
| 27 | +constpattern=newFrameURLPattern({pathname: "/books/:id(\\d+)"}); |
| 28 | + |
| 29 | +assert_true(pattern.hasRegExpGroups,"pattern should report regexp groups"); |
| 30 | + |
| 31 | +constresult=pattern.exec("https://example.com/books/123"); |
| 32 | +assert_not_equals(result,null,"regexp pattern should match"); |
| 33 | +assert_equals(result.pathname.input,"/books/123"); |
| 34 | +assert_equals(result.pathname.groups.id,"123"); |
| 35 | +},"Named regexp group matches after the owning frame is detached"); |
| 36 | + |
| 37 | +promise_test(asynct=>{ |
| 38 | +constFrameURLPattern=awaitwithDetachedPatternConstructor(t); |
| 39 | +constpattern=newFrameURLPattern({pathname: "/books/:id(\\d+)"}); |
| 40 | + |
| 41 | +assert_equals(pattern.exec("https://example.com/books/abc"),null, |
| 42 | +"input that violates the regexp constraint should not match"); |
| 43 | +},"Non-matching regexp input returns null after the owning frame is detached"); |
| 44 | + |
| 45 | +promise_test(asynct=>{ |
| 46 | +constFrameURLPattern=awaitwithDetachedPatternConstructor(t); |
| 47 | +// Anonymous regexp group, exercised through test() rather than exec(). |
| 48 | +constpattern=newFrameURLPattern({pathname: "/(foo|bar)"}); |
| 49 | + |
| 50 | +assert_true(pattern.test("https://example.com/foo"), |
| 51 | +"anonymous regexp alternation should match after detach"); |
| 52 | +assert_false(pattern.test("https://example.com/baz"), |
| 53 | +"anonymous regexp alternation should reject non-matching input after detach"); |
| 54 | +},"Anonymous regexp group via test() after the owning frame is detached"); |
| 55 | + |
| 56 | +promise_test(asynct=>{ |
| 57 | +constFrameURLPattern=awaitwithDetachedPatternConstructor(t); |
| 58 | +// Regexp groups across several components at once. |
| 59 | +constpattern=newFrameURLPattern({ |
| 60 | +hostname: ":sub(.*)\\.example\\.com", |
| 61 | +pathname: "/v:version(\\d+)/:rest*", |
| 62 | +}); |
| 63 | + |
| 64 | +constresult=pattern.exec("https://api.example.com/v2/users/42"); |
| 65 | +assert_not_equals(result,null,"multi-component regexp pattern should match after detach"); |
| 66 | +assert_equals(result.hostname.groups.sub,"api"); |
| 67 | +assert_equals(result.pathname.groups.version,"2"); |
| 68 | +assert_equals(result.pathname.groups.rest,"users/42"); |
| 69 | +},"Regexp groups across multiple components after the owning frame is detached"); |
| 70 | +</script> |
| 71 | +</body> |
0 commit comments