%PDF- <> %âãÏÓ endobj 2 0 obj <> endobj 3 0 obj <>/ExtGState<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 28 0 R 29 0 R] /MediaBox[ 0 0 595.5 842.25] /Contents 4 0 R/Group<>/Tabs/S>> endobj ºaâÚÎΞ-ÌE1ÍØÄ÷{òò2ÿ ÛÖ^ÔÀá TÎ{¦?§®¥kuµùÕ5sLOšuY>endobj 2 0 obj<>endobj 2 0 obj<>endobj 2 0 obj<>endobj 2 0 obj<> endobj 2 0 obj<>endobj 2 0 obj<>es 3 0 R>> endobj 2 0 obj<> ox[ 0.000000 0.000000 609.600000 935.600000]/Fi endobj 3 0 obj<> endobj 7 1 obj<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI]>>/Subtype/Form>> stream
/** * These functions are for handling of query-string free URLs, necessitated * by query string stripping of URLs in JavaScriptCore stack traces * introduced in iOS 16.4. * * See https://github.com/facebook/react-native/issues/36794 for context. * * @flow strict */ // We use regex-based URL parsing as defined in RFC3986 because it's easier to // determine whether the input is a complete URI, a path-absolute or a // path-rootless (as defined in the spec), and be as faithful to the input as // possible. This will match any string, and does not imply validity. // // https://www.rfc-editor.org/rfc/rfc3986#appendix-B const URI_REGEX = /^(([^:/?#]+):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/; function _rfc3986Parse(url /*:string */) { const match = url.match(URI_REGEX); if (match == null) { throw new Error("Unexpected error - failed to regex-match URL"); } return { schemeAndAuthority: (match[1] || "") + (match[3] || ""), path: match[5] || "", hasQueryPart: match[6] != null, queryWithoutQuestionMark: match[7] || "", fragmentWithHash: match[8] || "", }; } function isJscSafeUrl(url /*:string */) /*:boolean*/ { const parsedUrl = _rfc3986Parse(url); return !parsedUrl.hasQueryPart; } /** * @param {string} urlToNormalize * @returns string */ function toNormalUrl(urlToNormalize /*:string */) /*:string */ { const parsedUrl = _rfc3986Parse(urlToNormalize); if (parsedUrl.path.indexOf("//&") === -1) { return urlToNormalize; } return ( parsedUrl.schemeAndAuthority + parsedUrl.path.replace("//&", "?") + // We don't expect JSC urls to also have query strings, but interpret // liberally and append them. (parsedUrl.queryWithoutQuestionMark.length > 0 ? "&" + parsedUrl.queryWithoutQuestionMark : "") + // Likewise, JSC URLs will usually have their fragments stripped, but // preserve if we find one. parsedUrl.fragmentWithHash ); } /** * @param {string} urlToConvert * @returns string */ function toJscSafeUrl(urlToConvert /*:string */) /*:string */ { if (!_rfc3986Parse(urlToConvert).hasQueryPart) { return urlToConvert; } const parsedUrl = _rfc3986Parse(toNormalUrl(urlToConvert)); if ( parsedUrl.queryWithoutQuestionMark.length > 0 && (parsedUrl.path === "" || parsedUrl.path === "/") ) { throw new Error( `The given URL "${urlToConvert}" has an empty path and cannot be converted to a JSC-safe format.` ); } return ( parsedUrl.schemeAndAuthority + parsedUrl.path + (parsedUrl.queryWithoutQuestionMark.length > 0 ? "//&" + // Query strings may contain '?' (e.g. in key or value names) - these // must be percent-encoded to form a valid path, and not be stripped. parsedUrl.queryWithoutQuestionMark.replace(/\?/g, "%3F") : "") + // We expect JSC to strip this - we don't handle fragments for now. parsedUrl.fragmentWithHash ); } module.exports = { isJscSafeUrl, toNormalUrl, toJscSafeUrl, };