bare-url 2.5.1 → 2.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/binding.c CHANGED
@@ -1,113 +1,230 @@
1
1
  #include <assert.h>
2
2
  #include <bare.h>
3
3
  #include <js.h>
4
+ #include <stdbool.h>
4
5
  #include <stddef.h>
5
6
  #include <stdlib.h>
6
7
  #include <string.h>
7
8
  #include <url.h>
8
- #include <url/character-set.h>
9
- #include <url/percent-encode.h>
10
9
  #include <utf.h>
11
10
  #include <utf/string.h>
11
+ #include <uv.h>
12
12
 
13
- // https://url.spec.whatwg.org/#concept-urlencoded-byte-serializer
14
- //
15
- // Everything except ASCII alphanumerics and `*-._` is percent-encoded. A space
16
- // (0x20) is a special case, encoded as `+` rather than `%20`, so it is left out
17
- // of the set and handled separately below.
18
- static url_character_set_t bare_url__form_urlencoded_percent_encode_set = {
19
- // 00 01 02 03 04 05 06 07
20
- 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80,
21
- // 08 09 0a 0b 0c 0d 0e 0f
22
- 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80,
23
- // 10 11 12 13 14 15 16 17
24
- 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80,
25
- // 18 19 1a 1b 1c 1d 1e 1f
26
- 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80,
27
- // 20 21 22 23 24 25 26 27
28
- 0x00 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80,
29
- // 28 29 2a 2b 2c 2d 2e 2f
30
- 0x01 | 0x02 | 0x00 | 0x08 | 0x10 | 0x00 | 0x00 | 0x80,
31
- // 30 31 32 33 34 35 36 37
32
- 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00,
33
- // 38 39 3a 3b 3c 3d 3e 3f
34
- 0x00 | 0x00 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80,
35
- // 40 41 42 43 44 45 46 47
36
- 0x01 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00,
37
- // 48 49 4a 4b 4c 4d 4e 4f
38
- 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00,
39
- // 50 51 52 53 54 55 56 57
40
- 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00,
41
- // 58 59 5a 5b 5c 5d 5e 5f
42
- 0x00 | 0x00 | 0x00 | 0x08 | 0x10 | 0x20 | 0x40 | 0x00,
43
- // 60 61 62 63 64 65 66 67
44
- 0x01 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00,
45
- // 68 69 6a 6b 6c 6d 6e 6f
46
- 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00,
47
- // 70 71 72 73 74 75 76 77
48
- 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00,
49
- // 78 79 7a 7b 7c 7d 7e 7f
50
- 0x00 | 0x00 | 0x00 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80,
51
- // 80 81 82 83 84 85 86 87
52
- 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80,
53
- // 88 89 8a 8b 8c 8d 8e 8f
54
- 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80,
55
- // 90 91 92 93 94 95 96 97
56
- 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80,
57
- // 98 99 9a 9b 9c 9d 9e 9f
58
- 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80,
59
- // a0 a1 a2 a3 a4 a5 a6 a7
60
- 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80,
61
- // a8 a9 aa ab ac ad ae af
62
- 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80,
63
- // b0 b1 b2 b3 b4 b5 b6 b7
64
- 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80,
65
- // b8 b9 ba bb bc bd be bf
66
- 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80,
67
- // c0 c1 c2 c3 c4 c5 c6 c7
68
- 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80,
69
- // c8 c9 ca cb cc cd ce cf
70
- 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80,
71
- // d0 d1 d2 d3 d4 d5 d6 d7
72
- 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80,
73
- // d8 d9 da db dc dd de df
74
- 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80,
75
- // e0 e1 e2 e3 e4 e5 e6 e7
76
- 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80,
77
- // e8 e9 ea eb ec ed ee ef
78
- 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80,
79
- // f0 f1 f2 f3 f4 f5 f6 f7
80
- 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80,
81
- // f8 f9 fa fb fc fd fe ff
82
- 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80,
83
- };
84
-
85
- // https://url.spec.whatwg.org/#concept-urlencoded-serializer
86
- static void
87
- bare_url__serialize_form_urlencoded_component(js_env_t *env, js_value_t *value, utf8_string_t *result) {
13
+ // Maximum length, in bytes, of a UTF-8 string that is read into a stack buffer.
14
+ // Longer strings fall back to a heap allocation. This covers the vast majority
15
+ // of URLs without touching the heap.
16
+ #define BARE_URL_STACK_STRING_MAX 1024
17
+
18
+ // The number of component offsets the parser writes out.
19
+ #define BARE_URL_COMPONENTS_LEN (sizeof(((url_t *) 0)->components) / sizeof(url_component_t))
20
+
21
+ static bool
22
+ bare_url__check_argc(js_env_t *env, size_t argc, size_t expected) {
88
23
  int err;
89
24
 
90
- size_t len;
91
- err = js_get_value_string_utf8(env, value, NULL, 0, &len);
25
+ if (argc < expected) {
26
+ err = js_throw_type_errorf(env, NULL, "Expected %zu arguments, got %zu", expected, argc);
27
+ assert(err == 0);
28
+
29
+ return false;
30
+ }
31
+
32
+ return true;
33
+ }
34
+
35
+ static bool
36
+ bare_url__check_string(js_env_t *env, js_value_t *value, const char *message) {
37
+ int err;
38
+
39
+ bool is_string;
40
+ err = js_is_string(env, value, &is_string);
92
41
  assert(err == 0);
93
42
 
94
- utf8_t *input = malloc(len);
95
- err = js_get_value_string_utf8(env, value, input, len, NULL);
43
+ if (!is_string) {
44
+ err = js_throw_type_error(env, NULL, message);
45
+ assert(err == 0);
46
+ }
47
+
48
+ return is_string;
49
+ }
50
+
51
+ static bool
52
+ bare_url__check_base(js_env_t *env, js_value_t *value, bool *has_base) {
53
+ int err;
54
+
55
+ js_value_type_t type;
56
+ err = js_typeof(env, value, &type);
96
57
  assert(err == 0);
97
58
 
98
- for (size_t i = 0; i < len; i++) {
99
- utf8_t c = input[i];
59
+ *has_base = type == js_string;
100
60
 
101
- if (c == 0x20 /* space */) {
102
- err = utf8_string_append_character(result, '+');
103
- } else {
104
- err = url__percent_encode_character(c, bare_url__form_urlencoded_percent_encode_set, result);
105
- }
61
+ if (type == js_string || type == js_null || type == js_undefined) return true;
62
+
63
+ err = js_throw_type_error(env, NULL, "Base must be a string, null, or undefined");
64
+ assert(err == 0);
65
+
66
+ return false;
67
+ }
68
+
69
+ static bool
70
+ bare_url__check_boolean(js_env_t *env, js_value_t *value, const char *message) {
71
+ int err;
72
+
73
+ bool is_boolean;
74
+ err = js_is_boolean(env, value, &is_boolean);
75
+ assert(err == 0);
76
+
77
+ if (!is_boolean) {
78
+ err = js_throw_type_error(env, NULL, message);
79
+ assert(err == 0);
80
+ }
81
+
82
+ return is_boolean;
83
+ }
84
+
85
+ static bool
86
+ bare_url__check_components(js_env_t *env, js_value_t *value, uint32_t **result) {
87
+ int err;
88
+
89
+ bool is_typedarray;
90
+ err = js_is_typedarray(env, value, &is_typedarray);
91
+ assert(err == 0);
92
+
93
+ js_typedarray_type_t type;
94
+ size_t len;
95
+ js_value_t *arraybuffer;
96
+
97
+ if (is_typedarray) {
98
+ err = js_get_typedarray_info(env, value, &type, (void **) result, &len, &arraybuffer, NULL);
99
+ if (err < 0) return false;
100
+ }
101
+
102
+ if (!is_typedarray || type != js_uint32array) {
103
+ err = js_throw_type_error(env, NULL, "Components must be a Uint32Array");
104
+ assert(err == 0);
106
105
 
106
+ return false;
107
+ }
108
+
109
+ // A detached typed array reports no length of its own, but its data pointer
110
+ // is stale rather than null and so must not be written to.
111
+ bool is_detached;
112
+ err = js_is_detached_arraybuffer(env, arraybuffer, &is_detached);
113
+ assert(err == 0);
114
+
115
+ if (is_detached) {
116
+ err = js_throw_type_error(env, NULL, "Components must not be detached");
107
117
  assert(err == 0);
118
+
119
+ return false;
120
+ }
121
+
122
+ if (len < BARE_URL_COMPONENTS_LEN) {
123
+ err = js_throw_range_errorf(env, NULL, "Components must have at least %zu elements, got %zu", (size_t) BARE_URL_COMPONENTS_LEN, len);
124
+ assert(err == 0);
125
+
126
+ return false;
127
+ }
128
+
129
+ return true;
130
+ }
131
+
132
+ // The UTF-8 encoding of a JavaScript string, together with whatever backs it.
133
+ typedef struct {
134
+ const utf8_t *data;
135
+ size_t len;
136
+
137
+ js_string_view_t *view;
138
+ utf8_t *heap;
139
+ } bare_url_string_t;
140
+
141
+ // Exposes `value` as UTF-8. Strings that are stored as ASCII, which is nearly
142
+ // all of them, are borrowed directly from the engine without being copied.
143
+ // Anything else is transcoded into `stack`, or into a freshly allocated heap
144
+ // buffer when it does not fit. A non-zero return leaves an exception pending.
145
+ // The result must be released with bare_url__free_string() either way.
146
+ static inline int
147
+ bare_url__read_string(js_env_t *env, js_value_t *value, utf8_t *stack, size_t stack_len, bare_url_string_t *result) {
148
+ int err;
149
+
150
+ result->data = NULL;
151
+ result->len = 0;
152
+ result->view = NULL;
153
+ result->heap = NULL;
154
+
155
+ js_string_encoding_t encoding;
156
+ const void *data;
157
+ size_t len;
158
+
159
+ err = js_get_string_view(env, value, &encoding, &data, &len, &result->view);
160
+ if (err < 0) return err;
161
+
162
+ size_t utf8_len;
163
+
164
+ if (encoding == js_utf8) {
165
+ result->data = (const utf8_t *) data;
166
+ result->len = len;
167
+
168
+ return 0;
169
+ }
170
+
171
+ if (encoding == js_latin1) {
172
+ utf8_len = utf8_length_from_latin1((const latin1_t *) data, len);
173
+
174
+ // A Latin-1 string that is no longer as UTF-8 contains only ASCII, whose
175
+ // Latin-1 and UTF-8 encodings are identical.
176
+ if (utf8_len == len) {
177
+ result->data = (const utf8_t *) data;
178
+ result->len = len;
179
+
180
+ return 0;
181
+ }
182
+ } else {
183
+ assert(encoding == js_utf16le);
184
+
185
+ utf8_len = utf8_length_from_utf16le((const utf16_t *) data, len);
186
+ }
187
+
188
+ utf8_t *buffer;
189
+
190
+ if (utf8_len <= stack_len) {
191
+ buffer = stack;
192
+ } else {
193
+ buffer = result->heap = malloc(utf8_len);
194
+
195
+ if (buffer == NULL) {
196
+ err = js_throw_error(env, uv_err_name(UV_ENOMEM), uv_strerror(UV_ENOMEM));
197
+ assert(err == 0);
198
+
199
+ return -1;
200
+ }
201
+ }
202
+
203
+ if (encoding == js_latin1) {
204
+ latin1_convert_to_utf8((const latin1_t *) data, len, buffer);
205
+ } else {
206
+ utf16le_convert_to_utf8((const utf16_t *) data, len, buffer);
108
207
  }
109
208
 
110
- free(input);
209
+ result->data = buffer;
210
+ result->len = utf8_len;
211
+
212
+ return 0;
213
+ }
214
+
215
+ // Releases a string read with bare_url__read_string(), freeing its buffer only
216
+ // when it was heap allocated rather than borrowed or written to the caller's
217
+ // stack buffer.
218
+ static inline void
219
+ bare_url__free_string(js_env_t *env, bare_url_string_t *string) {
220
+ int err;
221
+
222
+ free(string->heap);
223
+
224
+ if (string->view == NULL) return;
225
+
226
+ err = js_release_string_view(env, string->view);
227
+ assert(err == 0);
111
228
  }
112
229
 
113
230
  static js_value_t *
@@ -120,80 +237,89 @@ bare_url_parse(js_env_t *env, js_callback_info_t *info) {
120
237
  err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
121
238
  assert(err == 0);
122
239
 
123
- assert(argc == 4);
240
+ if (!bare_url__check_argc(env, argc, 4)) return NULL;
241
+
242
+ if (!bare_url__check_string(env, argv[0], "Input must be a string")) return NULL;
243
+
244
+ bool has_base;
245
+ if (!bare_url__check_base(env, argv[1], &has_base)) return NULL;
246
+
247
+ uint32_t *components;
248
+ if (!bare_url__check_components(env, argv[2], &components)) return NULL;
249
+
250
+ if (!bare_url__check_boolean(env, argv[3], "Throw must be a boolean")) return NULL;
124
251
 
125
252
  bool should_throw;
126
253
  err = js_get_value_bool(env, argv[3], &should_throw);
127
254
  assert(err == 0);
128
255
 
129
- bool has_base;
130
- err = js_is_string(env, argv[1], &has_base);
131
- assert(err == 0);
256
+ // Set when the input could not be read, which leaves an exception of its own
257
+ // pending and so must not be reported as a parse failure on top.
258
+ bool threw = false;
132
259
 
133
260
  url_t base;
134
261
  url_init(&base);
135
262
 
136
263
  if (has_base) {
137
- size_t len;
138
- err = js_get_value_string_utf8(env, argv[1], NULL, 0, &len);
139
- assert(err == 0);
264
+ utf8_t stack[BARE_URL_STACK_STRING_MAX];
140
265
 
141
- utf8_t *input = malloc(len);
142
- err = js_get_value_string_utf8(env, argv[1], input, len, NULL);
143
- assert(err == 0);
266
+ bare_url_string_t input;
267
+ err = bare_url__read_string(env, argv[1], stack, sizeof(stack), &input);
144
268
 
145
- err = url_parse(&base, input, len, NULL);
269
+ if (err == 0) err = url_parse(&base, input.data, input.len, NULL);
270
+ else threw = true;
146
271
 
147
- free(input);
272
+ bare_url__free_string(env, &input);
148
273
 
149
274
  if (err < 0) {
150
275
  url_destroy(&base);
151
276
 
152
- if (should_throw) js_throw_error(env, NULL, "Invalid base URL");
277
+ if (should_throw && !threw) {
278
+ err = js_throw_error(env, NULL, "Invalid base URL");
279
+ assert(err == 0);
280
+ }
153
281
 
154
282
  return NULL;
155
283
  }
156
284
  }
157
285
 
158
- size_t len;
159
- err = js_get_value_string_utf8(env, argv[0], NULL, 0, &len);
160
- assert(err == 0);
161
-
162
- utf8_t *input = malloc(len);
163
- err = js_get_value_string_utf8(env, argv[0], input, len, NULL);
164
- assert(err == 0);
286
+ utf8_t stack[BARE_URL_STACK_STRING_MAX];
165
287
 
166
- js_value_t *handle;
288
+ bare_url_string_t input;
289
+ err = bare_url__read_string(env, argv[0], stack, sizeof(stack), &input);
167
290
 
168
291
  url_t url;
169
292
  url_init(&url);
170
293
 
171
- err = url_parse(&url, input, len, has_base ? &base : NULL);
294
+ if (err == 0) err = url_parse(&url, input.data, input.len, has_base ? &base : NULL);
295
+ else threw = true;
172
296
 
173
- free(input);
297
+ bare_url__free_string(env, &input);
174
298
 
175
299
  if (err < 0) {
176
300
  url_destroy(&base);
177
301
  url_destroy(&url);
178
302
 
179
- if (should_throw) js_throw_error(env, NULL, "Invalid URL");
303
+ if (should_throw && !threw) {
304
+ err = js_throw_error(env, NULL, "Invalid URL");
305
+ assert(err == 0);
306
+ }
180
307
 
181
308
  return NULL;
182
309
  }
183
310
 
184
311
  js_value_t *href;
185
- err = js_create_string_utf8(env, url.href.data, url.href.len, &href);
186
- assert(err == 0);
312
+ err = js_create_string_latin1(env, (const latin1_t *) url.href.data, url.href.len, &href);
187
313
 
188
- uint32_t *components;
189
- err = js_get_typedarray_info(env, argv[2], NULL, (void **) &components, NULL, NULL, NULL);
190
- assert(err == 0);
191
-
192
- memcpy(components, &url.components, sizeof(url.components));
314
+ // The offsets are only handed over once the href they refer to is, so a
315
+ // failure here leaves the caller's buffer as it was.
316
+ if (err == 0) memcpy(components, &url.components, sizeof(url.components));
193
317
 
194
318
  url_destroy(&base);
195
319
  url_destroy(&url);
196
320
 
321
+ if (err < 0) return NULL;
322
+
197
323
  return href;
198
324
  }
199
325
 
@@ -207,31 +333,34 @@ bare_url_can_parse(js_env_t *env, js_callback_info_t *info) {
207
333
  err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
208
334
  assert(err == 0);
209
335
 
210
- assert(argc == 2);
336
+ if (!bare_url__check_argc(env, argc, 2)) return NULL;
337
+
338
+ if (!bare_url__check_string(env, argv[0], "Input must be a string")) return NULL;
211
339
 
212
340
  bool has_base;
213
- err = js_is_string(env, argv[1], &has_base);
214
- assert(err == 0);
341
+ if (!bare_url__check_base(env, argv[1], &has_base)) return NULL;
342
+
343
+ bool threw = false;
215
344
 
216
345
  url_t base;
217
346
  url_init(&base);
218
347
 
219
348
  if (has_base) {
220
- size_t len;
221
- err = js_get_value_string_utf8(env, argv[1], NULL, 0, &len);
222
- assert(err == 0);
349
+ utf8_t stack[BARE_URL_STACK_STRING_MAX];
223
350
 
224
- utf8_t *input = malloc(len);
225
- err = js_get_value_string_utf8(env, argv[1], input, len, NULL);
226
- assert(err == 0);
351
+ bare_url_string_t input;
352
+ err = bare_url__read_string(env, argv[1], stack, sizeof(stack), &input);
227
353
 
228
- err = url_parse(&base, input, len, NULL);
354
+ if (err == 0) err = url_parse(&base, input.data, input.len, NULL);
355
+ else threw = true;
229
356
 
230
- free(input);
357
+ bare_url__free_string(env, &input);
231
358
 
232
359
  if (err < 0) {
233
360
  url_destroy(&base);
234
361
 
362
+ if (threw) return NULL;
363
+
235
364
  js_value_t *result;
236
365
  err = js_get_boolean(env, false, &result);
237
366
  assert(err == 0);
@@ -240,24 +369,24 @@ bare_url_can_parse(js_env_t *env, js_callback_info_t *info) {
240
369
  }
241
370
  }
242
371
 
243
- size_t len;
244
- err = js_get_value_string_utf8(env, argv[0], NULL, 0, &len);
245
- assert(err == 0);
372
+ utf8_t stack[BARE_URL_STACK_STRING_MAX];
246
373
 
247
- utf8_t *input = malloc(len);
248
- err = js_get_value_string_utf8(env, argv[0], input, len, NULL);
249
- assert(err == 0);
374
+ bare_url_string_t input;
375
+ err = bare_url__read_string(env, argv[0], stack, sizeof(stack), &input);
250
376
 
251
377
  url_t url;
252
378
  url_init(&url);
253
379
 
254
- err = url_parse(&url, input, len, has_base ? &base : NULL);
380
+ if (err == 0) err = url_parse(&url, input.data, input.len, has_base ? &base : NULL);
381
+ else threw = true;
255
382
 
256
- free(input);
383
+ bare_url__free_string(env, &input);
257
384
 
258
385
  url_destroy(&base);
259
386
  url_destroy(&url);
260
387
 
388
+ if (threw) return NULL;
389
+
261
390
  js_value_t *result;
262
391
  err = js_get_boolean(env, err == 0, &result);
263
392
  assert(err == 0);
@@ -265,56 +394,6 @@ bare_url_can_parse(js_env_t *env, js_callback_info_t *info) {
265
394
  return result;
266
395
  }
267
396
 
268
- static js_value_t *
269
- bare_url_serialize_form_urlencoded(js_env_t *env, js_callback_info_t *info) {
270
- int err;
271
-
272
- size_t argc = 1;
273
- js_value_t *argv[1];
274
-
275
- err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
276
- assert(err == 0);
277
-
278
- assert(argc == 1);
279
-
280
- uint32_t len;
281
- err = js_get_array_length(env, argv[0], &len);
282
- assert(err == 0);
283
-
284
- utf8_string_t result;
285
- utf8_string_init(&result);
286
-
287
- for (uint32_t i = 0; i + 1 < len; i += 2) {
288
- js_value_t *pair[2];
289
-
290
- err = js_get_element(env, argv[0], i, &pair[0]);
291
- assert(err == 0);
292
-
293
- err = js_get_element(env, argv[0], i + 1, &pair[1]);
294
- assert(err == 0);
295
-
296
- if (i != 0) {
297
- err = utf8_string_append_character(&result, '&');
298
- assert(err == 0);
299
- }
300
-
301
- bare_url__serialize_form_urlencoded_component(env, pair[0], &result);
302
-
303
- err = utf8_string_append_character(&result, '=');
304
- assert(err == 0);
305
-
306
- bare_url__serialize_form_urlencoded_component(env, pair[1], &result);
307
- }
308
-
309
- js_value_t *output;
310
- err = js_create_string_utf8(env, result.data, result.len, &output);
311
- assert(err == 0);
312
-
313
- utf8_string_destroy(&result);
314
-
315
- return output;
316
- }
317
-
318
397
  static js_value_t *
319
398
  bare_url_exports(js_env_t *env, js_value_t *exports) {
320
399
  int err;
@@ -330,7 +409,6 @@ bare_url_exports(js_env_t *env, js_value_t *exports) {
330
409
 
331
410
  V("parse", bare_url_parse)
332
411
  V("canParse", bare_url_can_parse)
333
- V("serializeSearchParams", bare_url_serialize_form_urlencoded)
334
412
  #undef V
335
413
 
336
414
  return exports;
package/global.d.ts CHANGED
@@ -4,7 +4,19 @@ type URLConstructor = typeof url.URL
4
4
  type URLSearchParamsConstructor = typeof url.URLSearchParams
5
5
 
6
6
  declare global {
7
+ /**
8
+ * Parse `input` as a URL. If `base` is provided, `input` is resolved relative to `base`.
9
+ * @param input - The URL string to parse.
10
+ * @param base - A base URL that `input` is resolved relative to, if provided.
11
+ * @throws {INVALID_URL} `input` is not a valid URL.
12
+ */
7
13
  type URL = url.URL
14
+ /**
15
+ * Create a new `URLSearchParams` instance. `init` may be a query string, an iterable of `[name,
16
+ * value]` pairs, or an object of key-value pairs.
17
+ * @param init - A query string, an iterable of `[name, value]` pairs, or an object of key-value
18
+ * pairs to initialize the params from.
19
+ */
8
20
  type URLSearchParams = url.URLSearchParams
9
21
 
10
22
  const URL: URLConstructor
package/index.d.ts CHANGED
@@ -2,37 +2,92 @@ import URLError from './lib/errors'
2
2
  import URLSearchParams from './lib/url-search-params'
3
3
 
4
4
  interface URL {
5
+ /** The full serialized URL string. Setting this property reparses the URL. */
5
6
  href: string
7
+ /** The URL scheme followed by `':'`, for example `'https:'`. */
6
8
  protocol: string
9
+ /** The username portion of the URL, or an empty string. */
7
10
  username: string
11
+ /** The password portion of the URL, or an empty string. */
8
12
  password: string
13
+ /** The hostname and port, for example `'example.com:8080'`. */
9
14
  host: string
15
+ /** The hostname without the port. */
10
16
  hostname: string
17
+ /** The port as a string, or an empty string if not present. */
11
18
  port: string
19
+ /** The path portion of the URL. */
12
20
  pathname: string
21
+ /** The query string including the leading `'?'`, or an empty string. */
13
22
  search: string
23
+ /**
24
+ * A `URLSearchParams` object for the query string. Mutations to the params are reflected in the
25
+ * URL.
26
+ */
14
27
  searchParams: URLSearchParams
28
+ /** The fragment including the leading `'#'`, or an empty string. */
15
29
  hash: string
16
30
 
31
+ /** Returns the serialized string form. */
17
32
  toString(): string
33
+ /** Returns the serialized string form. Suitable for JSON serialization. */
18
34
  toJSON(): string
19
35
  }
20
36
 
21
37
  declare class URL {
38
+ /**
39
+ * Parse `input` as a URL. If `base` is provided, `input` is resolved relative to `base`.
40
+ * @param input - The URL string to parse.
41
+ * @param base - A base URL that `input` is resolved relative to, if provided.
42
+ * @throws {INVALID_URL} `input` is not a valid URL.
43
+ */
22
44
  constructor(input: string | URL, base?: string | URL)
23
45
  }
24
46
 
25
47
  declare namespace URL {
48
+ /**
49
+ * Return `true` if `value` is a `URL` instance.
50
+ * @param value - The value to test.
51
+ */
26
52
  export function isURL(value: unknown): value is URL
27
53
 
54
+ /**
55
+ * Return `true` if `value` is a `URLSearchParams` instance.
56
+ * @param value - The value to test.
57
+ */
28
58
  export function isURLSearchParams(value: unknown): value is URLSearchParams
29
59
 
60
+ /**
61
+ * Parse `input` as a URL without throwing.
62
+ * @param input - The URL string to parse.
63
+ * @param base - A base URL that `input` is resolved relative to, if provided.
64
+ * @returns A `URL` instance if `input` parses successfully, or `null` on failure.
65
+ */
30
66
  export function parse(input: string, base?: string | URL): URL | null
31
67
 
68
+ /**
69
+ * Return `true` if `input` can be parsed as a valid URL, optionally relative to `base`.
70
+ * @param input - The URL string to test.
71
+ * @param base - A base URL that `input` is resolved relative to, if provided.
72
+ */
32
73
  export function canParse(input: string, base?: string | URL): boolean
33
74
 
75
+ /**
76
+ * Convert a `file:` URL to a platform-specific file path. `url` may be a `URL` instance or a
77
+ * string.
78
+ * @param url - The `file:` URL to convert, as a `URL` instance or a string.
79
+ * @throws {INVALID_URL_SCHEME} the URL does not use the `file:` protocol.
80
+ * @throws {INVALID_FILE_URL_HOST} (non-Windows) the URL has a host other than empty or
81
+ * `'localhost'`.
82
+ * @throws {INVALID_FILE_URL_PATH} the URL path contains an encoded path-separator or NUL
83
+ * character, or, on Windows, is not an absolute drive path.
84
+ */
34
85
  export function fileURLToPath(url: URL | string): string
35
86
 
87
+ /**
88
+ * Convert a platform-specific file path to a `file:` URL.
89
+ * @param pathname - The platform-specific file path to convert.
90
+ */
36
91
  export function pathToFileURL(pathname: string): URL
37
92
 
38
93
  export { URL, type URLError, URLError as errors, URLSearchParams }