super-hands
Version:
All-in-one natural hand controller interaction component for A-Frame.
1,471 lines (1,408 loc) • 2.86 MB
JavaScript
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
require('aframe')
require('../index.js')
// require('aframe-motion-capture-components')
/* used in examples to allow a desktop playback without HMD
defined here to keep example files clear of clutter */
window.playDemoRecording = function (spectate) {
const l = document.querySelector('a-link, a-entity[link]')
const s = document.querySelector('a-scene')
const b = document.getElementById('replayer-button')
b && b.setAttribute('visible', 'false')
l && l.setAttribute('visible', 'false')
s.addEventListener('replayingstopped', e => {
const c = document.querySelector('[camera]')
window.setTimeout(function () {
c.setAttribute('position', '0 1.6 2')
c.setAttribute('rotation', '0 0 0')
})
})
s.setAttribute('avatar-replayer', {
src: './demo-recording.json',
spectatorMode: spectate === undefined ? true : spectate,
spectatorPosition: { x: 0, y: 1.6, z: 2 }
})
}
},{"../index.js":2,"aframe":3}],2:[function(require,module,exports){
/* global AFRAME */
if (typeof AFRAME === 'undefined') {
throw new Error('Component attempted to register before AFRAME was available.')
}
require('./systems/super-hands-system.js')
require('./reaction_components/hoverable.js')
require('./reaction_components/grabbable.js')
require('./reaction_components/stretchable.js')
require('./reaction_components/drag-droppable.js')
require('./reaction_components/draggable.js')
require('./reaction_components/droppable.js')
require('./reaction_components/clickable.js')
/**
* Super Hands component for A-Frame.
*/
AFRAME.registerComponent('super-hands', {
schema: {
colliderEvent: { default: 'hit' },
colliderEventProperty: { default: 'el' },
colliderEndEvent: { default: 'hitend' },
colliderEndEventProperty: { default: 'el' },
grabStartButtons: {
default: ['gripdown', 'trackpaddown', 'triggerdown', 'gripclose',
'abuttondown', 'bbuttondown', 'xbuttondown', 'ybuttondown',
'pointup', 'thumbup', 'pointingstart', 'pistolstart',
'thumbstickdown', 'mousedown', 'touchstart']
},
grabEndButtons: {
default: ['gripup', 'trackpadup', 'triggerup', 'gripopen',
'abuttonup', 'bbuttonup', 'xbuttonup', 'ybuttonup',
'pointdown', 'thumbdown', 'pointingend', 'pistolend',
'thumbstickup', 'mouseup', 'touchend']
},
stretchStartButtons: {
default: ['gripdown', 'trackpaddown', 'triggerdown', 'gripclose',
'abuttondown', 'bbuttondown', 'xbuttondown', 'ybuttondown',
'pointup', 'thumbup', 'pointingstart', 'pistolstart',
'thumbstickdown', 'mousedown', 'touchstart']
},
stretchEndButtons: {
default: ['gripup', 'trackpadup', 'triggerup', 'gripopen',
'abuttonup', 'bbuttonup', 'xbuttonup', 'ybuttonup',
'pointdown', 'thumbdown', 'pointingend', 'pistolend',
'thumbstickup', 'mouseup', 'touchend']
},
dragDropStartButtons: {
default: ['gripdown', 'trackpaddown', 'triggerdown', 'gripclose',
'abuttondown', 'bbuttondown', 'xbuttondown', 'ybuttondown',
'pointup', 'thumbup', 'pointingstart', 'pistolstart',
'thumbstickdown', 'mousedown', 'touchstart']
},
dragDropEndButtons: {
default: ['gripup', 'trackpadup', 'triggerup', 'gripopen',
'abuttonup', 'bbuttonup', 'xbuttonup', 'ybuttonup',
'pointdown', 'thumbdown', 'pointingend', 'pistolend',
'thumbstickup', 'mouseup', 'touchend']
},
interval: { default: 0 }
},
/**
* Set if component needs multiple instancing.
*/
multiple: false,
/**
* Called once when component is attached. Generally for initial setup.
*/
init: function () {
// constants
this.HOVER_EVENT = 'hover-start'
this.UNHOVER_EVENT = 'hover-end'
this.GRAB_EVENT = 'grab-start'
this.UNGRAB_EVENT = 'grab-end'
this.STRETCH_EVENT = 'stretch-start'
this.UNSTRETCH_EVENT = 'stretch-end'
this.DRAG_EVENT = 'drag-start'
this.UNDRAG_EVENT = 'drag-end'
this.DRAGOVER_EVENT = 'dragover-start'
this.UNDRAGOVER_EVENT = 'dragover-end'
this.DRAGDROP_EVENT = 'drag-drop'
// links to other systems/components
this.otherSuperHand = null
// state tracking - global event handlers (GEH)
this.gehDragged = new Set()
this.gehClicking = new Set()
// state tracking - reaction components
this.hoverEls = []
this.hoverElsIntersections = []
this.prevCheckTime = null
this.state = new Map()
this.dragging = false
this.unHover = this.unHover.bind(this)
this.unWatch = this.unWatch.bind(this)
this.onHit = this.onHit.bind(this)
this.onGrabStartButton = this.onGrabStartButton.bind(this)
this.onGrabEndButton = this.onGrabEndButton.bind(this)
this.onStretchStartButton = this.onStretchStartButton.bind(this)
this.onStretchEndButton = this.onStretchEndButton.bind(this)
this.onDragDropStartButton = this.onDragDropStartButton.bind(this)
this.onDragDropEndButton = this.onDragDropEndButton.bind(this)
this.system.registerMe(this)
},
/**
* Called when component is attached and when component data changes.
* Generally modifies the entity based on the data.
*/
update: function (oldData) {
this.unRegisterListeners(oldData)
this.registerListeners()
},
/**
* Called when a component is removed (e.g., via removeAttribute).
* Generally undoes all modifications to the entity.
*/
remove: function () {
this.system.unregisterMe(this)
this.unRegisterListeners()
this.hoverEls.length = 0
if (this.state.get(this.HOVER_EVENT)) {
this._unHover(this.state.get(this.HOVER_EVENT))
}
this.onGrabEndButton()
this.onStretchEndButton()
this.onDragDropEndButton()
},
tick: (function () {
// closer objects and objects with no distance come later in list
function sorter (a, b) {
const aDist = a.distance == null ? -1 : a.distance
const bDist = b.distance == null ? -1 : b.distance
if (aDist < bDist) {
return 1
}
if (bDist < aDist) {
return -1
}
return 0
}
return function (time) {
const data = this.data
const prevCheckTime = this.prevCheckTime
if (prevCheckTime && (time - prevCheckTime < data.interval)) { return }
this.prevCheckTime = time
let orderChanged = false
this.hoverElsIntersections.sort(sorter)
for (let i = 0; i < this.hoverElsIntersections.length; i++) {
if (this.hoverEls[i] !== this.hoverElsIntersections[i].object.el) {
orderChanged = true
this.hoverEls[i] = this.hoverElsIntersections[i].object.el
}
}
if (orderChanged) {
this.hover()
}
}
})(),
onGrabStartButton: function (evt) {
let carried = this.state.get(this.GRAB_EVENT)
this.dispatchMouseEventAll('mousedown', this.el)
this.gehClicking = new Set(this.hoverEls)
if (!carried) {
carried = this.findTarget(this.GRAB_EVENT, {
hand: this.el,
buttonEvent: evt
})
if (carried) {
this.state.set(this.GRAB_EVENT, carried)
this._unHover(carried)
}
}
},
onGrabEndButton: function (evt) {
const clickables = this.hoverEls.filter(h => this.gehClicking.has(h))
const grabbed = this.state.get(this.GRAB_EVENT)
const endEvt = { hand: this.el, buttonEvent: evt }
this.dispatchMouseEventAll('mouseup', this.el)
for (let i = 0; i < clickables.length; i++) {
this.dispatchMouseEvent(clickables[i], 'click', this.el)
}
this.gehClicking.clear()
// check if grabbed entity accepts ungrab event
if (grabbed && !this.emitCancelable(grabbed, this.UNGRAB_EVENT, endEvt)) {
/* push to top of stack so a drop followed by re-grab gets the same
target */
this.promoteHoveredEl(this.state.get(this.GRAB_EVENT))
this.state.delete(this.GRAB_EVENT)
this.hover()
}
},
onStretchStartButton: function (evt) {
let stretched = this.state.get(this.STRETCH_EVENT)
if (!stretched) {
stretched = this.findTarget(this.STRETCH_EVENT, {
hand: this.el,
buttonEvent: evt
})
if (stretched) {
this.state.set(this.STRETCH_EVENT, stretched)
this._unHover(stretched)
}
}
},
onStretchEndButton: function (evt) {
const stretched = this.state.get(this.STRETCH_EVENT)
const endEvt = { hand: this.el, buttonEvent: evt }
// check if end event accepted
if (stretched &&
!this.emitCancelable(stretched, this.UNSTRETCH_EVENT, endEvt)) {
this.promoteHoveredEl(stretched)
this.state.delete(this.STRETCH_EVENT)
this.hover()
}
},
onDragDropStartButton: function (evt) {
let dragged = this.state.get(this.DRAG_EVENT)
this.dragging = true
if (this.hoverEls.length) {
this.gehDragged = new Set(this.hoverEls)
this.dispatchMouseEventAll('dragstart', this.el)
}
if (!dragged) {
/* prefer carried so that a drag started after a grab will work
with carried element rather than a currently intersected drop target.
fall back to queue in case a drag is initiated independent
of a grab */
if (this.state.get(this.GRAB_EVENT) &&
!this.emitCancelable(this.state.get(this.GRAB_EVENT), this.DRAG_EVENT,
{ hand: this.el, buttonEvent: evt })) {
dragged = this.state.get(this.GRAB_EVENT)
} else {
dragged = this.findTarget(this.DRAG_EVENT, {
hand: this.el,
buttonEvent: evt
})
}
if (dragged) {
this.state.set(this.DRAG_EVENT, dragged)
this._unHover(dragged)
}
}
},
onDragDropEndButton: function (evt) {
const carried = this.state.get(this.DRAG_EVENT)
this.dragging = false // keep _unHover() from activating another droptarget
this.gehDragged.forEach(carried => {
this.dispatchMouseEvent(carried, 'dragend', this.el)
// fire event both ways for all intersected targets
this.dispatchMouseEventAll('drop', carried, true, true)
this.dispatchMouseEventAll('dragleave', carried, true, true)
})
this.gehDragged.clear()
if (carried) {
const ddEvt = {
hand: this.el,
dropped: carried,
on: null,
buttonEvent: evt
}
const endEvt = { hand: this.el, buttonEvent: evt }
const dropTarget = this.findTarget(this.DRAGDROP_EVENT, ddEvt, true)
if (dropTarget) {
ddEvt.on = dropTarget
this.emitCancelable(carried, this.DRAGDROP_EVENT, ddEvt)
this._unHover(dropTarget)
}
// check if end event accepted
if (!this.emitCancelable(carried, this.UNDRAG_EVENT, endEvt)) {
this.promoteHoveredEl(carried)
this.state.delete(this.DRAG_EVENT)
this.hover()
}
}
},
processHitEl: function (hitEl, intersection) {
const dist = intersection && intersection.distance
const sects = this.hoverElsIntersections
const hoverEls = this.hoverEls
const hitElIndex = this.hoverEls.indexOf(hitEl)
let hoverNeedsUpdate = false
if (dist && intersection.instanceId !== undefined)
hitEl.object3D.userData = { instanceId: intersection.instanceId };
if (hitElIndex === -1) {
hoverNeedsUpdate = true
// insert in order of distance when available
if (dist != null) {
let i = 0
while (i < sects.length && dist < sects[i].distance) { i++ }
hoverEls.splice(i, 0, hitEl)
sects.splice(i, 0, intersection)
} else {
hoverEls.push(hitEl)
sects.push({ object: { el: hitEl } })
}
this.dispatchMouseEvent(hitEl, 'mouseover', this.el)
if (this.dragging && this.gehDragged.size) {
// events on targets and on dragged
this.gehDragged.forEach(dragged => {
this.dispatchMouseEventAll('dragenter', dragged, true, true)
})
}
}
return hoverNeedsUpdate
},
onHit: function (evt) {
const hitEl = evt.detail[this.data.colliderEventProperty]
let hoverNeedsUpdate = 0
if (!hitEl) { return }
if (Array.isArray(hitEl)) {
for (let i = 0, sect; i < hitEl.length; i++) {
sect = evt.detail.intersections && evt.detail.intersections[i]
hoverNeedsUpdate += this.processHitEl(hitEl[i], sect)
}
} else {
hoverNeedsUpdate += this.processHitEl(hitEl, null)
}
if (hoverNeedsUpdate) { this.hover() }
},
/* search collided entities for target to hover/dragover */
hover: function () {
let hvrevt, hoverEl
// end previous hover
if (this.state.has(this.HOVER_EVENT)) {
this._unHover(this.state.get(this.HOVER_EVENT), true)
}
if (this.state.has(this.DRAGOVER_EVENT)) {
this._unHover(this.state.get(this.DRAGOVER_EVENT), true)
}
if (this.dragging && this.state.get(this.DRAG_EVENT)) {
hvrevt = {
hand: this.el,
hovered: hoverEl,
carried: this.state.get(this.DRAG_EVENT)
}
hoverEl = this.findTarget(this.DRAGOVER_EVENT, hvrevt, true)
if (hoverEl) {
this.emitCancelable(this.state.get(this.DRAG_EVENT), this.DRAGOVER_EVENT, hvrevt)
this.state.set(this.DRAGOVER_EVENT, hoverEl)
}
}
// fallback to hover if not dragging or dragover wasn't successful
if (!this.state.has(this.DRAGOVER_EVENT)) {
hoverEl = this.findTarget(this.HOVER_EVENT, { hand: this.el }, true)
if (hoverEl) {
this.state.set(this.HOVER_EVENT, hoverEl)
}
}
},
/* called when controller moves out of collision range of entity */
unHover: function (evt) {
const clearedEls = evt.detail[this.data.colliderEndEventProperty]
if (clearedEls) {
if (Array.isArray(clearedEls)) {
clearedEls.forEach(el => this._unHover(el))
} else {
this._unHover(clearedEls)
}
}
},
/* inner unHover steps needed regardless of cause of unHover */
_unHover: function (el, skipNextHover) {
let unHovered = false
let evt
if (el === this.state.get(this.DRAGOVER_EVENT)) {
this.state.delete(this.DRAGOVER_EVENT)
unHovered = true
evt = {
hand: this.el,
hovered: el,
carried: this.state.get(this.DRAG_EVENT)
}
this.emitCancelable(el, this.UNDRAGOVER_EVENT, evt)
if (this.state.has(this.DRAG_EVENT)) {
this.emitCancelable(
this.state.get(this.DRAG_EVENT),
this.UNDRAGOVER_EVENT,
evt
)
}
}
if (el === this.state.get(this.HOVER_EVENT)) {
this.state.delete(this.HOVER_EVENT)
unHovered = true
this.emitCancelable(el, this.UNHOVER_EVENT, { hand: this.el })
}
// activate next target, if present
if (unHovered && !skipNextHover) {
this.hover()
}
},
unWatch: function (evt) {
const clearedEls = evt.detail[this.data.colliderEndEventProperty]
if (clearedEls) {
if (Array.isArray(clearedEls)) {
clearedEls.forEach(el => this._unWatch(el))
} else {
// deprecation path: sphere-collider
this._unWatch(clearedEls)
}
}
},
_unWatch: function (target) {
const hoverIndex = this.hoverEls.indexOf(target)
if (hoverIndex !== -1) {
this.hoverEls.splice(hoverIndex, 1)
this.hoverElsIntersections.splice(hoverIndex, 1)
}
this.gehDragged.forEach(dragged => {
this.dispatchMouseEvent(target, 'dragleave', dragged)
this.dispatchMouseEvent(dragged, 'dragleave', target)
})
this.dispatchMouseEvent(target, 'mouseout', this.el)
},
registerListeners: function () {
this.el.addEventListener(this.data.colliderEvent, this.onHit)
this.el.addEventListener(this.data.colliderEndEvent, this.unWatch)
this.el.addEventListener(this.data.colliderEndEvent, this.unHover)
// binding order to keep grabEnd from triggering dragover
// again before dragDropEnd can delete its carried state
this.data.grabStartButtons.forEach(b => {
this.el.addEventListener(b, this.onGrabStartButton)
})
this.data.stretchStartButtons.forEach(b => {
this.el.addEventListener(b, this.onStretchStartButton)
})
this.data.dragDropStartButtons.forEach(b => {
this.el.addEventListener(b, this.onDragDropStartButton)
})
this.data.dragDropEndButtons.forEach(b => {
this.el.addEventListener(b, this.onDragDropEndButton)
})
this.data.stretchEndButtons.forEach(b => {
this.el.addEventListener(b, this.onStretchEndButton)
})
this.data.grabEndButtons.forEach(b => {
this.el.addEventListener(b, this.onGrabEndButton)
})
},
unRegisterListeners: function (data) {
data = data || this.data
if (Object.keys(data).length === 0) {
// Empty object passed on initalization
return
}
this.el.removeEventListener(data.colliderEvent, this.onHit)
this.el.removeEventListener(data.colliderEndEvent, this.unHover)
this.el.removeEventListener(data.colliderEndEvent, this.unWatch)
data.grabStartButtons.forEach(b => {
this.el.removeEventListener(b, this.onGrabStartButton)
})
data.grabEndButtons.forEach(b => {
this.el.removeEventListener(b, this.onGrabEndButton)
})
data.stretchStartButtons.forEach(b => {
this.el.removeEventListener(b, this.onStretchStartButton)
})
data.stretchEndButtons.forEach(b => {
this.el.removeEventListener(b, this.onStretchEndButton)
})
data.dragDropStartButtons.forEach(b => {
this.el.removeEventListener(b, this.onDragDropStartButton)
})
data.dragDropEndButtons.forEach(b => {
this.el.removeEventListener(b, this.onDragDropEndButton)
})
},
emitCancelable: function (target, name, detail) {
detail = detail || {}
const data = { bubbles: true, cancelable: true, detail }
data.detail.target = data.detail.target || target
const evt = new window.CustomEvent(name, data)
return target.dispatchEvent(evt)
},
dispatchMouseEvent: function (target, name, relatedTarget) {
const mEvt = new window.MouseEvent(name, { relatedTarget })
target.dispatchEvent(mEvt)
},
dispatchMouseEventAll: function (name, relatedTarget, filterUsed, alsoReverse) {
let els = this.hoverEls
if (filterUsed) {
els = els
.filter(el => el !== this.state.get(this.GRAB_EVENT) &&
el !== this.state.get(this.DRAG_EVENT) &&
el !== this.state.get(this.STRETCH_EVENT) &&
!this.gehDragged.has(el))
}
if (alsoReverse) {
for (let i = 0; i < els.length; i++) {
this.dispatchMouseEvent(els[i], name, relatedTarget)
this.dispatchMouseEvent(relatedTarget, name, els[i])
}
} else {
for (let i = 0; i < els.length; i++) {
this.dispatchMouseEvent(els[i], name, relatedTarget)
}
}
},
findTarget: function (evType, detail, filterUsed) {
let elIndex
let eligibleEls = this.hoverEls
if (filterUsed) {
eligibleEls = eligibleEls
.filter(el => el !== this.state.get(this.GRAB_EVENT) &&
el !== this.state.get(this.DRAG_EVENT) &&
el !== this.state.get(this.STRETCH_EVENT))
}
for (elIndex = eligibleEls.length - 1; elIndex >= 0; elIndex--) {
if (!this.emitCancelable(eligibleEls[elIndex], evType, detail)) {
return eligibleEls[elIndex]
}
}
return null
},
// Helper to ensure dropping and regrabbing finds the same target for
// for order-sorted hoverEls (grabbing; no-op for distance-sorted (pointing)
promoteHoveredEl: function (el) {
const hoverIndex = this.hoverEls.indexOf(el)
if (hoverIndex !== -1 &&
this.hoverElsIntersections[hoverIndex].distance == null) {
this.hoverEls.splice(hoverIndex, 1)
const sect = this.hoverElsIntersections.splice(hoverIndex, 1)
this.hoverEls.push(el)
this.hoverElsIntersections.push(sect[0])
}
}
})
},{"./reaction_components/clickable.js":8,"./reaction_components/drag-droppable.js":9,"./reaction_components/draggable.js":10,"./reaction_components/droppable.js":11,"./reaction_components/grabbable.js":12,"./reaction_components/hoverable.js":13,"./reaction_components/stretchable.js":16,"./systems/super-hands-system.js":17}],3:[function(require,module,exports){
(function (process,Buffer){(function (){
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if(typeof define === 'function' && define.amd)
define([], factory);
else if(typeof exports === 'object')
exports["AFRAME"] = factory();
else
root["AFRAME"] = factory();
})(self, () => {
return /******/ (() => { // webpackBootstrap
/******/ var __webpack_modules__ = ({
/***/ "./node_modules/an-array/index.js":
/*!****************************************!*\
!*** ./node_modules/an-array/index.js ***!
\****************************************/
/***/ ((module) => {
var str = Object.prototype.toString;
module.exports = anArray;
function anArray(arr) {
return arr.BYTES_PER_ELEMENT && str.call(arr.buffer) === '[object ArrayBuffer]' || Array.isArray(arr);
}
/***/ }),
/***/ "./node_modules/as-number/index.js":
/*!*****************************************!*\
!*** ./node_modules/as-number/index.js ***!
\*****************************************/
/***/ ((module) => {
module.exports = function numtype(num, def) {
return typeof num === 'number' ? num : typeof def === 'number' ? def : 0;
};
/***/ }),
/***/ "./node_modules/base64-js/index.js":
/*!*****************************************!*\
!*** ./node_modules/base64-js/index.js ***!
\*****************************************/
/***/ ((__unused_webpack_module, exports) => {
"use strict";
exports.byteLength = byteLength;
exports.toByteArray = toByteArray;
exports.fromByteArray = fromByteArray;
var lookup = [];
var revLookup = [];
var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array;
var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
for (var i = 0, len = code.length; i < len; ++i) {
lookup[i] = code[i];
revLookup[code.charCodeAt(i)] = i;
}
// Support decoding URL-safe base64 strings, as Node.js does.
// See: https://en.wikipedia.org/wiki/Base64#URL_applications
revLookup['-'.charCodeAt(0)] = 62;
revLookup['_'.charCodeAt(0)] = 63;
function getLens(b64) {
var len = b64.length;
if (len % 4 > 0) {
throw new Error('Invalid string. Length must be a multiple of 4');
}
// Trim off extra bytes after placeholder bytes are found
// See: https://github.com/beatgammit/base64-js/issues/42
var validLen = b64.indexOf('=');
if (validLen === -1) validLen = len;
var placeHoldersLen = validLen === len ? 0 : 4 - validLen % 4;
return [validLen, placeHoldersLen];
}
// base64 is 4/3 + up to two characters of the original data
function byteLength(b64) {
var lens = getLens(b64);
var validLen = lens[0];
var placeHoldersLen = lens[1];
return (validLen + placeHoldersLen) * 3 / 4 - placeHoldersLen;
}
function _byteLength(b64, validLen, placeHoldersLen) {
return (validLen + placeHoldersLen) * 3 / 4 - placeHoldersLen;
}
function toByteArray(b64) {
var tmp;
var lens = getLens(b64);
var validLen = lens[0];
var placeHoldersLen = lens[1];
var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen));
var curByte = 0;
// if there are placeholders, only get up to the last complete 4 chars
var len = placeHoldersLen > 0 ? validLen - 4 : validLen;
var i;
for (i = 0; i < len; i += 4) {
tmp = revLookup[b64.charCodeAt(i)] << 18 | revLookup[b64.charCodeAt(i + 1)] << 12 | revLookup[b64.charCodeAt(i + 2)] << 6 | revLookup[b64.charCodeAt(i + 3)];
arr[curByte++] = tmp >> 16 & 0xFF;
arr[curByte++] = tmp >> 8 & 0xFF;
arr[curByte++] = tmp & 0xFF;
}
if (placeHoldersLen === 2) {
tmp = revLookup[b64.charCodeAt(i)] << 2 | revLookup[b64.charCodeAt(i + 1)] >> 4;
arr[curByte++] = tmp & 0xFF;
}
if (placeHoldersLen === 1) {
tmp = revLookup[b64.charCodeAt(i)] << 10 | revLookup[b64.charCodeAt(i + 1)] << 4 | revLookup[b64.charCodeAt(i + 2)] >> 2;
arr[curByte++] = tmp >> 8 & 0xFF;
arr[curByte++] = tmp & 0xFF;
}
return arr;
}
function tripletToBase64(num) {
return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F];
}
function encodeChunk(uint8, start, end) {
var tmp;
var output = [];
for (var i = start; i < end; i += 3) {
tmp = (uint8[i] << 16 & 0xFF0000) + (uint8[i + 1] << 8 & 0xFF00) + (uint8[i + 2] & 0xFF);
output.push(tripletToBase64(tmp));
}
return output.join('');
}
function fromByteArray(uint8) {
var tmp;
var len = uint8.length;
var extraBytes = len % 3; // if we have 1 byte left, pad 2 bytes
var parts = [];
var maxChunkLength = 16383; // must be multiple of 3
// go through the array every three bytes, we'll deal with trailing stuff later
for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {
parts.push(encodeChunk(uint8, i, i + maxChunkLength > len2 ? len2 : i + maxChunkLength));
}
// pad the end with zeros, but make sure to not forget the extra bytes
if (extraBytes === 1) {
tmp = uint8[len - 1];
parts.push(lookup[tmp >> 2] + lookup[tmp << 4 & 0x3F] + '==');
} else if (extraBytes === 2) {
tmp = (uint8[len - 2] << 8) + uint8[len - 1];
parts.push(lookup[tmp >> 10] + lookup[tmp >> 4 & 0x3F] + lookup[tmp << 2 & 0x3F] + '=');
}
return parts.join('');
}
/***/ }),
/***/ "./node_modules/buffer-equal/index.js":
/*!********************************************!*\
!*** ./node_modules/buffer-equal/index.js ***!
\********************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
var Buffer = (__webpack_require__(/*! buffer */ "./node_modules/buffer/index.js").Buffer); // for use with browserify
module.exports = function (a, b) {
if (!Buffer.isBuffer(a)) return undefined;
if (!Buffer.isBuffer(b)) return undefined;
if (typeof a.equals === 'function') return a.equals(b);
if (a.length !== b.length) return false;
for (var i = 0; i < a.length; i++) {
if (a[i] !== b[i]) return false;
}
return true;
};
/***/ }),
/***/ "./node_modules/buffer/index.js":
/*!**************************************!*\
!*** ./node_modules/buffer/index.js ***!
\**************************************/
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
"use strict";
/*!
* The buffer module from node.js, for the browser.
*
* @author Feross Aboukhadijeh <https://feross.org>
* @license MIT
*/
/* eslint-disable no-proto */
const base64 = __webpack_require__(/*! base64-js */ "./node_modules/base64-js/index.js");
const ieee754 = __webpack_require__(/*! ieee754 */ "./node_modules/ieee754/index.js");
const customInspectSymbol = typeof Symbol === 'function' && typeof Symbol['for'] === 'function' // eslint-disable-line dot-notation
? Symbol['for']('nodejs.util.inspect.custom') // eslint-disable-line dot-notation
: null;
exports.Buffer = Buffer;
exports.SlowBuffer = SlowBuffer;
exports.INSPECT_MAX_BYTES = 50;
const K_MAX_LENGTH = 0x7fffffff;
exports.kMaxLength = K_MAX_LENGTH;
/**
* If `Buffer.TYPED_ARRAY_SUPPORT`:
* === true Use Uint8Array implementation (fastest)
* === false Print warning and recommend using `buffer` v4.x which has an Object
* implementation (most compatible, even IE6)
*
* Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
* Opera 11.6+, iOS 4.2+.
*
* We report that the browser does not support typed arrays if the are not subclassable
* using __proto__. Firefox 4-29 lacks support for adding new properties to `Uint8Array`
* (See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438). IE 10 lacks support
* for __proto__ and has a buggy typed array implementation.
*/
Buffer.TYPED_ARRAY_SUPPORT = typedArraySupport();
if (!Buffer.TYPED_ARRAY_SUPPORT && typeof console !== 'undefined' && typeof console.error === 'function') {
console.error('This browser lacks typed array (Uint8Array) support which is required by ' + '`buffer` v5.x. Use `buffer` v4.x if you require old browser support.');
}
function typedArraySupport() {
// Can typed array instances can be augmented?
try {
const arr = new Uint8Array(1);
const proto = {
foo: function () {
return 42;
}
};
Object.setPrototypeOf(proto, Uint8Array.prototype);
Object.setPrototypeOf(arr, proto);
return arr.foo() === 42;
} catch (e) {
return false;
}
}
Object.defineProperty(Buffer.prototype, 'parent', {
enumerable: true,
get: function () {
if (!Buffer.isBuffer(this)) return undefined;
return this.buffer;
}
});
Object.defineProperty(Buffer.prototype, 'offset', {
enumerable: true,
get: function () {
if (!Buffer.isBuffer(this)) return undefined;
return this.byteOffset;
}
});
function createBuffer(length) {
if (length > K_MAX_LENGTH) {
throw new RangeError('The value "' + length + '" is invalid for option "size"');
}
// Return an augmented `Uint8Array` instance
const buf = new Uint8Array(length);
Object.setPrototypeOf(buf, Buffer.prototype);
return buf;
}
/**
* The Buffer constructor returns instances of `Uint8Array` that have their
* prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of
* `Uint8Array`, so the returned instances will have all the node `Buffer` methods
* and the `Uint8Array` methods. Square bracket notation works as expected -- it
* returns a single octet.
*
* The `Uint8Array` prototype remains unmodified.
*/
function Buffer(arg, encodingOrOffset, length) {
// Common case.
if (typeof arg === 'number') {
if (typeof encodingOrOffset === 'string') {
throw new TypeError('The "string" argument must be of type string. Received type number');
}
return allocUnsafe(arg);
}
return from(arg, encodingOrOffset, length);
}
Buffer.poolSize = 8192; // not used by this implementation
function from(value, encodingOrOffset, length) {
if (typeof value === 'string') {
return fromString(value, encodingOrOffset);
}
if (ArrayBuffer.isView(value)) {
return fromArrayView(value);
}
if (value == null) {
throw new TypeError('The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' + 'or Array-like Object. Received type ' + typeof value);
}
if (isInstance(value, ArrayBuffer) || value && isInstance(value.buffer, ArrayBuffer)) {
return fromArrayBuffer(value, encodingOrOffset, length);
}
if (typeof SharedArrayBuffer !== 'undefined' && (isInstance(value, SharedArrayBuffer) || value && isInstance(value.buffer, SharedArrayBuffer))) {
return fromArrayBuffer(value, encodingOrOffset, length);
}
if (typeof value === 'number') {
throw new TypeError('The "value" argument must not be of type number. Received type number');
}
const valueOf = value.valueOf && value.valueOf();
if (valueOf != null && valueOf !== value) {
return Buffer.from(valueOf, encodingOrOffset, length);
}
const b = fromObject(value);
if (b) return b;
if (typeof Symbol !== 'undefined' && Symbol.toPrimitive != null && typeof value[Symbol.toPrimitive] === 'function') {
return Buffer.from(value[Symbol.toPrimitive]('string'), encodingOrOffset, length);
}
throw new TypeError('The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' + 'or Array-like Object. Received type ' + typeof value);
}
/**
* Functionally equivalent to Buffer(arg, encoding) but throws a TypeError
* if value is a number.
* Buffer.from(str[, encoding])
* Buffer.from(array)
* Buffer.from(buffer)
* Buffer.from(arrayBuffer[, byteOffset[, length]])
**/
Buffer.from = function (value, encodingOrOffset, length) {
return from(value, encodingOrOffset, length);
};
// Note: Change prototype *after* Buffer.from is defined to workaround Chrome bug:
// https://github.com/feross/buffer/pull/148
Object.setPrototypeOf(Buffer.prototype, Uint8Array.prototype);
Object.setPrototypeOf(Buffer, Uint8Array);
function assertSize(size) {
if (typeof size !== 'number') {
throw new TypeError('"size" argument must be of type number');
} else if (size < 0) {
throw new RangeError('The value "' + size + '" is invalid for option "size"');
}
}
function alloc(size, fill, encoding) {
assertSize(size);
if (size <= 0) {
return createBuffer(size);
}
if (fill !== undefined) {
// Only pay attention to encoding if it's a string. This
// prevents accidentally sending in a number that would
// be interpreted as a start offset.
return typeof encoding === 'string' ? createBuffer(size).fill(fill, encoding) : createBuffer(size).fill(fill);
}
return createBuffer(size);
}
/**
* Creates a new filled Buffer instance.
* alloc(size[, fill[, encoding]])
**/
Buffer.alloc = function (size, fill, encoding) {
return alloc(size, fill, encoding);
};
function allocUnsafe(size) {
assertSize(size);
return createBuffer(size < 0 ? 0 : checked(size) | 0);
}
/**
* Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance.
* */
Buffer.allocUnsafe = function (size) {
return allocUnsafe(size);
};
/**
* Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance.
*/
Buffer.allocUnsafeSlow = function (size) {
return allocUnsafe(size);
};
function fromString(string, encoding) {
if (typeof encoding !== 'string' || encoding === '') {
encoding = 'utf8';
}
if (!Buffer.isEncoding(encoding)) {
throw new TypeError('Unknown encoding: ' + encoding);
}
const length = byteLength(string, encoding) | 0;
let buf = createBuffer(length);
const actual = buf.write(string, encoding);
if (actual !== length) {
// Writing a hex string, for example, that contains invalid characters will
// cause everything after the first invalid character to be ignored. (e.g.
// 'abxxcd' will be treated as 'ab')
buf = buf.slice(0, actual);
}
return buf;
}
function fromArrayLike(array) {
const length = array.length < 0 ? 0 : checked(array.length) | 0;
const buf = createBuffer(length);
for (let i = 0; i < length; i += 1) {
buf[i] = array[i] & 255;
}
return buf;
}
function fromArrayView(arrayView) {
if (isInstance(arrayView, Uint8Array)) {
const copy = new Uint8Array(arrayView);
return fromArrayBuffer(copy.buffer, copy.byteOffset, copy.byteLength);
}
return fromArrayLike(arrayView);
}
function fromArrayBuffer(array, byteOffset, length) {
if (byteOffset < 0 || array.byteLength < byteOffset) {
throw new RangeError('"offset" is outside of buffer bounds');
}
if (array.byteLength < byteOffset + (length || 0)) {
throw new RangeError('"length" is outside of buffer bounds');
}
let buf;
if (byteOffset === undefined && length === undefined) {
buf = new Uint8Array(array);
} else if (length === undefined) {
buf = new Uint8Array(array, byteOffset);
} else {
buf = new Uint8Array(array, byteOffset, length);
}
// Return an augmented `Uint8Array` instance
Object.setPrototypeOf(buf, Buffer.prototype);
return buf;
}
function fromObject(obj) {
if (Buffer.isBuffer(obj)) {
const len = checked(obj.length) | 0;
const buf = createBuffer(len);
if (buf.length === 0) {
return buf;
}
obj.copy(buf, 0, 0, len);
return buf;
}
if (obj.length !== undefined) {
if (typeof obj.length !== 'number' || numberIsNaN(obj.length)) {
return createBuffer(0);
}
return fromArrayLike(obj);
}
if (obj.type === 'Buffer' && Array.isArray(obj.data)) {
return fromArrayLike(obj.data);
}
}
function checked(length) {
// Note: cannot use `length < K_MAX_LENGTH` here because that fails when
// length is NaN (which is otherwise coerced to zero.)
if (length >= K_MAX_LENGTH) {
throw new RangeError('Attempt to allocate Buffer larger than maximum ' + 'size: 0x' + K_MAX_LENGTH.toString(16) + ' bytes');
}
return length | 0;
}
function SlowBuffer(length) {
if (+length != length) {
// eslint-disable-line eqeqeq
length = 0;
}
return Buffer.alloc(+length);
}
Buffer.isBuffer = function isBuffer(b) {
return b != null && b._isBuffer === true && b !== Buffer.prototype; // so Buffer.isBuffer(Buffer.prototype) will be false
};
Buffer.compare = function compare(a, b) {
if (isInstance(a, Uint8Array)) a = Buffer.from(a, a.offset, a.byteLength);
if (isInstance(b, Uint8Array)) b = Buffer.from(b, b.offset, b.byteLength);
if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) {
throw new TypeError('The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array');
}
if (a === b) return 0;
let x = a.length;
let y = b.length;
for (let i = 0, len = Math.min(x, y); i < len; ++i) {
if (a[i] !== b[i]) {
x = a[i];
y = b[i];
break;
}
}
if (x < y) return -1;
if (y < x) return 1;
return 0;
};
Buffer.isEncoding = function isEncoding(encoding) {
switch (String(encoding).toLowerCase()) {
case 'hex':
case 'utf8':
case 'utf-8':
case 'ascii':
case 'latin1':
case 'binary':
case 'base64':
case 'ucs2':
case 'ucs-2':
case 'utf16le':
case 'utf-16le':
return true;
default:
return false;
}
};
Buffer.concat = function concat(list, length) {
if (!Array.isArray(list)) {
throw new TypeError('"list" argument must be an Array of Buffers');
}
if (list.length === 0) {
return Buffer.alloc(0);
}
let i;
if (length === undefined) {
length = 0;
for (i = 0; i < list.length; ++i) {
length += list[i].length;
}
}
const buffer = Buffer.allocUnsafe(length);
let pos = 0;
for (i = 0; i < list.length; ++i) {
let buf = list[i];
if (isInstance(buf, Uint8Array)) {
if (pos + buf.length > buffer.length) {
if (!Buffer.isBuffer(buf)) buf = Buffer.from(buf);
buf.copy(buffer, pos);
} else {
Uint8Array.prototype.set.call(buffer, buf, pos);
}
} else if (!Buffer.isBuffer(buf)) {
throw new TypeError('"list" argument must be an Array of Buffers');
} else {
buf.copy(buffer, pos);
}
pos += buf.length;
}
return buffer;
};
function byteLength(string, encoding) {
if (Buffer.isBuffer(string)) {
return string.length;
}
if (ArrayBuffer.isView(string) || isInstance(string, ArrayBuffer)) {
return string.byteLength;
}
if (typeof string !== 'string') {
throw new TypeError('The "string" argument must be one of type string, Buffer, or ArrayBuffer. ' + 'Received type ' + typeof string);
}
const len = string.length;
const mustMatch = arguments.length > 2 && arguments[2] === true;
if (!mustMatch && len === 0) return 0;
// Use a for loop to avoid recursion
let loweredCase = false;
for (;;) {
switch (encoding) {
case 'ascii':
case 'latin1':
case 'binary':
return len;
case 'utf8':
case 'utf-8':
return utf8ToBytes(string).length;
case 'ucs2':
case 'ucs-2':
case 'utf16le':
case 'utf-16le':
return len * 2;
case 'hex':
return len >>> 1;
case 'base64':
return base64ToBytes(string).length;
default:
if (loweredCase) {
return mustMatch ? -1 : utf8ToBytes(string).length; // assume utf8
}
encoding = ('' + encoding).toLowerCase();
loweredCase = true;
}
}
}
Buffer.byteLength = byteLength;
function slowToString(encoding, start, end) {
let loweredCase = false;
// No need to verify that "this.length <= MAX_UINT32" since it's a read-only
// property of a typed array.
// This behaves neither like String nor Uint8Array in that we set start/end
// to their upper/lower bounds if the value passed is out of range.
// undefined is handled specially as per ECMA-262 6th Edition,
// Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization.
if (start === undefined || start < 0) {
start = 0;
}
// Return early if start > this.length. Done here to prevent potential uint32
// coercion fail below.
if (start > this.length) {
return '';
}
if (end === undefined || end > this.length) {
end = this.length;
}
if (end <= 0) {
return '';
}
// Force coercion to uint32. This will also coerce falsey/NaN values to 0.
end >>>= 0;
start >>>= 0;
if (end <= start) {
return '';
}
if (!encoding) encoding = 'utf8';
while (true) {
switch (encoding) {
case 'hex':
return hexSlice(this, start, end);
case 'utf8':
case 'utf-8':
return utf8Slice(this, start, end);
case 'ascii':
return asciiSlice(this, start, end);
case 'latin1':
case 'binary':
return latin1Slice(this, start, end);
case 'base64':
return base64Slice(this, start, end);
case 'ucs2':
case 'ucs-2':
case 'utf16le':
case 'utf-16le':
return utf16leSlice(this, start, end);
default:
if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding);
encoding = (encoding + '').toLowerCase();
loweredCase = true;
}
}
}
// This property is used by `Buffer.isBuffer` (and the `is-buffer` npm package)
// to detect a Buffer instance. It's not possible to use `instanceof Buffer`
// reliably in a browserify context because there could be multiple different
// copies of the 'buffer' package in use. This method works even for Buffer
// instances that were created from another copy of the `buffer` package.
// See: https://github.com/feross/buffer/issues/154
Buffer.prototype._isBuffer = true;
function swap(b, n, m) {
const i = b[n];
b[n] = b[m];
b[m] = i;
}
Buffer.prototype.swap16 = function swap16() {
const len = this.length;
if (len % 2 !== 0) {
throw new RangeError('Buffer size must be a multiple of 16-bits');
}
for (let i = 0; i < len; i += 2) {
swap(this, i, i + 1);
}
return this;
};
Buffer.prototype.swap32 = function swap32() {
const len = this.length;
if (len % 4 !== 0) {
throw new RangeError('Buffer size must be a multiple of 32-bits');
}
for (let i = 0; i < len; i += 4) {
swap(this, i, i + 3);
swap(this, i + 1, i + 2);
}
return this;
};
Buffer.prototype.swap64 = function swap64() {
const len = this.length;
if (len % 8 !== 0) {
throw new RangeError('Buffer size must be a multiple of 64-bits');
}
for (let i = 0; i < len; i += 8) {
swap(this, i, i + 7);
swap(this, i + 1, i + 6);
swap(this, i + 2, i + 5);
swap(this, i + 3, i + 4);
}
return this;
};
Buffer.prototype.toString = function toString() {
const length = this.length;
if (length === 0) return '';
if (arguments.length === 0) return utf8Slice(this, 0, length);
return slowToString.apply(this, arguments);
};
Buffer.prototype.toLocaleString = Buffer.prototype.toString;
Buffer.prototype.equals = function equals(b) {
if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer');
if (this === b) return true;
return Buffer.compare(this, b) === 0;
};
Buffer.prototype.inspect = function inspect() {
let str = '';
const max = exports.INSPECT_MAX_BYTES;
str = this.toString('hex', 0, max).replace(/(.{2})/g, '$1 ').trim();
if (this.length > max) str += ' ... ';
return '<Buffer ' + str + '>';
};
if (customInspectSymbol) {
Buffer.prototype[customInspectSymbol] = Buffer.prototype.inspect;
}
Buffer.prototype.compare = function compare(target, start, end, thisStart, thisEnd) {
if (isInstance(target, Uint8Array)) {
target = Buffer.from(target, target.offset, target.byteLength);
}
if (!Buffer.isBuffer(target)) {
throw new TypeError('The "target" argument must be one of type Buffer or Uint8Array. ' + 'Received type ' + typeof target);
}
if (start === undefined) {
start = 0;
}
if (end === undefined) {
end = target ? target.length : 0;
}
if (thisStart === undefined) {
thisStart = 0;
}
if (thisEnd === undefined) {
thisEnd = this.length;
}
if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) {
throw new RangeError('out of range index');
}
if (thisStart >= thisEnd && start >= end) {
return 0;
}
if (thisStart >= thisEnd) {
return -1;
}
if (start >= end) {
return 1;
}
start >>>= 0;
end >>>= 0;
thisStart >>>= 0;
thisEnd >>>= 0;
if (this === target) return 0;
let x = thisEnd - thisStart;
let y = end - start;
const len = Math.min(x, y);
const thisCopy = this.slice(thisStart, thisEnd);
const targetCopy = target.slice(start, end);
for (let i = 0; i < len; ++i) {
if (thisCopy[i] !== targetCopy[i]) {
x = thisCopy[i];
y = targetCopy[i];
break;
}
}
if (x < y) return -1;
if (y < x) return 1;
return 0;
};
// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`,
// OR the last index of `val` in `buffer` at offset <= `byteOffset`.
//
// Arguments:
// - buffer - a Buffer to search
// - val - a string, Buffer, or number
// - byteOffset - an index into `buffer`; will be clamped to an int32
// - encoding - an optional encoding, relevant is val is a string
// - dir - true for indexOf, false for lastIndexOf
function bidirectionalIndexOf(buffer, val, byteOffset, encoding, dir) {
// Empty buffer means no match
if (buffer.length === 0) return -1;
// Normalize byteOffset
if (typeof byteOffset === 'string') {
encoding = byteOffset;
byteOffset = 0;
} else if (byteOffset > 0x7fffffff) {
byteOffset = 0x7fffffff;
} else if (byteOffset < -0x80000000) {
byteOffset = -0x80000000;
}
byteOffset = +byteOffset; // Coerce to Number.
if (numberIsNaN(byteOffset)) {
// byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer
byteOffset = dir ? 0 : buffer.length - 1;
}
// Normalize byteOffset: negative offsets start from the end of the buffer
if (byteOffset < 0) byteOffset = buffer.length + byteOffset;
if (byteOffset >= buffer.length) {
if (dir) return -1;else byteOffset = buffer.length - 1;
} else if (byteOffset < 0) {
if (dir) byteOffset = 0;else return -1;
}
// Normalize val
if (typeof val === 'string') {
val = Buffer.from(val, encoding);
}
// Finally, search either indexOf (if dir is true) or lastIndexOf
if (Buffer.isBuffer(val)) {
// Special case: looking for empty string/buffer always fails
if (val.length === 0) {
return -1;
}
return arrayIndexOf(buffer, val, byteOffset, encoding, dir);
} else if (typeof val === 'number') {
val = val & 0xFF; // Search for a byte value [0-255]
if (typeof Uint8Array.prototype.indexOf === 'function') {
if (dir) {
return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset);
} else {
return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset);
}
}
return arrayIndexOf(buffer, [val], byteOffset, encoding, dir);
}
throw new TypeError('val must be string, number or Buffer');
}
function arrayIndexOf(arr, val, byteOffset, encoding, dir) {
let indexSize = 1;
let arrLength = arr.length;
let valLength = val.length;
if (encoding !== undefined) {
encoding = String(encoding).toLowerCase();
if (encoding === 'ucs2' || encoding === 'ucs-2' || encoding === 'utf16le' || encoding === 'utf-16le') {
if (arr.length < 2 || val.length < 2) {
return -1;
}
indexSize = 2;
arrLength /= 2;
valLength /= 2;
byteOffset /= 2;
}
}
function read(buf, i) {
if (indexSize === 1) {
return buf[i];
} else {
return buf.readUInt16BE(i * indexSize);
}
}
let i;
if (dir) {
let foundIndex = -1;
for (i = byteOffset; i < arrLength; i++) {
if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) {
if (foundIndex === -1) foundIndex = i;
if (i - foundIndex + 1 === valLength) return foundIndex * indexSize;
} else {
if (foundIndex !== -1) i -= i - foundIndex;
foundIndex = -1;
}
}
} else {
if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength;
for (i = byteOffset; i >= 0; i--) {
let found = true;
for (let j = 0; j < valLength; j++) {
if (read(arr, i + j) !== read(val, j)) {
found = false;
break;
}
}
if (found) return i;
}
}
return -1;
}
Buffer.prototype.includes = function includes(val, byteOffset, encoding) {
return this.indexOf(val, byteOffset, encoding) !== -1;
};
Buffer.prototype.indexOf = function indexOf(val, byteOffset, encoding) {
return bidirectionalIndexOf(this, val, byteOffset, encoding, true);
};
Buffer.prototype.lastIndexOf = function lastIndexOf(val, byteOffset, encoding) {
return bidirectionalIndexOf(this, val, byteOffset, encoding, false);
};
function hexWrite(buf, string, offset, length) {
offset = Number(offset) || 0;
const remaining = buf.length - offset;
if (!length) {
length = remaining;
} else {
length = Number(length);
if (length > remaining) {
length = remaining;
}
}
const strLen = string.length;
if (length > strLen / 2) {
length = strLen / 2;
}
let i;
for (i = 0; i < length; ++i) {
const parsed = parseInt(string.substr(i * 2, 2), 16);
if (numberIsNaN(parsed)) return i;
buf[offset + i]