Commit updated Javascript packages
This commit is contained in:
69
build/javascript/node_modules/@videojs/vhs-utils/src/byte-helpers.js
generated
vendored
Normal file
69
build/javascript/node_modules/@videojs/vhs-utils/src/byte-helpers.js
generated
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
export const isTypedArray = (obj) => ArrayBuffer.isView(obj);
|
||||
export const toUint8 = (bytes) => (bytes instanceof Uint8Array) ?
|
||||
bytes :
|
||||
new Uint8Array(
|
||||
bytes && bytes.buffer || bytes,
|
||||
bytes && bytes.byteOffset || 0,
|
||||
bytes && bytes.byteLength || 0
|
||||
);
|
||||
|
||||
export const bytesToString = (bytes) => {
|
||||
if (!bytes) {
|
||||
return '';
|
||||
}
|
||||
|
||||
bytes = Array.prototype.slice.call(bytes);
|
||||
|
||||
const string = String.fromCharCode.apply(null, toUint8(bytes));
|
||||
|
||||
try {
|
||||
return decodeURIComponent(escape(string));
|
||||
} catch (e) {
|
||||
// if decodeURIComponent/escape fails, we are dealing with partial
|
||||
// or full non string data. Just return the potentially garbled string.
|
||||
}
|
||||
|
||||
return string;
|
||||
};
|
||||
|
||||
export const stringToBytes = (string, stringIsBytes = false) => {
|
||||
const bytes = [];
|
||||
|
||||
if (typeof string !== 'string' && string && typeof string.toString === 'function') {
|
||||
string = string.toString();
|
||||
}
|
||||
|
||||
if (typeof string !== 'string') {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
// If the string already is bytes, we don't have to do this
|
||||
if (!stringIsBytes) {
|
||||
string = unescape(encodeURIComponent(string));
|
||||
}
|
||||
|
||||
return string.split('').map((s) => s.charCodeAt(0) & 0xFF);
|
||||
};
|
||||
|
||||
export const concatTypedArrays = (...buffers) => {
|
||||
const totalLength = buffers.reduce((total, buf) => {
|
||||
const len = buf && (buf.byteLength || buf.length);
|
||||
|
||||
total += len || 0;
|
||||
|
||||
return total;
|
||||
}, 0);
|
||||
|
||||
const tempBuffer = new Uint8Array(totalLength);
|
||||
|
||||
let offset = 0;
|
||||
|
||||
buffers.forEach(function(buf) {
|
||||
buf = toUint8(buf);
|
||||
|
||||
tempBuffer.set(buf, offset);
|
||||
offset += buf.byteLength;
|
||||
});
|
||||
|
||||
return tempBuffer;
|
||||
};
|
||||
198
build/javascript/node_modules/@videojs/vhs-utils/src/codecs.js
generated
vendored
Normal file
198
build/javascript/node_modules/@videojs/vhs-utils/src/codecs.js
generated
vendored
Normal file
@@ -0,0 +1,198 @@
|
||||
import window from 'global/window';
|
||||
|
||||
const regexs = {
|
||||
// to determine mime types
|
||||
mp4: /^(av0?1|avc0?[1234]|vp0?9|flac|opus|mp3|mp4a|mp4v)/,
|
||||
webm: /^(vp0?[89]|av0?1|opus|vorbis)/,
|
||||
ogg: /^(vp0?[89]|theora|flac|opus|vorbis)/,
|
||||
|
||||
// to determine if a codec is audio or video
|
||||
video: /^(av0?1|avc0?[1234]|vp0?[89]|hvc1|hev1|theora|mp4v)/,
|
||||
audio: /^(mp4a|flac|vorbis|opus|ac-[34]|ec-3|alac|mp3)/,
|
||||
|
||||
// mux.js support regex
|
||||
muxerVideo: /^(avc0?1)/,
|
||||
muxerAudio: /^(mp4a)/
|
||||
};
|
||||
|
||||
/**
|
||||
* Replace the old apple-style `avc1.<dd>.<dd>` codec string with the standard
|
||||
* `avc1.<hhhhhh>`
|
||||
*
|
||||
* @param {string} codec
|
||||
* Codec string to translate
|
||||
* @return {string}
|
||||
* The translated codec string
|
||||
*/
|
||||
export const translateLegacyCodec = function(codec) {
|
||||
if (!codec) {
|
||||
return codec;
|
||||
}
|
||||
|
||||
return codec.replace(/avc1\.(\d+)\.(\d+)/i, function(orig, profile, avcLevel) {
|
||||
const profileHex = ('00' + Number(profile).toString(16)).slice(-2);
|
||||
const avcLevelHex = ('00' + Number(avcLevel).toString(16)).slice(-2);
|
||||
|
||||
return 'avc1.' + profileHex + '00' + avcLevelHex;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Replace the old apple-style `avc1.<dd>.<dd>` codec strings with the standard
|
||||
* `avc1.<hhhhhh>`
|
||||
*
|
||||
* @param {string[]} codecs
|
||||
* An array of codec strings to translate
|
||||
* @return {string[]}
|
||||
* The translated array of codec strings
|
||||
*/
|
||||
export const translateLegacyCodecs = function(codecs) {
|
||||
return codecs.map(translateLegacyCodec);
|
||||
};
|
||||
|
||||
/**
|
||||
* Replace codecs in the codec string with the old apple-style `avc1.<dd>.<dd>` to the
|
||||
* standard `avc1.<hhhhhh>`.
|
||||
*
|
||||
* @param {string} codecString
|
||||
* The codec string
|
||||
* @return {string}
|
||||
* The codec string with old apple-style codecs replaced
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
export const mapLegacyAvcCodecs = function(codecString) {
|
||||
return codecString.replace(/avc1\.(\d+)\.(\d+)/i, (match) => {
|
||||
return translateLegacyCodecs([match])[0];
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @typedef {Object} ParsedCodecInfo
|
||||
* @property {number} codecCount
|
||||
* Number of codecs parsed
|
||||
* @property {string} [videoCodec]
|
||||
* Parsed video codec (if found)
|
||||
* @property {string} [videoObjectTypeIndicator]
|
||||
* Video object type indicator (if found)
|
||||
* @property {string|null} audioProfile
|
||||
* Audio profile
|
||||
*/
|
||||
|
||||
/**
|
||||
* Parses a codec string to retrieve the number of codecs specified, the video codec and
|
||||
* object type indicator, and the audio profile.
|
||||
*
|
||||
* @param {string} [codecString]
|
||||
* The codec string to parse
|
||||
* @return {ParsedCodecInfo}
|
||||
* Parsed codec info
|
||||
*/
|
||||
export const parseCodecs = function(codecString = '') {
|
||||
const codecs = codecString.split(',');
|
||||
const result = {};
|
||||
|
||||
codecs.forEach(function(codec) {
|
||||
codec = codec.trim();
|
||||
|
||||
['video', 'audio'].forEach(function(name) {
|
||||
const match = regexs[name].exec(codec.toLowerCase());
|
||||
|
||||
if (!match || match.length <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// maintain codec case
|
||||
const type = codec.substring(0, match[1].length);
|
||||
const details = codec.replace(type, '');
|
||||
|
||||
result[name] = {type, details};
|
||||
});
|
||||
});
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a ParsedCodecInfo object for the default alternate audio playlist if there is
|
||||
* a default alternate audio playlist for the provided audio group.
|
||||
*
|
||||
* @param {Object} master
|
||||
* The master playlist
|
||||
* @param {string} audioGroupId
|
||||
* ID of the audio group for which to find the default codec info
|
||||
* @return {ParsedCodecInfo}
|
||||
* Parsed codec info
|
||||
*/
|
||||
export const codecsFromDefault = (master, audioGroupId) => {
|
||||
if (!master.mediaGroups.AUDIO || !audioGroupId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const audioGroup = master.mediaGroups.AUDIO[audioGroupId];
|
||||
|
||||
if (!audioGroup) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (const name in audioGroup) {
|
||||
const audioType = audioGroup[name];
|
||||
|
||||
if (audioType.default && audioType.playlists) {
|
||||
// codec should be the same for all playlists within the audio type
|
||||
return parseCodecs(audioType.playlists[0].attributes.CODECS);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
export const isVideoCodec = (codec = '') => regexs.video.test(codec.trim().toLowerCase());
|
||||
export const isAudioCodec = (codec = '') => regexs.audio.test(codec.trim().toLowerCase());
|
||||
|
||||
export const getMimeForCodec = (codecString) => {
|
||||
if (!codecString || typeof codecString !== 'string') {
|
||||
return;
|
||||
}
|
||||
const codecs = codecString
|
||||
.toLowerCase()
|
||||
.split(',')
|
||||
.map((c) => translateLegacyCodec(c.trim()));
|
||||
|
||||
// default to video type
|
||||
let type = 'video';
|
||||
|
||||
// only change to audio type if the only codec we have is
|
||||
// audio
|
||||
if (codecs.length === 1 && isAudioCodec(codecs[0])) {
|
||||
type = 'audio';
|
||||
}
|
||||
|
||||
// default the container to mp4
|
||||
let container = 'mp4';
|
||||
|
||||
// every codec must be able to go into the container
|
||||
// for that container to be the correct one
|
||||
if (codecs.every((c) => regexs.mp4.test(c))) {
|
||||
container = 'mp4';
|
||||
} else if (codecs.every((c) => regexs.webm.test(c))) {
|
||||
container = 'webm';
|
||||
} else if (codecs.every((c) => regexs.ogg.test(c))) {
|
||||
container = 'ogg';
|
||||
}
|
||||
|
||||
return `${type}/${container};codecs="${codecString}"`;
|
||||
};
|
||||
|
||||
export const browserSupportsCodec = (codecString = '') => window.MediaSource &&
|
||||
window.MediaSource.isTypeSupported &&
|
||||
window.MediaSource.isTypeSupported(getMimeForCodec(codecString)) || false;
|
||||
|
||||
export const muxerSupportsCodec = (codecString = '') => codecString.toLowerCase().split(',').every((codec) => {
|
||||
codec = codec.trim();
|
||||
|
||||
return regexs.muxerVideo.test(codec) || regexs.muxerAudio.test(codec);
|
||||
});
|
||||
|
||||
export const DEFAULT_AUDIO_CODEC = 'mp4a.40.2';
|
||||
export const DEFAULT_VIDEO_CODEC = 'avc1.4d400d';
|
||||
154
build/javascript/node_modules/@videojs/vhs-utils/src/containers.js
generated
vendored
Normal file
154
build/javascript/node_modules/@videojs/vhs-utils/src/containers.js
generated
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
import {bytesToString, toUint8} from './byte-helpers.js';
|
||||
|
||||
export const id3Size = function(bytes, offset = 0) {
|
||||
bytes = toUint8(bytes);
|
||||
|
||||
const returnSize = (bytes[offset + 6] << 21) |
|
||||
(bytes[offset + 7] << 14) |
|
||||
(bytes[offset + 8] << 7) |
|
||||
(bytes[offset + 9]);
|
||||
const flags = bytes[offset + 5];
|
||||
const footerPresent = (flags & 16) >> 4;
|
||||
|
||||
if (footerPresent) {
|
||||
return returnSize + 20;
|
||||
}
|
||||
|
||||
return returnSize + 10;
|
||||
};
|
||||
|
||||
export const getId3Offset = function(bytes, offset = 0) {
|
||||
bytes = toUint8(bytes);
|
||||
|
||||
if ((bytes.length - offset) < 10 || bytesToString(bytes.subarray(offset, offset + 3)) !== 'ID3') {
|
||||
return offset;
|
||||
}
|
||||
|
||||
offset += id3Size(bytes, offset);
|
||||
|
||||
// recursive check for id3 tags as some files
|
||||
// have multiple ID3 tag sections even though
|
||||
// they should not.
|
||||
return getId3Offset(bytes, offset);
|
||||
};
|
||||
|
||||
export const isLikely = {
|
||||
aac(bytes) {
|
||||
const offset = getId3Offset(bytes);
|
||||
|
||||
return bytes.length >= offset + 2 &&
|
||||
(bytes[offset] & 0xFF) === 0xFF &&
|
||||
(bytes[offset + 1] & 0xE0) === 0xE0 &&
|
||||
(bytes[offset + 1] & 0x16) === 0x10;
|
||||
},
|
||||
|
||||
mp3(bytes) {
|
||||
const offset = getId3Offset(bytes);
|
||||
|
||||
return bytes.length >= offset + 2 &&
|
||||
(bytes[offset] & 0xFF) === 0xFF &&
|
||||
(bytes[offset + 1] & 0xE0) === 0xE0 &&
|
||||
(bytes[offset + 1] & 0x06) === 0x02;
|
||||
},
|
||||
|
||||
webm(bytes) {
|
||||
return bytes.length >= 4 &&
|
||||
(bytes[0] & 0xFF) === 0x1A &&
|
||||
(bytes[1] & 0xFF) === 0x45 &&
|
||||
(bytes[2] & 0xFF) === 0xDF &&
|
||||
(bytes[3] & 0xFF) === 0xA3;
|
||||
},
|
||||
|
||||
mp4(bytes) {
|
||||
return bytes.length >= 8 &&
|
||||
(/^(f|s)typ$/).test(bytesToString(bytes.subarray(4, 8))) &&
|
||||
// not 3gp data
|
||||
!(/^ftyp3g$/).test(bytesToString(bytes.subarray(4, 10)));
|
||||
},
|
||||
|
||||
'3gp'(bytes) {
|
||||
return bytes.length >= 10 &&
|
||||
(/^ftyp3g$/).test(bytesToString(bytes.subarray(4, 10)));
|
||||
},
|
||||
|
||||
ts(bytes) {
|
||||
if (bytes.length < 189 && bytes.length >= 1) {
|
||||
return bytes[0] === 0x47;
|
||||
}
|
||||
|
||||
let i = 0;
|
||||
|
||||
// check the first 376 bytes for two matching sync bytes
|
||||
while (i + 188 < bytes.length && i < 188) {
|
||||
if (bytes[i] === 0x47 && bytes[i + 188] === 0x47) {
|
||||
return true;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
flac(bytes) {
|
||||
return bytes.length >= 4 &&
|
||||
(/^fLaC$/).test(bytesToString(bytes.subarray(0, 4)));
|
||||
},
|
||||
ogg(bytes) {
|
||||
return bytes.length >= 4 &&
|
||||
(/^OggS$/).test(bytesToString(bytes.subarray(0, 4)));
|
||||
}
|
||||
};
|
||||
|
||||
// get all the isLikely functions
|
||||
// but make sure 'ts' is at the bottom
|
||||
// as it is the least specific
|
||||
const isLikelyTypes = Object.keys(isLikely)
|
||||
// remove ts
|
||||
.filter((t) => t !== 'ts')
|
||||
// add it back to the bottom
|
||||
.concat('ts');
|
||||
|
||||
// make sure we are dealing with uint8 data.
|
||||
isLikelyTypes.forEach(function(type) {
|
||||
const isLikelyFn = isLikely[type];
|
||||
|
||||
isLikely[type] = (bytes) => isLikelyFn(toUint8(bytes));
|
||||
});
|
||||
|
||||
// A useful list of file signatures can be found here
|
||||
// https://en.wikipedia.org/wiki/List_of_file_signatures
|
||||
export const detectContainerForBytes = (bytes) => {
|
||||
bytes = toUint8(bytes);
|
||||
|
||||
for (let i = 0; i < isLikelyTypes.length; i++) {
|
||||
const type = isLikelyTypes[i];
|
||||
|
||||
if (isLikely[type](bytes)) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
};
|
||||
|
||||
// fmp4 is not a container
|
||||
export const isLikelyFmp4MediaSegment = (bytes) => {
|
||||
bytes = toUint8(bytes);
|
||||
let i = 0;
|
||||
|
||||
while (i < bytes.length) {
|
||||
const size = (bytes[i] << 24 | bytes[i + 1] << 16 | bytes[i + 2] << 8 | bytes[i + 3]) >>> 0;
|
||||
const type = bytesToString(bytes.subarray(i + 4, i + 8));
|
||||
|
||||
if (type === 'moof') {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (size === 0 || (size + i) > bytes.length) {
|
||||
i = bytes.length;
|
||||
} else {
|
||||
i += size;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
13
build/javascript/node_modules/@videojs/vhs-utils/src/decode-b64-to-uint8-array.js
generated
vendored
Normal file
13
build/javascript/node_modules/@videojs/vhs-utils/src/decode-b64-to-uint8-array.js
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
import window from 'global/window';
|
||||
|
||||
const atob = (s) => window.atob ? window.atob(s) : Buffer.from(s, 'base64').toString('binary');
|
||||
|
||||
export default function decodeB64ToUint8Array(b64Text) {
|
||||
const decodedString = atob(b64Text);
|
||||
const array = new Uint8Array(decodedString.length);
|
||||
|
||||
for (let i = 0; i < decodedString.length; i++) {
|
||||
array[i] = decodedString.charCodeAt(i);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
22
build/javascript/node_modules/@videojs/vhs-utils/src/media-groups.js
generated
vendored
Normal file
22
build/javascript/node_modules/@videojs/vhs-utils/src/media-groups.js
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Loops through all supported media groups in master and calls the provided
|
||||
* callback for each group
|
||||
*
|
||||
* @param {Object} master
|
||||
* The parsed master manifest object
|
||||
* @param {string[]} groups
|
||||
* The media groups to call the callback for
|
||||
* @param {Function} callback
|
||||
* Callback to call for each media group
|
||||
*/
|
||||
export const forEachMediaGroup = (master, groups, callback) => {
|
||||
groups.forEach((mediaType) => {
|
||||
for (const groupKey in master.mediaGroups[mediaType]) {
|
||||
for (const labelKey in master.mediaGroups[mediaType][groupKey]) {
|
||||
const mediaProperties = master.mediaGroups[mediaType][groupKey][labelKey];
|
||||
|
||||
callback(mediaProperties, mediaType, groupKey, labelKey);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
36
build/javascript/node_modules/@videojs/vhs-utils/src/media-types.js
generated
vendored
Normal file
36
build/javascript/node_modules/@videojs/vhs-utils/src/media-types.js
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
const MPEGURL_REGEX = /^(audio|video|application)\/(x-|vnd\.apple\.)?mpegurl/i;
|
||||
const DASH_REGEX = /^application\/dash\+xml/i;
|
||||
|
||||
/**
|
||||
* Returns a string that describes the type of source based on a video source object's
|
||||
* media type.
|
||||
*
|
||||
* @see {@link https://dev.w3.org/html5/pf-summary/video.html#dom-source-type|Source Type}
|
||||
*
|
||||
* @param {string} type
|
||||
* Video source object media type
|
||||
* @return {('hls'|'dash'|'vhs-json'|null)}
|
||||
* VHS source type string
|
||||
*/
|
||||
export const simpleTypeFromSourceType = (type) => {
|
||||
if (MPEGURL_REGEX.test(type)) {
|
||||
return 'hls';
|
||||
}
|
||||
|
||||
if (DASH_REGEX.test(type)) {
|
||||
return 'dash';
|
||||
}
|
||||
|
||||
// Denotes the special case of a manifest object passed to http-streaming instead of a
|
||||
// source URL.
|
||||
//
|
||||
// See https://en.wikipedia.org/wiki/Media_type for details on specifying media types.
|
||||
//
|
||||
// In this case, vnd stands for vendor, video.js for the organization, VHS for this
|
||||
// project, and the +json suffix identifies the structure of the media type.
|
||||
if (type === 'application/vnd.videojs.vhs+json') {
|
||||
return 'vhs-json';
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
18
build/javascript/node_modules/@videojs/vhs-utils/src/resolve-url.js
generated
vendored
Normal file
18
build/javascript/node_modules/@videojs/vhs-utils/src/resolve-url.js
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
import URLToolkit from 'url-toolkit';
|
||||
import window from 'global/window';
|
||||
|
||||
const resolveUrl = (baseUrl, relativeUrl) => {
|
||||
// return early if we don't need to resolve
|
||||
if ((/^[a-z]+:/i).test(relativeUrl)) {
|
||||
return relativeUrl;
|
||||
}
|
||||
|
||||
// if the base URL is relative then combine with the current location
|
||||
if (!(/\/\//i).test(baseUrl)) {
|
||||
baseUrl = URLToolkit.buildAbsoluteURL(window.location && window.location.href || '', baseUrl);
|
||||
}
|
||||
|
||||
return URLToolkit.buildAbsoluteURL(baseUrl, relativeUrl);
|
||||
};
|
||||
|
||||
export default resolveUrl;
|
||||
108
build/javascript/node_modules/@videojs/vhs-utils/src/stream.js
generated
vendored
Normal file
108
build/javascript/node_modules/@videojs/vhs-utils/src/stream.js
generated
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* @file stream.js
|
||||
*/
|
||||
/**
|
||||
* A lightweight readable stream implemention that handles event dispatching.
|
||||
*
|
||||
* @class Stream
|
||||
*/
|
||||
export default class Stream {
|
||||
constructor() {
|
||||
this.listeners = {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a listener for a specified event type.
|
||||
*
|
||||
* @param {string} type the event name
|
||||
* @param {Function} listener the callback to be invoked when an event of
|
||||
* the specified type occurs
|
||||
*/
|
||||
on(type, listener) {
|
||||
if (!this.listeners[type]) {
|
||||
this.listeners[type] = [];
|
||||
}
|
||||
this.listeners[type].push(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a listener for a specified event type.
|
||||
*
|
||||
* @param {string} type the event name
|
||||
* @param {Function} listener a function previously registered for this
|
||||
* type of event through `on`
|
||||
* @return {boolean} if we could turn it off or not
|
||||
*/
|
||||
off(type, listener) {
|
||||
if (!this.listeners[type]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const index = this.listeners[type].indexOf(listener);
|
||||
|
||||
// TODO: which is better?
|
||||
// In Video.js we slice listener functions
|
||||
// on trigger so that it does not mess up the order
|
||||
// while we loop through.
|
||||
//
|
||||
// Here we slice on off so that the loop in trigger
|
||||
// can continue using it's old reference to loop without
|
||||
// messing up the order.
|
||||
this.listeners[type] = this.listeners[type].slice(0);
|
||||
this.listeners[type].splice(index, 1);
|
||||
return index > -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger an event of the specified type on this stream. Any additional
|
||||
* arguments to this function are passed as parameters to event listeners.
|
||||
*
|
||||
* @param {string} type the event name
|
||||
*/
|
||||
trigger(type) {
|
||||
const callbacks = this.listeners[type];
|
||||
|
||||
if (!callbacks) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Slicing the arguments on every invocation of this method
|
||||
// can add a significant amount of overhead. Avoid the
|
||||
// intermediate object creation for the common case of a
|
||||
// single callback argument
|
||||
if (arguments.length === 2) {
|
||||
const length = callbacks.length;
|
||||
|
||||
for (let i = 0; i < length; ++i) {
|
||||
callbacks[i].call(this, arguments[1]);
|
||||
}
|
||||
} else {
|
||||
const args = Array.prototype.slice.call(arguments, 1);
|
||||
const length = callbacks.length;
|
||||
|
||||
for (let i = 0; i < length; ++i) {
|
||||
callbacks[i].apply(this, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys the stream and cleans up.
|
||||
*/
|
||||
dispose() {
|
||||
this.listeners = {};
|
||||
}
|
||||
/**
|
||||
* Forwards all `data` events on this stream to the destination stream. The
|
||||
* destination stream should provide a method `push` to receive the data
|
||||
* events as they arrive.
|
||||
*
|
||||
* @param {Stream} destination the stream that will receive all `data` events
|
||||
* @see http://nodejs.org/api/stream.html#stream_readable_pipe_destination_options
|
||||
*/
|
||||
pipe(destination) {
|
||||
this.on('data', function(data) {
|
||||
destination.push(data);
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user