@gjsify/url 0.51.1 → 0.53.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.
package/lib/esm/index.js CHANGED
@@ -1 +1,2 @@
1
- import"./_virtual/_rolldown/runtime.js";import e from"@girs/glib-2.0";import{hostOs as t,isWin32 as n,isWindowsPath as r,pathToFileUrlHref as i}from"@gjsify/utils/core";const a=e.UriFlags.HAS_PASSWORD|e.UriFlags.ENCODED|e.UriFlags.SCHEME_NORMALIZE;function platformOrShapeIsWindows(e){return t()===void 0?r(e):n()}const o=new WeakMap;var s=class URLSearchParams{_entries=[];constructor(e){if(e)if(typeof e==`string`){let t=e.startsWith(`?`)?e.slice(1):e;if(t)for(let e of t.split(`&`)){if(e===``)continue;let t=e.indexOf(`=`);t===-1?this._entries.push([decodeComponent(e),``]):this._entries.push([decodeComponent(e.slice(0,t)),decodeComponent(e.slice(t+1))])}}else if(Array.isArray(e))for(let[t,n]of e)this._entries.push([String(t),String(n)]);else if(e instanceof URLSearchParams)this._entries=e._entries.map(([e,t])=>[e,t]);else for(let t of Object.keys(e))this._entries.push([t,String(e[t])])}get(e){for(let[t,n]of this._entries)if(t===e)return n;return null}getAll(e){return this._entries.filter(([t])=>t===e).map(([,e])=>e)}set(e,t){let n=!1;if(this._entries=this._entries.filter(([t])=>t===e?n?!1:(n=!0,!0):!0),n){for(let n=0;n<this._entries.length;n++)if(this._entries[n][0]===e){this._entries[n][1]=t;break}}else this._entries.push([e,t]);o.get(this)?.()}has(e,t){return t===void 0?this._entries.some(([t])=>t===e):this._entries.some(([n,r])=>n===e&&r===t)}delete(e,t){this._entries=t===void 0?this._entries.filter(([t])=>t!==e):this._entries.filter(([n,r])=>!(n===e&&r===t)),o.get(this)?.()}append(e,t){this._entries.push([e,t]),o.get(this)?.()}sort(){this._entries.sort((e,t)=>e[0]<t[0]?-1:+(e[0]>t[0])),o.get(this)?.()}toString(){return this._entries.map(([e,t])=>encodeComponent(e)+`=`+encodeComponent(t)).join(`&`)}forEach(e){for(let[t,n]of this._entries)e(n,t,this)}*entries(){yield*this._entries}*keys(){for(let[e]of this._entries)yield e}*values(){for(let[,e]of this._entries)yield e}[Symbol.iterator](){return this.entries()}get size(){return this._entries.length}};function decodeComponent(e){try{return decodeURIComponent(e.replace(/\+/g,` `))}catch{return e}}function percentEncodeUtf8(e){let t=``;for(let n of new TextEncoder().encode(e))t+=`%${n.toString(16).toUpperCase().padStart(2,`0`)}`;return t}function encodeComponent(e){let t=``;for(let n of e)n===` `?t+=`+`:/^[A-Za-z0-9*\-._]$/.test(n)?t+=n:t+=percentEncodeUtf8(n);return t}const c=new Set([`http:`,`https:`,`ws:`,`wss:`,`ftp:`,`file:`]);function encodeQuery(e,t){let n=``;for(let r of e){let e=r.codePointAt(0);n+=e<=32||e>126||r===`"`||r===`#`||r===`<`||r===`>`||t&&r===`'`?percentEncodeUtf8(r):r}return n}var l=class URL{#e;#t;#n;constructor(t,n){let r=t instanceof URL?t.href:String(t);try{if(n!==void 0){let t=n instanceof URL?n.href:String(n),i=e.Uri.parse(t,a);this.#e=i.parse_relative(r,a)}else this.#e=e.Uri.parse(r,a)}catch{throw TypeError(`Invalid URL: ${r}`)}if(!this.#e)throw TypeError(`Invalid URL: ${r}`);this.#n=this.#e.get_query()??null,this.#t=new s(this.#n||``),o.set(this.#t,()=>{let e=this.#t.toString();this.#n=e===``?null:e})}get protocol(){return this.#e.get_scheme()+`:`}get hostname(){return(this.#e.get_host()||``).toLowerCase()}get port(){let e=this.#e.get_port();if(e===-1)return``;let t=this.#e.get_scheme();return(t===`http`||t===`ws`)&&e===80||(t===`https`||t===`wss`)&&e===443||t===`ftp`&&e===21?``:String(e)}get host(){let e=this.hostname,t=this.port;return t?`${e}:${t}`:e}get pathname(){return this.#e.get_path()||`/`}get search(){return this.#n?`?`+this.#n:``}set search(e){let t=String(e).replace(/[\t\n\r]/g,``);if(t===``){this.#n=null,this.#t._entries=[];return}let n=t.startsWith(`?`)?t.slice(1):t;this.#n=encodeQuery(n,c.has(this.protocol)),this.#t._entries=new s(n)._entries}get hash(){let e=this.#e.get_fragment();return e?`#`+e:``}get origin(){let e=this.protocol;return e===`http:`||e===`https:`||e===`ftp:`?`${e}//${this.host}`:`null`}get username(){return this.#e.get_user()||``}get password(){return this.#e.get_password()||``}get href(){let e=this.protocol,t=this.#e.get_scheme();(t===`http`||t===`https`||t===`ftp`||t===`file`||t===`ws`||t===`wss`||this.hostname)&&(e+=`//`);let n=this.username,r=this.password;n&&(e+=n,r&&(e+=`:`+r),e+=`@`),e+=this.hostname,this.port&&(e+=`:`+this.port);let i=this.pathname;return e+=i,e+=this.#n===null?``:`?${this.#n}`,e+=this.hash,e}get searchParams(){return this.#t}toString(){return this.href}toJSON(){return this.href}static _objectURLPaths=new Map;static _objectURLCounter=0;static createObjectURL(e){let t=e?._tmpPath;if(typeof t==`string`&&t.length>0){let e=`file://${t}`;return URL._objectURLPaths.set(e,t),e}return`file:///dev/null`}static revokeObjectURL(t){let n=URL._objectURLPaths.get(t);n&&(e.unlink(n),URL._objectURLPaths.delete(t))}};function parse(e,t,n){if(typeof e!=`string`)throw TypeError(`The "url" argument must be of type string. Received type `+typeof e);let r={protocol:null,slashes:null,auth:null,host:null,port:null,hostname:null,hash:null,search:null,query:null,pathname:null,path:null,href:e},i=e.trim(),a=i.indexOf(`#`);a!==-1&&(r.hash=i.slice(a),i=i.slice(0,a));let o=i.indexOf(`?`);o!==-1&&(r.search=i.slice(o),r.query=t?Object.fromEntries(new s(i.slice(o+1))):i.slice(o+1),i=i.slice(0,o));let c=/^([a-z][a-z0-9.+-]*:)/i.exec(i);if(c&&(r.protocol=c[1].toLowerCase(),i=i.slice(r.protocol.length)),(n||r.protocol)&&i.startsWith(`//`)&&(r.slashes=!0,i=i.slice(2)),r.slashes||r.protocol&&![`javascript:`,`data:`,`mailto:`].includes(r.protocol)){let e=-1;for(let t=0;t<i.length;t++){let n=i[t];if(n===`/`||n===`\\`){e=t;break}}let t=e===-1?i:i.slice(0,e);i=e===-1?``:i.slice(e);let n=t.lastIndexOf(`@`);n===-1?parseHostPort(t,r):(r.auth=decodeURIComponent(t.slice(0,n)),parseHostPort(t.slice(n+1),r))}return r.pathname=i||(r.slashes?`/`:null),(r.pathname!==null||r.search!==null)&&(r.path=(r.pathname||``)+(r.search||``)),r.href=format(r),r}function parseHostPort(e,t){if(!e)return;let n=e.indexOf(`[`);if(n!==-1){let r=e.indexOf(`]`,n);if(r!==-1){let i=e.slice(r+1);i.startsWith(`:`)&&(t.port=i.slice(1)),t.hostname=e.slice(n,r+1),t.host=t.hostname+(t.port?`:`+t.port:``);return}}let r=e.lastIndexOf(`:`);if(r!==-1){let n=e.slice(r+1);/^\d*$/.test(n)?(t.port=n||null,t.hostname=e.slice(0,r).toLowerCase()):t.hostname=e.toLowerCase()}else t.hostname=e.toLowerCase();t.host=t.hostname+(t.port?`:`+t.port:``)}function format(e){if(typeof e==`string`)return e;if(e instanceof l)return e.href;let t=e,n=``;if(t.protocol&&(n+=t.protocol),(t.slashes||t.protocol&&![`javascript:`,`data:`,`mailto:`].includes(t.protocol||``))&&(n+=`//`),t.auth&&(n+=encodeURIComponent(t.auth)+`@`),t.host?n+=t.host:(t.hostname&&(n+=t.hostname),t.port&&(n+=`:`+t.port)),t.pathname&&(n+=t.pathname),t.search)n+=t.search;else if(t.query&&typeof t.query==`object`){let e=new s(t.query).toString();e&&(n+=`?`+e)}return t.hash&&(n+=t.hash),n}function resolve(e,t){return new l(t,new l(e,`resolve://`)).href.replace(/^resolve:\/\//,``)}function fileURLToPath(e,n){if(typeof e==`string`&&(e=new l(e)),!(e instanceof l))throw TypeError(`The "url" argument must be of type string or URL. Received type `+typeof e);if(e.protocol!==`file:`)throw TypeError(`The URL must be of scheme file`);let r=e.pathname,i=n?.windows??platformOrShapeIsWindows(r.slice(1));for(let e=0;e<r.length;e++){if(r[e]!==`%`)continue;let t=r.codePointAt(e+2)|32,n=r[e+1]===`2`&&t===102,a=r[e+1]===`5`&&t===99;if(i&&(n||a))throw TypeError(`File URL path must not include encoded \\ or / characters`);if(n)throw TypeError(`File URL path must not include encoded / characters`)}if(e.hostname!==``&&e.hostname!==`localhost`){if(!i)throw TypeError(`File URL host must be "localhost" or empty on ${t()??`this platform`}`);return`\\\\${e.hostname}${decodeURIComponent(r).replace(/\//g,`\\`)}`}if(i){let e=decodeURIComponent(r);return/^\/[A-Za-z]:/.test(e)?e.slice(1).replace(/\//g,`\\`):e.replace(/\//g,`\\`)}return decodeURIComponent(r)}function pathToFileURL(t,n){let a=n?.windows??platformOrShapeIsWindows(t),o=t;return a&&r(t)||t.startsWith(`/`)||(typeof globalThis.process?.cwd==`function`?o=globalThis.process.cwd()+`/`+t:e?.get_current_dir&&(o=e.get_current_dir()+`/`+t)),new l(i(o,{windows:a}))}function domainToASCII(e){try{return new l(`http://${e}`).hostname}catch{return``}}function domainToUnicode(e){try{return new l(`http://${e}`).hostname}catch{return``}}var u={URL:l,URLSearchParams:s,parse,format,resolve,fileURLToPath,pathToFileURL,domainToASCII,domainToUnicode};export{l as URL,s as URLSearchParams,u as default,domainToASCII,domainToUnicode,fileURLToPath,format,parse,pathToFileURL,resolve};
1
+ import"./_virtual/_rolldown/runtime.js";import e from"@girs/glib-2.0";import{encodePathForFileUrl as t,hostOs as n,isWin32 as r,isWindowsPath as i,pathToFileUrlHref as a}from"@gjsify/utils/core";import{posix as o,sep as s,win32 as c}from"node:path";const l=e.UriFlags.HAS_PASSWORD|e.UriFlags.ENCODED|e.UriFlags.SCHEME_NORMALIZE;function platformOrShapeIsWindows(e){return n()===void 0?i(e):r()}const u=new WeakMap;var d=class URLSearchParams{_entries=[];constructor(e){if(e)if(typeof e==`string`)this._entries=parseFormUrlencoded(e.startsWith(`?`)?e.slice(1):e);else if(Array.isArray(e))for(let[t,n]of e)this._entries.push([String(t),String(n)]);else if(e instanceof URLSearchParams)this._entries=e._entries.map(([e,t])=>[e,t]);else for(let t of Object.keys(e))this._entries.push([t,String(e[t])])}get(e){for(let[t,n]of this._entries)if(t===e)return n;return null}getAll(e){return this._entries.filter(([t])=>t===e).map(([,e])=>e)}set(e,t){let n=!1;if(this._entries=this._entries.filter(([t])=>t===e?n?!1:(n=!0,!0):!0),n){for(let n=0;n<this._entries.length;n++)if(this._entries[n][0]===e){this._entries[n][1]=t;break}}else this._entries.push([e,t]);u.get(this)?.()}has(e,t){return t===void 0?this._entries.some(([t])=>t===e):this._entries.some(([n,r])=>n===e&&r===t)}delete(e,t){this._entries=t===void 0?this._entries.filter(([t])=>t!==e):this._entries.filter(([n,r])=>!(n===e&&r===t)),u.get(this)?.()}append(e,t){this._entries.push([e,t]),u.get(this)?.()}sort(){this._entries.sort((e,t)=>e[0]<t[0]?-1:+(e[0]>t[0])),u.get(this)?.()}toString(){return this._entries.map(([e,t])=>encodeComponent(e)+`=`+encodeComponent(t)).join(`&`)}forEach(e){for(let[t,n]of this._entries)e(n,t,this)}*entries(){yield*this._entries}*keys(){for(let[e]of this._entries)yield e}*values(){for(let[,e]of this._entries)yield e}[Symbol.iterator](){return this.entries()}get size(){return this._entries.length}};function parseFormUrlencoded(e){let t=[];if(!e)return t;for(let n of e.split(`&`)){if(n===``)continue;let e=n.indexOf(`=`);e===-1?t.push([decodeComponent(n),``]):t.push([decodeComponent(n.slice(0,e)),decodeComponent(n.slice(e+1))])}return t}function decodeComponent(e){try{return decodeURIComponent(e.replace(/\+/g,` `))}catch{return e}}function percentEncodeUtf8(e){let t=``;for(let n of new TextEncoder().encode(e))t+=`%${n.toString(16).toUpperCase().padStart(2,`0`)}`;return t}function encodeComponent(e){let t=``;for(let n of e)n===` `?t+=`+`:/^[A-Za-z0-9*\-._]$/.test(n)?t+=n:t+=percentEncodeUtf8(n);return t}const f=new Map([[`ftp`,21],[`file`,null],[`http`,80],[`https`,443],[`ws`,80],[`wss`,443]]);function isSpecialScheme(e){return f.has(e)}function defaultPort(e){return f.get(e)??null}const p='"#/:;<=>?@[\\]^`{|}';function percentEncode(e,t){let n=``;for(let r of e){let e=r.codePointAt(0);n+=e<=32||e>126||t.includes(r)?percentEncodeUtf8(r):r}return n}function encodeQuery(e,t){return percentEncode(e,t?`"#<>'`:`"#<>`)}const m=/[\t\n\r]/g;function isSchemeChar(e){return e>=`a`&&e<=`z`||e>=`A`&&e<=`Z`||e>=`0`&&e<=`9`||e===`+`||e===`-`||e===`.`}function isAsciiDigit(e){return e!==void 0&&e>=`0`&&e<=`9`}function isHexDigit(e){return e!==void 0&&/^[0-9A-Fa-f]$/.test(e)}function digitPrefix(e){let t=``;for(let n of e){if(!isAsciiDigit(n))break;t+=n}return t}const h=new Set([`\0`,` `,`
2
+ `,`\r`,` `,`#`,`/`,`:`,`<`,`>`,`?`,`@`,`[`,`\\`,`]`,`^`,`|`]);function hasForbiddenDomainCodePoint(e){for(let t of e){let e=t.codePointAt(0);if(e<=31||e===127||t===`%`||h.has(t))return!0}return!1}function parseIPv6(e){let t=[0,0,0,0,0,0,0,0],n=0,r=null,i=0,at=()=>e[i];if(at()===`:`){if(e[i+1]!==`:`)return;i+=2,n++,r=n}for(;i<e.length;){if(n===8)return;if(at()===`:`){if(r!==null)return;i++,n++,r=n;continue}let a=0,o=0;for(;o<4&&isHexDigit(at());)a=a*16+Number.parseInt(at(),16),i++,o++;if(at()===`.`){if(o===0||(i-=o,n>6))return;let r=0;for(;i<e.length;){let e=null;if(r>0)if(at()===`.`&&r<4)i++;else return;if(!isAsciiDigit(at()))return;for(;isAsciiDigit(at());){let t=Number(at());if(e===null)e=t;else if(e===0)return;else e=e*10+t;if(e>255)return;i++}t[n]=t[n]*256+e,r++,(r===2||r===4)&&n++}if(r!==4)return;break}if(at()===`:`){if(i++,i>=e.length)return}else if(i<e.length)return;t[n]=a,n++}if(r!==null){let e=n-r;for(n=7;n!==0&&e>0;){let i=t[r+e-1];t[r+e-1]=t[n],t[n]=i,n--,e--}}else if(n!==8)return;return serializeIPv6(t)}function serializeIPv6(e){let t=null,n=1,r=-1,i=0;for(let a=0;a<8;a++){if(e[a]!==0){r=-1,i=0;continue}r===-1&&(r=a),i++,i>n&&(n=i,t=r)}let a=``,o=!1;for(let n=0;n<8;n++)if(!(o&&e[n]===0)){if(o=!1,t===n){a+=n===0?`::`:`:`,o=!0;continue}a+=e[n].toString(16),n!==7&&(a+=`:`)}return a}function parseHost(e,t){if(e.startsWith(`[`)){if(!e.endsWith(`]`))return;let t=parseIPv6(e.slice(1,-1));return t===void 0?void 0:`[${t}]`}if(t){for(let t of e)if(h.has(t))return;return percentEncode(e,``)}if(!hasForbiddenDomainCodePoint(e))return e.toLowerCase()}function parseHostSetterValue(e,t,n,r,i){let a=e.replace(m,``),o=isSpecialScheme(t);if(t===`file`){let e=a.length;for(let t=0;t<a.length;t++){let n=a[t];if(n===`/`||n===`\\`||n===`?`||n===`#`){e=t;break}}let t=a.slice(0,e);if(t===``)return{host:``};let n=parseHost(t,!1);return n===void 0?void 0:{host:n===`localhost`?``:n}}let s=!1,c=``;for(let e=0;e<a.length;e++){let n=a[e];if(n===`:`&&!s){if(c===``||i)return;let n=parseHost(c,!o);if(n===void 0)return;let r=digitPrefix(a.slice(e+1));if(r===``)return{host:n};let s=Number(r);return s>65535?{host:n}:{host:n,port:s===defaultPort(t)?null:s}}if(n===`/`||n===`?`||n===`#`||o&&n===`\\`)break;n===`[`?s=!0:n===`]`&&(s=!1),c+=n}if(c===``&&(o||n||r))return;let l=parseHost(c,!o);return l===void 0?void 0:{host:l}}function isDoubleDotSegment(e){let t=e.toLowerCase();return t===`..`||t===`.%2e`||t===`%2e.`||t===`%2e%2e`}function isSingleDotSegment(e){let t=e.toLowerCase();return t===`.`||t===`%2e`}function parsePathSetterValue(e,t,n){let r=e.replace(m,``);if(t&&(r=r.replace(/\\/g,`/`)),r===``)return t||n?`/`:``;let i=[],a=(r.startsWith(`/`)?r.slice(1):r).split(`/`);for(let e=0;e<a.length;e++){let t=a[e],n=e===a.length-1;isDoubleDotSegment(t)?(i.pop(),n&&i.push(``)):isSingleDotSegment(t)?n&&i.push(``):i.push(percentEncode(t,'"#<>?^`{}'))}return`/`+i.join(`/`)}function bracketIPv6Host(e){return e.includes(`:`)&&!e.startsWith(`[`)?`[${e}]`:e}var g=class URL{#e;#t;#n;#r;#i;#a;#o;#s;#c;#l;constructor(t,n){let r=t instanceof URL?t.href:String(t),i;try{if(n!==void 0){let t=n instanceof URL?n.href:String(n);i=e.Uri.parse(t,l).parse_relative(r,l)}else i=e.Uri.parse(r,l)}catch{throw TypeError(`Invalid URL: ${r}`)}if(!i)throw TypeError(`Invalid URL: ${r}`);this.#e=i.get_scheme();let a=isSpecialScheme(this.#e);this.#t=i.get_user()??``,this.#n=i.get_password()??``;let o=i.get_host(),s=o===null?null:bracketIPv6Host(o.toLowerCase());this.#r=s===null?a?``:null:this.#e===`file`&&s===`localhost`?``:s;let c=i.get_port();this.#i=c===-1||c===defaultPort(this.#e)?null:c,this.#a=i.get_path()??``,a&&this.#a===``&&(this.#a=`/`),this.#o=this.#r===null&&!this.#a.startsWith(`/`),this.#r===null&&!this.#o&&this.#a.startsWith(`/.//`)&&(this.#a=this.#a.slice(2)),this.#s=i.get_fragment()??null,this.#l=i.get_query()??null,this.#c=new d,this.#c._entries=parseFormUrlencoded(this.#l??``),u.set(this.#c,()=>{let e=this.#c.toString();this.#l=e===``?null:e})}get protocol(){return this.#e+`:`}set protocol(e){let t=String(e).replace(m,``)+`:`;if(!/^[A-Za-z]/.test(t))return;let n=``;for(let e of t){if(e===`:`)break;if(!isSchemeChar(e))return;n+=e.toLowerCase()}isSpecialScheme(this.#e)===isSpecialScheme(n)&&(n===`file`&&(this.#t!==``||this.#n!==``||this.#i!==null)||this.#e===`file`&&(this.#r===null||this.#r===``)||(this.#e=n,this.#i!==null&&this.#i===defaultPort(n)&&(this.#i=null)))}get hostname(){return this.#r??``}set hostname(e){if(this.#o)return;let t=parseHostSetterValue(String(e),this.#e,this.#t!==``||this.#n!==``,this.#i!==null,!0);t!==void 0&&(this.#r=t.host)}get port(){return this.#i===null?``:String(this.#i)}set port(e){if(this.#u())return;let t=String(e);if(t===``){this.#i=null;return}let n=digitPrefix(t.replace(m,``));if(n===``)return;let r=Number(n);r>65535||(this.#i=r===defaultPort(this.#e)?null:r)}get host(){let e=this.hostname,t=this.port;return t?`${e}:${t}`:e}set host(e){if(this.#o)return;let t=parseHostSetterValue(String(e),this.#e,this.#t!==``||this.#n!==``,this.#i!==null,!1);t!==void 0&&(this.#r=t.host,t.port!==void 0&&(this.#i=t.port))}get pathname(){return this.#a}set pathname(e){this.#o||(this.#a=parsePathSetterValue(String(e),isSpecialScheme(this.#e),this.#r===null))}get search(){return this.#l?`?`+this.#l:``}set search(e){let t=String(e);if(t===``){this.#l=null,this.#c._entries=[];return}let n=(t.startsWith(`?`)?t.slice(1):t).replace(m,``);this.#l=encodeQuery(n,isSpecialScheme(this.#e)),this.#c._entries=parseFormUrlencoded(n)}get hash(){return this.#s?`#`+this.#s:``}set hash(e){let t=String(e);if(t===``){this.#s=null;return}let n=(t.startsWith(`#`)?t.slice(1):t).replace(m,``);this.#s=percentEncode(n,'"<>`')}get origin(){return isSpecialScheme(this.#e)&&this.#e!==`file`?`${this.protocol}//${this.host}`:`null`}get username(){return this.#t}set username(e){this.#u()||(this.#t=percentEncode(String(e),p))}get password(){return this.#n}set password(e){this.#u()||(this.#n=percentEncode(String(e),p))}#u(){return this.#r===null||this.#r===``||this.#e===`file`}get href(){let e=this.#e+`:`;return this.#r===null?!this.#o&&this.#a.startsWith(`//`)&&(e+=`/.`):(e+=`//`,(this.#t!==``||this.#n!==``)&&(e+=this.#t,this.#n!==``&&(e+=`:`+this.#n),e+=`@`),e+=this.#r,this.#i!==null&&(e+=`:`+this.#i)),e+=this.#a,e+=this.#l===null?``:`?${this.#l}`,e+=this.#s===null?``:`#${this.#s}`,e}set href(e){let t=new URL(String(e));this.#e=t.#e,this.#t=t.#t,this.#n=t.#n,this.#r=t.#r,this.#i=t.#i,this.#a=t.#a,this.#o=t.#o,this.#l=t.#l,this.#s=t.#s,this.#c._entries=parseFormUrlencoded(this.#l??``)}get searchParams(){return this.#c}toString(){return this.href}toJSON(){return this.href}static _objectURLPaths=new Map;static _objectURLCounter=0;static createObjectURL(e){let t=e?._tmpPath;if(typeof t==`string`&&t.length>0){let e=`file://${t}`;return URL._objectURLPaths.set(e,t),e}return`file:///dev/null`}static revokeObjectURL(t){let n=URL._objectURLPaths.get(t);n&&(e.unlink(n),URL._objectURLPaths.delete(t))}};function parse(e,t,n){if(typeof e!=`string`)throw TypeError(`The "url" argument must be of type string. Received type `+typeof e);let r={protocol:null,slashes:null,auth:null,host:null,port:null,hostname:null,hash:null,search:null,query:null,pathname:null,path:null,href:e},i=e.trim(),a=i.indexOf(`#`);a!==-1&&(r.hash=i.slice(a),i=i.slice(0,a));let o=i.indexOf(`?`);o!==-1&&(r.search=i.slice(o),r.query=t?Object.fromEntries(new d(i.slice(o+1))):i.slice(o+1),i=i.slice(0,o));let s=/^([a-z][a-z0-9.+-]*:)/i.exec(i);if(s&&(r.protocol=s[1].toLowerCase(),i=i.slice(r.protocol.length)),(n||r.protocol)&&i.startsWith(`//`)&&(r.slashes=!0,i=i.slice(2)),r.slashes||r.protocol&&![`javascript:`,`data:`,`mailto:`].includes(r.protocol)){let e=-1;for(let t=0;t<i.length;t++){let n=i[t];if(n===`/`||n===`\\`){e=t;break}}let t=e===-1?i:i.slice(0,e);i=e===-1?``:i.slice(e);let n=t.lastIndexOf(`@`);n===-1?parseHostPort(t,r):(r.auth=decodeURIComponent(t.slice(0,n)),parseHostPort(t.slice(n+1),r))}return r.pathname=i||(r.slashes?`/`:null),(r.pathname!==null||r.search!==null)&&(r.path=(r.pathname||``)+(r.search||``)),r.href=format(r),r}function parseHostPort(e,t){if(!e)return;let n=e.indexOf(`[`);if(n!==-1){let r=e.indexOf(`]`,n);if(r!==-1){let i=e.slice(r+1);i.startsWith(`:`)&&(t.port=i.slice(1)),t.hostname=e.slice(n,r+1),t.host=t.hostname+(t.port?`:`+t.port:``);return}}let r=e.lastIndexOf(`:`);if(r!==-1){let n=e.slice(r+1);/^\d*$/.test(n)?(t.port=n||null,t.hostname=e.slice(0,r).toLowerCase()):t.hostname=e.toLowerCase()}else t.hostname=e.toLowerCase();t.host=t.hostname+(t.port?`:`+t.port:``)}function format(e){if(typeof e==`string`)return e;if(e instanceof g)return e.href;let t=e,n=``;if(t.protocol&&(n+=t.protocol),(t.slashes||t.protocol&&![`javascript:`,`data:`,`mailto:`].includes(t.protocol||``))&&(n+=`//`),t.auth&&(n+=encodeURIComponent(t.auth)+`@`),t.host?n+=t.host:(t.hostname&&(n+=t.hostname),t.port&&(n+=`:`+t.port)),t.pathname&&(n+=t.pathname),t.search)n+=t.search;else if(t.query&&typeof t.query==`object`){let e=new d(t.query).toString();e&&(n+=`?`+e)}return t.hash&&(n+=t.hash),n}function resolve(e,t){return new g(t,new g(e,`resolve://`)).href.replace(/^resolve:\/\//,``)}function fileURLToPath(e,t){if(typeof e==`string`&&(e=new g(e)),!(e instanceof g))throw TypeError(`The "url" argument must be of type string or URL. Received type `+typeof e);if(e.protocol!==`file:`)throw TypeError(`The URL must be of scheme file`);let r=e.pathname,i=t?.windows??platformOrShapeIsWindows(r.slice(1));for(let e=0;e<r.length;e++){if(r[e]!==`%`)continue;let t=r.codePointAt(e+2)|32,n=r[e+1]===`2`&&t===102,a=r[e+1]===`5`&&t===99;if(i&&(n||a))throw TypeError(`File URL path must not include encoded \\ or / characters`);if(n)throw TypeError(`File URL path must not include encoded / characters`)}if(e.hostname!==``&&e.hostname!==`localhost`){if(!i)throw TypeError(`File URL host must be "localhost" or empty on ${n()??`this platform`}`);return`\\\\${e.hostname}${decodeURIComponent(r).replace(/\//g,`\\`)}`}if(i){let e=decodeURIComponent(r);return/^\/[A-Za-z]:/.test(e)?e.slice(1).replace(/\//g,`\\`):e.replace(/\//g,`\\`)}return decodeURIComponent(r)}function pathToFileURL(e,t){let n=t?.windows??platformOrShapeIsWindows(e),r=n&&e.startsWith(`\\\\`)?e:(n?c:o).resolve(currentDir(),e);if(n&&r.startsWith(`\\\\`))return uncPathToFileURL(r);let i=e.charCodeAt(e.length-1);return(i===47||n&&i===92)&&r[r.length-1]!==s&&(r+=`/`),new g(a(r,{windows:n}))}function currentDir(){return typeof globalThis.process?.cwd==`function`?globalThis.process.cwd():e.get_current_dir()}function uncPathToFileURL(e){let n=e.startsWith(`\\\\?\\UNC\\`)?8:2,r=e.indexOf(`\\`,n);if(r===-1)throw invalidPathValue(e,`Missing UNC resource path`);if(r===2)throw invalidPathValue(e,`Empty UNC servername`);let i=e.slice(n,r);return new g(`file://${i===`?`?``:i}${t(e.slice(r).replace(/\\/g,`/`))}`)}function invalidPathValue(e,t){let n=TypeError(`The argument 'path' ${t}. Received '${e}'`);return n.code=`ERR_INVALID_ARG_VALUE`,n}function domainToASCII(e){try{return new g(`http://${e}`).hostname}catch{return``}}function domainToUnicode(e){try{return new g(`http://${e}`).hostname}catch{return``}}var _={URL:g,URLSearchParams:d,parse,format,resolve,fileURLToPath,pathToFileURL,domainToASCII,domainToUnicode};export{g as URL,d as URLSearchParams,_ as default,domainToASCII,domainToUnicode,fileURLToPath,format,parse,pathToFileURL,resolve};
@@ -21,14 +21,54 @@ export declare class URLSearchParams {
21
21
  [Symbol.iterator](): IterableIterator<[string, string]>;
22
22
  get size(): number;
23
23
  }
24
+ /**
25
+ * The WHATWG URL record: the eight components a URL is made of, held separately.
26
+ *
27
+ * `GLib.Uri` is IMMUTABLE, so it can parse a URL but cannot be one that changes. The query was
28
+ * already broken out of it for that reason (#1245); every other component still delegated to the
29
+ * parsed object, which is why nine of the ten setters could not exist. This holds all eight
30
+ * instead, and `GLib.Uri` is used once, in the constructor, to fill them.
31
+ *
32
+ * The alternative — rebuild the href on every assignment and re-parse it through `GLib.Uri` — was
33
+ * measured and rejected. GLib's parser normalises percent-encoding (`%c3%89` → `%C3%89`, `%2e` →
34
+ * `.`), and the spec requires the opposite: "bytes already percent-encoded are left as-is"
35
+ * (`refs/wpt/url/resources/setters_tests.json`). A re-parse therefore rewrites components nobody
36
+ * assigned to, and `u.username = '%c3%89té'` comes back as `%C3%89t%C3%A9` rather than the
37
+ * `%c3%89t%C3%A9` the spec asks for.
38
+ */
24
39
  export declare class URL {
25
40
  #private;
26
41
  constructor(url: string | URL, base?: string | URL);
27
42
  get protocol(): string;
43
+ /**
44
+ * Replace the scheme — but only where the spec allows it, and never by throwing.
45
+ *
46
+ * Three refusals, all silent, all real: a scheme may not cross the special/non-special
47
+ * boundary (`http:` → `b:` would leave a special URL with a host nothing would validate), a
48
+ * URL with credentials or a port may not become `file:` (which can have neither), and a
49
+ * `file:` URL with no host may not become anything else. An invalid scheme is IGNORED rather
50
+ * than reported, so a consumer feeding user input in cannot be made to throw.
51
+ */
52
+ set protocol(value: string);
28
53
  get hostname(): string;
54
+ /** Unlike {@link host}, a `:` in the value invalidates the whole assignment. */
55
+ set hostname(value: string);
29
56
  get port(): string;
57
+ /**
58
+ * A port is the ASCII-digit PREFIX of the value — `'8080stuff'` is 8080, not an error — and a
59
+ * value equal to the scheme's default serialises away, so `https://x/` and `https://x:443/`
60
+ * stay the same URL.
61
+ */
62
+ set port(value: string);
30
63
  get host(): string;
64
+ /** Carries an optional port after a `:`; a value without one leaves the port untouched. */
65
+ set host(value: string);
31
66
  get pathname(): string;
67
+ /**
68
+ * Replace the path — ignored outright on a URL with an opaque path, where there is no path
69
+ * list to replace.
70
+ */
71
+ set pathname(value: string);
32
72
  get search(): string;
33
73
  /**
34
74
  * Replace the whole query.
@@ -44,10 +84,32 @@ export declare class URL {
44
84
  */
45
85
  set search(value: string);
46
86
  get hash(): string;
87
+ /**
88
+ * Three states, as with {@link search}: no fragment, the empty fragment (which still
89
+ * serialises as a bare `#`), and a fragment with content. Only ONE leading `#` comes off, so
90
+ * `'##nav'` is the fragment `#nav`.
91
+ */
92
+ set hash(value: string);
93
+ /**
94
+ * Every SPECIAL scheme but `file:` has a tuple origin — `ws:` and `wss:` included, and they
95
+ * were answering `'null'` because this list was written out by hand instead of asking the one
96
+ * special-scheme table. A WebSocket URL's origin is what a server checks a handshake against,
97
+ * so `'null'` there is not a harmless approximation.
98
+ */
47
99
  get origin(): string;
48
100
  get username(): string;
101
+ set username(value: string);
49
102
  get password(): string;
103
+ set password(value: string);
50
104
  get href(): string;
105
+ /**
106
+ * Re-parse the whole URL — the ONE setter that throws, because there is no component left to
107
+ * fall back on when the value is not a URL at all.
108
+ *
109
+ * The existing `searchParams` is refilled rather than replaced, for the same reason as in
110
+ * {@link search}: the spec makes its identity stable across the assignment.
111
+ */
112
+ set href(value: string);
51
113
  get searchParams(): URLSearchParams;
52
114
  toString(): string;
53
115
  toJSON(): string;
@@ -93,9 +155,10 @@ export declare function fileURLToPath(url: string | URL, options?: {
93
155
  * own escape hatch (`refs/node/lib/internal/url.js`), and how the win32 behaviour is checked
94
156
  * from the Linux runner CI actually has (#1143).
95
157
  *
96
- * Not yet at Node parity: Node runs `path.win32.resolve()` first, so a RELATIVE path gets the
97
- * current drive. Here a relative path is still joined to the CWD with `/`. Recorded in
98
- * `status/open-todos.md` rather than half-done.
158
+ * A path is RESOLVED first, as Node does, by the flavour it is read in: on win32 a relative
159
+ * `app\dist` picks up the current DRIVE along with the directory, and a drive-relative `D:x`
160
+ * lands on `D:`. Joining it to the cwd with `/` — what this did before — named a path under
161
+ * the cwd for both.
99
162
  */
100
163
  export declare function pathToFileURL(filepath: string, options?: {
101
164
  windows?: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gjsify/url",
3
- "version": "0.51.1",
3
+ "version": "0.53.0",
4
4
  "description": "Node.js url module for Gjs",
5
5
  "type": "module",
6
6
  "module": "lib/esm/index.js",
@@ -39,12 +39,13 @@
39
39
  "fs"
40
40
  ],
41
41
  "dependencies": {
42
- "@girs/glib-2.0": "5.0.0",
43
- "@gjsify/utils": "^0.51.1"
42
+ "@girs/glib-2.0": "5.4.0",
43
+ "@gjsify/path": "^0.53.0",
44
+ "@gjsify/utils": "^0.53.0"
44
45
  },
45
46
  "devDependencies": {
46
- "@gjsify/cli": "^0.51.1",
47
- "@gjsify/unit": "^0.51.1",
47
+ "@gjsify/cli": "^0.53.0",
48
+ "@gjsify/unit": "^0.53.0",
48
49
  "@types/node": "^25.9.2",
49
50
  "typescript": "^6.0.3"
50
51
  },