Skip to content

Commit

Permalink
fix: Finish implementing URL accessors like host, hostname, username,…
Browse files Browse the repository at this point in the history
… password

facebook#45030
  • Loading branch information
krishpranav committed Jan 6, 2025
1 parent 7a85b91 commit 0b586a0
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 27 deletions.
46 changes: 19 additions & 27 deletions packages/react-native/Libraries/Blob/URL.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
*/

import type Blob from './Blob';

import NativeBlobModule from './NativeBlobModule';

let BLOB_URL_PREFIX = null;
Expand All @@ -19,8 +18,6 @@ if (
typeof NativeBlobModule.getConstants().BLOB_URI_SCHEME === 'string'
) {
const constants = NativeBlobModule.getConstants();
// $FlowFixMe[incompatible-type] asserted above
// $FlowFixMe[unsafe-addition]
BLOB_URL_PREFIX = constants.BLOB_URI_SCHEME + ':';
if (typeof constants.BLOB_URI_HOST === 'string') {
BLOB_URL_PREFIX += `//${constants.BLOB_URI_HOST}/`;
Expand Down Expand Up @@ -51,19 +48,16 @@ if (
* </resources>
* ```
*/

export {URLSearchParams} from './URLSearchParams';
export { URLSearchParams } from './URLSearchParams';

function validateBaseUrl(url: string) {
// from this MIT-licensed gist: https://gist.github.com/dperini/729294
return /^(?:(?:(?:https?|ftp):)?\/\/)(?:(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z0-9\u00a1-\uffff][a-z0-9\u00a1-\uffff_-]{0,62})?[a-z0-9\u00a1-\uffff]\.)*(?:[a-z\u00a1-\uffff]{2,}\.?))(?::\d{2,5})?(?:[/?#]\S*)?$/.test(
url,
);
return /^(?:(?:(?:https?|ftp):)?\/\/)(?:(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z0-9\u00a1-\uffff][a-z0-9\u00a1-\uffff_-]{0,62})?[a-z0-9\u00a1-\uffff]\.)*(?:[a-z\u00a1-\uffff]{2,}\.?))(?::\d{2,5})?(?:[/?#]\S*)?$/.test(url);
}

export class URL {
_url: string;
_searchParamsInstance: ?URLSearchParams = null;
_parsedUrl: URL;

static createObjectURL(blob: Blob): string {
if (BLOB_URL_PREFIX === null) {
Expand All @@ -76,7 +70,6 @@ export class URL {
// Do nothing.
}

// $FlowFixMe[missing-local-annot]
constructor(url: string, base: string | URL) {
let baseUrl = null;
if (!base || validateBaseUrl(url)) {
Expand Down Expand Up @@ -104,51 +97,54 @@ export class URL {
}
this._url = `${baseUrl}${url}`;
}

// Parsing the URL to use for accessors
this._parsedUrl = new globalThis.URL(this._url);
}

get hash(): string {
throw new Error('URL.hash is not implemented');
return this._parsedUrl.hash;
}

get host(): string {
throw new Error('URL.host is not implemented');
return this._parsedUrl.host;
}

get hostname(): string {
throw new Error('URL.hostname is not implemented');
return this._parsedUrl.hostname;
}

get href(): string {
return this.toString();
}

get origin(): string {
throw new Error('URL.origin is not implemented');
return this._parsedUrl.origin;
}

get password(): string {
throw new Error('URL.password is not implemented');
return this._parsedUrl.password;
}

get pathname(): string {
throw new Error('URL.pathname not implemented');
return this._parsedUrl.pathname;
}

get port(): string {
throw new Error('URL.port is not implemented');
return this._parsedUrl.port;
}

get protocol(): string {
throw new Error('URL.protocol is not implemented');
return this._parsedUrl.protocol;
}

get search(): string {
throw new Error('URL.search is not implemented');
return this._parsedUrl.search;
}

get searchParams(): URLSearchParams {
if (this._searchParamsInstance == null) {
this._searchParamsInstance = new URLSearchParams();
this._searchParamsInstance = new URLSearchParams(this._parsedUrl.search);
}
return this._searchParamsInstance;
}
Expand All @@ -158,16 +154,12 @@ export class URL {
}

toString(): string {
if (this._searchParamsInstance === null) {
return this._url;
}
// $FlowFixMe[incompatible-use]
const instanceString = this._searchParamsInstance.toString();
const instanceString = this._searchParamsInstance ? this._searchParamsInstance.toString() : '';
const separator = this._url.indexOf('?') > -1 ? '&' : '?';
return this._url + separator + instanceString;
return this._url + (instanceString ? separator + instanceString : '');
}

get username(): string {
throw new Error('URL.username is not implemented');
return this._parsedUrl.username;
}
}
16 changes: 16 additions & 0 deletions packages/react-native/Libraries/Blob/__tests__/URL-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,20 @@ describe('URL', function () {
const k = new URL('en-US/docs', 'https://developer.mozilla.org');
expect(k.href).toBe('https://developer.mozilla.org/en-US/docs');
});

it('should implement host, hostname, username, and password accessors correctly', () => {
const url = new URL('https://username:[email protected]:8080/en-US/docs?query=test#fragment');

// Test host
expect(url.host).toBe('developer.mozilla.org:8080');

// Test hostname
expect(url.hostname).toBe('developer.mozilla.org');

// Test username
expect(url.username).toBe('username');

// Test password
expect(url.password).toBe('password');
});
});

0 comments on commit 0b586a0

Please sign in to comment.