马宇豪
2024-07-16 f591c27b57e2418c9495bc02ae8cfff84d35bc18
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/*
    MIT License http://www.opensource.org/licenses/mit-license.php
    Author Ivan Kopeykin @vankop
*/
 
"use strict";
 
/** @typedef {import("./fs").InputFileSystem} InputFileSystem */
/** @typedef {(error: Error|null, result?: Buffer) => void} ErrorFirstCallback */
 
const backSlashCharCode = "\\".charCodeAt(0);
const slashCharCode = "/".charCodeAt(0);
const aLowerCaseCharCode = "a".charCodeAt(0);
const zLowerCaseCharCode = "z".charCodeAt(0);
const aUpperCaseCharCode = "A".charCodeAt(0);
const zUpperCaseCharCode = "Z".charCodeAt(0);
const _0CharCode = "0".charCodeAt(0);
const _9CharCode = "9".charCodeAt(0);
const plusCharCode = "+".charCodeAt(0);
const hyphenCharCode = "-".charCodeAt(0);
const colonCharCode = ":".charCodeAt(0);
const hashCharCode = "#".charCodeAt(0);
const queryCharCode = "?".charCodeAt(0);
/**
 * Get scheme if specifier is an absolute URL specifier
 * e.g. Absolute specifiers like 'file:///user/webpack/index.js'
 * https://tools.ietf.org/html/rfc3986#section-3.1
 * @param {string} specifier specifier
 * @returns {string|undefined} scheme if absolute URL specifier provided
 */
function getScheme(specifier) {
    const start = specifier.charCodeAt(0);
 
    // First char maybe only a letter
    if (
        (start < aLowerCaseCharCode || start > zLowerCaseCharCode) &&
        (start < aUpperCaseCharCode || start > zUpperCaseCharCode)
    ) {
        return undefined;
    }
 
    let i = 1;
    let ch = specifier.charCodeAt(i);
 
    while (
        (ch >= aLowerCaseCharCode && ch <= zLowerCaseCharCode) ||
        (ch >= aUpperCaseCharCode && ch <= zUpperCaseCharCode) ||
        (ch >= _0CharCode && ch <= _9CharCode) ||
        ch === plusCharCode ||
        ch === hyphenCharCode
    ) {
        if (++i === specifier.length) return undefined;
        ch = specifier.charCodeAt(i);
    }
 
    // Scheme must end with colon
    if (ch !== colonCharCode) return undefined;
 
    // Check for Windows absolute path
    // https://url.spec.whatwg.org/#url-miscellaneous
    if (i === 1) {
        const nextChar = i + 1 < specifier.length ? specifier.charCodeAt(i + 1) : 0;
        if (
            nextChar === 0 ||
            nextChar === backSlashCharCode ||
            nextChar === slashCharCode ||
            nextChar === hashCharCode ||
            nextChar === queryCharCode
        ) {
            return undefined;
        }
    }
 
    return specifier.slice(0, i).toLowerCase();
}
 
/**
 * @param {string} specifier specifier
 * @returns {string|null} protocol if absolute URL specifier provided
 */
function getProtocol(specifier) {
    const scheme = getScheme(specifier);
    return scheme === undefined ? undefined : scheme + ":";
}
 
exports.getScheme = getScheme;
exports.getProtocol = getProtocol;