Skip to content

Commit 7ba8917

Browse files
feat(NODE-6321): remove require('crypto') from Nodejs bundle (#825)
1 parent 94bf732 commit 7ba8917

File tree

4 files changed

+16
-75
lines changed

4 files changed

+16
-75
lines changed

etc/rollup/rollup-plugin-require-rewriter/require_rewriter.mjs

Lines changed: 0 additions & 50 deletions
This file was deleted.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,4 +115,4 @@
115115
"prepare": "node etc/prepare.js",
116116
"release": "standard-version -i HISTORY.md"
117117
}
118-
}
118+
}

rollup.config.mjs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { nodeResolve } from '@rollup/plugin-node-resolve';
22
import typescript from '@rollup/plugin-typescript';
3-
import { requireRewriter } from './etc/rollup/rollup-plugin-require-rewriter/require_rewriter.mjs';
43
import { RequireVendor } from './etc/rollup/rollup-plugin-require-vendor/require_vendor.mjs';
54

65
/** @type {typescript.RollupTypescriptOptions} */
@@ -57,7 +56,6 @@ const config = [
5756
input,
5857
plugins: [
5958
typescript(tsConfig),
60-
requireRewriter({ target: 'browser' }),
6159
nodeResolve({ resolveOnly: [] })
6260
],
6361
output: {
@@ -68,7 +66,7 @@ const config = [
6866
},
6967
{
7068
input,
71-
plugins: [typescript(tsConfig), requireRewriter({ target: 'node' }), nodeResolve({ resolveOnly: [] })],
69+
plugins: [typescript(tsConfig), nodeResolve({ resolveOnly: [] })],
7270
output: {
7371
file: 'lib/bson.node.mjs',
7472
format: 'esm',

src/utils/node_byte_utils.ts

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -26,34 +26,27 @@ type NodeJsBufferConstructor = Omit<Uint8ArrayConstructor, 'from'> & {
2626
// This can be nullish, but we gate the nodejs functions on being exported whether or not this exists
2727
// Node.js global
2828
declare const Buffer: NodeJsBufferConstructor;
29-
declare const require: (mod: 'crypto') => { randomBytes: (byteLength: number) => Uint8Array };
3029

3130
/** @internal */
32-
export function nodejsMathRandomBytes(byteLength: number) {
31+
function nodejsMathRandomBytes(byteLength: number): NodeJsBuffer {
3332
return nodeJsByteUtils.fromNumberArray(
3433
Array.from({ length: byteLength }, () => Math.floor(Math.random() * 256))
3534
);
3635
}
3736

38-
/**
39-
* @internal
40-
* WARNING: REQUIRE WILL BE REWRITTEN
41-
*
42-
* This code is carefully used by require_rewriter.mjs any modifications must be reflected in the plugin.
43-
*
44-
* @remarks
45-
* "crypto" is the only dependency BSON needs. This presents a problem for creating a bundle of the BSON library
46-
* in an es module format that can be used both on the browser and in Node.js. In Node.js when BSON is imported as
47-
* an es module, there will be no global require function defined, making the code below fallback to the much less desireable math.random bytes.
48-
* In order to make our es module bundle work as expected on Node.js we need to change this `require()` to a dynamic import, and the dynamic
49-
* import must be top-level awaited since es modules are async. So we rely on a custom rollup plugin to seek out the following lines of code
50-
* and replace `require` with `await import` and the IIFE line (`nodejsRandomBytes = (() => { ... })()`) with `nodejsRandomBytes = await (async () => { ... })()`
51-
* when generating an es module bundle.
52-
*/
53-
const nodejsRandomBytes: (byteLength: number) => Uint8Array = (() => {
54-
try {
55-
return require('crypto').randomBytes;
56-
} catch {
37+
/** @internal */
38+
function nodejsSecureRandomBytes(byteLength: number): NodeJsBuffer {
39+
// @ts-expect-error: crypto.getRandomValues cannot actually be null here
40+
return crypto.getRandomValues(nodeJsByteUtils.allocate(byteLength));
41+
}
42+
43+
const nodejsRandomBytes = (() => {
44+
const { crypto } = globalThis as {
45+
crypto?: { getRandomValues?: (space: Uint8Array) => Uint8Array };
46+
};
47+
if (crypto != null && typeof crypto.getRandomValues === 'function') {
48+
return nodejsSecureRandomBytes;
49+
} else {
5750
return nodejsMathRandomBytes;
5851
}
5952
})();

0 commit comments

Comments
 (0)