Skip to content

Commit 3b7513f

Browse files
committed
use platform-specific helpers in string methods in @sentry/utils
1 parent 3464937 commit 3b7513f

File tree

1 file changed

+21
-56
lines changed

1 file changed

+21
-56
lines changed

packages/utils/src/string.ts

Lines changed: 21 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { getGlobalObject } from './compat';
1+
import { getMainCarrier } from './compat';
22
import { SentryError } from './error';
33
import { isRegExp, isString } from './is';
44

@@ -112,42 +112,24 @@ export function isMatchingPattern(value: string, pattern: RegExp | string): bool
112112
* @returns A base64-encoded version of the string
113113
*/
114114
export function unicodeToBase64(plaintext: string): string {
115-
const global = getGlobalObject();
115+
const platformSpecificBase64Convertor = getMainCarrier().__SENTRY__?.extensions?.unsafeToBase64;
116116

117-
// Cast to a string just in case we're given something else
118-
const stringifiedInput = String(plaintext);
119-
const errMsg = `Unable to convert to base64: ${
120-
stringifiedInput.length > 256 ? `${stringifiedInput.slice(0, 256)}...` : stringifiedInput
121-
}`;
117+
if (!platformSpecificBase64Convertor) {
118+
throw new SentryError('`unsafeToBase64` not found. Cannot convert string from base64.');
119+
}
122120

123121
// To account for the fact that different platforms use different character encodings natively, our `tracestate`
124122
// spec calls for all jsonified data to be encoded in UTF-8 bytes before being passed to the base64 encoder.
125123
try {
126-
// browser
127-
if ('btoa' in global) {
128-
// encode using UTF-8
129-
const bytes = new TextEncoder().encode(plaintext);
130-
131-
// decode using UTF-16 (JS's native encoding) since `btoa` requires string input
132-
const bytesAsString = String.fromCharCode(...bytes);
133-
134-
return btoa(bytesAsString);
135-
}
136-
137-
// Node
138-
if ('Buffer' in global) {
139-
// encode using UTF-8
140-
const bytes = Buffer.from(plaintext, 'utf-8');
141-
142-
// unlike the browser, Node can go straight from bytes to base64
143-
return bytes.toString('base64');
144-
}
124+
return platformSpecificBase64Convertor(plaintext);
145125
} catch (err) {
126+
// Cast to a string just in case we're given something else
127+
const stringifiedInput = String(plaintext);
128+
const errMsg = `Unable to convert to base64: ${
129+
stringifiedInput.length > 256 ? `${stringifiedInput.slice(0, 256)}...` : stringifiedInput
130+
}`;
146131
throw new SentryError(`${errMsg}\nGot error: ${err}`);
147132
}
148-
149-
// we shouldn't ever get here, because one of `btoa` and `Buffer` should exist, but just in case...
150-
throw new SentryError(errMsg);
151133
}
152134

153135
/**
@@ -158,40 +140,23 @@ export function unicodeToBase64(plaintext: string): string {
158140
* @returns A Unicode string
159141
*/
160142
export function base64ToUnicode(base64String: string): string {
161-
const globalObject = getGlobalObject();
143+
const platformSpecificBase64Convertor = getMainCarrier().__SENTRY__?.extensions?.unsafeFromBase64;
162144

163-
// we cast to a string just in case we're given something else
164-
const stringifiedInput = String(base64String);
165-
const errMsg = `Unable to convert from base64: ${
166-
stringifiedInput.length > 256 ? `${stringifiedInput.slice(0, 256)}...` : stringifiedInput
167-
}`;
145+
if (!platformSpecificBase64Convertor) {
146+
throw new SentryError('`unsafeFromBase64` not found. Cannot convert string from base64.');
147+
}
168148

169149
// To account for the fact that different platforms use different character encodings natively, our `tracestate` spec
170150
// calls for all jsonified data to be encoded in UTF-8 bytes before being passed to the base64 encoder. So to reverse
171151
// the process, decode from base64 to bytes, then feed those bytes to a UTF-8 decoder.
172152
try {
173-
// browser
174-
if ('atob' in globalObject) {
175-
// `atob` returns a string rather than bytes, so we first need to encode using the native encoding (UTF-16)
176-
const bytesAsString = atob(base64String);
177-
const bytes = [...bytesAsString].map(char => char.charCodeAt(0));
178-
179-
// decode using UTF-8 (cast the `bytes` arry to a Uint8Array just because that's the format `decode()` expects)
180-
return new TextDecoder().decode(Uint8Array.from(bytes));
181-
}
182-
183-
// Node
184-
if ('Buffer' in globalObject) {
185-
// unlike the browser, Node can go straight from base64 to bytes
186-
const bytes = Buffer.from(base64String, 'base64');
187-
188-
// decode using UTF-8
189-
return bytes.toString('utf-8');
190-
}
153+
return platformSpecificBase64Convertor(base64String);
191154
} catch (err) {
155+
// we cast to a string just in case we're given something else
156+
const stringifiedInput = String(base64String);
157+
const errMsg = `Unable to convert from base64: ${
158+
stringifiedInput.length > 256 ? `${stringifiedInput.slice(0, 256)}...` : stringifiedInput
159+
}`;
192160
throw new SentryError(`${errMsg}\nGot error: ${err}`);
193161
}
194-
195-
// we shouldn't ever get here, because one of `atob` and `Buffer` should exist, but just in case...
196-
throw new SentryError(errMsg);
197162
}

0 commit comments

Comments
 (0)