Skip to content

Commit e93ff11

Browse files
committed
encoding: Expand on the context of our new base64Utf8Encode.
Also make the tests more informative -- 'W29iamVjdCBPYmplY3Rd' turns out to be the base64-encoding of the string '[object Object]'. :-)
1 parent 7ed22b8 commit e93ff11

File tree

2 files changed

+25
-25
lines changed

2 files changed

+25
-25
lines changed

src/utils/__tests__/encoding-test.js

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
hexToAscii,
66
asciiToHex,
77
xorHexStrings,
8-
strToBase64,
8+
base64Utf8Encode,
99
extractApiKey,
1010
} from '../encoding';
1111

@@ -62,33 +62,18 @@ describe('asciiToHex', () => {
6262
});
6363
});
6464

65-
describe('strToBase64', () => {
65+
describe('base64Utf8Encode', () => {
6666
test('can handle an empty string', () => {
67-
const obj = '';
67+
const text = '';
6868
const expected = '';
69-
70-
const result = strToBase64(obj);
71-
72-
expect(result).toBe(expected);
73-
});
74-
75-
test('can encode any string', () => {
76-
const obj = {
77-
key: 'ABCabc123',
78-
empty: null,
79-
array: [1, 2, 3],
80-
};
81-
const expected = 'W29iamVjdCBPYmplY3Rd';
82-
83-
const result = strToBase64(obj);
84-
69+
const result = base64Utf8Encode(text);
8570
expect(result).toBe(expected);
8671
});
8772

88-
test('supports unicode characters', () => {
89-
const obj = { key: '😇😈' };
90-
const expected = 'W29iamVjdCBPYmplY3Rd';
91-
const result = strToBase64(obj);
73+
test('supports Unicode characters outside the BMP', () => {
74+
const text = '😇😈';
75+
const expected = '8J+Yh/CfmIg=';
76+
const result = base64Utf8Encode(text);
9277
expect(result).toBe(expected);
9378
});
9479
});

src/utils/encoding.js

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,26 @@ export const base64ToHex = (bytes: string) => asciiToHex(base64.decode(bytes));
3232

3333
export const hexToBase64 = (hex: string) => base64.encode(hexToAscii(hex));
3434

35-
/** Encode a JavaScript string to a string in Base64 format. */
36-
export const strToBase64 = (text: string): string =>
35+
/**
36+
* Encode a string as the base64 representation of its UTF-8 bytes.
37+
*
38+
* This lets us pass an arbitrary string through a channel (like the
39+
* `postMessage` on RN's webviews on Android) that tries to do something
40+
* like percent-decode it.
41+
*/
42+
export const base64Utf8Encode = (text: string): string =>
3743
// References on reliably encoding strings to Base64:
3844
// https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/btoa#Unicode_strings
3945
// https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding
46+
//
47+
// In short:
48+
// * base64 encoders want bytes, not really Unicode strings, so they
49+
// insist their input consist of the characters U+0000 to U+00FF;
50+
// * `encodeURIComponent` together with `unescape` is a way of getting
51+
// that, effectively producing the UTF-8 encoding of the input.
52+
//
53+
// We use `base64.encode` because `btoa` is unavailable in the JS
54+
// environment provided by RN on iOS.
4055
base64.encode(unescape(encodeURIComponent(text)));
4156

4257
// Extract an API key encoded as a hex string XOR'ed with a one time pad (OTP)

0 commit comments

Comments
 (0)