Skip to content

Commit 3dac900

Browse files
riteshshukla04facebook-github-bot
authored andcommitted
Implementing url Methods (#49955)
Summary: Implemented Methods in URL which were not implemented yet The methods output are identical to outputs of window.url . Fixes #45030 ## Changelog: <!-- Help reviewers and the release process by writing your own changelog entry. Pick one each for the category and type tags: [ANDROID|GENERAL|IOS|INTERNAL] [BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY] - Message For more details, see: https://reactnative.dev/contributing/changelogs-in-pull-requests --> [General][Added] URL accessors for unimplemented Methods Pull Request resolved: #49955 Test Plan: Code:- <img width="558" alt="image" src="https://github.com/user-attachments/assets/a75e5429-0e03-4392-9fde-138c63b96ce5" /> Tested with Hermes ![image](https://github.com/user-attachments/assets/0075826a-df3a-4eae-a8f2-bec26be42fbf) Tested with JSC ![image](https://github.com/user-attachments/assets/bcdbd430-5ee3-48a2-873f-7d823c9072f6) Reviewed By: rshest Differential Revision: D71113046 Pulled By: cortinico fbshipit-source-id: 58093c61d2e7bb732d2f1af6b19508a100c86333
1 parent ef0de0e commit 3dac900

File tree

5 files changed

+137
-10
lines changed

5 files changed

+137
-10
lines changed

packages/react-native/Libraries/Blob/URL.js

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -107,43 +107,55 @@ export class URL {
107107
}
108108

109109
get hash(): string {
110-
throw new Error('URL.hash is not implemented');
110+
const hashMatch = this._url.match(/#([^/]*)/);
111+
return hashMatch ? `#${hashMatch[1]}` : '';
111112
}
112113

113114
get host(): string {
114-
throw new Error('URL.host is not implemented');
115+
const hostMatch = this._url.match(/^https?:\/\/(?:[^@]+@)?([^:/?#]+)/);
116+
const portMatch = this._url.match(/:(\d+)(?=[/?#]|$)/);
117+
return hostMatch
118+
? hostMatch[1] + (portMatch ? `:${portMatch[1]}` : '')
119+
: '';
115120
}
116121

117122
get hostname(): string {
118-
throw new Error('URL.hostname is not implemented');
123+
const hostnameMatch = this._url.match(/^https?:\/\/(?:[^@]+@)?([^:/?#]+)/);
124+
return hostnameMatch ? hostnameMatch[1] : '';
119125
}
120126

121127
get href(): string {
122128
return this.toString();
123129
}
124130

125131
get origin(): string {
126-
throw new Error('URL.origin is not implemented');
132+
const matches = this._url.match(/^(https?:\/\/[^/]+)/);
133+
return matches ? matches[1] : '';
127134
}
128135

129136
get password(): string {
130-
throw new Error('URL.password is not implemented');
137+
const passwordMatch = this._url.match(/https?:\/\/.*:(.*)@/);
138+
return passwordMatch ? passwordMatch[1] : '';
131139
}
132140

133141
get pathname(): string {
134-
throw new Error('URL.pathname not implemented');
142+
const pathMatch = this._url.match(/https?:\/\/[^/]+(\/[^?#]*)?/);
143+
return pathMatch ? pathMatch[1] || '/' : '/';
135144
}
136145

137146
get port(): string {
138-
throw new Error('URL.port is not implemented');
147+
const portMatch = this._url.match(/:(\d+)(?=[/?#]|$)/);
148+
return portMatch ? portMatch[1] : '';
139149
}
140150

141151
get protocol(): string {
142-
throw new Error('URL.protocol is not implemented');
152+
const protocolMatch = this._url.match(/^([a-zA-Z][a-zA-Z\d+\-.]*):/);
153+
return protocolMatch ? protocolMatch[1] + ':' : '';
143154
}
144155

145156
get search(): string {
146-
throw new Error('URL.search is not implemented');
157+
const searchMatch = this._url.match(/\?([^#]*)/);
158+
return searchMatch ? `?${searchMatch[1]}` : '';
147159
}
148160

149161
get searchParams(): URLSearchParams {
@@ -168,6 +180,7 @@ export class URL {
168180
}
169181

170182
get username(): string {
171-
throw new Error('URL.username is not implemented');
183+
const usernameMatch = this._url.match(/^https?:\/\/([^:@]+)(?::[^@]*)?@/);
184+
return usernameMatch ? usernameMatch[1] : '';
172185
}
173186
}

packages/react-native/Libraries/Blob/__tests__/URL-test.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,5 +40,17 @@ describe('URL', function () {
4040
// Insert / between Base and Path if missing
4141
const k = new URL('en-US/docs', 'https://developer.mozilla.org');
4242
expect(k.href).toBe('https://developer.mozilla.org/en-US/docs');
43+
//More cases
44+
const url = new URL(
45+
'https://username:[email protected]:8080/docs/path?query=testQuery&key=value#fragment',
46+
);
47+
expect(url.hash).toBe('#fragment');
48+
expect(url.host).toBe('reactnative.dev:8080');
49+
expect(url.hostname).toBe('reactnative.dev');
50+
expect(url.password).toBe('password');
51+
expect(url.username).toBe('username');
52+
expect(url.pathname).toBe('/docs/path');
53+
expect(url.port).toBe('8080');
54+
expect(url.search).toBe('?query=testQuery&key=value');
4355
});
4456
});
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/**
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @format
8+
* @flow
9+
*/
10+
11+
'use strict';
12+
13+
import type {RNTesterModuleExample} from '../../types/RNTesterTypes';
14+
15+
import RNTesterText from '../../components/RNTesterText';
16+
import React from 'react';
17+
import {StyleSheet, View} from 'react-native';
18+
19+
type Props = {
20+
url: string,
21+
};
22+
23+
function URLComponent(props: Props) {
24+
const parsedUrl = new URL(props.url);
25+
return (
26+
<View style={styles.container}>
27+
<RNTesterText testID="URL-href">{`href: ${parsedUrl.href}`}</RNTesterText>
28+
<RNTesterText testID="URL-hash">{`hash: ${parsedUrl.hash}`}</RNTesterText>
29+
<RNTesterText testID="URL-host">{`host: ${parsedUrl.host}`}</RNTesterText>
30+
<RNTesterText testID="URL-hostname">{`hostname: ${parsedUrl.hostname}`}</RNTesterText>
31+
<RNTesterText testID="URL-password">{`password: ${parsedUrl.password}`}</RNTesterText>
32+
<RNTesterText testID="URL-username">{`username: ${parsedUrl.username}`}</RNTesterText>
33+
<RNTesterText testID="URL-pathname">{`pathname: ${parsedUrl.pathname}`}</RNTesterText>
34+
<RNTesterText testID="URL-port">{`port: ${parsedUrl.port}`}</RNTesterText>
35+
<RNTesterText testID="URL-search">{`search: ${parsedUrl.search}`}</RNTesterText>
36+
</View>
37+
);
38+
}
39+
40+
const styles = StyleSheet.create({
41+
container: {
42+
padding: 10,
43+
},
44+
});
45+
46+
exports.title = 'URL';
47+
exports.category = 'Basic';
48+
exports.description = 'URL Parameters test';
49+
exports.examples = [
50+
{
51+
title: 'completeURL',
52+
description: 'URL with username,password,port,and queryparams',
53+
render(): React.Node {
54+
return (
55+
<URLComponent
56+
url={
57+
'https://username:[email protected]:8080/docs/path?query=testQuery&key=value#fragment'
58+
}
59+
/>
60+
);
61+
},
62+
},
63+
{
64+
title: 'basicURL',
65+
description: 'Basic URL without username, password, or port',
66+
render(): React.Node {
67+
return <URLComponent url={'https://reactnative.dev/docs/path'} />;
68+
},
69+
},
70+
{
71+
title: 'queryParamsURL',
72+
description: 'URL with query parameters',
73+
render(): React.Node {
74+
return (
75+
<URLComponent
76+
url={'https://reactnative.dev/docs/path?query=testQuery&key=value'}
77+
/>
78+
);
79+
},
80+
},
81+
{
82+
title: 'authAndPortURL',
83+
description: 'URL with username, password, and port',
84+
render(): React.Node {
85+
return (
86+
<URLComponent
87+
url={'https://username:[email protected]:8080/docs/path'}
88+
/>
89+
);
90+
},
91+
},
92+
] as Array<RNTesterModuleExample>;

packages/rn-tester/js/utils/RNTesterList.android.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,11 @@ const APIs: Array<RNTesterModuleInfo> = ([
187187
category: 'Basic',
188188
module: require('../examples/AppState/AppStateExample'),
189189
},
190+
{
191+
key: 'URLExample',
192+
category: 'Basic',
193+
module: require('../examples/Urls/UrlExample'),
194+
},
190195
{
191196
key: 'BorderExample',
192197
category: 'UI',

packages/rn-tester/js/utils/RNTesterList.ios.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,11 @@ const APIs: Array<RNTesterModuleInfo> = ([
192192
key: 'AppStateExample',
193193
module: require('../examples/AppState/AppStateExample'),
194194
},
195+
{
196+
key: 'URLExample',
197+
category: 'Basic',
198+
module: require('../examples/Urls/UrlExample'),
199+
},
195200
{
196201
key: 'BorderExample',
197202
module: require('../examples/Border/BorderExample').default,

0 commit comments

Comments
 (0)