• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2
3const {
4  ArrayBufferPrototypeSlice,
5  ArrayPrototypePush,
6  ArrayPrototypeShift,
7  AsyncIteratorPrototype,
8  FunctionPrototypeCall,
9  MathMax,
10  NumberIsNaN,
11  ObjectCreate,
12  PromisePrototypeThen,
13  PromiseResolve,
14  PromiseReject,
15  ReflectGet,
16  Symbol,
17  Uint8Array,
18} = primordials;
19
20const {
21  codes: {
22    ERR_INVALID_ARG_VALUE,
23    ERR_OPERATION_FAILED,
24  },
25} = require('internal/errors');
26
27const {
28  copyArrayBuffer,
29  detachArrayBuffer,
30} = internalBinding('buffer');
31
32const {
33  isPromise,
34} = require('internal/util/types');
35
36const {
37  inspect,
38} = require('util');
39
40const {
41  constants: {
42    kPending,
43  },
44  getPromiseDetails,
45} = internalBinding('util');
46
47const assert = require('internal/assert');
48const { isArrayBufferDetached } = require('internal/util');
49
50const {
51  validateFunction,
52} = require('internal/validators');
53
54const kState = Symbol('kState');
55const kType = Symbol('kType');
56
57const AsyncIterator = ObjectCreate(AsyncIteratorPrototype, {
58  next: {
59    __proto__: null,
60    configurable: true,
61    enumerable: true,
62    writable: true,
63  },
64  return: {
65    __proto__: null,
66    configurable: true,
67    enumerable: true,
68    writable: true,
69  },
70});
71
72function extractHighWaterMark(value, defaultHWM) {
73  if (value === undefined) return defaultHWM;
74  value = +value;
75  if (typeof value !== 'number' ||
76      NumberIsNaN(value) ||
77      value < 0)
78    throw new ERR_INVALID_ARG_VALUE.RangeError('strategy.highWaterMark', value);
79  return value;
80}
81
82function extractSizeAlgorithm(size) {
83  if (size === undefined) return () => 1;
84  validateFunction(size, 'strategy.size');
85  return size;
86}
87
88function customInspect(depth, options, name, data) {
89  if (depth < 0)
90    return this;
91
92  const opts = {
93    ...options,
94    depth: options.depth == null ? null : options.depth - 1,
95  };
96
97  return `${name} ${inspect(data, opts)}`;
98}
99
100// These are defensive to work around the possibility that
101// the buffer, byteLength, and byteOffset properties on
102// ArrayBuffer and ArrayBufferView's may have been tampered with.
103
104function ArrayBufferViewGetBuffer(view) {
105  return ReflectGet(view.constructor.prototype, 'buffer', view);
106}
107
108function ArrayBufferViewGetByteLength(view) {
109  return ReflectGet(view.constructor.prototype, 'byteLength', view);
110}
111
112function ArrayBufferViewGetByteOffset(view) {
113  return ReflectGet(view.constructor.prototype, 'byteOffset', view);
114}
115
116function cloneAsUint8Array(view) {
117  const buffer = ArrayBufferViewGetBuffer(view);
118  const byteOffset = ArrayBufferViewGetByteOffset(view);
119  const byteLength = ArrayBufferViewGetByteLength(view);
120  return new Uint8Array(
121    ArrayBufferPrototypeSlice(buffer, byteOffset, byteOffset + byteLength),
122  );
123}
124
125function isBrandCheck(brand) {
126  return (value) => {
127    return value != null &&
128           value[kState] !== undefined &&
129           value[kType] === brand;
130  };
131}
132
133function transferArrayBuffer(buffer) {
134  const res = detachArrayBuffer(buffer);
135  if (res === undefined) {
136    throw new ERR_OPERATION_FAILED.TypeError(
137      'The ArrayBuffer could not be transferred');
138  }
139  return res;
140}
141
142function isViewedArrayBufferDetached(view) {
143  return (
144    ArrayBufferViewGetByteLength(view) === 0 &&
145    isArrayBufferDetached(ArrayBufferViewGetBuffer(view))
146  );
147}
148
149function dequeueValue(controller) {
150  assert(controller[kState].queue !== undefined);
151  assert(controller[kState].queueTotalSize !== undefined);
152  assert(controller[kState].queue.length);
153  const {
154    value,
155    size,
156  } = ArrayPrototypeShift(controller[kState].queue);
157  controller[kState].queueTotalSize =
158    MathMax(0, controller[kState].queueTotalSize - size);
159  return value;
160}
161
162function resetQueue(controller) {
163  assert(controller[kState].queue !== undefined);
164  assert(controller[kState].queueTotalSize !== undefined);
165  controller[kState].queue = [];
166  controller[kState].queueTotalSize = 0;
167}
168
169function peekQueueValue(controller) {
170  assert(controller[kState].queue !== undefined);
171  assert(controller[kState].queueTotalSize !== undefined);
172  assert(controller[kState].queue.length);
173  return controller[kState].queue[0].value;
174}
175
176function enqueueValueWithSize(controller, value, size) {
177  assert(controller[kState].queue !== undefined);
178  assert(controller[kState].queueTotalSize !== undefined);
179  size = +size;
180  if (typeof size !== 'number' ||
181      size < 0 ||
182      NumberIsNaN(size) ||
183      size === Infinity) {
184    throw new ERR_INVALID_ARG_VALUE.RangeError('size', size);
185  }
186  ArrayPrototypePush(controller[kState].queue, { value, size });
187  controller[kState].queueTotalSize += size;
188}
189
190function ensureIsPromise(fn, thisArg, ...args) {
191  try {
192    const value = FunctionPrototypeCall(fn, thisArg, ...args);
193    return isPromise(value) ? value : PromiseResolve(value);
194  } catch (error) {
195    return PromiseReject(error);
196  }
197}
198
199function isPromisePending(promise) {
200  if (promise === undefined) return false;
201  const details = getPromiseDetails(promise);
202  return details?.[0] === kPending;
203}
204
205function setPromiseHandled(promise) {
206  // Alternatively, we could use the native API
207  // MarkAsHandled, but this avoids the extra boundary cross
208  // and is hopefully faster at the cost of an extra Promise
209  // allocation.
210  PromisePrototypeThen(promise, () => {}, () => {});
211}
212
213async function nonOpFlush() {}
214
215function nonOpStart() {}
216
217async function nonOpPull() {}
218
219async function nonOpCancel() {}
220
221async function nonOpWrite() {}
222
223let transfer;
224function lazyTransfer() {
225  if (transfer === undefined)
226    transfer = require('internal/webstreams/transfer');
227  return transfer;
228}
229
230module.exports = {
231  ArrayBufferViewGetBuffer,
232  ArrayBufferViewGetByteLength,
233  ArrayBufferViewGetByteOffset,
234  AsyncIterator,
235  cloneAsUint8Array,
236  copyArrayBuffer,
237  customInspect,
238  dequeueValue,
239  ensureIsPromise,
240  enqueueValueWithSize,
241  extractHighWaterMark,
242  extractSizeAlgorithm,
243  lazyTransfer,
244  isBrandCheck,
245  isPromisePending,
246  isViewedArrayBufferDetached,
247  peekQueueValue,
248  resetQueue,
249  setPromiseHandled,
250  transferArrayBuffer,
251  nonOpCancel,
252  nonOpFlush,
253  nonOpPull,
254  nonOpStart,
255  nonOpWrite,
256  kType,
257  kState,
258};
259