Skip to content
File

Blob: src/workerd/api/urlpattern-standard.h

cpp152 lines
1// Copyright (c) 2017-2022 Cloudflare, Inc.
2// Licensed under the Apache 2.0 license found in the LICENSE file or at:
3// https://opensource.org/licenses/Apache-2.0
4 
5#pragma once
6 
7#include "ada.h"
8 
9#include <workerd/jsg/jsg.h>
10 
11#include <kj/array.h>
12#include <kj/one-of.h>
13#include <kj/string.h>
14 
15#include <optional>
16#include <string>
17#include <string_view>
18#include <vector>
19 
20namespace workerd::api {
21 
22namespace urlpattern {
23#define URL_PATTERN_COMPONENTS(V) \
24 V(Protocol, protocol) \
25 V(Username, username) \
26 V(Password, password) \
27 V(Hostname, hostname) \
28 V(Port, port) \
29 V(Pathname, pathname) \
30 V(Search, search) \
31 V(Hash, hash)
32 
33// URLPattern is a Web Platform standard API for matching URLs against a
34// pattern syntax (think of it as a regular expression for URLs). It is
35// defined in https://wicg.github.io/urlpattern.
36// More information about the URL Pattern syntax can be found at
37// https://developer.mozilla.org/en-US/docs/Web/API/URL_Pattern_API
38class URLPattern final: public jsg::Object {
39 public:
40 class URLPatternRegexEngine {
41 public:
42 URLPatternRegexEngine() = default;
43 using regex_type = jsg::JsRef<jsg::JsRegExp>;
44 static std::optional<regex_type> create_instance(std::string_view pattern, bool ignore_case);
45 static std::optional<std::vector<std::optional<std::string>>> regex_search(
46 std::string_view input, const regex_type& pattern);
47 static bool regex_match(std::string_view input, const regex_type& pattern);
48 };
49 
50 // A structure providing matching patterns for individual components
51 // of a URL. When a URLPattern is created, or when a URLPattern is
52 // used to match or test against a URL, the input can be given as
53 // either a string or a URLPatternInit struct. If a string is given,
54 // it will be parsed to create a URLPatternInit. The URLPatternInit
55 // API is defined as part of the URLPattern specification.
56 struct URLPatternInit {
57#define V(_, name) jsg::Optional<jsg::USVString> name;
58 URL_PATTERN_COMPONENTS(V)
59#undef V
60 jsg::Optional<jsg::USVString> baseURL;
61 
62 JSG_STRUCT(protocol, username, password, hostname, port, pathname, search, hash, baseURL);
63 JSG_STRUCT_TS_OVERRIDE(URLPatternInit);
64 
65 ada::url_pattern_init toAdaType() const;
66 };
67 
68 // A struct providing the URLPattern matching results for a single
69 // URL component. The URLPatternComponentResult is only ever used
70 // as a member attribute of a URLPatternResult struct. The
71 // URLPatternComponentResult API is defined as part of the URLPattern
72 // specification.
73 struct URLPatternComponentResult final {
74 jsg::JsRef<jsg::JsString> input;
75 jsg::JsRef<jsg::JsObject> groups;
76 
77 JSG_STRUCT(input, groups);
78 JSG_STRUCT_TS_OVERRIDE(URLPatternComponentResult {
79 input: string;
80 groups: Record<string, string>;
81 });
82 };
83 
84 // A struct providing the URLPattern matching results for all
85 // components of a URL. The URLPatternResult API is defined as
86 // part of the URLPattern specification.
87 struct URLPatternResult final {
88 kj::Array<kj::OneOf<jsg::JsRef<jsg::JsString>, URLPatternInit>> inputs;
89#define V(_, name) URLPatternComponentResult name;
90 URL_PATTERN_COMPONENTS(V)
91#undef V
92 
93 JSG_STRUCT(inputs, protocol, username, password, hostname, port, pathname, search, hash);
94 JSG_STRUCT_TS_OVERRIDE(URLPatternResult);
95 };
96 
97 struct URLPatternOptions final {
98 jsg::Optional<bool> ignoreCase;
99 
100 JSG_STRUCT(ignoreCase);
101 JSG_STRUCT_TS_OVERRIDE(URLPatternOptions);
102 
103 ada::url_pattern_options toAdaType() const;
104 };
105 
106 explicit URLPattern(ada::url_pattern<URLPatternRegexEngine> i): inner(kj::mv(i)) {};
107 
108 static jsg::Ref<URLPattern> constructor(jsg::Lock& js,
109 jsg::Optional<kj::OneOf<jsg::USVString, URLPatternInit>> input,
110 jsg::Optional<kj::OneOf<jsg::USVString, URLPatternOptions>> baseURL,
111 jsg::Optional<URLPatternOptions> patternOptions);
112 
113 kj::Maybe<URLPatternResult> exec(jsg::Lock& js,
114 jsg::Optional<kj::OneOf<jsg::USVString, URLPatternInit>> input,
115 jsg::Optional<jsg::USVString> baseURL);
116 
117 bool test(jsg::Optional<kj::OneOf<jsg::USVString, URLPatternInit>> input,
118 jsg::Optional<jsg::USVString> baseURL);
119 
120 bool getHasRegExpGroups() const;
121 
122#define V(name, _) kj::StringPtr get##name() const;
123 URL_PATTERN_COMPONENTS(V)
124#undef V
125 
126 JSG_RESOURCE_TYPE(URLPattern) {
127#define V(Name, name) JSG_READONLY_PROTOTYPE_PROPERTY(name, get##Name);
128 URL_PATTERN_COMPONENTS(V)
129#undef V
130 JSG_READONLY_PROTOTYPE_PROPERTY(hasRegExpGroups, getHasRegExpGroups);
131 JSG_METHOD(test);
132 JSG_METHOD(exec);
133 }
134 
135 private:
136 ada::url_pattern<URLPatternRegexEngine> inner;
137 
138 static URLPatternInit createURLPatternInit(jsg::Lock& js, const ada::url_pattern_init& other);
139 static URLPatternComponentResult createURLPatternComponentResult(
140 jsg::Lock& js, const ada::url_pattern_component_result& other);
141 static URLPatternResult createURLPatternResult(
142 jsg::Lock& js, const ada::url_pattern_result& other);
143};
144} // namespace urlpattern
145#define EW_URLPATTERN_STANDARD_ISOLATE_TYPES \
146 api::urlpattern::URLPattern, api::urlpattern::URLPattern::URLPatternInit, \
147 api::urlpattern::URLPattern::URLPatternComponentResult, \
148 api::urlpattern::URLPattern::URLPatternResult, \
149 api::urlpattern::URLPattern::URLPatternOptions
150 
151} // namespace workerd::api