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/CMakeLists.txt +1 -1
- package/README.md +1 -140
- package/binding.c +268 -190
- package/global.d.ts +12 -0
- package/index.d.ts +55 -0
- package/index.js +339 -74
- package/lib/url-search-params.d.ts +43 -0
- package/lib/url-search-params.js +111 -29
- package/package.json +1 -1
- package/prebuilds/android-arm/bare-url.bare +0 -0
- package/prebuilds/android-arm64/bare-url.bare +0 -0
- package/prebuilds/android-ia32/bare-url.bare +0 -0
- package/prebuilds/android-x64/bare-url.bare +0 -0
- package/prebuilds/darwin-arm64/bare-url.bare +0 -0
- package/prebuilds/darwin-x64/bare-url.bare +0 -0
- package/prebuilds/ios-arm64/bare-url.bare +0 -0
- package/prebuilds/ios-arm64-simulator/bare-url.bare +0 -0
- package/prebuilds/ios-x64-simulator/bare-url.bare +0 -0
- package/prebuilds/linux-arm64/bare-url.bare +0 -0
- package/prebuilds/linux-x64/bare-url.bare +0 -0
- package/prebuilds/win32-arm64/bare-url.bare +0 -0
- package/prebuilds/win32-x64/bare-url.bare +0 -0
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
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
|
|
91
|
-
|
|
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
|
-
|
|
95
|
-
|
|
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
|
-
|
|
99
|
-
utf8_t c = input[i];
|
|
59
|
+
*has_base = type == js_string;
|
|
100
60
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
130
|
-
|
|
131
|
-
|
|
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
|
-
|
|
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
|
-
|
|
142
|
-
err =
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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 =
|
|
186
|
-
assert(err == 0);
|
|
312
|
+
err = js_create_string_latin1(env, (const latin1_t *) url.href.data, url.href.len, &href);
|
|
187
313
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
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
|
-
|
|
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
|
-
|
|
214
|
-
|
|
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
|
-
|
|
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
|
-
|
|
225
|
-
err =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
248
|
-
err =
|
|
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
|
-
|
|
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 }
|