Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a section on other specs integrating with URLPattern #199

Merged
merged 11 commits into from
Nov 30, 2023
94 changes: 93 additions & 1 deletion spec.bs
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,8 @@ interface URLPattern {
readonly attribute USVString pathname;
readonly attribute USVString search;
readonly attribute USVString hash;

readonly attribute boolean hasRegExpGroups;
};

dictionary URLPatternInit {
Expand Down Expand Up @@ -323,6 +325,11 @@ Each {{URLPattern}} object has an associated <dfn for=URLPattern>hash component<
<dd>
<p>Returns |urlPattern|'s normalized hash pattern string.
</dd>

<dt><code>|urlPattern|.{{URLPattern/hasRegExpGroups}}</code></dt>
<dd>
<p>Returns whether |urlPattern| contains one or more groups which uses regular expression matching.
</dd>
</dl>

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

<div algorithm>
The <dfn attribute for="URLPattern">hasRegExpGroups</dfn> getter steps are:

1. If [=this=] [=URLPattern/has regexp groups=], then return true.
1. Return false.
</div>

<div algorithm>
The <dfn method for="URLPattern">test(|input|, |baseURL|)</dfn> method steps are:

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

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

A [=component=] has an associated <dfn for=component>has regexp groups flag</dfn>, a [=boolean=], which must be set upon creation.
jeremyroman marked this conversation as resolved.
Show resolved Hide resolved

<div algorithm>
To <dfn>compile a component</dfn> given a string |input|, [=/encoding callback=] |encoding callback|, and [=/options=] |options|:

Expand All @@ -450,7 +466,24 @@ A [=component=] has an associated <dfn for=component>group name list</dfn>, a [=
1. Let |regular expression| be [$RegExpCreate$](|regular expression string|, |flags|). If this throws an exception, catch it, and throw a {{TypeError}}.
<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.
1. Let |pattern string| be the result of running [=generate a pattern string=] given |part list| and |options|.
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|.
1. Let |has regexp groups| be false.
1. [=list/For each=] |part| of |part list|:
1. If |part|'s [=part/type=] is "<a for=token/type>`regexp`</a>", then set |has regexp groups| to true.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<a for=token/type>`regexp`</a> : part/type is correct instead of token/type?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're correct; done.

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 flag=] is |has regexp groups|.
</div>

<div algorithm>
A {{URLPattern}} |pattern| <dfn for=URLPattern>has regexp groups</dfn> if the following steps return true:
domenic marked this conversation as resolved.
Show resolved Hide resolved

1. If |pattern|'s [=URLPattern/protocol component=] [=component/has regexp groups flag=] is true, then return true.
1. If |pattern|'s [=URLPattern/username component=] [=component/has regexp groups flag=] is true, then return true.
1. If |pattern|'s [=URLPattern/password component=] [=component/has regexp groups flag=] is true, then return true.
1. If |pattern|'s [=URLPattern/hostname component=] [=component/has regexp groups flag=] is true, then return true.
1. If |pattern|'s [=URLPattern/port component=] [=component/has regexp groups flag=] is true, then return true.
1. If |pattern|'s [=URLPattern/pathname component=] [=component/has regexp groups flag=] is true, then return true.
1. If |pattern|'s [=URLPattern/search component=] [=component/has regexp groups flag=] is true, then return true.
1. If |pattern|'s [=URLPattern/hash component=] [=component/has regexp groups flag=] is true, then return true.
1. Return false.
</div>

<div algorithm>
Expand Down Expand Up @@ -1902,6 +1935,65 @@ To <dfn>convert a modifier to a string</dfn> given a [=part/modifier=] |modifier
1. Return the result of running [=canonicalize a hash=] given |strippedValue|.
</div>

<h2 id=integrating>Integrating with other specs</h2>
domenic marked this conversation as resolved.
Show resolved Hide resolved

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.
domenic marked this conversation as resolved.
Show resolved Hide resolved

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.
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 {{URL}} constructor does not respect the base URL even though the rest of the platform does.
1. **Be clear about regexp groups**. Some APIs may benefit from only allowing URL patterns which do not [=URLPattern/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/hasRegExpGroups}}) 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.
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.

<h3 id=integrating-javascript>Integrating with JavaScript APIs</h3>

JavaScript APIs should accept all of:
* a {{URLPattern}} object
* a dictionary-like object which specifies the components required to construct a pattern
* a string (in the constructor string syntax)

To accomplish this, specifications should accept {{URLPatternInput}} 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.

<div algorithm>
To <dfn for=URLPattern>build a {{URLPattern}} from a WebIDL value</dfn> {{URLPatternInput}} |input| given [=URL=] |baseURL|, perform the following steps:

1. If the [=specific type=] of |input| is {{USVString}}:
1. Return the result of constructing a {{URLPattern/constructor(input, baseURL, options)}} given |input| and the [=URL serializer|serialization=] of |baseURL|.
1. Otherwise:
1. [=Assert=]: the [=specific type=] of |input| is {{URLPatternInit}}.
1. If |input|["`baseURL`"] does not [=map/exist=], set it to the [=URL serializer|serialization=] of |baseURL|.
domenic marked this conversation as resolved.
Show resolved Hide resolved
1. Return the result of constructing a {{URLPattern/constructor(input, options)}} given |input|.
domenic marked this conversation as resolved.
Show resolved Hide resolved

<div class=issue>Currently, {{URLPattern}} objects are not handled specially here, but perhaps they should be, since even though {{URLPattern}} has the properties necessary for {{URLPatternInit}}, this loses the {{URLPatternOptions/ignoreCase}} option (which is not exposed on the {{URLPattern}} interface).
</div>

This allows authors to concisely specify most patterns, and use the {{URLPattern/constructor|constructor}} to access uncommon options if necessary. The implicit use of the base URL is similar to, and consistent with, [[HTML]]'s [=parse a URL=] algorithm.
domenic marked this conversation as resolved.
Show resolved Hide resolved

<h3 id=integrating-json>Integrating with JSON data formats</h3>

JSON data formats which include URL patterns should mirror the behavior of <a href="#integrating-javascript">JavaScript APIs</a> and accept both:
* an object which specifies the components required to construct a pattern
* a string (in the constructor string syntax)

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).

<div algorithm>
To <dfn for=URLPattern>build a {{URLPattern}} from an Infra value</dfn> |rawPattern| given [=URL=] |baseURL|, perform the following steps.

1. Let |serializedBaseURL| be the [=URL serializer|serialization=] of |baseURL|.
domenic marked this conversation as resolved.
Show resolved Hide resolved
1. If |rawPattern| is a [=string=], then:
1. Return the result of constructing a {{URLPattern}} using the {{URLPattern/URLPattern(input, baseURL)}} constructor steps given |rawPattern| and |serializedBaseURL|.
1. Otherwise, if |rawPattern| is a [=map=], then:
1. Let |init| be «[ "`baseURL`" → |serializedBaseURL| ]», representing a dictionary of type {{URLPatternInit}}.
domenic marked this conversation as resolved.
Show resolved Hide resolved
1. [=map/For each=] |key| → |value| of |rawPattern|:
1. If |key| is not the [=identifier=] of a [=dictionary member=] of {{URLPatternInit}} or one of its [=inherited dictionaries=], |value| is not a [=string=], or the member's type is not declared to be {{USVString}}, then return null.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not 100% clear to me that every spec wants the kind of restrictive error handling we've used here. But I feel like we discussed this in the past when writing the speculation rules spec. I'm OK carrying it over for now, until someone raises an issue.


<div class="note">This will need to be updated if {{URLPatternInit}} gains members of other types.</div>
1. Set |init|[|key|] to |value|.
1. Return the result of constructing a {{URLPattern}} using the {{URLPattern/URLPattern(input, baseURL)}} constructor steps given |init|.
</div>

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.
domenic marked this conversation as resolved.
Show resolved Hide resolved

<h2 id=acknowledgments class=no-num>Acknowledgments</h2>

The editors would like to thank
Expand Down
Loading