mirror of
https://github.com/nodejs/node.git
synced 2025-04-29 06:19:07 +00:00

Store all primordials as properties of the primordials object. Static functions are prefixed by the constructor's name and prototype methods are prefixed by the constructor's name followed by "Prototype". For example: primordials.Object.keys becomes primordials.ObjectKeys. PR-URL: https://github.com/nodejs/node/pull/30610 Refs: https://github.com/nodejs/node/issues/29766 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
130 lines
3.4 KiB
JavaScript
130 lines
3.4 KiB
JavaScript
'use strict';
|
|
|
|
const {
|
|
MathMin,
|
|
} = primordials;
|
|
|
|
const { AsyncWrap, Providers } = internalBinding('async_wrap');
|
|
const { Buffer, kMaxLength } = require('buffer');
|
|
const { randomBytes: _randomBytes } = internalBinding('crypto');
|
|
const {
|
|
ERR_INVALID_ARG_TYPE,
|
|
ERR_INVALID_CALLBACK,
|
|
ERR_OUT_OF_RANGE
|
|
} = require('internal/errors').codes;
|
|
const { validateNumber } = require('internal/validators');
|
|
const { isArrayBufferView } = require('internal/util/types');
|
|
|
|
const kMaxUint32 = 2 ** 32 - 1;
|
|
const kMaxPossibleLength = MathMin(kMaxLength, kMaxUint32);
|
|
|
|
function assertOffset(offset, elementSize, length) {
|
|
validateNumber(offset, 'offset');
|
|
offset *= elementSize;
|
|
|
|
const maxLength = MathMin(length, kMaxPossibleLength);
|
|
if (Number.isNaN(offset) || offset > maxLength || offset < 0) {
|
|
throw new ERR_OUT_OF_RANGE('offset', `>= 0 && <= ${maxLength}`, offset);
|
|
}
|
|
|
|
return offset >>> 0; // Convert to uint32.
|
|
}
|
|
|
|
function assertSize(size, elementSize, offset, length) {
|
|
validateNumber(size, 'size');
|
|
size *= elementSize;
|
|
|
|
if (Number.isNaN(size) || size > kMaxPossibleLength || size < 0) {
|
|
throw new ERR_OUT_OF_RANGE('size',
|
|
`>= 0 && <= ${kMaxPossibleLength}`, size);
|
|
}
|
|
|
|
if (size + offset > length) {
|
|
throw new ERR_OUT_OF_RANGE('size + offset', `<= ${length}`, size + offset);
|
|
}
|
|
|
|
return size >>> 0; // Convert to uint32.
|
|
}
|
|
|
|
function randomBytes(size, cb) {
|
|
size = assertSize(size, 1, 0, Infinity);
|
|
if (cb !== undefined && typeof cb !== 'function')
|
|
throw new ERR_INVALID_CALLBACK(cb);
|
|
|
|
const buf = Buffer.alloc(size);
|
|
|
|
if (!cb) return handleError(_randomBytes(buf, 0, size), buf);
|
|
|
|
const wrap = new AsyncWrap(Providers.RANDOMBYTESREQUEST);
|
|
wrap.ondone = (ex) => { // Retains buf while request is in flight.
|
|
if (ex) return cb.call(wrap, ex);
|
|
cb.call(wrap, null, buf);
|
|
};
|
|
|
|
_randomBytes(buf, 0, size, wrap);
|
|
}
|
|
|
|
function randomFillSync(buf, offset = 0, size) {
|
|
if (!isArrayBufferView(buf)) {
|
|
throw new ERR_INVALID_ARG_TYPE('buf', 'ArrayBufferView', buf);
|
|
}
|
|
|
|
const elementSize = buf.BYTES_PER_ELEMENT || 1;
|
|
|
|
offset = assertOffset(offset, elementSize, buf.byteLength);
|
|
|
|
if (size === undefined) {
|
|
size = buf.byteLength - offset;
|
|
} else {
|
|
size = assertSize(size, elementSize, offset, buf.byteLength);
|
|
}
|
|
|
|
return handleError(_randomBytes(buf, offset, size), buf);
|
|
}
|
|
|
|
function randomFill(buf, offset, size, cb) {
|
|
if (!isArrayBufferView(buf)) {
|
|
throw new ERR_INVALID_ARG_TYPE('buf', 'ArrayBufferView', buf);
|
|
}
|
|
|
|
const elementSize = buf.BYTES_PER_ELEMENT || 1;
|
|
|
|
if (typeof offset === 'function') {
|
|
cb = offset;
|
|
offset = 0;
|
|
size = buf.bytesLength;
|
|
} else if (typeof size === 'function') {
|
|
cb = size;
|
|
size = buf.byteLength - offset;
|
|
} else if (typeof cb !== 'function') {
|
|
throw new ERR_INVALID_CALLBACK(cb);
|
|
}
|
|
|
|
offset = assertOffset(offset, elementSize, buf.byteLength);
|
|
|
|
if (size === undefined) {
|
|
size = buf.byteLength - offset;
|
|
} else {
|
|
size = assertSize(size, elementSize, offset, buf.byteLength);
|
|
}
|
|
|
|
const wrap = new AsyncWrap(Providers.RANDOMBYTESREQUEST);
|
|
wrap.ondone = (ex) => { // Retains buf while request is in flight.
|
|
if (ex) return cb.call(wrap, ex);
|
|
cb.call(wrap, null, buf);
|
|
};
|
|
|
|
_randomBytes(buf, offset, size, wrap);
|
|
}
|
|
|
|
function handleError(ex, buf) {
|
|
if (ex) throw ex;
|
|
return buf;
|
|
}
|
|
|
|
module.exports = {
|
|
randomBytes,
|
|
randomFill,
|
|
randomFillSync
|
|
};
|