bare-url 0.3.8 → 1.0.0

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.
Files changed (42) hide show
  1. package/CMakeLists.txt +27 -0
  2. package/binding.c +111 -0
  3. package/binding.js +1 -0
  4. package/index.js +74 -90
  5. package/lib/errors.js +0 -105
  6. package/package.json +14 -3
  7. package/prebuilds/darwin-arm64/bare-url.bare +0 -0
  8. package/prebuilds/darwin-x64/bare-url.bare +0 -0
  9. package/prebuilds/linux-arm64/bare-url.bare +0 -0
  10. package/prebuilds/linux-x64/bare-url.bare +0 -0
  11. package/prebuilds/win32-x64/bare-url.bare +0 -0
  12. package/vendor/liburl/CMakeLists.txt +79 -0
  13. package/vendor/liburl/LICENSE +201 -0
  14. package/vendor/liburl/README.md +27 -0
  15. package/vendor/liburl/include/url.h +107 -0
  16. package/vendor/liburl/src/character-set.h +41 -0
  17. package/vendor/liburl/src/idna.h +14 -0
  18. package/vendor/liburl/src/infra.h +141 -0
  19. package/vendor/liburl/src/parse.h +1390 -0
  20. package/vendor/liburl/src/percent-encode.h +567 -0
  21. package/vendor/liburl/src/punycode.h +21 -0
  22. package/vendor/liburl/src/serialize.h +91 -0
  23. package/vendor/liburl/src/type.h +61 -0
  24. package/vendor/liburl/src/url.c +81 -0
  25. package/vendor/libutf/CMakeLists.txt +76 -0
  26. package/vendor/libutf/LICENSE +201 -0
  27. package/vendor/libutf/README.md +11 -0
  28. package/vendor/libutf/include/utf/endianness.h +54 -0
  29. package/vendor/libutf/include/utf/string.h +759 -0
  30. package/vendor/libutf/include/utf.h +45 -0
  31. package/vendor/libutf/src/endianness.c +19 -0
  32. package/vendor/libutf/src/utf16/utf8-convert.c +77 -0
  33. package/vendor/libutf/src/utf16/utf8-length.c +45 -0
  34. package/vendor/libutf/src/utf16/validate.c +53 -0
  35. package/vendor/libutf/src/utf8/string.c +148 -0
  36. package/vendor/libutf/src/utf8/utf16-convert.c +90 -0
  37. package/vendor/libutf/src/utf8/utf16-length.c +39 -0
  38. package/vendor/libutf/src/utf8/validate.c +107 -0
  39. package/lib/constants.js +0 -25
  40. package/lib/infra.js +0 -39
  41. package/lib/parse.js +0 -941
  42. package/lib/serialize.js +0 -98
package/lib/parse.js DELETED
@@ -1,941 +0,0 @@
1
- const tr46 = require('tr46')
2
- const constants = require('./constants')
3
- const errors = require('./errors')
4
- const infra = require('./infra')
5
-
6
- // https://url.spec.whatwg.org/#url-parsing
7
- module.exports = function parse (
8
- input,
9
- base = null,
10
- // https://url.spec.whatwg.org/#url-representation
11
- url = {
12
- scheme: '',
13
- username: '',
14
- password: '',
15
- host: null,
16
- port: null,
17
- path: [],
18
- query: null,
19
- fragment: null
20
- },
21
- stateOverride = 0
22
- ) {
23
- let state = stateOverride || constants.STATE_SCHEME_START
24
- let buffer = ''
25
- let atSignSeen = false
26
- let insideBrackets = false
27
- let passwordTokenSeen = false
28
-
29
- for (let pointer = 0; pointer <= input.length; pointer++) {
30
- const c = pointer < input.length ? input.charCodeAt(pointer) : -1
31
-
32
- switch (state) {
33
- // https://url.spec.whatwg.org/#scheme-start-state
34
- case constants.STATE_SCHEME_START:
35
- if (infra.isASCIIAlpha(c)) {
36
- buffer += String.fromCharCode(c).toLowerCase()
37
- state = constants.STATE_SCHEME
38
- } else if (!stateOverride) {
39
- state = constants.STATE_NO_SCHEME
40
- pointer--
41
- } else {
42
- throw errors.INVALID_URL()
43
- }
44
- break
45
-
46
- // https://url.spec.whatwg.org/#scheme-state
47
- case constants.STATE_SCHEME:
48
- if (infra.isASCIIAlphanumeric(c) || c === 0x2b || c === 0x2d || c === 0x2e) {
49
- buffer += String.fromCharCode(c).toLowerCase()
50
- } else if (c === 0x3a) {
51
- if (stateOverride) {
52
- if (isSpecialScheme(url.scheme) && !isSpecialScheme(buffer)) {
53
- return
54
- }
55
-
56
- if (!isSpecialScheme(url.scheme) && isSpecialScheme(buffer)) {
57
- return
58
- }
59
-
60
- if ((includesCredentials(url) || url.port !== null) && buffer === 'file') {
61
- return
62
- }
63
-
64
- if (url.scheme === 'file' && url.host === '') {
65
- return
66
- }
67
- }
68
-
69
- url.scheme = buffer
70
-
71
- if (stateOverride) {
72
- if (url.port === defaultPort(url.scheme)) {
73
- url.port = null
74
- }
75
-
76
- return
77
- }
78
-
79
- buffer = ''
80
-
81
- if (url.scheme === 'file') {
82
- state = constants.STATE_FILE
83
- } else if (isSpecial(url)) {
84
- if (base && base.scheme === url.scheme) {
85
- state = constants.STATE_SPECIAL_RELATIVE_OR_AUTHORITY
86
- } else {
87
- state = constants.STATE_SPECIAL_AUTHORITY_SLASHES
88
- }
89
- } else if (input.charCodeAt(pointer + 1) === 0x2f) {
90
- state = constants.STATE_PATH_OR_AUTHORITY
91
- pointer++
92
- } else {
93
- url.path = ''
94
- state = constants.STATE_OPAQUE_PATH
95
- }
96
- } else if (!stateOverride) {
97
- buffer = ''
98
- state = constants.STATE_NO_SCHEME
99
- pointer = -1
100
- } else {
101
- throw errors.INVALID_URL()
102
- }
103
- break
104
-
105
- // https://url.spec.whatwg.org/#no-scheme-state
106
- case constants.STATE_NO_SCHEME:
107
- if (base === null || (hasOpaquePath(base) && c !== 0x23)) {
108
- throw errors.MISSING_SCHEME_NON_RELATIVE_URL()
109
- }
110
-
111
- if (hasOpaquePath(base) && c === 0x23) {
112
- url.scheme = base.scheme
113
- url.path = base.path
114
- url.query = base.query
115
- url.fragment = ''
116
- state = constants.STATE_FRAGMENT
117
- } else if (base.sceheme !== 'file') {
118
- state = constants.STATE_RELATIVE
119
- pointer--
120
- } else {
121
- state = constants.STATE_FILE
122
- pointer--
123
- }
124
- break
125
-
126
- // https://url.spec.whatwg.org/#special-relative-or-authority-state
127
- case constants.STATE_SPECIAL_RELATIVE_OR_AUTHORITY:
128
- if (c === 0x2f && input.charCodeAt(pointer + 1) === 0x2f) {
129
- state = constants.STATE_SPECIAL_AUTHORITY_IGNORE_SLASHES
130
- pointer++
131
- } else {
132
- state = constants.STATE_RELATIVE
133
- pointer--
134
- }
135
- break
136
-
137
- // https://url.spec.whatwg.org/#path-or-authority-state
138
- case constants.STATE_PATH_OR_AUTHORITY:
139
- if (c === 0x2f) {
140
- state = constants.STATE_AUTHORITY
141
- } else {
142
- state = constants.STATE_PATH
143
- pointer--
144
- }
145
- break
146
-
147
- // https://url.spec.whatwg.org/#relative-state
148
- case constants.STATE_RELATIVE:
149
- url.scheme = base.scheme
150
-
151
- if (c === 0x2f) {
152
- state = constants.STATE_RELATIVE_SLASH
153
- } else if (isSpecial(url) && c === 0x5c) {
154
- state = constants.STATE_RELATIVE_SLASH
155
- } else {
156
- url.username = base.username
157
- url.password = base.password
158
- url.host = base.host
159
- url.port = base.port
160
- url.path = [...base.path]
161
- url.query = base.query
162
-
163
- if (c === 0x3f) {
164
- url.query = ''
165
- state = constants.STATE_QUERY
166
- } else if (c === 0x23) {
167
- url.fragment = ''
168
- state = constants.STATE_FRAGMENT
169
- } else if (c !== -1) {
170
- url.query = null
171
- shortenPath(url)
172
- state = constants.STATE_PATH
173
- pointer--
174
- }
175
- }
176
- break
177
-
178
- // https://url.spec.whatwg.org/#relative-slash-state
179
- case constants.STATE_RELATIVE_SLASH:
180
- if (isSpecial(url) && (c === 0x2f || c === 0x5c)) {
181
- state = constants.STATE_SPECIAL_AUTHORITY_IGNORE_SLASHES
182
- } else if (c === 0x2f) {
183
- state = constants.STATE_AUTHORITY
184
- } else {
185
- url.username = base.username
186
- url.password = base.password
187
- url.host = base.host
188
- url.port = base.port
189
- state = constants.STATE_PATH
190
- pointer--
191
- }
192
- break
193
-
194
- // https://url.spec.whatwg.org/#special-authority-slashes-state
195
- case constants.STATE_SPECIAL_AUTHORITY_SLASHES:
196
- if (c === 0x2f && input.charCodeAt(pointer + 1) === 0x2f) {
197
- state = constants.STATE_SPECIAL_AUTHORITY_IGNORE_SLASHES
198
- pointer++
199
- } else {
200
- state = constants.STATE_SPECIAL_AUTHORITY_IGNORE_SLASHES
201
- pointer--
202
- }
203
- break
204
-
205
- // https://url.spec.whatwg.org/#special-authority-ignore-slashes-state
206
- case constants.STATE_SPECIAL_AUTHORITY_IGNORE_SLASHES:
207
- if (c !== 0x2f && c !== 0x5c) {
208
- state = constants.STATE_AUTHORITY
209
- pointer--
210
- }
211
- break
212
-
213
- // https://url.spec.whatwg.org/#authority-state
214
- case constants.STATE_AUTHORITY:
215
- if (c === 0x40) {
216
- if (atSignSeen) buffer = '%40' + buffer
217
-
218
- atSignSeen = true
219
-
220
- for (let i = 0, n = buffer.length; i < n; i++) {
221
- const c = buffer.charCodeAt(i)
222
-
223
- if (c === 0x3a && !passwordTokenSeen) {
224
- passwordTokenSeen = true
225
- continue
226
- }
227
-
228
- const encodedCodePoints = UTF8PercentEncode(buffer[i], userinfoPercentEncodeSet)
229
-
230
- if (passwordTokenSeen) {
231
- url.password += encodedCodePoints
232
- } else {
233
- url.username += encodedCodePoints
234
- }
235
- }
236
-
237
- buffer = ''
238
- } else if (
239
- (c === -1 || c === 0x2f || c === 0x3f || c === 0x23) ||
240
- (isSpecial(url) && c === 0x5c)
241
- ) {
242
- if (atSignSeen && buffer === '') {
243
- throw errors.INVALID_CREDENTIALS()
244
- }
245
-
246
- pointer -= buffer.length + 1
247
- buffer = ''
248
- state = constants.STATE_HOST
249
- } else {
250
- buffer += String.fromCharCode(c)
251
- }
252
- break
253
-
254
- // https://url.spec.whatwg.org/#host-state
255
- // https://url.spec.whatwg.org/#hostname-state
256
- case constants.STATE_HOST:
257
- case constants.STATE_HOSTNAME:
258
- if (stateOverride && url.scheme === 'file') {
259
- pointer--
260
- state = constants.STATE_FILE_HOST
261
- } else if (c === 0x3a && !insideBrackets) {
262
- if (buffer === '') {
263
- throw errors.HOST_MISSING()
264
- }
265
-
266
- if (stateOverride === constants.STATE_HOSTNAME) return
267
-
268
- url.host = parseHost(buffer, !isSpecial(url))
269
-
270
- buffer = ''
271
- state = constants.STATE_PORT
272
- } else if (
273
- (c === -1 || c === 0x2f || c === 0x3f || c === 0x23) ||
274
- (isSpecial(url) && c === 0x5c)
275
- ) {
276
- pointer--
277
-
278
- if (isSpecial(url) && buffer === '') {
279
- throw errors.HOST_MISSING()
280
- }
281
-
282
- if (stateOverride && buffer === '' && (includesCredentials(url) || url.port !== null)) {
283
- return
284
- }
285
-
286
- url.host = parseHost(buffer, !isSpecial(url))
287
-
288
- buffer = ''
289
- state = constants.STATE_PATH_START
290
-
291
- if (stateOverride) return
292
- } else {
293
- if (c === 0x5b) insideBrackets = true
294
- else if (c === 0x5d) insideBrackets = false
295
-
296
- buffer += String.fromCharCode(c)
297
- }
298
- break
299
-
300
- // https://url.spec.whatwg.org/#port-state
301
- case constants.STATE_PORT:
302
- if (infra.isASCIIDigit(c)) {
303
- buffer += String.fromCharCode(c)
304
- } else if (
305
- (c === -1 || c === 0x2f || c === 0x3f || c === 0x23) ||
306
- (isSpecial(url) && c === 0x5c) ||
307
- stateOverride
308
- ) {
309
- if (buffer) {
310
- const port = parseInt(buffer, 10)
311
-
312
- if (port > 2 ** 16 - 1) {
313
- throw errors.PORT_OUT_OF_RANGE()
314
- }
315
-
316
- url.port = port === defaultPort(url.scheme) ? null : port
317
-
318
- buffer = ''
319
- }
320
-
321
- if (stateOverride) return
322
-
323
- state = constants.STATE_PATH_START
324
- pointer--
325
- } else {
326
- throw errors.PORT_INVALID()
327
- }
328
- break
329
-
330
- // https://url.spec.whatwg.org/#file-state
331
- case constants.STATE_FILE:
332
- url.scheme = 'file'
333
- url.host = ''
334
-
335
- if (c === 0x2f || c === 0x5c) {
336
- state = constants.STATE_FILE_SLASH
337
- } else if (base && base.scheme === 'file') {
338
- url.host = base.host
339
- url.path = [...base.path]
340
- url.query = base.query
341
-
342
- if (c === 0x3f) {
343
- url.query = ''
344
- state = constants.STATE_QUERY
345
- } else if (c === 0x23) {
346
- url.fragment = ''
347
- state = constants.STATE_FRAGMENT
348
- } else if (c !== -1) {
349
- url.query = null
350
-
351
- if (!startsWithWindowsDriveLetter(input.substring(pointer))) {
352
- shortenPath(url)
353
- } else {
354
- url.path = []
355
- }
356
-
357
- state = constants.STATE_PATH
358
- pointer--
359
- }
360
- } else {
361
- state = constants.STATE_PATH
362
- pointer--
363
- }
364
- break
365
-
366
- // https://url.spec.whatwg.org/#file-slash-state
367
- case constants.STATE_FILE_SLASH:
368
- if (c === 0x2f || c === 0x5c) {
369
- state = constants.STATE_FILE_HOST
370
- } else {
371
- if (base && base.scheme === 'file') {
372
- url.host = base.host
373
-
374
- if (!startsWithWindowsDriveLetter(input.substring(pointer)) && isNormalizedWindowsDriveLetter(base.path[0])) {
375
- url.path.push(base.path[0])
376
- }
377
- }
378
-
379
- state = constants.STATE_PATH
380
- pointer--
381
- }
382
- break
383
-
384
- // https://url.spec.whatwg.org/#file-host-state
385
- case constants.STATE_FILE_HOST:
386
- if (c === -1 || c === 0x2f || c === 0x5c || c === 0x3f || c === 0x23) {
387
- pointer--
388
-
389
- if (!stateOverride && isWindowsDriveLetter(buffer)) {
390
- state = constants.STATE_PATH
391
- } else if (buffer === '') {
392
- url.host = ''
393
-
394
- if (stateOverride) return
395
-
396
- state = constants.STATE_PATH_START
397
- } else {
398
- let host = parseHost(buffer, !isSpecial(url))
399
- if (host === 'localhost') host = ''
400
-
401
- url.host = host
402
-
403
- if (stateOverride) return
404
-
405
- buffer = ''
406
- state = constants.STATE_PATH_START
407
- }
408
- } else {
409
- buffer += String.fromCharCode(c)
410
- }
411
- break
412
-
413
- // https://url.spec.whatwg.org/#path-start-state
414
- case constants.STATE_PATH_START:
415
- if (isSpecial(url)) {
416
- state = constants.STATE_PATH
417
-
418
- if (c !== 0x2f && c !== 0x5c) pointer--
419
- } else if (!stateOverride && c === 0x3f) {
420
- url.query = ''
421
- state = constants.STATE_QUERY
422
- } else if (!stateOverride && c === 0x23) {
423
- url.fragment = ''
424
- state = constants.STATE_FRAGMENT
425
- } else if (c !== -1) {
426
- state = constants.STATE_PATH
427
-
428
- if (c !== 0x2f) pointer--
429
- } else if (stateOverride && url.host === null) {
430
- url.path.push('')
431
- }
432
- break
433
-
434
- // https://url.spec.whatwg.org/#path-state
435
- case constants.STATE_PATH:
436
- if (
437
- (c === -1 || c === 0x2f) ||
438
- (isSpecial(url) && c === 0x5c) ||
439
- (!stateOverride && (c === 0x3f || c === 0x23))
440
- ) {
441
- if (isDoubleDotPathSegment(buffer)) {
442
- shortenPath(url)
443
-
444
- if (c !== 0x2f && !(isSpecial(url) && c === 0x5c)) {
445
- url.path.push('')
446
- }
447
- } else if (isSingleDotPathSegment(buffer)) {
448
- if (c !== 0x2f && !(isSpecial(url) && c === 0x5c)) {
449
- url.path.push('')
450
- }
451
- } else {
452
- if (url.scheme === 'file' && url.path.length === 0 && isWindowsDriveLetter(buffer)) {
453
- buffer = buffer.substring(0, 1) + ':' + buffer.substring(2)
454
- }
455
-
456
- url.path.push(buffer)
457
- }
458
-
459
- buffer = ''
460
-
461
- if (c === 0x3f) {
462
- url.query = ''
463
- state = constants.STATE_QUERY
464
- } else if (c === 0x23) {
465
- url.fragment = ''
466
- state = constants.STATE_FRAGMENT
467
- }
468
- } else {
469
- buffer += UTF8PercentEncode(String.fromCharCode(c), pathPercentEncodeSet)
470
- }
471
- break
472
-
473
- // https://url.spec.whatwg.org/#cannot-be-a-base-url-path-state
474
- case constants.STATE_OPAQUE_PATH:
475
- if (c === 0x3f) {
476
- url.query = ''
477
- state = constants.STATE_QUERY
478
- } else if (c === 0x23) {
479
- url.fragment = ''
480
- state = constants.STATE_FRAGMENT
481
- } else {
482
- if (c !== -1) {
483
- url.path += UTF8PercentEncode(String.fromCharCode(c), c0ControlPercentEncodeSet)
484
- }
485
- }
486
- break
487
-
488
- // https://url.spec.whatwg.org/#query-state
489
- case constants.STATE_QUERY:
490
- if ((!stateOverride && c === 0x23) || c === -1) {
491
- const percentEncodeSet = isSpecial(url) ? specialQueryPercentEncodeSet : queryPercentEncodeSet
492
-
493
- url.query += UTF8PercentEncode(buffer, percentEncodeSet)
494
- buffer = ''
495
-
496
- if (c === 0x23) {
497
- url.fragment = ''
498
- state = constants.STATE_FRAGMENT
499
- }
500
- } else if (c !== -1) {
501
- buffer += String.fromCharCode(c)
502
- }
503
- break
504
-
505
- // https://url.spec.whatwg.org/#fragment-state
506
- case constants.STATE_FRAGMENT:
507
- if (c !== -1) {
508
- url.fragment += UTF8PercentEncode(String.fromCharCode(c), fragmentPercentEncodeSet)
509
- }
510
- }
511
- }
512
-
513
- return url
514
- }
515
-
516
- // https://url.spec.whatwg.org/#concept-host-parser
517
- function parseHost (input, isOpaque = false) {
518
- if (input.charCodeAt(0) === 0x5b) {
519
- if (input.charCodeAt(input.length - 1) !== 0x5d) throw errors.IPV6_UNCLOSED()
520
-
521
- return parseIPv6(input.substring(1, input.length - 1))
522
- }
523
-
524
- if (isOpaque) return parseOpaqueHost(input)
525
-
526
- const domain = percentDecode(Buffer.from(input, 'utf8'))
527
-
528
- const asciiDomain = domainToASCII(domain.toString('utf8'), false)
529
-
530
- for (const codePoint of asciiDomain) {
531
- if (isForbiddenDomainCodePoint(codePoint.codePointAt(0))) {
532
- throw errors.DOMAIN_INVALID_CODE_POINT()
533
- }
534
- }
535
-
536
- if (endsInANumber(asciiDomain)) return parseIPv4(asciiDomain)
537
-
538
- return asciiDomain
539
- }
540
-
541
- // https://url.spec.whatwg.org/#ends-in-a-number-checker
542
- function endsInANumber (input) {
543
- const parts = input.split('.')
544
-
545
- const last = parts[parts.length - 1]
546
-
547
- if (last === '') {
548
- if (parts.length === 1) return false
549
- parts.pop()
550
- }
551
-
552
- try {
553
- parseIPv4Number(last)
554
-
555
- return true
556
- } catch {
557
- return false
558
- }
559
- }
560
-
561
- // https://url.spec.whatwg.org/#concept-ipv4-parser
562
- function parseIPv4 (input) {
563
- const parts = input.split('.')
564
-
565
- if (parts[parts.length - 1] === '') {
566
- if (parts.length > 1) parts.pop()
567
- }
568
-
569
- if (parts.length > 4) throw errors.IPV4_TOO_MANY_PARTS()
570
-
571
- const numbers = []
572
-
573
- for (const part of parts) {
574
- numbers.push(parseIPv4Number(part))
575
- }
576
-
577
- for (let i = 0, n = numbers.length - 1; i < n; i++) {
578
- if (numbers[i] > 255) {
579
- throw errors.IPV4_OUT_OF_RANGE_PART()
580
- }
581
- }
582
-
583
- if (numbers[numbers.length - 1] > 256 ** (5 - numbers.length)) {
584
- throw errors.IPV4_OUT_OF_RANGE_PART()
585
- }
586
-
587
- let ipv4 = numbers.pop()
588
- let counter = 0
589
-
590
- for (const n of numbers) ipv4 += n * 256 ** (3 - counter++)
591
-
592
- return ipv4
593
- }
594
-
595
- // https://url.spec.whatwg.org/#ipv4-number-parser
596
- function parseIPv4Number (input) {
597
- if (input === '') throw errors.IPV4_NON_NUMERIC_PART()
598
-
599
- input = input.toLowerCase()
600
-
601
- let R = 10
602
-
603
- if (input.length >= 2) {
604
- if (input[0] === '0') {
605
- if (input[1] === 'x') {
606
- input.substring(2)
607
- R = 16
608
- } else {
609
- input.substring(1)
610
- R = 8
611
- }
612
- }
613
- }
614
-
615
- if (input === '') return 0
616
-
617
- const n = parseInt(input, R)
618
-
619
- if (n.toString(R) !== input) throw errors.IPV4_NON_NUMERIC_PART()
620
-
621
- return n
622
- }
623
-
624
- // https://url.spec.whatwg.org/#concept-ipv6-parser
625
- function parseIPv6 (input) {
626
- const address = [0, 0, 0, 0, 0, 0, 0, 0]
627
- let pieceIndex = 0
628
- let compress = null
629
- let pointer = 0
630
-
631
- if (input.charCodeAt(pointer) === 0x3a) {
632
- if (input.charCodeAt(pointer + 1) !== 0x3a) {
633
- throw errors.IPV6_INVALID_COMPRESSION()
634
- }
635
-
636
- pointer += 2
637
- compress = ++pieceIndex
638
- }
639
-
640
- while (pointer < input.length) {
641
- if (pieceIndex === 8) throw errors.IPV6_TOO_MANY_PIECES()
642
-
643
- if (input.charCodeAt(pointer) === 0x3a) {
644
- if (compress !== null) throw errors.IPV6_MULTIPLE_COMPRESSION()
645
-
646
- pointer++
647
- compress = ++pieceIndex
648
- continue
649
- }
650
-
651
- let value = 0
652
- let length = 0
653
-
654
- while (length < 4 && infra.isASCIIHexDigit(input.charCodeAt(pointer))) {
655
- value = value * 0x10 + parseInt(input[pointer], 16)
656
-
657
- pointer++
658
- length++
659
- }
660
-
661
- if (input.charCodeAt(pointer) === 0x2e) {
662
- if (length === 0) throw errors.IPV4_IN_IPV6_INVALID_CODE_POINT()
663
-
664
- pointer -= length
665
-
666
- if (pieceIndex > 6) throw errors.IPV4_IN_IPV6_TOO_MANY_PIECES()
667
-
668
- let numbersSeen = 0
669
-
670
- while (pointer < input.length) {
671
- let ipv4Piece = null
672
-
673
- if (numbersSeen > 0) {
674
- if (input.charCodeAt(pointer) === 0x2e && numbersSeen < 4) {
675
- pointer++
676
- } else {
677
- throw errors.IPV4_IN_IPV6_INVALID_CODE_POINT()
678
- }
679
- }
680
-
681
- if (!infra.isASCIIDigit(input.charCodeAt(pointer))) {
682
- throw errors.IPV4_IN_IPV6_INVALID_CODE_POINT()
683
- }
684
-
685
- while (infra.isASCIIDigit(input.charCodeAt(pointer))) {
686
- const number = parseInt(input[pointer], 10)
687
-
688
- if (ipv4Piece === null) {
689
- ipv4Piece = number
690
- } else if (ipv4Piece === 0) {
691
- throw errors.IPV4_IN_IPV6_INVALID_CODE_POINT()
692
- } else {
693
- ipv4Piece = ipv4Piece * 10 + number
694
- }
695
-
696
- if (ipv4Piece > 255) throw errors.IPV4_IN_IPV6_OUT_OF_RANGE_PART()
697
-
698
- pointer++
699
- }
700
-
701
- address[pieceIndex] = address[pieceIndex] * 0x100 + ipv4Piece
702
-
703
- numbersSeen++
704
-
705
- if (numbersSeen === 2 || numbersSeen === 4) pieceIndex++
706
- }
707
-
708
- if (numbersSeen !== 4) throw errors.IPV4_IN_IPV6_TOO_FEW_PARTS()
709
-
710
- break
711
- }
712
-
713
- if (input.charCodeAt(pointer) === 0x3a) {
714
- pointer++
715
-
716
- if (pointer === input.length) {
717
- throw errors.IPV6_INVALID_CODE_POINT()
718
- }
719
- } else if (pointer !== input.length) {
720
- throw errors.IPV6_INVALID_CODE_POINT()
721
- }
722
-
723
- address[pieceIndex++] = value
724
- }
725
-
726
- if (compress !== null) {
727
- let swaps = pieceIndex - compress
728
-
729
- pieceIndex = 7
730
-
731
- while (pieceIndex !== 0 && swaps > 0) {
732
- [address[pieceIndex], address[compress + swaps - 1]] = [address[compress + swaps - 1], address[pieceIndex]]
733
-
734
- pieceIndex--
735
- swaps--
736
- }
737
- } else if (pieceIndex !== 8) {
738
- throw errors.IPV6_TOO_FEW_PIECES()
739
- }
740
-
741
- return address
742
- }
743
-
744
- // https://url.spec.whatwg.org/#concept-opaque-host-parser
745
- function parseOpaqueHost (input) {
746
- const bytes = Buffer.from(input, 'utf8')
747
-
748
- if (bytes.some(isForbiddenHostCodePoint)) throw errors.HOST_INVALID_CODE_POINT()
749
-
750
- return percentEncodeAfterEncoding(bytes, c0ControlPercentEncodeSet)
751
- }
752
-
753
- // https://url.spec.whatwg.org/#special-scheme
754
- function isSpecialScheme (scheme) {
755
- switch (scheme) {
756
- case 'ftp':
757
- case 'file':
758
- case 'http':
759
- case 'https':
760
- case 'ws':
761
- case 'wss':
762
- return true
763
- default:
764
- return false
765
- }
766
- }
767
-
768
- // https://url.spec.whatwg.org/#default-port
769
- function defaultPort (scheme) {
770
- switch (scheme) {
771
- case 'ftp': return 21
772
- case 'file': return null
773
- case 'http': return 80
774
- case 'https': return 443
775
- case 'ws': return 80
776
- case 'wss': return 443
777
- default: return null
778
- }
779
- }
780
-
781
- // https://url.spec.whatwg.org/#is-special
782
- function isSpecial (url) {
783
- return isSpecialScheme(url.scheme)
784
- }
785
-
786
- // https://url.spec.whatwg.org/#include-credentials
787
- function includesCredentials (url) {
788
- return url.username !== '' && url.password !== ''
789
- }
790
-
791
- // https://url.spec.whatwg.org/#url-opaque-path
792
- function hasOpaquePath (url) {
793
- return typeof url.path === 'string'
794
- }
795
-
796
- // https://url.spec.whatwg.org/#windows-drive-letter
797
- function isWindowsDriveLetter (input) {
798
- return input.length >= 2 && infra.isASCIIAlpha(input.charCodeAt(0)) && (
799
- input.charCodeAt(1) === 0x3a ||
800
- input.charCodeAt(1) === 0x7c
801
- )
802
- }
803
-
804
- // https://url.spec.whatwg.org/#normalized-windows-drive-letter
805
- function isNormalizedWindowsDriveLetter (input) {
806
- return input.length >= 2 && infra.isASCIIAlpha(input.charCodeAt(0)) && input.charCodeAt(1) === 0x3a
807
- }
808
-
809
- // https://url.spec.whatwg.org/#start-with-a-windows-drive-letter
810
- function startsWithWindowsDriveLetter (input) {
811
- return input.length >= 2 && isWindowsDriveLetter(input) && (
812
- input.length === 2 ||
813
- input.charCodeAt(2) === 0x2f ||
814
- input.charCodeAt(2) === 0x5c ||
815
- input.charCodeAt(2) === 0x3f ||
816
- input.charCodeAt(2) === 0x23
817
- )
818
- }
819
-
820
- // https://url.spec.whatwg.org/#shorten-a-urls-path
821
- function shortenPath (url) {
822
- const path = url.path
823
-
824
- if (url.scheme === 'file' && path.length === 1 && isNormalizedWindowsDriveLetter(path[0])) {
825
- return
826
- }
827
-
828
- path.pop()
829
- }
830
-
831
- // https://url.spec.whatwg.org/#single-dot-path-segment
832
- function isSingleDotPathSegment (segment) {
833
- return segment === '.' || decodeURIComponent(segment) === '.'
834
- }
835
-
836
- // https://url.spec.whatwg.org/#double-dot-path-segment
837
- function isDoubleDotPathSegment (segment) {
838
- return segment === '..' || decodeURIComponent(segment) === '..'
839
- }
840
-
841
- // https://url.spec.whatwg.org/#forbidden-host-code-point
842
- function isForbiddenHostCodePoint (c) {
843
- return c === 0x0 || c === 0x9 || c === 0xa || c === 0xd || c === 0x20 || c === 0x23 || c === 0x2f || c === 0x3a || c === 0x3c || c === 0x3e || c === 0x3f || c === 0x40 || c === 0x5b || c === 0x5c || c === 0x5d || c === 0x5e || c === 0x7c
844
- }
845
-
846
- // https://url.spec.whatwg.org/#forbidden-domain-code-point
847
- function isForbiddenDomainCodePoint (c) {
848
- return isForbiddenHostCodePoint(c) || c <= 0x1f || c === 0x25 || c === 0x7f
849
- }
850
-
851
- // https://url.spec.whatwg.org/#concept-domain-to-ascii
852
- function domainToASCII (domain, beStrict) {
853
- const result = tr46.toASCII(domain, {
854
- checkHyphens: false,
855
- checkBidi: true,
856
- checkJoiners: true,
857
- useSTD3ASCIIRules: beStrict,
858
- verifyDNSLength: beStrict
859
- })
860
-
861
- if (result === null || result === '') throw errors.DOMAIN_TO_ASCII()
862
-
863
- return result
864
- }
865
-
866
- // https://url.spec.whatwg.org/#percent-encode
867
- function percentEncode (byte) {
868
- return `%${byte.toString(16).toUpperCase().padStart(2, '0')}`
869
- }
870
-
871
- // https://url.spec.whatwg.org/#string-percent-encode-after-encoding
872
- function percentEncodeAfterEncoding (bytes, percentEncodeSet) {
873
- let output = ''
874
-
875
- for (const byte of bytes) {
876
- if (percentEncodeSet(byte)) {
877
- output += percentEncode(byte)
878
- } else {
879
- output += String.fromCharCode(byte)
880
- }
881
- }
882
-
883
- return output
884
- }
885
-
886
- // https://url.spec.whatwg.org/#percent-decode
887
- function percentDecode (input) {
888
- const output = Buffer.alloc(input.byteLength)
889
- let outputIndex = 0
890
-
891
- for (let i = 0, n = input.byteLength; i < n; i++) {
892
- const byte = input[i]
893
-
894
- if (byte !== 0x25) {
895
- output[outputIndex++] = byte
896
- } else if (byte === 0x25 && (!infra.isASCIIHexDigit(input[i + 1]) || !infra.isASCIIHexDigit(input[i + 2]))) {
897
- output[outputIndex++] = byte
898
- } else {
899
- const bytePoint = parseInt(String.fromCodePoint(input[i + 1], input[i + 2]), 16)
900
- output[outputIndex++] = bytePoint
901
- i += 2
902
- }
903
- }
904
-
905
- return output.subarray(0, outputIndex)
906
- }
907
-
908
- // https://url.spec.whatwg.org/#string-utf-8-percent-encode
909
- function UTF8PercentEncode (input, percentEncodeSet) {
910
- return percentEncodeAfterEncoding(Buffer.from(input, 'utf8'), percentEncodeSet)
911
- }
912
-
913
- // https://url.spec.whatwg.org/#c0-control-percent-encode-set
914
- function c0ControlPercentEncodeSet (c) {
915
- return c <= 0x1f || c > 0x7e
916
- }
917
-
918
- // https://url.spec.whatwg.org/#fragment-percent-encode-set
919
- function fragmentPercentEncodeSet (c) {
920
- return c0ControlPercentEncodeSet(c) || c === 0x20 || c === 0x22 || c === 0x3c || c === 0x3e || c === 0x60
921
- }
922
-
923
- // https://url.spec.whatwg.org/#query-percent-encode-set
924
- function queryPercentEncodeSet (c) {
925
- return c0ControlPercentEncodeSet(c) || c === 0x20 || c === 0x22 || c === 0x23 || c === 0x3c || c === 0x3e
926
- }
927
-
928
- // https://url.spec.whatwg.org/#special-query-percent-encode-set
929
- function specialQueryPercentEncodeSet (c) {
930
- return queryPercentEncodeSet(c) || c === 0x27
931
- }
932
-
933
- // https://url.spec.whatwg.org/#path-percent-encode-set
934
- function pathPercentEncodeSet (c) {
935
- return queryPercentEncodeSet(c) || c === 0x3f || c === 0x60 || c === 0x7b || c === 0x7d
936
- }
937
-
938
- // https://url.spec.whatwg.org/#userinfo-percent-encode-set
939
- function userinfoPercentEncodeSet (c) {
940
- return pathPercentEncodeSet(c) || c === 0x2f || c === 0x3a || c === 0x3b || c === 0x3d || c === 0x40 || c === 0x5b || c === 0x5c || c === 0x5d || c === 0x5e || c === 0x7c
941
- }