Skip to content

Commit 2c23b49

Browse files
authored
Add a section on other specs integrating with URLPattern
A section which covers how other specifications should use URLPattern and how developer-facing APIs should work is added, along with helpful algorithms. One of these is whether a pattern has regexp groups (which may require an ECMAScript regexp engine); a corresponding WebIDL attribute is added to expose this property to authors as well.
1 parent ed205a4 commit 2c23b49

File tree

1 file changed

+117
-2
lines changed

1 file changed

+117
-2
lines changed

spec.bs

+117-2
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,8 @@ interface URLPattern {
182182
readonly attribute USVString pathname;
183183
readonly attribute USVString search;
184184
readonly attribute USVString hash;
185+
186+
readonly attribute boolean hasRegExpGroups;
185187
};
186188

187189
dictionary URLPatternInit {
@@ -323,6 +325,11 @@ Each {{URLPattern}} object has an associated <dfn for=URLPattern>hash component<
323325
<dd>
324326
<p>Returns |urlPattern|'s normalized hash pattern string.
325327
</dd>
328+
329+
<dt><code>|urlPattern|.{{URLPattern/hasRegExpGroups}}</code></dt>
330+
<dd>
331+
<p>Returns whether |urlPattern| contains one or more groups which uses regular expression matching.
332+
</dd>
326333
</dl>
327334

328335
<div algorithm>
@@ -414,6 +421,13 @@ Each {{URLPattern}} object has an associated <dfn for=URLPattern>hash component<
414421
1. Return [=this=]'s [=URLPattern/hash component=]'s [=component/pattern string=].
415422
</div>
416423

424+
<div algorithm>
425+
The <dfn attribute for="URLPattern">hasRegExpGroups</dfn> getter steps are:
426+
427+
1. If [=this=] [=URLPattern/has regexp groups=], then return true.
428+
1. Return false.
429+
</div>
430+
417431
<div algorithm>
418432
The <dfn method for="URLPattern">test(|input|, |baseURL|)</dfn> method steps are:
419433

@@ -438,6 +452,8 @@ A [=component=] has an associated <dfn for=component>regular expression</dfn>, a
438452

439453
A [=component=] has an associated <dfn for=component>group name list</dfn>, a [=list=] of strings, which must be set upon creation.
440454

455+
A [=component=] has an associated <dfn for=component>has regexp groups</dfn>, a [=boolean=], which must be set upon creation.
456+
441457
<div algorithm>
442458
To <dfn>compile a component</dfn> given a string |input|, [=/encoding callback=] |encoding callback|, and [=/options=] |options|:
443459

@@ -450,11 +466,28 @@ A [=component=] has an associated <dfn for=component>group name list</dfn>, a [=
450466
1. Let |regular expression| be [$RegExpCreate$](|regular expression string|, |flags|). If this throws an exception, catch it, and throw a {{TypeError}}.
451467
<p class="note">The specification uses regular expressions to perform all matching, but this is not mandated. Implementations are free to perform matching directly against the [=/part list=] when possible; e.g. when there are no custom regexp matching groups. If there are custom regular expressions, however, its important that they be immediately evaluated in the [=compile a component=] algorithm so an error can be thrown if they are invalid.
452468
1. Let |pattern string| be the result of running [=generate a pattern string=] given |part list| and |options|.
453-
1. Return a new [=component=] whose [=component/pattern string=] is |pattern string|, [=component/regular expression=] is |regular expression|, and [=component/group name list=] is |name list|.
469+
1. Let |has regexp groups| be false.
470+
1. [=list/For each=] |part| of |part list|:
471+
1. If |part|'s [=part/type=] is "<a for=part/type>`regexp`</a>", then set |has regexp groups| to true.
472+
1. Return a new [=component=] whose [=component/pattern string=] is |pattern string|, [=component/regular expression=] is |regular expression|, [=component/group name list=] is |name list|, and [=component/has regexp groups=] is |has regexp groups|.
454473
</div>
455474

456475
<div algorithm>
457-
To perform a <dfn>match</dfn> given a {{URLPattern}} |urlpattern|, a {{URLPatternInput}} |input|, and an optional string |baseURLString|:
476+
A {{URLPattern}} |pattern| <dfn export for=URLPattern>has regexp groups</dfn> if the following steps return true:
477+
478+
1. If |pattern|'s [=URLPattern/protocol component=] [=component/has regexp groups=] is true, then return true.
479+
1. If |pattern|'s [=URLPattern/username component=] [=component/has regexp groups=] is true, then return true.
480+
1. If |pattern|'s [=URLPattern/password component=] [=component/has regexp groups=] is true, then return true.
481+
1. If |pattern|'s [=URLPattern/hostname component=] [=component/has regexp groups=] is true, then return true.
482+
1. If |pattern|'s [=URLPattern/port component=] [=component/has regexp groups=] is true, then return true.
483+
1. If |pattern|'s [=URLPattern/pathname component=] [=component/has regexp groups=] is true, then return true.
484+
1. If |pattern|'s [=URLPattern/search component=] [=component/has regexp groups=] is true, then return true.
485+
1. If |pattern|'s [=URLPattern/hash component=] [=component/has regexp groups=] is true, then return true.
486+
1. Return false.
487+
</div>
488+
489+
<div algorithm>
490+
To perform a <dfn export>match</dfn> given a {{URLPattern}} |urlpattern|, a {{URLPatternInput}} |input|, and an optional string |baseURLString|:
458491

459492
1. Let |protocol| be the empty string.
460493
1. Let |username| be the empty string.
@@ -1902,6 +1935,88 @@ To <dfn>convert a modifier to a string</dfn> given a [=part/modifier=] |modifier
19021935
1. Return the result of running [=canonicalize a hash=] given |strippedValue|.
19031936
</div>
19041937

1938+
<h2 id=other-specs>Using URL patterns in other specifications</h2>
1939+
1940+
To promote consistency on the web platform, other documents integrating with this specification should adhere to the following guidelines, unless there is good reason to diverge.
1941+
1942+
1. **Accept shorthands**. Most author patterns will be simple and straightforward. Accordingly, APIs should accept shorthands for those common cases and avoid the need for authors to take additional steps to transform these into complete {{URLPattern}} objects.
1943+
1. **Respect the base URL**. Just as URLs are generally parsed relative to a base URL for their environment (most commonly, a [=document base URL=]), URL patterns should respect this as well. The {{URLPattern}} constructor itself is an exception because it directly exposes the concept itself, similar to how the <a interface spec=URL>URL</a> constructor does not respect the base URL even though the rest of the platform does.
1944+
1. **Be clear about regexp groups**. Some APIs may benefit from only allowing URL patterns which do not [=URLPattern/has regexp groups|have regexp groups=], for example, because user agents are likely to implement them in a different thread or process from those executing author script, and because of security or performance concerns, a JavaScript engine would not ordinarily run there. If so, this should be clearly documented (with reference to [=URLPattern/has regexp groups=]) and the operation should report an error as soon as possible (e.g., by throwing a JavaScript exception). If possible, this should be feature-detectable to allow for the possibility of this constraint being lifted in the future. Avoid creating different subsets of URL patterns without consulting the editors of this specification.
1945+
1. **Be clear about what URLs will be matched**. For instance, algorithms during fetching are likely to operate on URLs with no [=url/fragment=]. If so, the specification should be clear that this is the case, and may advise showing a developer warning if a pattern which cannot match (e.g., because it requires a non-empty fragment) is used.
1946+
1947+
<h3 id=other-specs-javascript>Integrating with JavaScript APIs</h3>
1948+
1949+
<xmp class="idl">
1950+
typedef (USVString or URLPatternInit or URLPattern) URLPatternCompatible;
1951+
</xmp>
1952+
1953+
JavaScript APIs should accept all of:
1954+
* a {{URLPattern}} object
1955+
* a dictionary-like object which specifies the components required to construct a pattern
1956+
* a string (in the constructor string syntax)
1957+
1958+
To accomplish this, specifications should accept {{URLPatternCompatible}} as an argument to an [=operation=] or [=dictionary member=], and process it using the following algorithm, using the appropriate [=environment settings object=]'s [=environment settings object/API base URL=] or equivalent.
1959+
1960+
<div algorithm>
1961+
To <dfn export>build a {{URLPattern}} from a WebIDL value</dfn> {{URLPatternCompatible}} |input| given [=/URL=] |baseURL| and [=ECMAScript/realm=] |realm|, perform the following steps:
1962+
1963+
1. If the [=specific type=] of |input| is {{URLPattern}}:
1964+
1. Return |input|.
1965+
1. Otherwise, if the [=specific type=] of |input| is {{URLPatternInit}}:
1966+
1. Let |init| be a [=map/clone=] of |input|.
1967+
1. If |init|["{{URLPatternInit/baseURL}}"] does not [=map/exist=], set it to the [=URL serializer|serialization=] of |baseURL|.
1968+
1. Let |pattern| be a [=new=] {{URLPattern}} with |realm|.
1969+
1. Run [=initialize=] given |pattern|, |init|, null, and an empty [=map=].
1970+
1. Return |pattern|.
1971+
1. Otherwise:
1972+
1. [=Assert=]: The [=specific type=] of |input| is {{USVString}}.
1973+
1. Let |pattern| be a [=new=] {{URLPattern}} with |realm|.
1974+
1. Run [=initialize=] given |pattern|, |input|, the [=URL serializer|serialization=] of |baseURL|, and an empty [=map=].
1975+
1. Return |pattern|.
1976+
1977+
<p class="XXX">Ideally we wouldn't need a realm here. If we extricate the URL pattern concept from the {{URLPattern}} interface, we won't anymore.</p>
1978+
</div>
1979+
1980+
This allows authors to concisely specify most patterns, and use the <a constructor for="URLPattern">constructor</a> to access uncommon options if necessary. The implicit use of the base URL is similar to, and consistent with, <cite>HTML</cite>'s [=parse a URL=] algorithm. [[HTML]]
1981+
1982+
<h3 id=other-specs-json>Integrating with JSON data formats</h3>
1983+
1984+
JSON data formats which include URL patterns should mirror the behavior of <a href="#other-specs-javascript">JavaScript APIs</a> and accept both:
1985+
* an object which specifies the components required to construct a pattern
1986+
* a string (in the constructor string syntax)
1987+
1988+
If a specification has an Infra value (e.g., after using [=parse a JSON string to an Infra value=]), use the following algorithm, using the appropriate base URL (by default, the URL of the JSON resource). [[INFRA]]
1989+
1990+
<div algorithm>
1991+
To <dfn export>build a {{URLPattern}} from an Infra value</dfn> |rawPattern| given [=/URL=] |baseURL| and [=ECMAScript/realm=] |realm|, perform the following steps.
1992+
1993+
1. Let |serializedBaseURL| be the [=URL serializer|serialization=] of |baseURL|.
1994+
1. If |rawPattern| is a [=string=], then:
1995+
1. Let |pattern| be a [=new=] {{URLPattern}} with |realm|.
1996+
1. Run [=initialize=] given |pattern|, |rawPattern|, |serializedBaseURL|, and an empty [=map=].
1997+
1998+
<div class="note">It may become necessary in the future to plumb non-empty options here.</div>
1999+
1. Return |pattern|.
2000+
1. Otherwise, if |rawPattern| is a [=map=], then:
2001+
1. Let |init| be «[ "{{URLPatternInit/baseURL}}" → |serializedBaseURL| ]», representing a dictionary of type {{URLPatternInit}}.
2002+
1. [=map/For each=] |key| → |value| of |rawPattern|:
2003+
1. If |key| is not the <a spec=webidl>identifier</a> of a <a spec=webidl>dictionary member</a> of {{URLPatternInit}} or one of its <a spec=webidl>inherited dictionaries</a>, |value| is not a [=string=], or the member's type is not declared to be {{USVString}}, then return null.
2004+
2005+
<div class="note">This will need to be updated if {{URLPatternInit}} gains members of other types.</div>
2006+
<div class="note">A future version of this specification might also have a less strict mode, if that proves useful to other specifications.</div>
2007+
1. Set |init|[|key|] to |value|.
2008+
1. Let |pattern| be a [=new=] {{URLPattern}} with |realm|.
2009+
1. Run [=initialize=] given |pattern|, |init|, null, and an empty [=map=].
2010+
2011+
<div class="note">It may become necessary in the future to plumb non-empty options here.</div>
2012+
1. Return |pattern|.
2013+
1. Otherwise, return null.
2014+
2015+
<p class="XXX">Ideally we wouldn't need a realm here. If we extricate the URL pattern concept from the {{URLPattern}} interface, we won't anymore.</p>
2016+
</div>
2017+
2018+
Specifications may wish to leave room in their formats to accept options for {{URLPatternOptions}}, override the base URL, or similar, since it is not possible to construct a {{URLPattern}} object directly in this case, unlike in a JavaScript API. For example, <cite>Speculation Rules</cite> accepts a "`relative_to`" key which can be used to switch to using the [=document base URL=] instead of the JSON resource's URL. [[SPECULATION-RULES]]
2019+
19052020
<h2 id=acknowledgments class=no-num>Acknowledgments</h2>
19062021

19072022
The editors would like to thank

0 commit comments

Comments
 (0)