Last active
December 19, 2023 04:22
-
-
Save ray007/a55ceac9c7ab538ac39189943fde870f to your computer and use it in GitHub Desktop.
URL polyfill for nativescript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// polyfill URL since that seems to not be done for nativescript | |
import { path } from "@nativescript/core"; | |
import 'url-search-params-polyfill'; | |
if (!global.URL) { | |
class URL { | |
constructor(sUrl, base) { | |
if (base) parse(this, base); | |
parse(this, sUrl); | |
} | |
toString() { | |
let p = this.protocol, h = ""; | |
if (p) h = `${this.protocol}//${getAuth(this)}${this.host}`; | |
return `${h}${this.pathname}${this.search}${this.hash}`; | |
} | |
get href() { | |
return this.toString(); | |
} | |
set href(value) { | |
parse(this, value); | |
} | |
get origin() { | |
return `${this.protocol}//${this.host}`; | |
} | |
set origin(v) {} | |
get host() { | |
let { protocol, hostname, port } = this, h = hostname; | |
if (port && (!protocol || port != dp[protocol])) h += `:${port}`; | |
return h; | |
} | |
set host(value) { | |
let m = value.match(/^([^:]*)(:\d+)?$/); | |
this.hostname = m[1] || ""; | |
this.port = m[2] ? m[2].substr(1) : ""; | |
} | |
get search() { | |
let s = `${this.searchParams}`; | |
return s && `?${s}`; | |
} | |
set search(value) { | |
this.searchParams = new URLSearchParams(value); | |
} | |
} | |
URL.prototype.protocol = ""; | |
URL.prototype.username = ""; | |
URL.prototype.password = ""; | |
URL.prototype.host = ""; | |
URL.prototype.port = ""; | |
URL.prototype.pathname = ""; | |
URL.prototype.hash = ""; | |
const dp = URL.defaultProtocols = { | |
"http:": 80, | |
"https:": 443, | |
}; | |
const rxUrl = /^(?:([\w-]+:)\/\/)?([^/]*)(\/[^?#]*)?(\?[^#]*)?(#.*)?$/; | |
function parse(url, str) { | |
let parts = str.match(rxUrl); | |
let [ _all, prot, hostAuth, pathname = "", search = "", hash = ""] = parts; | |
if (prot) url.protocol = prot; | |
if (hostAuth) setHostAuth(url, hostAuth); | |
if (pathname && pathname[0] != '/') { | |
let pn = url.pathname; | |
if (pn && !pn.endsWith('/')) { | |
let i = pn.lastIndexOf('/'); | |
pn = (i >= 0) ? pn.substr(0, i+1) : ""; | |
} | |
pathname = pn + pathname; | |
} | |
url.pathname = path.normalize(pathname || ""); | |
url.search = search; | |
url.hash = hash; | |
} | |
function getAuth(url) { | |
var { username, password } = url, a = username || ""; | |
if (username) { | |
if (password) a += `:${password}`; | |
a += '@'; | |
} | |
return a; | |
} | |
function setHostAuth(url, hostAuth) { | |
let i = hostAuth.indexOf('@'), creds = ""; | |
if (i > 0) { | |
creds = hostAuth.substr(0, i); | |
hostAuth = hostAuth.substr(i+1); | |
} | |
url.host = hostAuth; | |
creds = creds.split(':'); | |
url.username = creds[0]; | |
url.password = creds[1] || ""; | |
} | |
global.URL = URL; | |
} |
This is super helpful 🤗 For those wondering how to use this in, for example, an Angular app, you can do the following:
- Create
src/polyfills-custom.ts
and copy/paste above into it. npm install url-search-params-polyfill -D
- Now import it into the
src/polyfills.ts
like this:
/**
* NativeScript Polyfills
*/
// Install @nativescript/core polyfills (XHR, setTimeout, requestAnimationFrame)
import '@nativescript/core/globals';
import '@valor/nativescript-websockets';
// Install @nativescript/angular specific polyfills
import '@nativescript/angular/polyfills';
// IMPORT CUSTOM POLYFILLS HERE:
import './polyfills-custom';
/**
* Zone.js and patches
*/
// Add pre-zone.js patches needed for the NativeScript platform
import '@nativescript/zone-js/dist/pre-zone-polyfills';
// Zone JS is required by default for Angular itself
import 'zone.js';
// Add NativeScript specific Zone JS patches
import '@nativescript/zone-js';
Noting that Url
and UrlSearchParams
will become optional automatic polyfills that a user can choose to polyfill likely through nativescript.config
in the future. Reason being is that they can provide extra weight to bundle that when not used may be wasteful so the working group is aiming to allow easy automatic polyfiling of the most popular optionals via config option in future.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks for sharing this!