Skip to content

Commit b4d64f0

Browse files
authored
Fixed fast-base64-decode dependency issue in react-native-package. (#286)
1 parent 892e172 commit b4d64f0

File tree

4 files changed

+18279
-23799
lines changed

4 files changed

+18279
-23799
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@powersync/react-native': patch
3+
---
4+
5+
Updated crypto.js vendor file to include fast-base64-decode dependency instead of bundling it.

packages/react-native/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@
5050
"@types/async-lock": "^1.4.0",
5151
"async-lock": "^1.4.0",
5252
"bson": "^6.6.0",
53-
"fast-base64-decode": "^1.0.0",
5453
"react": "18.2.0",
5554
"react-native": "0.72.4",
5655
"react-native-fetch-api": "^3.0.0",
Lines changed: 94 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,85 +1,152 @@
1-
// This file is based on code from the react-native-get-random-values repository
1+
// This file is based on code from the fast-base64-decode repository.
2+
// Source: https://github.com/LinusU/fast-base64-decode/blob/master/index.js
3+
// Modifications:
4+
// - None
5+
6+
const lookup = new Uint8Array([
7+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8+
0, 0, 0, 0, 62, 0, 62, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8,
9+
9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 63, 0, 26, 27, 28, 29, 30, 31, 32, 33,
10+
34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
11+
]);
12+
13+
function base64Decode(source, target) {
14+
const sourceLength = source.length;
15+
const paddingLength = source[sourceLength - 2] === '=' ? 2 : source[sourceLength - 1] === '=' ? 1 : 0;
16+
const baseLength = (sourceLength - paddingLength) & 0xfffffffc;
17+
18+
let tmp;
19+
let i = 0;
20+
let byteIndex = 0;
21+
22+
for (; i < baseLength; i += 4) {
23+
tmp =
24+
(lookup[source.charCodeAt(i)] << 18) |
25+
(lookup[source.charCodeAt(i + 1)] << 12) |
26+
(lookup[source.charCodeAt(i + 2)] << 6) |
27+
lookup[source.charCodeAt(i + 3)];
28+
29+
target[byteIndex++] = (tmp >> 16) & 0xff;
30+
target[byteIndex++] = (tmp >> 8) & 0xff;
31+
target[byteIndex++] = tmp & 0xff;
32+
}
33+
34+
if (paddingLength === 1) {
35+
tmp =
36+
(lookup[source.charCodeAt(i)] << 10) |
37+
(lookup[source.charCodeAt(i + 1)] << 4) |
38+
(lookup[source.charCodeAt(i + 2)] >> 2);
39+
40+
target[byteIndex++] = (tmp >> 8) & 0xff;
41+
target[byteIndex++] = tmp & 0xff;
42+
}
43+
44+
if (paddingLength === 2) {
45+
tmp = (lookup[source.charCodeAt(i)] << 2) | (lookup[source.charCodeAt(i + 1)] >> 4);
46+
47+
target[byteIndex++] = tmp & 0xff;
48+
}
49+
}
50+
51+
// This file is based on code from the react-native-get-random-values repository.
252
// Source: https://github.com/LinusU/react-native-get-random-values/blob/modern/index.js
353
// Modifications:
454
// - Instead of applying to all global references of crypto, provide a ponyfill export.
55+
// - Instead of having a package dependency on fast-base64-decode, copy the code here. There are issues with injecting a vendor file in the rollup config.
556

6-
const base64Decode = require('fast-base64-decode')
7-
const { NativeModules } = require('react-native')
57+
const { NativeModules } = require('react-native');
858

959
class TypeMismatchError extends Error {}
1060
class QuotaExceededError extends Error {}
1161

12-
let warned = false
13-
function insecureRandomValues (array) {
62+
let warned = false;
63+
function insecureRandomValues(array) {
1464
if (!warned) {
15-
console.warn('Using an insecure random number generator, this should only happen when running in a debugger without support for crypto.getRandomValues')
16-
warned = true
65+
console.warn(
66+
'Using an insecure random number generator, this should only happen when running in a debugger without support for crypto.getRandomValues'
67+
);
68+
warned = true;
1769
}
1870

1971
for (let i = 0, r; i < array.length; i++) {
20-
if ((i & 0x03) === 0) r = Math.random() * 0x100000000
21-
array[i] = (r >>> ((i & 0x03) << 3)) & 0xff
72+
if ((i & 0x03) === 0) r = Math.random() * 0x100000000;
73+
array[i] = (r >>> ((i & 0x03) << 3)) & 0xff;
2274
}
2375

24-
return array
76+
return array;
2577
}
2678

2779
/**
2880
* @param {number} byteLength
2981
* @returns {string}
3082
*/
31-
function getRandomBase64 (byteLength) {
83+
function getRandomBase64(byteLength) {
3284
if (NativeModules.RNGetRandomValues) {
33-
return NativeModules.RNGetRandomValues.getRandomBase64(byteLength)
85+
return NativeModules.RNGetRandomValues.getRandomBase64(byteLength);
3486
} else if (NativeModules.ExpoRandom) {
3587
// Expo SDK 41-44
36-
return NativeModules.ExpoRandom.getRandomBase64String(byteLength)
88+
return NativeModules.ExpoRandom.getRandomBase64String(byteLength);
3789
} else if (global.ExpoModules) {
3890
// Expo SDK 45+
3991
return global.ExpoModules.ExpoRandom.getRandomBase64String(byteLength);
4092
} else {
41-
throw new Error('Native module not found')
93+
throw new Error('Native module not found');
4294
}
4395
}
4496

4597
/**
4698
* @param {Int8Array|Uint8Array|Int16Array|Uint16Array|Int32Array|Uint32Array|Uint8ClampedArray} array
4799
*/
48-
function getRandomValues (array) {
49-
if (!(array instanceof Int8Array || array instanceof Uint8Array || array instanceof Int16Array || array instanceof Uint16Array || array instanceof Int32Array || array instanceof Uint32Array || array instanceof Uint8ClampedArray)) {
50-
throw new TypeMismatchError('Expected an integer array')
100+
function getRandomValues(array) {
101+
if (
102+
!(
103+
array instanceof Int8Array ||
104+
array instanceof Uint8Array ||
105+
array instanceof Int16Array ||
106+
array instanceof Uint16Array ||
107+
array instanceof Int32Array ||
108+
array instanceof Uint32Array ||
109+
array instanceof Uint8ClampedArray
110+
)
111+
) {
112+
throw new TypeMismatchError('Expected an integer array');
51113
}
52114

53115
if (array.byteLength > 65536) {
54-
throw new QuotaExceededError('Can only request a maximum of 65536 bytes')
116+
throw new QuotaExceededError('Can only request a maximum of 65536 bytes');
55117
}
56118

57119
// Expo SDK 48+
58-
if (global.expo && global.expo.modules && global.expo.modules.ExpoCrypto && global.expo.modules.ExpoCrypto.getRandomValues) {
120+
if (
121+
global.expo &&
122+
global.expo.modules &&
123+
global.expo.modules.ExpoCrypto &&
124+
global.expo.modules.ExpoCrypto.getRandomValues
125+
) {
59126
// ExpoCrypto.getRandomValues doesn't return the array
60-
global.expo.modules.ExpoCrypto.getRandomValues(array)
61-
return array
127+
global.expo.modules.ExpoCrypto.getRandomValues(array);
128+
return array;
62129
}
63130

64131
// Calling getRandomBase64 in remote debugging mode leads to the error
65132
// "Calling synchronous methods on native modules is not supported in Chrome".
66133
// So in that specific case we fall back to just using Math.random().
67134
if (isRemoteDebuggingInChrome()) {
68-
return insecureRandomValues(array)
135+
return insecureRandomValues(array);
69136
}
70137

71-
base64Decode(getRandomBase64(array.byteLength), new Uint8Array(array.buffer, array.byteOffset, array.byteLength))
138+
base64Decode(getRandomBase64(array.byteLength), new Uint8Array(array.buffer, array.byteOffset, array.byteLength));
72139

73-
return array
140+
return array;
74141
}
75142

76-
function isRemoteDebuggingInChrome () {
143+
function isRemoteDebuggingInChrome() {
77144
// Remote debugging in Chrome is not supported in bridgeless
78145
if ('RN$Bridgeless' in global && RN$Bridgeless === true) {
79-
return false
146+
return false;
80147
}
81148

82-
return __DEV__ && typeof global.nativeCallSyncHook === 'undefined'
149+
return __DEV__ && typeof global.nativeCallSyncHook === 'undefined';
83150
}
84151

85152
export default { getRandomValues };

0 commit comments

Comments
 (0)