current commit
261015.10 · stream: avoid per-write allocations in stream/iter writers
'use strict';

const {
  converters: baseConverters,
  convertToInt,
  createDictionaryConverter,
  createEnumConverter,
  createSequenceConverter,
} = require('internal/webidl');
// Load AbortSignal to register its Web IDL converter in baseConverters.
require('internal/abort_controller');
const { isUint8Array } = require('internal/util/types');

const converters = { __proto__: null };

function unsignedLongLong(value, options) {
  return convertToInt(value, 64, 'unsigned', options);
}

function enforceRangeUnsignedLongLong(value, options = { __proto__: null }) {
  return convertToInt(value, 64, 'unsigned', {
    __proto__: null,
    prefix: options.prefix,
    context: options.context,
    code: options.code,
    enforceRange: true,
  });
}

converters.AbortSignal = baseConverters.AbortSignal;
converters.BackpressurePolicy = createEnumConverter('BackpressurePolicy', [
  'strict',
  'unbounded',
  'drop-oldest',
  'drop-newest',
]);
converters.unsignedLongLong = unsignedLongLong;
converters.enforceRangeUnsignedLongLong = enforceRangeUnsignedLongLong;
converters.WriterChunk = (value, options = { __proto__: null }) => {
  // The chunk is a Uint8Array with [AllowShared] and [AllowResizable]. The
  // Uint8Array conversion cannot reject a value isUint8Array() accepts when
  // both are allowed, and returns the same object, so skip it: writes are
  // hot, and the conversion would need its own options object.
  if (isUint8Array(value)) return value;
  return baseConverters.USVString(value, options);
};
converters.WriterChunkSequence = createSequenceConverter(
  converters.WriterChunk);

const signalMember = {
  __proto__: null,
  key: 'signal',
  converter: converters.AbortSignal,
};
const budgetMember = {
  __proto__: null,
  key: 'budget',
  converter: converters.unsignedLongLong,
};
const backpressureMember = {
  __proto__: null,
  key: 'backpressure',
  converter: converters.BackpressurePolicy,
  defaultValue: () => 'strict',
};
const limitMember = {
  __proto__: null,
  key: 'limit',
  converter: converters.enforceRangeUnsignedLongLong,
};

converters.WriteOptions = createDictionaryConverter('WriteOptions', [
  signalMember,
]);
converters.PushStreamOptions = createDictionaryConverter(
  'PushStreamOptions', [budgetMember, backpressureMember, signalMember]);
converters.PullOptions = createDictionaryConverter('PullOptions', [
  signalMember,
]);
converters.PipeToOptions = createDictionaryConverter('PipeToOptions', [
  {
    __proto__: null,
    key: 'preventClose',
    converter: baseConverters.boolean,
    defaultValue: () => false,
  },
  {
    __proto__: null,
    key: 'preventFail',
    converter: baseConverters.boolean,
    defaultValue: () => false,
  },
  signalMember,
]);
converters.PipeToSyncOptions = createDictionaryConverter(
  'PipeToSyncOptions', [
    // Node.js extension.
    {
      __proto__: null,
      key: 'failOnIncompleteClose',
      converter: baseConverters.boolean,
      defaultValue: () => false,
    },
    {
      __proto__: null,
      key: 'preventClose',
      converter: baseConverters.boolean,
      defaultValue: () => false,
    },
    {
      __proto__: null,
      key: 'preventFail',
      converter: baseConverters.boolean,
      defaultValue: () => false,
    },
  ]);
converters.ConsumeOptions = createDictionaryConverter('ConsumeOptions', [
  limitMember,
  signalMember,
]);
converters.ConsumeSyncOptions = createDictionaryConverter(
  'ConsumeSyncOptions', [limitMember]);
const encodingMember = {
  __proto__: null,
  key: 'encoding',
  converter: baseConverters.DOMString,
  defaultValue: () => 'utf-8',
};
converters.TextConsumeOptions = createDictionaryConverter(
  'TextConsumeOptions', [
    [limitMember, signalMember],
    [encodingMember],
  ]);
converters.TextConsumeSyncOptions = createDictionaryConverter(
  'TextConsumeSyncOptions', [
    [limitMember],
    [encodingMember],
  ]);
converters.MergeOptions = createDictionaryConverter('MergeOptions', [
  signalMember,
]);
converters.BroadcastOptions = createDictionaryConverter(
  'BroadcastOptions', [budgetMember, backpressureMember, signalMember]);
converters.ShareOptions = createDictionaryConverter(
  'ShareOptions', [budgetMember, backpressureMember, signalMember]);
converters.ShareSyncOptions = createDictionaryConverter(
  'ShareSyncOptions', [budgetMember, backpressureMember]);
converters.DuplexDirectionOptions = createDictionaryConverter(
  'DuplexDirectionOptions', [
    budgetMember,
    {
      __proto__: null,
      key: 'backpressure',
      converter: converters.BackpressurePolicy,
    },
  ]);
converters.DuplexOptions = createDictionaryConverter('DuplexOptions', [
  {
    __proto__: null,
    key: 'a',
    converter: converters.DuplexDirectionOptions,
  },
  {
    __proto__: null,
    key: 'b',
    converter: converters.DuplexDirectionOptions,
  },
  budgetMember,
  backpressureMember,
  signalMember,
]);

module.exports = { converters };