fix!: expect crypto to be global everywhere (requires node@20+) (#935)

This commit is contained in:
Robert Kieffer
2026-04-19 03:01:26 -10:00
committed by GitHub
parent d56acac357
commit 6a1b881b49
12 changed files with 1192 additions and 2098 deletions
+6 -6
View File
@@ -34,7 +34,7 @@ npm install uuid
```javascript
import { v4 as uuidv4 } from "uuid";
uuidv4(); // ⇨ 'd02fd2bc-0baa-4a06-ae2f-fde2bbaff694'
uuidv4(); // ⇨ 'ab16e731-6cee-424d-81a0-5929e9bdb0cc'
```
For timestamp UUIDs, namespace UUIDs, and other options read on ...
@@ -179,7 +179,7 @@ Example:
```javascript
import { v1 as uuidv1 } from "uuid";
uuidv1(); // ⇨ '56eaf9f0-310a-11f1-8b06-cf0bf06de9bb'
uuidv1(); // ⇨ '4d9d2960-31d0-11f1-aba8-29728d41eeed'
```
Example using `options`:
@@ -234,7 +234,7 @@ Example:
```javascript
import { v4 as uuidv4 } from "uuid";
uuidv4(); // ⇨ 'c3d46383-7242-4b80-973b-eb3c66ad8d9e'
uuidv4(); // ⇨ '7934256a-bc92-4b69-b240-f9e463881aea'
```
Example using predefined `random` values:
@@ -310,7 +310,7 @@ This method takes the same arguments as uuid.v1().
```javascript
import { v6 as uuidv6 } from "uuid";
uuidv6(); // ⇨ '1f1310a5-6eb9-6630-bf43-2b49087aab53'
uuidv6(); // ⇨ '1f131d04-d9dc-65a0-9516-5be66631ce97'
```
Example using `options`:
@@ -357,7 +357,7 @@ Example:
```javascript
import { v7 as uuidv7 } from "uuid";
uuidv7(); // ⇨ '019d5e6b-6713-7339-951f-6e19a533527d'
uuidv7(); // ⇨ '019d637c-c6fb-74e9-8b9d-2f1d459a4201'
```
### ~~uuid.v8()~~
@@ -470,7 +470,7 @@ Prior to `uuid@11`, it was possible for `options` state to interfere with the in
## Known issues
<!-- This header is referenced as an anchor in src/rng-browser.ts -->
<!-- This header is referenced as an anchor in src/rng.ts -->
### "getRandomValues() not supported"
+1 -2
View File
@@ -467,8 +467,7 @@ Prior to `uuid@11`, it was possible for `options` state to interfere with the in
## Known issues
<!-- This header is referenced as an anchor in src/rng-browser.ts -->
<!-- This header is referenced as an anchor in src/rng.ts -->
### "getRandomValues() not supported"
This error occurs in environments where the standard [`crypto.getRandomValues()`](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues) API is not supported. This issue can be resolved by adding an appropriate polyfill:
+1
View File
@@ -33,6 +33,7 @@ export default function test(callback) {
function done() {
const div = document.createElement('h2');
div.id = 'done';
div.innerHTML = 'Done';
document.body.appendChild(div);
}
+1136 -1987
View File
File diff suppressed because it is too large Load Diff
+6 -6
View File
@@ -54,12 +54,12 @@
"typescript": "5.4.3"
},
"optionalDevDependencies": {
"@wdio/browserstack-service": "9.2.1",
"@wdio/cli": "9.2.1",
"@wdio/jasmine-framework": "9.2.1",
"@wdio/local-runner": "9.2.1",
"@wdio/spec-reporter": "9.1.3",
"@wdio/static-server-service": "9.1.3"
"@wdio/browserstack-service": "9.27.0",
"@wdio/cli": "9.27.0",
"@wdio/jasmine-framework": "9.27.0",
"@wdio/local-runner": "9.27.0",
"@wdio/spec-reporter": "9.27.0",
"@wdio/static-server-service": "9.27.0"
},
"scripts": {
"build": "./scripts/build.sh",
-6
View File
@@ -1,6 +0,0 @@
const randomUUID =
typeof crypto !== 'undefined' &&
crypto.randomUUID &&
crypto.randomUUID.bind(crypto);
export default { randomUUID };
-3
View File
@@ -1,3 +0,0 @@
import { randomUUID } from 'node:crypto';
export default { randomUUID };
-22
View File
@@ -1,22 +0,0 @@
// Unique ID creation requires a high quality random # generator. In the browser we therefore
// require the crypto API and do not support built-in fallback to lower quality random number
// generators (like Math.random()).
let getRandomValues: typeof crypto.getRandomValues | undefined;
const rnds8 = new Uint8Array(16);
export default function rng() {
// lazy load so that environments that need to polyfill have a chance to do so
if (!getRandomValues) {
if (typeof crypto === 'undefined' || !crypto.getRandomValues) {
throw new Error(
'crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported',
);
}
getRandomValues = crypto.getRandomValues.bind(crypto);
}
return getRandomValues(rnds8);
}
+5 -10
View File
@@ -1,12 +1,7 @@
import { randomFillSync } from 'node:crypto';
const rnds8Pool = new Uint8Array(256); // # of random values to pre-allocate
let poolPtr = rnds8Pool.length;
// RNG values for use in UUID generation. This *must* use a high-quality source
// of entropy, such as `crypto.getRandomValues()`. And we reuse an array for
// performance.
const rnds8 = new Uint8Array(16);
export default function rng() {
if (poolPtr > rnds8Pool.length - 16) {
randomFillSync(rnds8Pool);
poolPtr = 0;
}
return rnds8Pool.slice(poolPtr, (poolPtr += 16));
return crypto.getRandomValues(rnds8);
}
+10 -27
View File
@@ -1,6 +1,5 @@
import * as assert from 'node:assert/strict';
import { describe, test } from 'node:test';
import native from '../native.js';
import v4 from '../v4.js';
const randomBytesFixture = Uint8Array.of(
@@ -49,40 +48,24 @@ describe('v4', () => {
assert.ok(id1 !== id2);
});
test('should uses native randomUUID() if no option is passed', async () => {
// TODO: `mock` is not supported until node@18, so we feature-detect it
// here. Once node@16 drops off our support matrix, we can just
// static-import it normally
const mock = (await import('node:test')).default.mock;
if (!mock) {
return;
}
test('should use native randomUUID() if no option is passed', async (t) => {
const mocked = t.mock.method(crypto, 'randomUUID', () => 'mocked-uuid');
const mockRandomUUID = mock.method(native, 'randomUUID');
assert.equal(mockRandomUUID.mock.callCount(), 0);
assert.equal(mocked.mock.callCount(), 0);
v4();
assert.equal(mockRandomUUID.mock.callCount(), 1);
assert.equal(mocked.mock.callCount(), 1);
mock.restoreAll();
t.mock.reset();
});
test('should not use native randomUUID() if an option is passed', async () => {
// TODO: `mock` is not supported until node@18, so we feature-detect it
// here. Once node@16 drops off our support matrix, we can just
// static-import it normally
const mock = (await import('node:test')).default.mock;
if (!mock) {
return;
}
test('should not use native randomUUID() if an option is passed', async (t) => {
const mocked = t.mock.method(crypto, 'randomUUID', () => 'mocked-uuid');
const mockRandomUUID = mock.method(native, 'randomUUID');
assert.equal(mockRandomUUID.mock.callCount(), 0);
assert.equal(mocked.mock.callCount(), 0);
v4({});
assert.equal(mockRandomUUID.mock.callCount(), 0);
assert.equal(mocked.mock.callCount(), 0);
mock.restoreAll();
t.mock.reset();
});
test('explicit options.random produces expected result', () => {
+26 -28
View File
@@ -1,8 +1,33 @@
import native from './native.js';
import rng from './rng.js';
import { unsafeStringify } from './stringify.js';
import type { UUIDTypes, Version4Options } from './types.js';
function v4(
options?: Version4Options,
buf?: undefined,
offset?: number,
): string;
function v4<TBuf extends Uint8Array = Uint8Array>(
options: Version4Options | undefined,
buf: TBuf,
offset?: number,
): TBuf;
function v4<TBuf extends Uint8Array = Uint8Array>(
options?: Version4Options,
buf?: TBuf,
offset?: number,
): UUIDTypes<TBuf> {
if (!buf && !options && crypto.randomUUID) {
return crypto.randomUUID();
}
// Putting tail-code that could just go inline here in a separate function to
// enable compiler optimizations that dramatically improve performance.
//
// REF: https://github.com/uuidjs/uuid/issues/892
return _v4(options, buf, offset);
}
function _v4<TBuf extends Uint8Array = Uint8Array>(
options?: Version4Options,
buf?: TBuf,
@@ -37,31 +62,4 @@ function _v4<TBuf extends Uint8Array = Uint8Array>(
return unsafeStringify(rnds);
}
function v4(
options?: Version4Options,
buf?: undefined,
offset?: number,
): string;
function v4<TBuf extends Uint8Array = Uint8Array>(
options: Version4Options | undefined,
buf: TBuf,
offset?: number,
): TBuf;
function v4<TBuf extends Uint8Array = Uint8Array>(
options?: Version4Options,
buf?: TBuf,
offset?: number,
): UUIDTypes<TBuf> {
if (native.randomUUID && !buf && !options) {
return native.randomUUID();
}
// Putting tail-code that could just go inline here in a separate function
// allows for compiler optimizations that dramatically improve performance.
//
// REF: https://github.com/uuidjs/uuid/issues/892
return _v4(options, buf, offset);
}
export default v4;
+1 -1
View File
@@ -57,7 +57,7 @@ const capabilities = [
'bstack:options': {
...commonCapabilities,
os: 'OS X',
osVersion: 'Monterey',
osVersion: 'Tahoe',
},
},
];